From: David Howells Date: Tue, 15 Jan 2013 15:33:39 +0000 (+0000) Subject: PKCS#7: Find the right key in the PKCS#7 key list and verify the signature X-Git-Tag: next-20130218~61^2~10 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=73afc6dc745fcb1f2686978f526127bf46c2d31a;p=karo-tx-linux.git PKCS#7: Find the right key in the PKCS#7 key list and verify the signature Find the appropriate key in the PKCS#7 key list and verify the signature with it. There may be several keys in there forming a chain. Any link in that chain or the root of that chain may be in our keyrings. Signed-off-by: David Howells Reviewed-by: Kees Cook --- diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 2f9f26c55f8b..3f6f0e2b5ed5 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -117,6 +117,53 @@ error_no_desc: return ret; } +/* + * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 + * uses the issuer's name and the issuing certificate serial number for + * matching purposes. These must match the certificate issuer's name (not + * subject's name) and the certificate serial number [RFC 2315 6.7]. + */ +static int pkcs7_find_key(struct pkcs7_message *pkcs7) +{ + struct x509_certificate *x509; + + kenter("%u,%u", pkcs7->raw_serial_size, pkcs7->raw_issuer_size); + + for (x509 = pkcs7->certs; x509; x509 = x509->next) { + pr_devel("- x509 %u,%u\n", + x509->raw_serial_size, x509->raw_issuer_size); + + /* I'm _assuming_ that the generator of the PKCS#7 message will + * encode the fields from the X.509 cert in the same way in the + * PKCS#7 message - but I can't be 100% sure of that. It's + * possible this will need element-by-element comparison. + */ + if (x509->raw_serial_size != pkcs7->raw_serial_size || + memcmp(x509->raw_serial, pkcs7->raw_serial, + pkcs7->raw_serial_size) != 0) + continue; + pr_devel("Found cert serial match\n"); + + if (x509->raw_issuer_size != pkcs7->raw_issuer_size || + memcmp(x509->raw_issuer, pkcs7->raw_issuer, + pkcs7->raw_issuer_size) != 0) { + pr_warn("X.509 subject and PKCS#7 issuer don't match\n"); + continue; + } + + if (x509->pub->pkey_algo != pkcs7->sig.pkey_algo) { + pr_warn("X.509 algo and PKCS#7 sig algo don't match\n"); + continue; + } + + pkcs7->signer = x509; + return 0; + } + pr_warn("Issuing X.509 cert not found (#%*ph)\n", + pkcs7->raw_serial_size, pkcs7->raw_serial); + return -ENOKEY; +} + /* * Verify a PKCS#7 message */ @@ -129,6 +176,20 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) if (ret < 0) return ret; + /* Find the key for the message signature */ + ret = pkcs7_find_key(pkcs7); + if (ret < 0) + return ret; + + pr_devel("Found X.509 cert\n"); + + /* Verify the PKCS#7 binary against the key */ + ret = public_key_verify_signature(pkcs7->signer->pub, &pkcs7->sig); + if (ret < 0) + return ret; + + pr_devel("Verified signature\n"); + return 0; } EXPORT_SYMBOL_GPL(pkcs7_verify);