LCOV - code coverage report
Current view: top level - crypto/asymmetric_keys - x509_public_key.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 68 89 76.4 %
Date: 2020-09-30 20:25:40 Functions: 4 5 80.0 %
Branches: 21 54 38.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Instantiate a public key crypto key from an X.509 Certificate
       3                 :            :  *
       4                 :            :  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
       5                 :            :  * Written by David Howells (dhowells@redhat.com)
       6                 :            :  */
       7                 :            : 
       8                 :            : #define pr_fmt(fmt) "X.509: "fmt
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/kernel.h>
      11                 :            : #include <linux/slab.h>
      12                 :            : #include <keys/asymmetric-subtype.h>
      13                 :            : #include <keys/asymmetric-parser.h>
      14                 :            : #include <keys/system_keyring.h>
      15                 :            : #include <crypto/hash.h>
      16                 :            : #include "asymmetric_keys.h"
      17                 :            : #include "x509_parser.h"
      18                 :            : 
      19                 :            : /*
      20                 :            :  * Set up the signature parameters in an X.509 certificate.  This involves
      21                 :            :  * digesting the signed data and extracting the signature.
      22                 :            :  */
      23                 :        414 : int x509_get_sig_params(struct x509_certificate *cert)
      24                 :            : {
      25                 :        414 :         struct public_key_signature *sig = cert->sig;
      26                 :            :         struct crypto_shash *tfm;
      27                 :            :         struct shash_desc *desc;
      28                 :            :         size_t desc_size;
      29                 :            :         int ret;
      30                 :            : 
      31                 :            :         pr_devel("==>%s()\n", __func__);
      32                 :            : 
      33         [ -  + ]:        414 :         if (!cert->pub->pkey_algo)
      34                 :          0 :                 cert->unsupported_key = true;
      35                 :            : 
      36         [ -  + ]:        414 :         if (!sig->pkey_algo)
      37                 :          0 :                 cert->unsupported_sig = true;
      38                 :            : 
      39                 :            :         /* We check the hash if we can - even if we can't then verify it */
      40         [ -  + ]:        414 :         if (!sig->hash_algo) {
      41                 :          0 :                 cert->unsupported_sig = true;
      42                 :          0 :                 return 0;
      43                 :            :         }
      44                 :            : 
      45                 :        414 :         sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
      46         [ +  - ]:        414 :         if (!sig->s)
      47                 :            :                 return -ENOMEM;
      48                 :            : 
      49                 :        414 :         sig->s_size = cert->raw_sig_size;
      50                 :            : 
      51                 :            :         /* Allocate the hashing algorithm we're going to need and find out how
      52                 :            :          * big the hash operational data will be.
      53                 :            :          */
      54                 :        414 :         tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
      55         [ -  + ]:        414 :         if (IS_ERR(tfm)) {
      56         [ #  # ]:          0 :                 if (PTR_ERR(tfm) == -ENOENT) {
      57                 :          0 :                         cert->unsupported_sig = true;
      58                 :          0 :                         return 0;
      59                 :            :                 }
      60                 :            :                 return PTR_ERR(tfm);
      61                 :            :         }
      62                 :            : 
      63                 :        414 :         desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
      64                 :        414 :         sig->digest_size = crypto_shash_digestsize(tfm);
      65                 :            : 
      66                 :            :         ret = -ENOMEM;
      67                 :        828 :         sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
      68         [ +  - ]:        414 :         if (!sig->digest)
      69                 :            :                 goto error;
      70                 :            : 
      71                 :        414 :         desc = kzalloc(desc_size, GFP_KERNEL);
      72         [ +  - ]:        414 :         if (!desc)
      73                 :            :                 goto error;
      74                 :            : 
      75                 :        414 :         desc->tfm = tfm;
      76                 :            : 
      77                 :        414 :         ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
      78         [ +  - ]:        414 :         if (ret < 0)
      79                 :            :                 goto error_2;
      80                 :            : 
      81                 :            :         ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs");
      82                 :            :         if (ret == -EKEYREJECTED) {
      83                 :            :                 pr_err("Cert %*phN is blacklisted\n",
      84                 :            :                        sig->digest_size, sig->digest);
      85                 :            :                 cert->blacklisted = true;
      86                 :            :                 ret = 0;
      87                 :            :         }
      88                 :            : 
      89                 :            : error_2:
      90                 :        414 :         kfree(desc);
      91                 :            : error:
      92                 :            :         crypto_free_shash(tfm);
      93                 :            :         pr_devel("<==%s() = %d\n", __func__, ret);
      94                 :        414 :         return ret;
      95                 :            : }
      96                 :            : 
      97                 :            : /*
      98                 :            :  * Check for self-signedness in an X.509 cert and if found, check the signature
      99                 :            :  * immediately if we can.
     100                 :            :  */
     101                 :        414 : int x509_check_for_self_signed(struct x509_certificate *cert)
     102                 :            : {
     103                 :            :         int ret = 0;
     104                 :            : 
     105                 :            :         pr_devel("==>%s()\n", __func__);
     106                 :            : 
     107   [ +  -  +  - ]:        828 :         if (cert->raw_subject_size != cert->raw_issuer_size ||
     108                 :        414 :             memcmp(cert->raw_subject, cert->raw_issuer,
     109                 :            :                    cert->raw_issuer_size) != 0)
     110                 :            :                 goto not_self_signed;
     111                 :            : 
     112   [ +  -  -  + ]:        414 :         if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
     113                 :            :                 /* If the AKID is present it may have one or two parts.  If
     114                 :            :                  * both are supplied, both must match.
     115                 :            :                  */
     116                 :          0 :                 bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
     117                 :          0 :                 bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
     118                 :            : 
     119         [ #  # ]:          0 :                 if (!a && !b)
     120                 :            :                         goto not_self_signed;
     121                 :            : 
     122                 :            :                 ret = -EKEYREJECTED;
     123   [ #  #  #  # ]:          0 :                 if (((a && !b) || (b && !a)) &&
     124         [ #  # ]:          0 :                     cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
     125                 :            :                         goto out;
     126                 :            :         }
     127                 :            : 
     128                 :            :         ret = -EKEYREJECTED;
     129         [ +  - ]:        414 :         if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
     130                 :            :                 goto out;
     131                 :            : 
     132                 :        414 :         ret = public_key_verify_signature(cert->pub, cert->sig);
     133         [ -  + ]:        414 :         if (ret < 0) {
     134         [ #  # ]:          0 :                 if (ret == -ENOPKG) {
     135                 :          0 :                         cert->unsupported_sig = true;
     136                 :            :                         ret = 0;
     137                 :            :                 }
     138                 :            :                 goto out;
     139                 :            :         }
     140                 :            : 
     141                 :            :         pr_devel("Cert Self-signature verified");
     142                 :        414 :         cert->self_signed = true;
     143                 :            : 
     144                 :            : out:
     145                 :            :         pr_devel("<==%s() = %d\n", __func__, ret);
     146                 :        414 :         return ret;
     147                 :            : 
     148                 :            : not_self_signed:
     149                 :            :         pr_devel("<==%s() = 0 [not]\n", __func__);
     150                 :            :         return 0;
     151                 :            : }
     152                 :            : 
     153                 :            : /*
     154                 :            :  * Attempt to parse a data blob for a key as an X509 certificate.
     155                 :            :  */
     156                 :        207 : static int x509_key_preparse(struct key_preparsed_payload *prep)
     157                 :            : {
     158                 :            :         struct asymmetric_key_ids *kids;
     159                 :            :         struct x509_certificate *cert;
     160                 :            :         const char *q;
     161                 :            :         size_t srlen, sulen;
     162                 :            :         char *desc = NULL, *p;
     163                 :            :         int ret;
     164                 :            : 
     165                 :        207 :         cert = x509_cert_parse(prep->data, prep->datalen);
     166         [ -  + ]:        207 :         if (IS_ERR(cert))
     167                 :          0 :                 return PTR_ERR(cert);
     168                 :            : 
     169                 :            :         pr_devel("Cert Issuer: %s\n", cert->issuer);
     170                 :            :         pr_devel("Cert Subject: %s\n", cert->subject);
     171                 :            : 
     172         [ +  - ]:        207 :         if (cert->unsupported_key) {
     173                 :            :                 ret = -ENOPKG;
     174                 :            :                 goto error_free_cert;
     175                 :            :         }
     176                 :            : 
     177                 :            :         pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
     178                 :            :         pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
     179                 :            : 
     180                 :        207 :         cert->pub->id_type = "X509";
     181                 :            : 
     182         [ -  + ]:        207 :         if (cert->unsupported_sig) {
     183                 :          0 :                 public_key_signature_free(cert->sig);
     184                 :          0 :                 cert->sig = NULL;
     185                 :            :         } else {
     186                 :            :                 pr_devel("Cert Signature: %s + %s\n",
     187                 :            :                          cert->sig->pkey_algo, cert->sig->hash_algo);
     188                 :            :         }
     189                 :            : 
     190                 :            :         /* Don't permit addition of blacklisted keys */
     191                 :            :         ret = -EKEYREJECTED;
     192         [ +  - ]:        207 :         if (cert->blacklisted)
     193                 :            :                 goto error_free_cert;
     194                 :            : 
     195                 :            :         /* Propose a description */
     196                 :        207 :         sulen = strlen(cert->subject);
     197         [ -  + ]:        207 :         if (cert->raw_skid) {
     198                 :          0 :                 srlen = cert->raw_skid_size;
     199                 :            :                 q = cert->raw_skid;
     200                 :            :         } else {
     201                 :        207 :                 srlen = cert->raw_serial_size;
     202                 :        207 :                 q = cert->raw_serial;
     203                 :            :         }
     204                 :            : 
     205                 :            :         ret = -ENOMEM;
     206                 :        207 :         desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
     207         [ +  - ]:        207 :         if (!desc)
     208                 :            :                 goto error_free_cert;
     209                 :        207 :         p = memcpy(desc, cert->subject, sulen);
     210                 :        207 :         p += sulen;
     211                 :        207 :         *p++ = ':';
     212                 :        207 :         *p++ = ' ';
     213                 :        207 :         p = bin2hex(p, q, srlen);
     214                 :        207 :         *p = 0;
     215                 :            : 
     216                 :            :         kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
     217         [ +  - ]:        207 :         if (!kids)
     218                 :            :                 goto error_free_desc;
     219                 :        207 :         kids->id[0] = cert->id;
     220                 :        207 :         kids->id[1] = cert->skid;
     221                 :            : 
     222                 :            :         /* We're pinning the module by being linked against it */
     223                 :        207 :         __module_get(public_key_subtype.owner);
     224                 :        207 :         prep->payload.data[asym_subtype] = &public_key_subtype;
     225                 :        207 :         prep->payload.data[asym_key_ids] = kids;
     226                 :        207 :         prep->payload.data[asym_crypto] = cert->pub;
     227                 :        207 :         prep->payload.data[asym_auth] = cert->sig;
     228                 :        207 :         prep->description = desc;
     229                 :        207 :         prep->quotalen = 100;
     230                 :            : 
     231                 :            :         /* We've finished with the certificate */
     232                 :        207 :         cert->pub = NULL;
     233                 :        207 :         cert->id = NULL;
     234                 :        207 :         cert->skid = NULL;
     235                 :        207 :         cert->sig = NULL;
     236                 :            :         desc = NULL;
     237                 :            :         ret = 0;
     238                 :            : 
     239                 :            : error_free_desc:
     240                 :        207 :         kfree(desc);
     241                 :            : error_free_cert:
     242                 :        207 :         x509_free_certificate(cert);
     243                 :        207 :         return ret;
     244                 :            : }
     245                 :            : 
     246                 :            : static struct asymmetric_key_parser x509_key_parser = {
     247                 :            :         .owner  = THIS_MODULE,
     248                 :            :         .name   = "x509",
     249                 :            :         .parse  = x509_key_preparse,
     250                 :            : };
     251                 :            : 
     252                 :            : /*
     253                 :            :  * Module stuff
     254                 :            :  */
     255                 :        207 : static int __init x509_key_init(void)
     256                 :            : {
     257                 :        207 :         return register_asymmetric_key_parser(&x509_key_parser);
     258                 :            : }
     259                 :            : 
     260                 :          0 : static void __exit x509_key_exit(void)
     261                 :            : {
     262                 :          0 :         unregister_asymmetric_key_parser(&x509_key_parser);
     263                 :          0 : }
     264                 :            : 
     265                 :            : module_init(x509_key_init);
     266                 :            : module_exit(x509_key_exit);
     267                 :            : 
     268                 :            : MODULE_DESCRIPTION("X.509 certificate parser");
     269                 :            : MODULE_AUTHOR("Red Hat, Inc.");
     270                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14