linux/crypto/rsa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* RSA asymmetric public-key algorithm [RFC3447]
   3 *
   4 * Copyright (c) 2015, Intel Corporation
   5 * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/mpi.h>
  10#include <crypto/internal/rsa.h>
  11#include <crypto/internal/akcipher.h>
  12#include <crypto/akcipher.h>
  13#include <crypto/algapi.h>
  14
  15struct rsa_mpi_key {
  16        MPI n;
  17        MPI e;
  18        MPI d;
  19};
  20
  21/*
  22 * RSAEP function [RFC3447 sec 5.1.1]
  23 * c = m^e mod n;
  24 */
  25static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
  26{
  27        /* (1) Validate 0 <= m < n */
  28        if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
  29                return -EINVAL;
  30
  31        /* (2) c = m^e mod n */
  32        return mpi_powm(c, m, key->e, key->n);
  33}
  34
  35/*
  36 * RSADP function [RFC3447 sec 5.1.2]
  37 * m = c^d mod n;
  38 */
  39static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
  40{
  41        /* (1) Validate 0 <= c < n */
  42        if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
  43                return -EINVAL;
  44
  45        /* (2) m = c^d mod n */
  46        return mpi_powm(m, c, key->d, key->n);
  47}
  48
  49static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
  50{
  51        return akcipher_tfm_ctx(tfm);
  52}
  53
  54static int rsa_enc(struct akcipher_request *req)
  55{
  56        struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
  57        const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
  58        MPI m, c = mpi_alloc(0);
  59        int ret = 0;
  60        int sign;
  61
  62        if (!c)
  63                return -ENOMEM;
  64
  65        if (unlikely(!pkey->n || !pkey->e)) {
  66                ret = -EINVAL;
  67                goto err_free_c;
  68        }
  69
  70        ret = -ENOMEM;
  71        m = mpi_read_raw_from_sgl(req->src, req->src_len);
  72        if (!m)
  73                goto err_free_c;
  74
  75        ret = _rsa_enc(pkey, c, m);
  76        if (ret)
  77                goto err_free_m;
  78
  79        ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign);
  80        if (ret)
  81                goto err_free_m;
  82
  83        if (sign < 0)
  84                ret = -EBADMSG;
  85
  86err_free_m:
  87        mpi_free(m);
  88err_free_c:
  89        mpi_free(c);
  90        return ret;
  91}
  92
  93static int rsa_dec(struct akcipher_request *req)
  94{
  95        struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
  96        const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
  97        MPI c, m = mpi_alloc(0);
  98        int ret = 0;
  99        int sign;
 100
 101        if (!m)
 102                return -ENOMEM;
 103
 104        if (unlikely(!pkey->n || !pkey->d)) {
 105                ret = -EINVAL;
 106                goto err_free_m;
 107        }
 108
 109        ret = -ENOMEM;
 110        c = mpi_read_raw_from_sgl(req->src, req->src_len);
 111        if (!c)
 112                goto err_free_m;
 113
 114        ret = _rsa_dec(pkey, m, c);
 115        if (ret)
 116                goto err_free_c;
 117
 118        ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
 119        if (ret)
 120                goto err_free_c;
 121
 122        if (sign < 0)
 123                ret = -EBADMSG;
 124err_free_c:
 125        mpi_free(c);
 126err_free_m:
 127        mpi_free(m);
 128        return ret;
 129}
 130
 131static void rsa_free_mpi_key(struct rsa_mpi_key *key)
 132{
 133        mpi_free(key->d);
 134        mpi_free(key->e);
 135        mpi_free(key->n);
 136        key->d = NULL;
 137        key->e = NULL;
 138        key->n = NULL;
 139}
 140
 141static int rsa_check_key_length(unsigned int len)
 142{
 143        switch (len) {
 144        case 512:
 145        case 1024:
 146        case 1536:
 147        case 2048:
 148        case 3072:
 149        case 4096:
 150                return 0;
 151        }
 152
 153        return -EINVAL;
 154}
 155
 156static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
 157                           unsigned int keylen)
 158{
 159        struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
 160        struct rsa_key raw_key = {0};
 161        int ret;
 162
 163        /* Free the old MPI key if any */
 164        rsa_free_mpi_key(mpi_key);
 165
 166        ret = rsa_parse_pub_key(&raw_key, key, keylen);
 167        if (ret)
 168                return ret;
 169
 170        mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
 171        if (!mpi_key->e)
 172                goto err;
 173
 174        mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
 175        if (!mpi_key->n)
 176                goto err;
 177
 178        if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
 179                rsa_free_mpi_key(mpi_key);
 180                return -EINVAL;
 181        }
 182
 183        return 0;
 184
 185err:
 186        rsa_free_mpi_key(mpi_key);
 187        return -ENOMEM;
 188}
 189
 190static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 191                            unsigned int keylen)
 192{
 193        struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
 194        struct rsa_key raw_key = {0};
 195        int ret;
 196
 197        /* Free the old MPI key if any */
 198        rsa_free_mpi_key(mpi_key);
 199
 200        ret = rsa_parse_priv_key(&raw_key, key, keylen);
 201        if (ret)
 202                return ret;
 203
 204        mpi_key->d = mpi_read_raw_data(raw_key.d, raw_key.d_sz);
 205        if (!mpi_key->d)
 206                goto err;
 207
 208        mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
 209        if (!mpi_key->e)
 210                goto err;
 211
 212        mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
 213        if (!mpi_key->n)
 214                goto err;
 215
 216        if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
 217                rsa_free_mpi_key(mpi_key);
 218                return -EINVAL;
 219        }
 220
 221        return 0;
 222
 223err:
 224        rsa_free_mpi_key(mpi_key);
 225        return -ENOMEM;
 226}
 227
 228static unsigned int rsa_max_size(struct crypto_akcipher *tfm)
 229{
 230        struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
 231
 232        return mpi_get_size(pkey->n);
 233}
 234
 235static void rsa_exit_tfm(struct crypto_akcipher *tfm)
 236{
 237        struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
 238
 239        rsa_free_mpi_key(pkey);
 240}
 241
 242static struct akcipher_alg rsa = {
 243        .encrypt = rsa_enc,
 244        .decrypt = rsa_dec,
 245        .set_priv_key = rsa_set_priv_key,
 246        .set_pub_key = rsa_set_pub_key,
 247        .max_size = rsa_max_size,
 248        .exit = rsa_exit_tfm,
 249        .base = {
 250                .cra_name = "rsa",
 251                .cra_driver_name = "rsa-generic",
 252                .cra_priority = 100,
 253                .cra_module = THIS_MODULE,
 254                .cra_ctxsize = sizeof(struct rsa_mpi_key),
 255        },
 256};
 257
 258static int rsa_init(void)
 259{
 260        int err;
 261
 262        err = crypto_register_akcipher(&rsa);
 263        if (err)
 264                return err;
 265
 266        err = crypto_register_template(&rsa_pkcs1pad_tmpl);
 267        if (err) {
 268                crypto_unregister_akcipher(&rsa);
 269                return err;
 270        }
 271
 272        return 0;
 273}
 274
 275static void rsa_exit(void)
 276{
 277        crypto_unregister_template(&rsa_pkcs1pad_tmpl);
 278        crypto_unregister_akcipher(&rsa);
 279}
 280
 281subsys_initcall(rsa_init);
 282module_exit(rsa_exit);
 283MODULE_ALIAS_CRYPTO("rsa");
 284MODULE_LICENSE("GPL");
 285MODULE_DESCRIPTION("RSA generic algorithm");
 286
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.