diff options
-rw-r--r-- | crypto/Kconfig | 8 | ||||
-rw-r--r-- | crypto/Makefile | 8 | ||||
-rw-r--r-- | crypto/rsa.c | 315 | ||||
-rw-r--r-- | crypto/rsa_helper.c | 121 | ||||
-rw-r--r-- | crypto/rsakey.asn1 | 5 | ||||
-rw-r--r-- | include/crypto/internal/rsa.h | 27 |
6 files changed, 484 insertions, 0 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index eb0aca45d430..d6b2a8b68143 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -100,6 +100,14 @@ config CRYPTO_AKCIPHER | |||
100 | select CRYPTO_AKCIPHER2 | 100 | select CRYPTO_AKCIPHER2 |
101 | select CRYPTO_ALGAPI | 101 | select CRYPTO_ALGAPI |
102 | 102 | ||
103 | config CRYPTO_RSA | ||
104 | tristate "RSA algorithm" | ||
105 | select AKCIPHER | ||
106 | select MPILIB | ||
107 | select ASN1 | ||
108 | help | ||
109 | Generic implementation of the RSA public key algorithm. | ||
110 | |||
103 | config CRYPTO_MANAGER | 111 | config CRYPTO_MANAGER |
104 | tristate "Cryptographic algorithm manager" | 112 | tristate "Cryptographic algorithm manager" |
105 | select CRYPTO_MANAGER2 | 113 | select CRYPTO_MANAGER2 |
diff --git a/crypto/Makefile b/crypto/Makefile index 1ed382df7db9..0077476f5024 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o | |||
30 | obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o | 30 | obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o |
31 | obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o | 31 | obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o |
32 | 32 | ||
33 | $(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h | ||
34 | clean-files += rsakey-asn1.c rsakey-asn1.h | ||
35 | |||
36 | rsa_generic-y := rsakey-asn1.o | ||
37 | rsa_generic-y += rsa.o | ||
38 | rsa_generic-y += rsa_helper.o | ||
39 | obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o | ||
40 | |||
33 | cryptomgr-y := algboss.o testmgr.o | 41 | cryptomgr-y := algboss.o testmgr.o |
34 | 42 | ||
35 | obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o | 43 | obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o |
diff --git a/crypto/rsa.c b/crypto/rsa.c new file mode 100644 index 000000000000..752af0656f2e --- /dev/null +++ b/crypto/rsa.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* RSA asymmetric public-key algorithm [RFC3447] | ||
2 | * | ||
3 | * Copyright (c) 2015, Intel Corporation | ||
4 | * Authors: Tadeusz Struk <tadeusz.struk@intel.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <crypto/internal/rsa.h> | ||
14 | #include <crypto/internal/akcipher.h> | ||
15 | #include <crypto/akcipher.h> | ||
16 | |||
17 | /* | ||
18 | * RSAEP function [RFC3447 sec 5.1.1] | ||
19 | * c = m^e mod n; | ||
20 | */ | ||
21 | static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m) | ||
22 | { | ||
23 | /* (1) Validate 0 <= m < n */ | ||
24 | if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) | ||
25 | return -EINVAL; | ||
26 | |||
27 | /* (2) c = m^e mod n */ | ||
28 | return mpi_powm(c, m, key->e, key->n); | ||
29 | } | ||
30 | |||
31 | /* | ||
32 | * RSADP function [RFC3447 sec 5.1.2] | ||
33 | * m = c^d mod n; | ||
34 | */ | ||
35 | static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c) | ||
36 | { | ||
37 | /* (1) Validate 0 <= c < n */ | ||
38 | if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0) | ||
39 | return -EINVAL; | ||
40 | |||
41 | /* (2) m = c^d mod n */ | ||
42 | return mpi_powm(m, c, key->d, key->n); | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * RSASP1 function [RFC3447 sec 5.2.1] | ||
47 | * s = m^d mod n | ||
48 | */ | ||
49 | static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m) | ||
50 | { | ||
51 | /* (1) Validate 0 <= m < n */ | ||
52 | if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) | ||
53 | return -EINVAL; | ||
54 | |||
55 | /* (2) s = m^d mod n */ | ||
56 | return mpi_powm(s, m, key->d, key->n); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * RSAVP1 function [RFC3447 sec 5.2.2] | ||
61 | * m = s^e mod n; | ||
62 | */ | ||
63 | static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s) | ||
64 | { | ||
65 | /* (1) Validate 0 <= s < n */ | ||
66 | if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0) | ||
67 | return -EINVAL; | ||
68 | |||
69 | /* (2) m = s^e mod n */ | ||
70 | return mpi_powm(m, s, key->e, key->n); | ||
71 | } | ||
72 | |||
73 | static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm) | ||
74 | { | ||
75 | return akcipher_tfm_ctx(tfm); | ||
76 | } | ||
77 | |||
78 | static int rsa_enc(struct akcipher_request *req) | ||
79 | { | ||
80 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | ||
81 | const struct rsa_key *pkey = rsa_get_key(tfm); | ||
82 | MPI m, c = mpi_alloc(0); | ||
83 | int ret = 0; | ||
84 | int sign; | ||
85 | |||
86 | if (!c) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | if (unlikely(!pkey->n || !pkey->e)) { | ||
90 | ret = -EINVAL; | ||
91 | goto err_free_c; | ||
92 | } | ||
93 | |||
94 | if (req->dst_len < mpi_get_size(pkey->n)) { | ||
95 | req->dst_len = mpi_get_size(pkey->n); | ||
96 | ret = -EOVERFLOW; | ||
97 | goto err_free_c; | ||
98 | } | ||
99 | |||
100 | m = mpi_read_raw_data(req->src, req->src_len); | ||
101 | if (!m) { | ||
102 | ret = -ENOMEM; | ||
103 | goto err_free_c; | ||
104 | } | ||
105 | |||
106 | ret = _rsa_enc(pkey, c, m); | ||
107 | if (ret) | ||
108 | goto err_free_m; | ||
109 | |||
110 | ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len, &sign); | ||
111 | if (ret) | ||
112 | goto err_free_m; | ||
113 | |||
114 | if (sign < 0) { | ||
115 | ret = -EBADMSG; | ||
116 | goto err_free_m; | ||
117 | } | ||
118 | |||
119 | err_free_m: | ||
120 | mpi_free(m); | ||
121 | err_free_c: | ||
122 | mpi_free(c); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static int rsa_dec(struct akcipher_request *req) | ||
127 | { | ||
128 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | ||
129 | const struct rsa_key *pkey = rsa_get_key(tfm); | ||
130 | MPI c, m = mpi_alloc(0); | ||
131 | int ret = 0; | ||
132 | int sign; | ||
133 | |||
134 | if (!m) | ||
135 | return -ENOMEM; | ||
136 | |||
137 | if (unlikely(!pkey->n || !pkey->d)) { | ||
138 | ret = -EINVAL; | ||
139 | goto err_free_m; | ||
140 | } | ||
141 | |||
142 | if (req->dst_len < mpi_get_size(pkey->n)) { | ||
143 | req->dst_len = mpi_get_size(pkey->n); | ||
144 | ret = -EOVERFLOW; | ||
145 | goto err_free_m; | ||
146 | } | ||
147 | |||
148 | c = mpi_read_raw_data(req->src, req->src_len); | ||
149 | if (!c) { | ||
150 | ret = -ENOMEM; | ||
151 | goto err_free_m; | ||
152 | } | ||
153 | |||
154 | ret = _rsa_dec(pkey, m, c); | ||
155 | if (ret) | ||
156 | goto err_free_c; | ||
157 | |||
158 | ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); | ||
159 | if (ret) | ||
160 | goto err_free_c; | ||
161 | |||
162 | if (sign < 0) { | ||
163 | ret = -EBADMSG; | ||
164 | goto err_free_c; | ||
165 | } | ||
166 | |||
167 | err_free_c: | ||
168 | mpi_free(c); | ||
169 | err_free_m: | ||
170 | mpi_free(m); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static int rsa_sign(struct akcipher_request *req) | ||
175 | { | ||
176 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | ||
177 | const struct rsa_key *pkey = rsa_get_key(tfm); | ||
178 | MPI m, s = mpi_alloc(0); | ||
179 | int ret = 0; | ||
180 | int sign; | ||
181 | |||
182 | if (!s) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | if (unlikely(!pkey->n || !pkey->d)) { | ||
186 | ret = -EINVAL; | ||
187 | goto err_free_s; | ||
188 | } | ||
189 | |||
190 | if (req->dst_len < mpi_get_size(pkey->n)) { | ||
191 | req->dst_len = mpi_get_size(pkey->n); | ||
192 | ret = -EOVERFLOW; | ||
193 | goto err_free_s; | ||
194 | } | ||
195 | |||
196 | m = mpi_read_raw_data(req->src, req->src_len); | ||
197 | if (!m) { | ||
198 | ret = -ENOMEM; | ||
199 | goto err_free_s; | ||
200 | } | ||
201 | |||
202 | ret = _rsa_sign(pkey, s, m); | ||
203 | if (ret) | ||
204 | goto err_free_m; | ||
205 | |||
206 | ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len, &sign); | ||
207 | if (ret) | ||
208 | goto err_free_m; | ||
209 | |||
210 | if (sign < 0) { | ||
211 | ret = -EBADMSG; | ||
212 | goto err_free_m; | ||
213 | } | ||
214 | |||
215 | err_free_m: | ||
216 | mpi_free(m); | ||
217 | err_free_s: | ||
218 | mpi_free(s); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int rsa_verify(struct akcipher_request *req) | ||
223 | { | ||
224 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); | ||
225 | const struct rsa_key *pkey = rsa_get_key(tfm); | ||
226 | MPI s, m = mpi_alloc(0); | ||
227 | int ret = 0; | ||
228 | int sign; | ||
229 | |||
230 | if (!m) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | if (unlikely(!pkey->n || !pkey->e)) { | ||
234 | ret = -EINVAL; | ||
235 | goto err_free_m; | ||
236 | } | ||
237 | |||
238 | if (req->dst_len < mpi_get_size(pkey->n)) { | ||
239 | req->dst_len = mpi_get_size(pkey->n); | ||
240 | ret = -EOVERFLOW; | ||
241 | goto err_free_m; | ||
242 | } | ||
243 | |||
244 | s = mpi_read_raw_data(req->src, req->src_len); | ||
245 | if (!s) { | ||
246 | ret = -ENOMEM; | ||
247 | goto err_free_m; | ||
248 | } | ||
249 | |||
250 | ret = _rsa_verify(pkey, m, s); | ||
251 | if (ret) | ||
252 | goto err_free_s; | ||
253 | |||
254 | ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); | ||
255 | if (ret) | ||
256 | goto err_free_s; | ||
257 | |||
258 | if (sign < 0) { | ||
259 | ret = -EBADMSG; | ||
260 | goto err_free_s; | ||
261 | } | ||
262 | |||
263 | err_free_s: | ||
264 | mpi_free(s); | ||
265 | err_free_m: | ||
266 | mpi_free(m); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static int rsa_setkey(struct crypto_akcipher *tfm, const void *key, | ||
271 | unsigned int keylen) | ||
272 | { | ||
273 | struct rsa_key *pkey = akcipher_tfm_ctx(tfm); | ||
274 | |||
275 | return rsa_parse_key(pkey, key, keylen); | ||
276 | } | ||
277 | |||
278 | static void rsa_exit_tfm(struct crypto_akcipher *tfm) | ||
279 | { | ||
280 | struct rsa_key *pkey = akcipher_tfm_ctx(tfm); | ||
281 | |||
282 | rsa_free_key(pkey); | ||
283 | } | ||
284 | |||
285 | static struct akcipher_alg rsa = { | ||
286 | .encrypt = rsa_enc, | ||
287 | .decrypt = rsa_dec, | ||
288 | .sign = rsa_sign, | ||
289 | .verify = rsa_verify, | ||
290 | .setkey = rsa_setkey, | ||
291 | .exit = rsa_exit_tfm, | ||
292 | .base = { | ||
293 | .cra_name = "rsa", | ||
294 | .cra_driver_name = "rsa-generic", | ||
295 | .cra_priority = 100, | ||
296 | .cra_module = THIS_MODULE, | ||
297 | .cra_ctxsize = sizeof(struct rsa_key), | ||
298 | }, | ||
299 | }; | ||
300 | |||
301 | static int rsa_init(void) | ||
302 | { | ||
303 | return crypto_register_akcipher(&rsa); | ||
304 | } | ||
305 | |||
306 | static void rsa_exit(void) | ||
307 | { | ||
308 | crypto_unregister_akcipher(&rsa); | ||
309 | } | ||
310 | |||
311 | module_init(rsa_init); | ||
312 | module_exit(rsa_exit); | ||
313 | MODULE_ALIAS_CRYPTO("rsa"); | ||
314 | MODULE_LICENSE("GPL"); | ||
315 | MODULE_DESCRIPTION("RSA generic algorithm"); | ||
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c new file mode 100644 index 000000000000..3e8e0a9e5a8e --- /dev/null +++ b/crypto/rsa_helper.c | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * RSA key extract helper | ||
3 | * | ||
4 | * Copyright (c) 2015, Intel Corporation | ||
5 | * Authors: Tadeusz Struk <tadeusz.struk@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/fips.h> | ||
17 | #include <crypto/internal/rsa.h> | ||
18 | #include "rsakey-asn1.h" | ||
19 | |||
20 | int rsa_get_n(void *context, size_t hdrlen, unsigned char tag, | ||
21 | const void *value, size_t vlen) | ||
22 | { | ||
23 | struct rsa_key *key = context; | ||
24 | |||
25 | key->n = mpi_read_raw_data(value, vlen); | ||
26 | |||
27 | if (!key->n) | ||
28 | return -ENOMEM; | ||
29 | |||
30 | /* In FIPS mode only allow key size 2K & 3K */ | ||
31 | if (fips_enabled && (mpi_get_size(key->n) != 256 || | ||
32 | mpi_get_size(key->n) != 384)) { | ||
33 | pr_err("RSA: key size not allowed in FIPS mode\n"); | ||
34 | mpi_free(key->n); | ||
35 | key->n = NULL; | ||
36 | return -EINVAL; | ||
37 | } | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | int rsa_get_e(void *context, size_t hdrlen, unsigned char tag, | ||
42 | const void *value, size_t vlen) | ||
43 | { | ||
44 | struct rsa_key *key = context; | ||
45 | |||
46 | key->e = mpi_read_raw_data(value, vlen); | ||
47 | |||
48 | if (!key->e) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | int rsa_get_d(void *context, size_t hdrlen, unsigned char tag, | ||
55 | const void *value, size_t vlen) | ||
56 | { | ||
57 | struct rsa_key *key = context; | ||
58 | |||
59 | key->d = mpi_read_raw_data(value, vlen); | ||
60 | |||
61 | if (!key->d) | ||
62 | return -ENOMEM; | ||
63 | |||
64 | /* In FIPS mode only allow key size 2K & 3K */ | ||
65 | if (fips_enabled && (mpi_get_size(key->d) != 256 || | ||
66 | mpi_get_size(key->d) != 384)) { | ||
67 | pr_err("RSA: key size not allowed in FIPS mode\n"); | ||
68 | mpi_free(key->d); | ||
69 | key->d = NULL; | ||
70 | return -EINVAL; | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static void free_mpis(struct rsa_key *key) | ||
76 | { | ||
77 | mpi_free(key->n); | ||
78 | mpi_free(key->e); | ||
79 | mpi_free(key->d); | ||
80 | key->n = NULL; | ||
81 | key->e = NULL; | ||
82 | key->d = NULL; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * rsa_free_key() - frees rsa key allocated by rsa_parse_key() | ||
87 | * | ||
88 | * @rsa_key: struct rsa_key key representation | ||
89 | */ | ||
90 | void rsa_free_key(struct rsa_key *key) | ||
91 | { | ||
92 | free_mpis(key); | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(rsa_free_key); | ||
95 | |||
96 | /** | ||
97 | * rsa_parse_key() - extracts an rsa key from BER encoded buffer | ||
98 | * and stores it in the provided struct rsa_key | ||
99 | * | ||
100 | * @rsa_key: struct rsa_key key representation | ||
101 | * @key: key in BER format | ||
102 | * @key_len: length of key | ||
103 | * | ||
104 | * Return: 0 on success or error code in case of error | ||
105 | */ | ||
106 | int rsa_parse_key(struct rsa_key *rsa_key, const void *key, | ||
107 | unsigned int key_len) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | free_mpis(rsa_key); | ||
112 | ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len); | ||
113 | if (ret < 0) | ||
114 | goto error; | ||
115 | |||
116 | return 0; | ||
117 | error: | ||
118 | free_mpis(rsa_key); | ||
119 | return ret; | ||
120 | } | ||
121 | EXPORT_SYMBOL_GPL(rsa_parse_key); | ||
diff --git a/crypto/rsakey.asn1 b/crypto/rsakey.asn1 new file mode 100644 index 000000000000..3c7b5df7b428 --- /dev/null +++ b/crypto/rsakey.asn1 | |||
@@ -0,0 +1,5 @@ | |||
1 | RsaKey ::= SEQUENCE { | ||
2 | n INTEGER ({ rsa_get_n }), | ||
3 | e INTEGER ({ rsa_get_e }), | ||
4 | d INTEGER ({ rsa_get_d }) | ||
5 | } | ||
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h new file mode 100644 index 000000000000..a8c86365439f --- /dev/null +++ b/include/crypto/internal/rsa.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * RSA internal helpers | ||
3 | * | ||
4 | * Copyright (c) 2015, Intel Corporation | ||
5 | * Authors: Tadeusz Struk <tadeusz.struk@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the Free | ||
9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
10 | * any later version. | ||
11 | * | ||
12 | */ | ||
13 | #ifndef _RSA_HELPER_ | ||
14 | #define _RSA_HELPER_ | ||
15 | #include <linux/mpi.h> | ||
16 | |||
17 | struct rsa_key { | ||
18 | MPI n; | ||
19 | MPI e; | ||
20 | MPI d; | ||
21 | }; | ||
22 | |||
23 | int rsa_parse_key(struct rsa_key *rsa_key, const void *key, | ||
24 | unsigned int key_len); | ||
25 | |||
26 | void rsa_free_key(struct rsa_key *rsa_key); | ||
27 | #endif | ||