]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
PKCS#7: Verify internal certificate chain
authorDavid Howells <dhowells@redhat.com>
Tue, 15 Jan 2013 15:33:39 +0000 (15:33 +0000)
committerDavid Howells <dhowells@redhat.com>
Sat, 19 Jan 2013 01:05:20 +0000 (01:05 +0000)
Verify certificate chain in the X.509 certificates contained within the PKCS#7
message as far as possible.  If any signature that we should be able to verify
fails, we reject the whole lot.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
crypto/asymmetric_keys/pkcs7_verify.c
crypto/asymmetric_keys/x509_parser.h

index 3f6f0e2b5ed5b79b4ed77adff4387c139cad3129..b3774bdee63de419b613ae8d033326922cdceb89 100644 (file)
@@ -164,6 +164,70 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7)
        return -ENOKEY;
 }
 
+/*
+ * Verify the internal certificate chain as best we can.
+ */
+static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7)
+{
+       struct x509_certificate *x509 = pkcs7->signer, *p;
+       int ret;
+
+       kenter("");
+
+       for (;;) {
+               pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
+               ret = x509_get_sig_params(x509);
+               if (ret < 0)
+                       return ret;
+
+               if (x509->issuer)
+                       pr_debug("- issuer %s\n", x509->issuer);
+               if (x509->authority)
+                       pr_debug("- authkeyid %s\n", x509->authority);
+
+               if (!x509->authority ||
+                   (x509->subject &&
+                    strcmp(x509->subject, x509->authority) == 0)) {
+                       /* If there's no authority certificate specified, then
+                        * the certificate must be self-signed and is the root
+                        * of the chain.  Likewise if the cert is its own
+                        * authority.
+                        */
+                       pr_debug("- no auth?\n");
+                       if (x509->raw_subject_size != x509->raw_issuer_size ||
+                           memcmp(x509->raw_subject, x509->raw_issuer,
+                                  x509->raw_issuer_size) != 0)
+                               return 0;
+
+                       ret = x509_check_signature(x509->pub, x509);
+                       if (ret < 0)
+                               return ret;
+                       x509->signer = x509;
+                       pr_debug("- self-signed\n");
+                       return 0;
+               }
+
+               for (p = pkcs7->certs; p; p = p->next)
+                       if (!p->signer &&
+                           p->raw_subject_size == x509->raw_issuer_size &&
+                           strcmp(p->fingerprint, x509->authority) == 0 &&
+                           memcmp(p->raw_subject, x509->raw_issuer,
+                                  x509->raw_issuer_size) == 0)
+                               goto found_issuer;
+               pr_debug("- top\n");
+               return 0;
+
+       found_issuer:
+               pr_debug("- issuer %s\n", p->subject);
+               ret = x509_check_signature(p->pub, x509);
+               if (ret < 0)
+                       return ret;
+               x509->signer = p;
+               x509 = p;
+               might_sleep();
+       }
+}
+
 /*
  * Verify a PKCS#7 message
  */
@@ -190,6 +254,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
 
        pr_devel("Verified signature\n");
 
-       return 0;
+       /* Verify the internal certificate chain */
+       return pkcs7_verify_sig_chain(pkcs7);
 }
 EXPORT_SYMBOL_GPL(pkcs7_verify);
index 6b1d87791be73808cb025e9f46c941c4b0c399d4..5e35fba2124589dacba3b1ff41d11837df74ad44 100644 (file)
@@ -14,6 +14,7 @@
 
 struct x509_certificate {
        struct x509_certificate *next;
+       const struct x509_certificate *signer;  /* Certificate that signed this one */
        struct public_key *pub;                 /* Public key details */
        char            *issuer;                /* Name of certificate issuer */
        char            *subject;               /* Name of certificate subject */