[PATCH 13/23] PKCS#7: Find the right key in the PKCS#7 key list andverify the signature

From: David Howells
Date: Tue Oct 30 2012 - 15:21:29 EST


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 <dhowells@xxxxxxxxxx>
---

crypto/asymmetric_keys/pkcs7_verify.c | 61 +++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)


diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 7d7ac8a..614f2b6 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -114,6 +114,53 @@ 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 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
*/
int pkcs7_verify(struct pkcs7_message *pkcs7)
@@ -125,6 +172,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);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/