From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755105AbaGHNQD (ORCPT ); Tue, 8 Jul 2014 09:16:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8791 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755072AbaGHNP6 (ORCPT ); Tue, 8 Jul 2014 09:15:58 -0400 Subject: [PATCH4/7] PKCS#7: Find the right key in the PKCS#7 key list and verify the signature From: David Howells To: keyrings@linux-nfs.org Cc: linux-security-module@vger.kernel.org, kexec@lists.infradead.org, Kees Cook , Vivek Goyal , linux-kernel@vger.kernel.org Date: Tue, 08 Jul 2014 14:15:31 +0100 Message-ID: <20140708131531.28621.21506.stgit@warthog.procyon.org.uk> In-Reply-To: <20140708131504.28621.61165.stgit@warthog.procyon.org.uk> References: <20140708131504.28621.61165.stgit@warthog.procyon.org.uk> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Acked-by: Vivek Goyal Reviewed-by: Kees Cook --- crypto/asymmetric_keys/pkcs7_verify.c | 64 +++++++++++++++++++++++++++++++++ include/crypto/pkcs7.h | 5 +++ 2 files changed, 69 insertions(+) diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 0bb408a..745e5c8 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -120,6 +120,55 @@ error_no_desc: } /* + * 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 pkcs7_signed_info *sinfo) +{ + struct x509_certificate *x509; + unsigned certix = 1; + + kenter("%u,%u,%u", + sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size); + + for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { + /* 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 != sinfo->raw_serial_size || + memcmp(x509->raw_serial, sinfo->raw_serial, + sinfo->raw_serial_size) != 0) + continue; + pr_devel("Sig %u: Found cert serial match X.509[%u]\n", + sinfo->index, certix); + + if (x509->raw_issuer_size != sinfo->raw_issuer_size || + memcmp(x509->raw_issuer, sinfo->raw_issuer, + sinfo->raw_issuer_size) != 0) { + pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n", + sinfo->index); + continue; + } + + if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { + pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", + sinfo->index); + continue; + } + + sinfo->signer = x509; + return 0; + } + pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", + sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial); + return -ENOKEY; +} + /* * Verify one signed information block from a PKCS#7 message. */ @@ -137,6 +186,21 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, if (ret < 0) return ret; + /* Find the key for the signature */ + ret = pkcs7_find_key(pkcs7, sinfo); + if (ret < 0) + return ret; + + pr_devel("Using X.509[%u] for sig %u\n", + sinfo->signer->index, sinfo->index); + + /* Verify the PKCS#7 binary against the key */ + ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); + if (ret < 0) + return ret; + + pr_devel("Verified signature %u\n", sinfo->index); + return 0; } diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h index 8f2628f..8ba0f38 100644 --- a/include/crypto/pkcs7.h +++ b/include/crypto/pkcs7.h @@ -21,3 +21,8 @@ extern void pkcs7_free_message(struct pkcs7_message *pkcs7); extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_datalen, bool want_wrapper); + +/* + * pkcs7_verify.c + */ +extern int pkcs7_verify(struct pkcs7_message *pkcs7);