Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Instantiate a public key crypto key from an X.509 Certificate
0003  *
0004  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #define pr_fmt(fmt) "X.509: "fmt
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <keys/asymmetric-subtype.h>
0013 #include <keys/asymmetric-parser.h>
0014 #include <keys/system_keyring.h>
0015 #include <crypto/hash.h>
0016 #include "asymmetric_keys.h"
0017 #include "x509_parser.h"
0018 
0019 /*
0020  * Set up the signature parameters in an X.509 certificate.  This involves
0021  * digesting the signed data and extracting the signature.
0022  */
0023 int x509_get_sig_params(struct x509_certificate *cert)
0024 {
0025     struct public_key_signature *sig = cert->sig;
0026     struct crypto_shash *tfm;
0027     struct shash_desc *desc;
0028     size_t desc_size;
0029     int ret;
0030 
0031     pr_devel("==>%s()\n", __func__);
0032 
0033     sig->data = cert->tbs;
0034     sig->data_size = cert->tbs_size;
0035 
0036     sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
0037     if (!sig->s)
0038         return -ENOMEM;
0039 
0040     sig->s_size = cert->raw_sig_size;
0041 
0042     /* Allocate the hashing algorithm we're going to need and find out how
0043      * big the hash operational data will be.
0044      */
0045     tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
0046     if (IS_ERR(tfm)) {
0047         if (PTR_ERR(tfm) == -ENOENT) {
0048             cert->unsupported_sig = true;
0049             return 0;
0050         }
0051         return PTR_ERR(tfm);
0052     }
0053 
0054     desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
0055     sig->digest_size = crypto_shash_digestsize(tfm);
0056 
0057     ret = -ENOMEM;
0058     sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
0059     if (!sig->digest)
0060         goto error;
0061 
0062     desc = kzalloc(desc_size, GFP_KERNEL);
0063     if (!desc)
0064         goto error;
0065 
0066     desc->tfm = tfm;
0067 
0068     ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
0069     if (ret < 0)
0070         goto error_2;
0071 
0072     ret = is_hash_blacklisted(sig->digest, sig->digest_size,
0073                   BLACKLIST_HASH_X509_TBS);
0074     if (ret == -EKEYREJECTED) {
0075         pr_err("Cert %*phN is blacklisted\n",
0076                sig->digest_size, sig->digest);
0077         cert->blacklisted = true;
0078         ret = 0;
0079     }
0080 
0081 error_2:
0082     kfree(desc);
0083 error:
0084     crypto_free_shash(tfm);
0085     pr_devel("<==%s() = %d\n", __func__, ret);
0086     return ret;
0087 }
0088 
0089 /*
0090  * Check for self-signedness in an X.509 cert and if found, check the signature
0091  * immediately if we can.
0092  */
0093 int x509_check_for_self_signed(struct x509_certificate *cert)
0094 {
0095     int ret = 0;
0096 
0097     pr_devel("==>%s()\n", __func__);
0098 
0099     if (cert->raw_subject_size != cert->raw_issuer_size ||
0100         memcmp(cert->raw_subject, cert->raw_issuer,
0101            cert->raw_issuer_size) != 0)
0102         goto not_self_signed;
0103 
0104     if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
0105         /* If the AKID is present it may have one or two parts.  If
0106          * both are supplied, both must match.
0107          */
0108         bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
0109         bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
0110 
0111         if (!a && !b)
0112             goto not_self_signed;
0113 
0114         ret = -EKEYREJECTED;
0115         if (((a && !b) || (b && !a)) &&
0116             cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
0117             goto out;
0118     }
0119 
0120     ret = public_key_verify_signature(cert->pub, cert->sig);
0121     if (ret < 0) {
0122         if (ret == -ENOPKG) {
0123             cert->unsupported_sig = true;
0124             ret = 0;
0125         }
0126         goto out;
0127     }
0128 
0129     pr_devel("Cert Self-signature verified");
0130     cert->self_signed = true;
0131 
0132 out:
0133     pr_devel("<==%s() = %d\n", __func__, ret);
0134     return ret;
0135 
0136 not_self_signed:
0137     pr_devel("<==%s() = 0 [not]\n", __func__);
0138     return 0;
0139 }
0140 
0141 /*
0142  * Attempt to parse a data blob for a key as an X509 certificate.
0143  */
0144 static int x509_key_preparse(struct key_preparsed_payload *prep)
0145 {
0146     struct asymmetric_key_ids *kids;
0147     struct x509_certificate *cert;
0148     const char *q;
0149     size_t srlen, sulen;
0150     char *desc = NULL, *p;
0151     int ret;
0152 
0153     cert = x509_cert_parse(prep->data, prep->datalen);
0154     if (IS_ERR(cert))
0155         return PTR_ERR(cert);
0156 
0157     pr_devel("Cert Issuer: %s\n", cert->issuer);
0158     pr_devel("Cert Subject: %s\n", cert->subject);
0159     pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
0160     pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
0161 
0162     cert->pub->id_type = "X509";
0163 
0164     if (cert->unsupported_sig) {
0165         public_key_signature_free(cert->sig);
0166         cert->sig = NULL;
0167     } else {
0168         pr_devel("Cert Signature: %s + %s\n",
0169              cert->sig->pkey_algo, cert->sig->hash_algo);
0170     }
0171 
0172     /* Don't permit addition of blacklisted keys */
0173     ret = -EKEYREJECTED;
0174     if (cert->blacklisted)
0175         goto error_free_cert;
0176 
0177     /* Propose a description */
0178     sulen = strlen(cert->subject);
0179     if (cert->raw_skid) {
0180         srlen = cert->raw_skid_size;
0181         q = cert->raw_skid;
0182     } else {
0183         srlen = cert->raw_serial_size;
0184         q = cert->raw_serial;
0185     }
0186 
0187     ret = -ENOMEM;
0188     desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
0189     if (!desc)
0190         goto error_free_cert;
0191     p = memcpy(desc, cert->subject, sulen);
0192     p += sulen;
0193     *p++ = ':';
0194     *p++ = ' ';
0195     p = bin2hex(p, q, srlen);
0196     *p = 0;
0197 
0198     kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
0199     if (!kids)
0200         goto error_free_desc;
0201     kids->id[0] = cert->id;
0202     kids->id[1] = cert->skid;
0203     kids->id[2] = asymmetric_key_generate_id(cert->raw_subject,
0204                          cert->raw_subject_size,
0205                          "", 0);
0206     if (IS_ERR(kids->id[2])) {
0207         ret = PTR_ERR(kids->id[2]);
0208         goto error_free_kids;
0209     }
0210 
0211     /* We're pinning the module by being linked against it */
0212     __module_get(public_key_subtype.owner);
0213     prep->payload.data[asym_subtype] = &public_key_subtype;
0214     prep->payload.data[asym_key_ids] = kids;
0215     prep->payload.data[asym_crypto] = cert->pub;
0216     prep->payload.data[asym_auth] = cert->sig;
0217     prep->description = desc;
0218     prep->quotalen = 100;
0219 
0220     /* We've finished with the certificate */
0221     cert->pub = NULL;
0222     cert->id = NULL;
0223     cert->skid = NULL;
0224     cert->sig = NULL;
0225     desc = NULL;
0226     kids = NULL;
0227     ret = 0;
0228 
0229 error_free_kids:
0230     kfree(kids);
0231 error_free_desc:
0232     kfree(desc);
0233 error_free_cert:
0234     x509_free_certificate(cert);
0235     return ret;
0236 }
0237 
0238 static struct asymmetric_key_parser x509_key_parser = {
0239     .owner  = THIS_MODULE,
0240     .name   = "x509",
0241     .parse  = x509_key_preparse,
0242 };
0243 
0244 /*
0245  * Module stuff
0246  */
0247 extern int __init certs_selftest(void);
0248 static int __init x509_key_init(void)
0249 {
0250     int ret;
0251 
0252     ret = register_asymmetric_key_parser(&x509_key_parser);
0253     if (ret < 0)
0254         return ret;
0255     return fips_signature_selftest();
0256 }
0257 
0258 static void __exit x509_key_exit(void)
0259 {
0260     unregister_asymmetric_key_parser(&x509_key_parser);
0261 }
0262 
0263 module_init(x509_key_init);
0264 module_exit(x509_key_exit);
0265 
0266 MODULE_DESCRIPTION("X.509 certificate parser");
0267 MODULE_AUTHOR("Red Hat, Inc.");
0268 MODULE_LICENSE("GPL");