X.509: Allow X.509 certs to be blacklisted
authorDavid Howells <dhowells@redhat.com>
Mon, 3 Apr 2017 15:07:25 +0000 (16:07 +0100)
committerDavid Howells <dhowells@redhat.com>
Mon, 3 Apr 2017 15:07:25 +0000 (16:07 +0100)
Allow X.509 certs to be blacklisted based on their TBSCertificate hash.
This is convenient since we have to determine this anyway to be able to
check the signature on an X.509 certificate.  This is also what UEFI uses
in its blacklist.

If a certificate built into the kernel is blacklisted, something like the
following might then be seen during boot:

X.509: Cert 123412341234c55c1dcc601ab8e172917706aa32fb5eaf826813547fdf02dd46 is blacklisted
Problem loading in-kernel X.509 certificate (-129)

where the hex string shown is the blacklisted hash.

Signed-off-by: David Howells <dhowells@redhat.com>
crypto/asymmetric_keys/x509_parser.h
crypto/asymmetric_keys/x509_public_key.c

index 05eef1c68881b9214af04857be0803aaf44c02cc..e373e74838120400b11ceec39e614aea3f4a08cd 100644 (file)
@@ -42,6 +42,7 @@ struct x509_certificate {
        bool            self_signed;            /* T if self-signed (check unsupported_sig too) */
        bool            unsupported_key;        /* T if key uses unsupported crypto */
        bool            unsupported_sig;        /* T if signature uses unsupported crypto */
+       bool            blacklisted;
 };
 
 /*
index fb732296cd36437950e9228baaecce4373a329eb..eea71dc9686c29fd2c3fe07d2c9fc0b213bc99b7 100644 (file)
@@ -84,6 +84,16 @@ int x509_get_sig_params(struct x509_certificate *cert)
                goto error_2;
        might_sleep();
        ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
+       if (ret < 0)
+               goto error_2;
+
+       ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs");
+       if (ret == -EKEYREJECTED) {
+               pr_err("Cert %*phN is blacklisted\n",
+                      sig->digest_size, sig->digest);
+               cert->blacklisted = true;
+               ret = 0;
+       }
 
 error_2:
        kfree(desc);
@@ -186,6 +196,11 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
                         cert->sig->pkey_algo, cert->sig->hash_algo);
        }
 
+       /* Don't permit addition of blacklisted keys */
+       ret = -EKEYREJECTED;
+       if (cert->blacklisted)
+               goto error_free_cert;
+
        /* Propose a description */
        sulen = strlen(cert->subject);
        if (cert->raw_skid) {