uboot/lib/crypto/public_key.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* In-software asymmetric public-key crypto subtype
   3 *
   4 * See Documentation/crypto/asymmetric-keys.txt
   5 *
   6 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
   7 * Written by David Howells (dhowells@redhat.com)
   8 */
   9
  10#define pr_fmt(fmt) "PKEY: "fmt
  11#ifdef __UBOOT__
  12#include <dm/devres.h>
  13#include <linux/bug.h>
  14#include <linux/compat.h>
  15#include <linux/err.h>
  16#else
  17#include <linux/module.h>
  18#include <linux/export.h>
  19#endif
  20#include <linux/kernel.h>
  21#ifndef __UBOOT__
  22#include <linux/slab.h>
  23#include <linux/seq_file.h>
  24#include <linux/scatterlist.h>
  25#include <keys/asymmetric-subtype.h>
  26#endif
  27#include <crypto/public_key.h>
  28#ifdef __UBOOT__
  29#include <image.h>
  30#include <u-boot/rsa.h>
  31#else
  32#include <crypto/akcipher.h>
  33#endif
  34
  35MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
  36MODULE_AUTHOR("Red Hat, Inc.");
  37MODULE_LICENSE("GPL");
  38
  39#ifndef __UBOOT__
  40/*
  41 * Provide a part of a description of the key for /proc/keys.
  42 */
  43static void public_key_describe(const struct key *asymmetric_key,
  44                                struct seq_file *m)
  45{
  46        struct public_key *key = asymmetric_key->payload.data[asym_crypto];
  47
  48        if (key)
  49                seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
  50}
  51#endif
  52
  53/*
  54 * Destroy a public key algorithm key.
  55 */
  56void public_key_free(struct public_key *key)
  57{
  58        if (key) {
  59                kfree(key->key);
  60                kfree(key->params);
  61                kfree(key);
  62        }
  63}
  64EXPORT_SYMBOL_GPL(public_key_free);
  65
  66#ifdef __UBOOT__
  67/*
  68 * from <linux>/crypto/asymmetric_keys/signature.c
  69 *
  70 * Destroy a public key signature.
  71 */
  72void public_key_signature_free(struct public_key_signature *sig)
  73{
  74        int i;
  75
  76        if (sig) {
  77                for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++)
  78                        free(sig->auth_ids[i]);
  79                free(sig->s);
  80                free(sig->digest);
  81                free(sig);
  82        }
  83}
  84EXPORT_SYMBOL_GPL(public_key_signature_free);
  85
  86/**
  87 * public_key_verify_signature - Verify a signature using a public key.
  88 *
  89 * @pkey:       Public key
  90 * @sig:        Signature
  91 *
  92 * Verify a signature, @sig, using a RSA public key, @pkey.
  93 *
  94 * Return:      0 - verified, non-zero error code - otherwise
  95 */
  96int public_key_verify_signature(const struct public_key *pkey,
  97                                const struct public_key_signature *sig)
  98{
  99        struct image_sign_info info;
 100        int ret;
 101
 102        pr_devel("==>%s()\n", __func__);
 103
 104        if (!pkey || !sig)
 105                return -EINVAL;
 106
 107        if (pkey->key_is_private)
 108                return -EINVAL;
 109
 110        memset(&info, '\0', sizeof(info));
 111        info.padding = image_get_padding_algo("pkcs-1.5");
 112        /*
 113         * Note: image_get_[checksum|crypto]_algo takes a string
 114         * argument like "<checksum>,<crypto>"
 115         * TODO: support other hash algorithms
 116         */
 117        if (strcmp(sig->pkey_algo, "rsa") || (sig->s_size * 8) != 2048) {
 118                pr_warn("Encryption is not RSA2048: %s%d\n",
 119                        sig->pkey_algo, sig->s_size * 8);
 120                return -ENOPKG;
 121        }
 122        if (!strcmp(sig->hash_algo, "sha1")) {
 123                info.checksum = image_get_checksum_algo("sha1,rsa2048");
 124                info.name = "sha1,rsa2048";
 125        } else if (!strcmp(sig->hash_algo, "sha256")) {
 126                info.checksum = image_get_checksum_algo("sha256,rsa2048");
 127                info.name = "sha256,rsa2048";
 128        } else {
 129                pr_warn("unknown msg digest algo: %s\n", sig->hash_algo);
 130                return -ENOPKG;
 131        }
 132        info.crypto = image_get_crypto_algo(info.name);
 133        if (IS_ERR(info.checksum) || IS_ERR(info.crypto))
 134                return -ENOPKG;
 135
 136        info.key = pkey->key;
 137        info.keylen = pkey->keylen;
 138
 139        if (rsa_verify_with_pkey(&info, sig->digest, sig->s, sig->s_size))
 140                ret = -EKEYREJECTED;
 141        else
 142                ret = 0;
 143
 144        pr_devel("<==%s() = %d\n", __func__, ret);
 145        return ret;
 146}
 147#else
 148/*
 149 * Destroy a public key algorithm key.
 150 */
 151static void public_key_destroy(void *payload0, void *payload3)
 152{
 153        public_key_free(payload0);
 154        public_key_signature_free(payload3);
 155}
 156
 157/*
 158 * Determine the crypto algorithm name.
 159 */
 160static
 161int software_key_determine_akcipher(const char *encoding,
 162                                    const char *hash_algo,
 163                                    const struct public_key *pkey,
 164                                    char alg_name[CRYPTO_MAX_ALG_NAME])
 165{
 166        int n;
 167
 168        if (strcmp(encoding, "pkcs1") == 0) {
 169                /* The data wangled by the RSA algorithm is typically padded
 170                 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
 171                 * sec 8.2].
 172                 */
 173                if (!hash_algo)
 174                        n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 175                                     "pkcs1pad(%s)",
 176                                     pkey->pkey_algo);
 177                else
 178                        n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 179                                     "pkcs1pad(%s,%s)",
 180                                     pkey->pkey_algo, hash_algo);
 181                return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
 182        }
 183
 184        if (strcmp(encoding, "raw") == 0) {
 185                strcpy(alg_name, pkey->pkey_algo);
 186                return 0;
 187        }
 188
 189        return -ENOPKG;
 190}
 191
 192static u8 *pkey_pack_u32(u8 *dst, u32 val)
 193{
 194        memcpy(dst, &val, sizeof(val));
 195        return dst + sizeof(val);
 196}
 197
 198/*
 199 * Query information about a key.
 200 */
 201static int software_key_query(const struct kernel_pkey_params *params,
 202                              struct kernel_pkey_query *info)
 203{
 204        struct crypto_akcipher *tfm;
 205        struct public_key *pkey = params->key->payload.data[asym_crypto];
 206        char alg_name[CRYPTO_MAX_ALG_NAME];
 207        u8 *key, *ptr;
 208        int ret, len;
 209
 210        ret = software_key_determine_akcipher(params->encoding,
 211                                              params->hash_algo,
 212                                              pkey, alg_name);
 213        if (ret < 0)
 214                return ret;
 215
 216        tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 217        if (IS_ERR(tfm))
 218                return PTR_ERR(tfm);
 219
 220        key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
 221                      GFP_KERNEL);
 222        if (!key)
 223                goto error_free_tfm;
 224        memcpy(key, pkey->key, pkey->keylen);
 225        ptr = key + pkey->keylen;
 226        ptr = pkey_pack_u32(ptr, pkey->algo);
 227        ptr = pkey_pack_u32(ptr, pkey->paramlen);
 228        memcpy(ptr, pkey->params, pkey->paramlen);
 229
 230        if (pkey->key_is_private)
 231                ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
 232        else
 233                ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
 234        if (ret < 0)
 235                goto error_free_key;
 236
 237        len = crypto_akcipher_maxsize(tfm);
 238        info->key_size = len * 8;
 239        info->max_data_size = len;
 240        info->max_sig_size = len;
 241        info->max_enc_size = len;
 242        info->max_dec_size = len;
 243        info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
 244                               KEYCTL_SUPPORTS_VERIFY);
 245        if (pkey->key_is_private)
 246                info->supported_ops |= (KEYCTL_SUPPORTS_DECRYPT |
 247                                        KEYCTL_SUPPORTS_SIGN);
 248        ret = 0;
 249
 250error_free_key:
 251        kfree(key);
 252error_free_tfm:
 253        crypto_free_akcipher(tfm);
 254        pr_devel("<==%s() = %d\n", __func__, ret);
 255        return ret;
 256}
 257
 258/*
 259 * Do encryption, decryption and signing ops.
 260 */
 261static int software_key_eds_op(struct kernel_pkey_params *params,
 262                               const void *in, void *out)
 263{
 264        const struct public_key *pkey = params->key->payload.data[asym_crypto];
 265        struct akcipher_request *req;
 266        struct crypto_akcipher *tfm;
 267        struct crypto_wait cwait;
 268        struct scatterlist in_sg, out_sg;
 269        char alg_name[CRYPTO_MAX_ALG_NAME];
 270        char *key, *ptr;
 271        int ret;
 272
 273        pr_devel("==>%s()\n", __func__);
 274
 275        ret = software_key_determine_akcipher(params->encoding,
 276                                              params->hash_algo,
 277                                              pkey, alg_name);
 278        if (ret < 0)
 279                return ret;
 280
 281        tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 282        if (IS_ERR(tfm))
 283                return PTR_ERR(tfm);
 284
 285        req = akcipher_request_alloc(tfm, GFP_KERNEL);
 286        if (!req)
 287                goto error_free_tfm;
 288
 289        key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
 290                      GFP_KERNEL);
 291        if (!key)
 292                goto error_free_req;
 293
 294        memcpy(key, pkey->key, pkey->keylen);
 295        ptr = key + pkey->keylen;
 296        ptr = pkey_pack_u32(ptr, pkey->algo);
 297        ptr = pkey_pack_u32(ptr, pkey->paramlen);
 298        memcpy(ptr, pkey->params, pkey->paramlen);
 299
 300        if (pkey->key_is_private)
 301                ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
 302        else
 303                ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
 304        if (ret)
 305                goto error_free_key;
 306
 307        sg_init_one(&in_sg, in, params->in_len);
 308        sg_init_one(&out_sg, out, params->out_len);
 309        akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
 310                                   params->out_len);
 311        crypto_init_wait(&cwait);
 312        akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 313                                      CRYPTO_TFM_REQ_MAY_SLEEP,
 314                                      crypto_req_done, &cwait);
 315
 316        /* Perform the encryption calculation. */
 317        switch (params->op) {
 318        case kernel_pkey_encrypt:
 319                ret = crypto_akcipher_encrypt(req);
 320                break;
 321        case kernel_pkey_decrypt:
 322                ret = crypto_akcipher_decrypt(req);
 323                break;
 324        case kernel_pkey_sign:
 325                ret = crypto_akcipher_sign(req);
 326                break;
 327        default:
 328                BUG();
 329        }
 330
 331        ret = crypto_wait_req(ret, &cwait);
 332        if (ret == 0)
 333                ret = req->dst_len;
 334
 335error_free_key:
 336        kfree(key);
 337error_free_req:
 338        akcipher_request_free(req);
 339error_free_tfm:
 340        crypto_free_akcipher(tfm);
 341        pr_devel("<==%s() = %d\n", __func__, ret);
 342        return ret;
 343}
 344
 345/*
 346 * Verify a signature using a public key.
 347 */
 348int public_key_verify_signature(const struct public_key *pkey,
 349                                const struct public_key_signature *sig)
 350{
 351        struct crypto_wait cwait;
 352        struct crypto_akcipher *tfm;
 353        struct akcipher_request *req;
 354        struct scatterlist src_sg[2];
 355        char alg_name[CRYPTO_MAX_ALG_NAME];
 356        char *key, *ptr;
 357        int ret;
 358
 359        pr_devel("==>%s()\n", __func__);
 360
 361        BUG_ON(!pkey);
 362        BUG_ON(!sig);
 363        BUG_ON(!sig->s);
 364
 365        ret = software_key_determine_akcipher(sig->encoding,
 366                                              sig->hash_algo,
 367                                              pkey, alg_name);
 368        if (ret < 0)
 369                return ret;
 370
 371        tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 372        if (IS_ERR(tfm))
 373                return PTR_ERR(tfm);
 374
 375        ret = -ENOMEM;
 376        req = akcipher_request_alloc(tfm, GFP_KERNEL);
 377        if (!req)
 378                goto error_free_tfm;
 379
 380        key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
 381                      GFP_KERNEL);
 382        if (!key)
 383                goto error_free_req;
 384
 385        memcpy(key, pkey->key, pkey->keylen);
 386        ptr = key + pkey->keylen;
 387        ptr = pkey_pack_u32(ptr, pkey->algo);
 388        ptr = pkey_pack_u32(ptr, pkey->paramlen);
 389        memcpy(ptr, pkey->params, pkey->paramlen);
 390
 391        if (pkey->key_is_private)
 392                ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
 393        else
 394                ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
 395        if (ret)
 396                goto error_free_key;
 397
 398        sg_init_table(src_sg, 2);
 399        sg_set_buf(&src_sg[0], sig->s, sig->s_size);
 400        sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
 401        akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
 402                                   sig->digest_size);
 403        crypto_init_wait(&cwait);
 404        akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 405                                      CRYPTO_TFM_REQ_MAY_SLEEP,
 406                                      crypto_req_done, &cwait);
 407        ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
 408
 409error_free_key:
 410        kfree(key);
 411error_free_req:
 412        akcipher_request_free(req);
 413error_free_tfm:
 414        crypto_free_akcipher(tfm);
 415        pr_devel("<==%s() = %d\n", __func__, ret);
 416        if (WARN_ON_ONCE(ret > 0))
 417                ret = -EINVAL;
 418        return ret;
 419}
 420EXPORT_SYMBOL_GPL(public_key_verify_signature);
 421
 422static int public_key_verify_signature_2(const struct key *key,
 423                                         const struct public_key_signature *sig)
 424{
 425        const struct public_key *pk = key->payload.data[asym_crypto];
 426        return public_key_verify_signature(pk, sig);
 427}
 428
 429/*
 430 * Public key algorithm asymmetric key subtype
 431 */
 432struct asymmetric_key_subtype public_key_subtype = {
 433        .owner                  = THIS_MODULE,
 434        .name                   = "public_key",
 435        .name_len               = sizeof("public_key") - 1,
 436        .describe               = public_key_describe,
 437        .destroy                = public_key_destroy,
 438        .query                  = software_key_query,
 439        .eds_op                 = software_key_eds_op,
 440        .verify_signature       = public_key_verify_signature_2,
 441};
 442EXPORT_SYMBOL_GPL(public_key_subtype);
 443#endif /* !__UBOOT__ */
 444