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