1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Verify the signature on a PKCS#7 message. 3 * 4 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #define pr_fmt(fmt) "PKCS7: "fmt 9 #include <linux/kernel.h> 10 #include <linux/export.h> 11 #include <linux/slab.h> 12 #include <linux/err.h> 13 #include <linux/asn1.h> 14 #include <crypto/hash.h> 15 #include <crypto/hash_info.h> 16 #include <crypto/public_key.h> 17 #include "pkcs7_parser.h" 18 19 /* 20 * Digest the relevant parts of the PKCS#7 data 21 */ 22 static int pkcs7_digest(struct pkcs7_message *pkcs7, 23 struct pkcs7_signed_info *sinfo) 24 { 25 struct public_key_signature *sig = sinfo->sig; 26 struct crypto_shash *tfm; 27 struct shash_desc *desc; 28 size_t desc_size; 29 int ret; 30 31 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); 32 33 /* The digest was calculated already. */ 34 if (sig->digest) 35 return 0; 36 37 if (!sinfo->sig->hash_algo) 38 return -ENOPKG; 39 40 /* Allocate the hashing algorithm we're going to need and find out how 41 * big the hash operational data will be. 42 */ 43 tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0); 44 if (IS_ERR(tfm)) 45 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 46 47 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 48 sig->digest_size = crypto_shash_digestsize(tfm); 49 50 ret = -ENOMEM; 51 sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); 52 if (!sig->digest) 53 goto error_no_desc; 54 55 desc = kzalloc(desc_size, GFP_KERNEL); 56 if (!desc) 57 goto error_no_desc; 58 59 desc->tfm = tfm; 60 61 /* Digest the message [RFC2315 9.3] */ 62 ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, 63 sig->digest); 64 if (ret < 0) 65 goto error; 66 pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); 67 68 /* However, if there are authenticated attributes, there must be a 69 * message digest attribute amongst them which corresponds to the 70 * digest we just calculated. 71 */ 72 if (sinfo->authattrs) { 73 u8 tag; 74 75 if (!sinfo->msgdigest) { 76 pr_warn("Sig %u: No messageDigest\n", sinfo->index); 77 ret = -EKEYREJECTED; 78 goto error; 79 } 80 81 if (sinfo->msgdigest_len != sig->digest_size) { 82 pr_warn("Sig %u: Invalid digest size (%u)\n", 83 sinfo->index, sinfo->msgdigest_len); 84 ret = -EBADMSG; 85 goto error; 86 } 87 88 if (memcmp(sig->digest, sinfo->msgdigest, 89 sinfo->msgdigest_len) != 0) { 90 pr_warn("Sig %u: Message digest doesn't match\n", 91 sinfo->index); 92 ret = -EKEYREJECTED; 93 goto error; 94 } 95 96 /* We then calculate anew, using the authenticated attributes 97 * as the contents of the digest instead. Note that we need to 98 * convert the attributes from a CONT.0 into a SET before we 99 * hash it. 100 */ 101 memset(sig->digest, 0, sig->digest_size); 102 103 ret = crypto_shash_init(desc); 104 if (ret < 0) 105 goto error; 106 tag = ASN1_CONS_BIT | ASN1_SET; 107 ret = crypto_shash_update(desc, &tag, 1); 108 if (ret < 0) 109 goto error; 110 ret = crypto_shash_finup(desc, sinfo->authattrs, 111 sinfo->authattrs_len, sig->digest); 112 if (ret < 0) 113 goto error; 114 pr_devel("AADigest = [%*ph]\n", 8, sig->digest); 115 } 116 117 error: 118 kfree(desc); 119 error_no_desc: 120 crypto_free_shash(tfm); 121 kleave(" = %d", ret); 122 return ret; 123 } 124 125 int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len, 126 enum hash_algo *hash_algo) 127 { 128 struct pkcs7_signed_info *sinfo = pkcs7->signed_infos; 129 int i, ret; 130 131 /* 132 * This function doesn't support messages with more than one signature. 133 */ 134 if (sinfo == NULL || sinfo->next != NULL) 135 return -EBADMSG; 136 137 ret = pkcs7_digest(pkcs7, sinfo); 138 if (ret) 139 return ret; 140 141 *buf = sinfo->sig->digest; 142 *len = sinfo->sig->digest_size; 143 144 i = match_string(hash_algo_name, HASH_ALGO__LAST, 145 sinfo->sig->hash_algo); 146 if (i >= 0) 147 *hash_algo = i; 148 149 return 0; 150 } 151 152 /* 153 * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 154 * uses the issuer's name and the issuing certificate serial number for 155 * matching purposes. These must match the certificate issuer's name (not 156 * subject's name) and the certificate serial number [RFC 2315 6.7]. 157 */ 158 static int pkcs7_find_key(struct pkcs7_message *pkcs7, 159 struct pkcs7_signed_info *sinfo) 160 { 161 struct x509_certificate *x509; 162 unsigned certix = 1; 163 164 kenter("%u", sinfo->index); 165 166 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { 167 /* I'm _assuming_ that the generator of the PKCS#7 message will 168 * encode the fields from the X.509 cert in the same way in the 169 * PKCS#7 message - but I can't be 100% sure of that. It's 170 * possible this will need element-by-element comparison. 171 */ 172 if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0])) 173 continue; 174 pr_devel("Sig %u: Found cert serial match X.509[%u]\n", 175 sinfo->index, certix); 176 177 sinfo->signer = x509; 178 return 0; 179 } 180 181 /* The relevant X.509 cert isn't found here, but it might be found in 182 * the trust keyring. 183 */ 184 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", 185 sinfo->index, 186 sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data); 187 return 0; 188 } 189 190 /* 191 * Verify the internal certificate chain as best we can. 192 */ 193 static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, 194 struct pkcs7_signed_info *sinfo) 195 { 196 struct public_key_signature *sig; 197 struct x509_certificate *x509 = sinfo->signer, *p; 198 struct asymmetric_key_id *auth; 199 int ret; 200 201 kenter(""); 202 203 for (p = pkcs7->certs; p; p = p->next) 204 p->seen = false; 205 206 for (;;) { 207 pr_debug("verify %s: %*phN\n", 208 x509->subject, 209 x509->raw_serial_size, x509->raw_serial); 210 x509->seen = true; 211 212 if (x509->blacklisted) { 213 /* If this cert is blacklisted, then mark everything 214 * that depends on this as blacklisted too. 215 */ 216 sinfo->blacklisted = true; 217 for (p = sinfo->signer; p != x509; p = p->signer) 218 p->blacklisted = true; 219 pr_debug("- blacklisted\n"); 220 return 0; 221 } 222 223 pr_debug("- issuer %s\n", x509->issuer); 224 sig = x509->sig; 225 if (sig->auth_ids[0]) 226 pr_debug("- authkeyid.id %*phN\n", 227 sig->auth_ids[0]->len, sig->auth_ids[0]->data); 228 if (sig->auth_ids[1]) 229 pr_debug("- authkeyid.skid %*phN\n", 230 sig->auth_ids[1]->len, sig->auth_ids[1]->data); 231 232 if (x509->self_signed) { 233 /* If there's no authority certificate specified, then 234 * the certificate must be self-signed and is the root 235 * of the chain. Likewise if the cert is its own 236 * authority. 237 */ 238 if (x509->unsupported_sig) 239 goto unsupported_sig_in_x509; 240 x509->signer = x509; 241 pr_debug("- self-signed\n"); 242 return 0; 243 } 244 245 /* Look through the X.509 certificates in the PKCS#7 message's 246 * list to see if the next one is there. 247 */ 248 auth = sig->auth_ids[0]; 249 if (auth) { 250 pr_debug("- want %*phN\n", auth->len, auth->data); 251 for (p = pkcs7->certs; p; p = p->next) { 252 pr_debug("- cmp [%u] %*phN\n", 253 p->index, p->id->len, p->id->data); 254 if (asymmetric_key_id_same(p->id, auth)) 255 goto found_issuer_check_skid; 256 } 257 } else if (sig->auth_ids[1]) { 258 auth = sig->auth_ids[1]; 259 pr_debug("- want %*phN\n", auth->len, auth->data); 260 for (p = pkcs7->certs; p; p = p->next) { 261 if (!p->skid) 262 continue; 263 pr_debug("- cmp [%u] %*phN\n", 264 p->index, p->skid->len, p->skid->data); 265 if (asymmetric_key_id_same(p->skid, auth)) 266 goto found_issuer; 267 } 268 } 269 270 /* We didn't find the root of this chain */ 271 pr_debug("- top\n"); 272 return 0; 273 274 found_issuer_check_skid: 275 /* We matched issuer + serialNumber, but if there's an 276 * authKeyId.keyId, that must match the CA subjKeyId also. 277 */ 278 if (sig->auth_ids[1] && 279 !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) { 280 pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n", 281 sinfo->index, x509->index, p->index); 282 return -EKEYREJECTED; 283 } 284 found_issuer: 285 pr_debug("- subject %s\n", p->subject); 286 if (p->seen) { 287 pr_warn("Sig %u: X.509 chain contains loop\n", 288 sinfo->index); 289 return 0; 290 } 291 ret = public_key_verify_signature(p->pub, x509->sig); 292 if (ret < 0) 293 return ret; 294 x509->signer = p; 295 if (x509 == p) { 296 pr_debug("- self-signed\n"); 297 return 0; 298 } 299 x509 = p; 300 might_sleep(); 301 } 302 303 unsupported_sig_in_x509: 304 /* Just prune the certificate chain at this point if we lack some 305 * crypto module to go further. Note, however, we don't want to set 306 * sinfo->unsupported_crypto as the signed info block may still be 307 * validatable against an X.509 cert lower in the chain that we have a 308 * trusted copy of. 309 */ 310 return 0; 311 } 312 313 /* 314 * Verify one signed information block from a PKCS#7 message. 315 */ 316 static int pkcs7_verify_one(struct pkcs7_message *pkcs7, 317 struct pkcs7_signed_info *sinfo) 318 { 319 int ret; 320 321 kenter(",%u", sinfo->index); 322 323 /* First of all, digest the data in the PKCS#7 message and the 324 * signed information block 325 */ 326 ret = pkcs7_digest(pkcs7, sinfo); 327 if (ret < 0) 328 return ret; 329 330 /* Find the key for the signature if there is one */ 331 ret = pkcs7_find_key(pkcs7, sinfo); 332 if (ret < 0) 333 return ret; 334 335 if (!sinfo->signer) 336 return 0; 337 338 pr_devel("Using X.509[%u] for sig %u\n", 339 sinfo->signer->index, sinfo->index); 340 341 /* Check that the PKCS#7 signing time is valid according to the X.509 342 * certificate. We can't, however, check against the system clock 343 * since that may not have been set yet and may be wrong. 344 */ 345 if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { 346 if (sinfo->signing_time < sinfo->signer->valid_from || 347 sinfo->signing_time > sinfo->signer->valid_to) { 348 pr_warn("Message signed outside of X.509 validity window\n"); 349 return -EKEYREJECTED; 350 } 351 } 352 353 /* Verify the PKCS#7 binary against the key */ 354 ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig); 355 if (ret < 0) 356 return ret; 357 358 pr_devel("Verified signature %u\n", sinfo->index); 359 360 /* Verify the internal certificate chain */ 361 return pkcs7_verify_sig_chain(pkcs7, sinfo); 362 } 363 364 /** 365 * pkcs7_verify - Verify a PKCS#7 message 366 * @pkcs7: The PKCS#7 message to be verified 367 * @usage: The use to which the key is being put 368 * 369 * Verify a PKCS#7 message is internally consistent - that is, the data digest 370 * matches the digest in the AuthAttrs and any signature in the message or one 371 * of the X.509 certificates it carries that matches another X.509 cert in the 372 * message can be verified. 373 * 374 * This does not look to match the contents of the PKCS#7 message against any 375 * external public keys. 376 * 377 * Returns, in order of descending priority: 378 * 379 * (*) -EKEYREJECTED if a key was selected that had a usage restriction at 380 * odds with the specified usage, or: 381 * 382 * (*) -EKEYREJECTED if a signature failed to match for which we found an 383 * appropriate X.509 certificate, or: 384 * 385 * (*) -EBADMSG if some part of the message was invalid, or: 386 * 387 * (*) 0 if a signature chain passed verification, or: 388 * 389 * (*) -EKEYREJECTED if a blacklisted key was encountered, or: 390 * 391 * (*) -ENOPKG if none of the signature chains are verifiable because suitable 392 * crypto modules couldn't be found. 393 */ 394 int pkcs7_verify(struct pkcs7_message *pkcs7, 395 enum key_being_used_for usage) 396 { 397 struct pkcs7_signed_info *sinfo; 398 int actual_ret = -ENOPKG; 399 int ret; 400 401 kenter(""); 402 403 switch (usage) { 404 case VERIFYING_MODULE_SIGNATURE: 405 if (pkcs7->data_type != OID_data) { 406 pr_warn("Invalid module sig (not pkcs7-data)\n"); 407 return -EKEYREJECTED; 408 } 409 if (pkcs7->have_authattrs) { 410 pr_warn("Invalid module sig (has authattrs)\n"); 411 return -EKEYREJECTED; 412 } 413 break; 414 case VERIFYING_FIRMWARE_SIGNATURE: 415 if (pkcs7->data_type != OID_data) { 416 pr_warn("Invalid firmware sig (not pkcs7-data)\n"); 417 return -EKEYREJECTED; 418 } 419 if (!pkcs7->have_authattrs) { 420 pr_warn("Invalid firmware sig (missing authattrs)\n"); 421 return -EKEYREJECTED; 422 } 423 break; 424 case VERIFYING_KEXEC_PE_SIGNATURE: 425 if (pkcs7->data_type != OID_msIndirectData) { 426 pr_warn("Invalid kexec sig (not Authenticode)\n"); 427 return -EKEYREJECTED; 428 } 429 /* Authattr presence checked in parser */ 430 break; 431 case VERIFYING_UNSPECIFIED_SIGNATURE: 432 if (pkcs7->data_type != OID_data) { 433 pr_warn("Invalid unspecified sig (not pkcs7-data)\n"); 434 return -EKEYREJECTED; 435 } 436 break; 437 default: 438 return -EINVAL; 439 } 440 441 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 442 ret = pkcs7_verify_one(pkcs7, sinfo); 443 if (sinfo->blacklisted) { 444 if (actual_ret == -ENOPKG) 445 actual_ret = -EKEYREJECTED; 446 continue; 447 } 448 if (ret < 0) { 449 if (ret == -ENOPKG) { 450 sinfo->unsupported_crypto = true; 451 continue; 452 } 453 kleave(" = %d", ret); 454 return ret; 455 } 456 actual_ret = 0; 457 } 458 459 kleave(" = %d", actual_ret); 460 return actual_ret; 461 } 462 EXPORT_SYMBOL_GPL(pkcs7_verify); 463 464 /** 465 * pkcs7_supply_detached_data - Supply the data needed to verify a PKCS#7 message 466 * @pkcs7: The PKCS#7 message 467 * @data: The data to be verified 468 * @datalen: The amount of data 469 * 470 * Supply the detached data needed to verify a PKCS#7 message. Note that no 471 * attempt to retain/pin the data is made. That is left to the caller. The 472 * data will not be modified by pkcs7_verify() and will not be freed when the 473 * PKCS#7 message is freed. 474 * 475 * Returns -EINVAL if data is already supplied in the message, 0 otherwise. 476 */ 477 int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 478 const void *data, size_t datalen) 479 { 480 if (pkcs7->data) { 481 pr_warn("Data already supplied\n"); 482 return -EINVAL; 483 } 484 pkcs7->data = data; 485 pkcs7->data_len = datalen; 486 return 0; 487 } 488 EXPORT_SYMBOL_GPL(pkcs7_supply_detached_data); 489
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.