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