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 <dhowe...@redhat.com>
---

 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to