]>
Commit | Line | Data |
---|---|---|
b4d0d230 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
cfc2bb32 TS |
2 | /* RSA asymmetric public-key algorithm [RFC3447] |
3 | * | |
4 | * Copyright (c) 2015, Intel Corporation | |
5 | * Authors: Tadeusz Struk <[email protected]> | |
cfc2bb32 TS |
6 | */ |
7 | ||
8 | #include <linux/module.h> | |
5a7de973 | 9 | #include <linux/mpi.h> |
cfc2bb32 TS |
10 | #include <crypto/internal/rsa.h> |
11 | #include <crypto/internal/akcipher.h> | |
12 | #include <crypto/akcipher.h> | |
3d5b1ecd | 13 | #include <crypto/algapi.h> |
cfc2bb32 | 14 | |
5a7de973 TA |
15 | struct rsa_mpi_key { |
16 | MPI n; | |
17 | MPI e; | |
18 | MPI d; | |
19 | }; | |
20 | ||
cfc2bb32 TS |
21 | /* |
22 | * RSAEP function [RFC3447 sec 5.1.1] | |
23 | * c = m^e mod n; | |
24 | */ | |
5a7de973 | 25 | static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m) |
cfc2bb32 TS |
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 | */ | |
5a7de973 | 39 | static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c) |
cfc2bb32 TS |
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 | ||
5a7de973 | 49 | static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm) |
cfc2bb32 TS |
50 | { |
51 | return akcipher_tfm_ctx(tfm); | |
52 | } | |
53 | ||
54 | static int rsa_enc(struct akcipher_request *req) | |
55 | { | |
56 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | |
5a7de973 | 57 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |
cfc2bb32 TS |
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 | ||
22287b0b TS |
70 | ret = -ENOMEM; |
71 | m = mpi_read_raw_from_sgl(req->src, req->src_len); | |
72 | if (!m) | |
cfc2bb32 | 73 | goto err_free_c; |
cfc2bb32 TS |
74 | |
75 | ret = _rsa_enc(pkey, c, m); | |
76 | if (ret) | |
77 | goto err_free_m; | |
78 | ||
9b45b7bb | 79 | ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign); |
cfc2bb32 TS |
80 | if (ret) |
81 | goto err_free_m; | |
82 | ||
22287b0b | 83 | if (sign < 0) |
cfc2bb32 | 84 | ret = -EBADMSG; |
cfc2bb32 TS |
85 | |
86 | err_free_m: | |
87 | mpi_free(m); | |
88 | err_free_c: | |
89 | mpi_free(c); | |
90 | return ret; | |
91 | } | |
92 | ||
93 | static int rsa_dec(struct akcipher_request *req) | |
94 | { | |
95 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | |
5a7de973 | 96 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |
cfc2bb32 TS |
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 | ||
22287b0b TS |
109 | ret = -ENOMEM; |
110 | c = mpi_read_raw_from_sgl(req->src, req->src_len); | |
111 | if (!c) | |
cfc2bb32 | 112 | goto err_free_m; |
cfc2bb32 TS |
113 | |
114 | ret = _rsa_dec(pkey, m, c); | |
115 | if (ret) | |
116 | goto err_free_c; | |
117 | ||
9b45b7bb | 118 | ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign); |
cfc2bb32 TS |
119 | if (ret) |
120 | goto err_free_c; | |
121 | ||
22287b0b | 122 | if (sign < 0) |
cfc2bb32 | 123 | ret = -EBADMSG; |
cfc2bb32 TS |
124 | err_free_c: |
125 | mpi_free(c); | |
126 | err_free_m: | |
127 | mpi_free(m); | |
128 | return ret; | |
129 | } | |
130 | ||
5a7de973 TA |
131 | static 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 | ||
6e8ec66c TS |
141 | static 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 | ||
22287b0b TS |
156 | static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, |
157 | unsigned int keylen) | |
cfc2bb32 | 158 | { |
5a7de973 TA |
159 | struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm); |
160 | struct rsa_key raw_key = {0}; | |
6e8ec66c | 161 | int ret; |
cfc2bb32 | 162 | |
5a7de973 TA |
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); | |
6e8ec66c TS |
167 | if (ret) |
168 | return ret; | |
169 | ||
5a7de973 TA |
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; | |
6e8ec66c | 181 | } |
5a7de973 TA |
182 | |
183 | return 0; | |
184 | ||
185 | err: | |
186 | rsa_free_mpi_key(mpi_key); | |
187 | return -ENOMEM; | |
cfc2bb32 TS |
188 | } |
189 | ||
22287b0b TS |
190 | static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, |
191 | unsigned int keylen) | |
192 | { | |
5a7de973 TA |
193 | struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm); |
194 | struct rsa_key raw_key = {0}; | |
22287b0b TS |
195 | int ret; |
196 | ||
5a7de973 TA |
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); | |
22287b0b TS |
201 | if (ret) |
202 | return ret; | |
203 | ||
5a7de973 TA |
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; | |
22287b0b | 219 | } |
5a7de973 TA |
220 | |
221 | return 0; | |
222 | ||
223 | err: | |
224 | rsa_free_mpi_key(mpi_key); | |
225 | return -ENOMEM; | |
22287b0b TS |
226 | } |
227 | ||
1c23b466 | 228 | static unsigned int rsa_max_size(struct crypto_akcipher *tfm) |
22287b0b | 229 | { |
5a7de973 | 230 | struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm); |
22287b0b | 231 | |
1c23b466 | 232 | return mpi_get_size(pkey->n); |
22287b0b TS |
233 | } |
234 | ||
cfc2bb32 TS |
235 | static void rsa_exit_tfm(struct crypto_akcipher *tfm) |
236 | { | |
5a7de973 | 237 | struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm); |
cfc2bb32 | 238 | |
5a7de973 | 239 | rsa_free_mpi_key(pkey); |
cfc2bb32 TS |
240 | } |
241 | ||
242 | static struct akcipher_alg rsa = { | |
243 | .encrypt = rsa_enc, | |
244 | .decrypt = rsa_dec, | |
22287b0b TS |
245 | .set_priv_key = rsa_set_priv_key, |
246 | .set_pub_key = rsa_set_pub_key, | |
247 | .max_size = rsa_max_size, | |
cfc2bb32 TS |
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, | |
5a7de973 | 254 | .cra_ctxsize = sizeof(struct rsa_mpi_key), |
cfc2bb32 TS |
255 | }, |
256 | }; | |
257 | ||
258 | static int rsa_init(void) | |
259 | { | |
3d5b1ecd AZ |
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; | |
cfc2bb32 TS |
273 | } |
274 | ||
275 | static void rsa_exit(void) | |
276 | { | |
3d5b1ecd | 277 | crypto_unregister_template(&rsa_pkcs1pad_tmpl); |
cfc2bb32 TS |
278 | crypto_unregister_akcipher(&rsa); |
279 | } | |
280 | ||
c4741b23 | 281 | subsys_initcall(rsa_init); |
cfc2bb32 TS |
282 | module_exit(rsa_exit); |
283 | MODULE_ALIAS_CRYPTO("rsa"); | |
284 | MODULE_LICENSE("GPL"); | |
285 | MODULE_DESCRIPTION("RSA generic algorithm"); |