]>
Commit | Line | Data |
---|---|---|
29be6023 RL |
1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <openssl/core_numbers.h> | |
11 | #include <openssl/core_names.h> | |
12 | #include <openssl/bn.h> | |
8baa49ae | 13 | #include <openssl/err.h> |
29be6023 | 14 | #include <openssl/rsa.h> |
8baa49ae | 15 | #include <openssl/evp.h> |
29be6023 RL |
16 | #include <openssl/params.h> |
17 | #include <openssl/types.h> | |
1640d48c | 18 | #include "internal/param_build.h" |
29be6023 | 19 | #include "prov/implementations.h" |
1640d48c | 20 | #include "prov/providercommon.h" |
afb638f1 | 21 | #include "prov/provider_ctx.h" |
29be6023 RL |
22 | #include "crypto/rsa.h" |
23 | ||
8dd5c603 RL |
24 | static OSSL_OP_keymgmt_new_fn rsa_newdata; |
25 | static OSSL_OP_keymgmt_free_fn rsa_freedata; | |
273a67e3 RL |
26 | static OSSL_OP_keymgmt_get_params_fn rsa_get_params; |
27 | static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params; | |
8dd5c603 | 28 | static OSSL_OP_keymgmt_has_fn rsa_has; |
273a67e3 | 29 | static OSSL_OP_keymgmt_validate_fn rsa_validate; |
8dd5c603 RL |
30 | static OSSL_OP_keymgmt_import_fn rsa_import; |
31 | static OSSL_OP_keymgmt_import_types_fn rsa_import_types; | |
32 | static OSSL_OP_keymgmt_export_fn rsa_export; | |
33 | static OSSL_OP_keymgmt_export_types_fn rsa_export_types; | |
29be6023 | 34 | |
8baa49ae | 35 | #define RSA_DEFAULT_MD "SHA256" |
8dd5c603 RL |
36 | #define RSA_POSSIBLE_SELECTIONS \ |
37 | (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) | |
8baa49ae | 38 | |
29be6023 RL |
39 | DEFINE_STACK_OF(BIGNUM) |
40 | DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) | |
41 | ||
42 | static int collect_numbers(STACK_OF(BIGNUM) *numbers, | |
43 | const OSSL_PARAM params[], const char *key) | |
44 | { | |
45 | const OSSL_PARAM *p = NULL; | |
46 | ||
47 | if (numbers == NULL) | |
48 | return 0; | |
49 | ||
50 | for (p = params; (p = OSSL_PARAM_locate_const(p, key)) != NULL; p++) { | |
51 | BIGNUM *tmp = NULL; | |
52 | ||
53 | if (!OSSL_PARAM_get_BN(p, &tmp)) | |
54 | return 0; | |
55 | sk_BIGNUM_push(numbers, tmp); | |
56 | } | |
57 | ||
58 | return 1; | |
59 | } | |
60 | ||
61 | static int params_to_key(RSA *rsa, const OSSL_PARAM params[]) | |
62 | { | |
63 | const OSSL_PARAM *param_n, *param_e, *param_d; | |
64 | BIGNUM *n = NULL, *e = NULL, *d = NULL; | |
65 | STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; | |
66 | int is_private = 0; | |
67 | ||
68 | if (rsa == NULL) | |
69 | return 0; | |
70 | ||
71 | param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); | |
72 | param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); | |
73 | param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); | |
74 | ||
75 | if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) | |
76 | || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) | |
77 | || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d))) | |
78 | goto err; | |
79 | ||
80 | is_private = (d != NULL); | |
81 | ||
82 | if (!RSA_set0_key(rsa, n, e, d)) | |
83 | goto err; | |
84 | n = e = d = NULL; | |
85 | ||
86 | if (is_private) { | |
87 | if (!collect_numbers(factors = sk_BIGNUM_new_null(), params, | |
88 | OSSL_PKEY_PARAM_RSA_FACTOR) | |
89 | || !collect_numbers(exps = sk_BIGNUM_new_null(), params, | |
90 | OSSL_PKEY_PARAM_RSA_EXPONENT) | |
91 | || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params, | |
92 | OSSL_PKEY_PARAM_RSA_COEFFICIENT)) | |
93 | goto err; | |
94 | ||
95 | /* It's ok if this private key just has n, e and d */ | |
96 | if (sk_BIGNUM_num(factors) != 0 | |
97 | && !rsa_set0_all_params(rsa, factors, exps, coeffs)) | |
98 | goto err; | |
99 | } | |
100 | ||
101 | sk_BIGNUM_free(factors); | |
102 | sk_BIGNUM_free(exps); | |
103 | sk_BIGNUM_free(coeffs); | |
104 | return 1; | |
105 | ||
106 | err: | |
107 | BN_free(n); | |
108 | BN_free(e); | |
109 | BN_free(d); | |
110 | sk_BIGNUM_pop_free(factors, BN_free); | |
111 | sk_BIGNUM_pop_free(exps, BN_free); | |
112 | sk_BIGNUM_pop_free(coeffs, BN_free); | |
113 | return 0; | |
114 | } | |
115 | ||
1640d48c | 116 | static int export_numbers(OSSL_PARAM_BLD *tmpl, const char *key, |
29be6023 RL |
117 | STACK_OF(BIGNUM_const) *numbers) |
118 | { | |
29be6023 RL |
119 | int i, nnum; |
120 | ||
121 | if (numbers == NULL) | |
122 | return 0; | |
123 | ||
124 | nnum = sk_BIGNUM_const_num(numbers); | |
125 | ||
1640d48c RL |
126 | for (i = 0; i < nnum; i++) { |
127 | if (!ossl_param_bld_push_BN(tmpl, key, | |
128 | sk_BIGNUM_const_value(numbers, i))) | |
29be6023 RL |
129 | return 0; |
130 | } | |
131 | ||
1640d48c | 132 | return 1; |
29be6023 RL |
133 | } |
134 | ||
1640d48c | 135 | static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl) |
29be6023 RL |
136 | { |
137 | int ret = 0; | |
29be6023 RL |
138 | const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; |
139 | STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); | |
140 | STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); | |
141 | STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); | |
142 | ||
143 | if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL) | |
144 | goto err; | |
145 | ||
146 | RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); | |
147 | rsa_get0_all_params(rsa, factors, exps, coeffs); | |
148 | ||
1640d48c RL |
149 | if (rsa_n != NULL |
150 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, rsa_n)) | |
29be6023 | 151 | goto err; |
1640d48c RL |
152 | if (rsa_e != NULL |
153 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, rsa_e)) | |
29be6023 | 154 | goto err; |
1640d48c RL |
155 | if (rsa_d != NULL |
156 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, rsa_d)) | |
29be6023 RL |
157 | goto err; |
158 | ||
1640d48c RL |
159 | if (!export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, factors) |
160 | || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, exps) | |
161 | || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs)) | |
29be6023 RL |
162 | goto err; |
163 | ||
164 | ret = 1; | |
165 | err: | |
166 | sk_BIGNUM_const_free(factors); | |
167 | sk_BIGNUM_const_free(exps); | |
168 | sk_BIGNUM_const_free(coeffs); | |
169 | return ret; | |
170 | } | |
171 | ||
8dd5c603 | 172 | static void *rsa_newdata(void *provctx) |
29be6023 | 173 | { |
afb638f1 MC |
174 | OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); |
175 | ||
176 | return rsa_new_with_ctx(libctx); | |
8dd5c603 | 177 | } |
29be6023 | 178 | |
8dd5c603 RL |
179 | static void rsa_freedata(void *keydata) |
180 | { | |
181 | RSA_free(keydata); | |
29be6023 RL |
182 | } |
183 | ||
8dd5c603 | 184 | static int rsa_has(void *keydata, int selection) |
29be6023 | 185 | { |
8dd5c603 RL |
186 | RSA *rsa = keydata; |
187 | int ok = 0; | |
188 | ||
189 | if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) | |
190 | ok = 1; | |
191 | ||
192 | ok = ok && (RSA_get0_e(rsa) != NULL); | |
193 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) | |
194 | ok = ok && (RSA_get0_n(rsa) != NULL); | |
195 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) | |
196 | ok = ok && (RSA_get0_d(rsa) != NULL); | |
197 | return ok; | |
198 | } | |
199 | ||
200 | static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) | |
201 | { | |
202 | RSA *rsa = keydata; | |
203 | int ok = 1; | |
204 | ||
205 | if (rsa == NULL) | |
206 | return 0; | |
207 | ||
208 | /* TODO(3.0) PSS and OAEP should bring on parameters */ | |
209 | ||
210 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
211 | ok = ok && params_to_key(rsa, params); | |
212 | ||
213 | return ok; | |
214 | } | |
215 | ||
216 | static int rsa_export(void *keydata, int selection, | |
217 | OSSL_CALLBACK *param_callback, void *cbarg) | |
218 | { | |
219 | RSA *rsa = keydata; | |
1640d48c RL |
220 | OSSL_PARAM_BLD tmpl; |
221 | OSSL_PARAM *params = NULL; | |
8dd5c603 RL |
222 | int ok = 1; |
223 | ||
224 | if (rsa == NULL) | |
225 | return 0; | |
226 | ||
227 | /* TODO(3.0) PSS and OAEP should bring on parameters */ | |
1640d48c RL |
228 | |
229 | ossl_param_bld_init(&tmpl); | |
8dd5c603 RL |
230 | |
231 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
232 | ok = ok && key_to_params(rsa, &tmpl); | |
233 | ||
234 | if (!ok | |
1640d48c RL |
235 | || (params = ossl_param_bld_to_param(&tmpl)) == NULL) |
236 | return 0; | |
8dd5c603 RL |
237 | |
238 | ok = param_callback(params, cbarg); | |
1640d48c | 239 | ossl_param_bld_free(params); |
8dd5c603 | 240 | return ok; |
29be6023 RL |
241 | } |
242 | ||
243 | /* | |
244 | * This provider can export everything in an RSA key, so we use the exact | |
245 | * same type description for export as for import. Other providers might | |
246 | * choose to import full keys, but only export the public parts, and will | |
247 | * therefore have the importkey_types and importkey_types functions return | |
248 | * different arrays. | |
249 | */ | |
250 | static const OSSL_PARAM rsa_key_types[] = { | |
251 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), | |
252 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), | |
253 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), | |
254 | /* We tolerate up to 10 factors... */ | |
255 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
256 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
257 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
258 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
259 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
260 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
261 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
262 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
263 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
264 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), | |
265 | /* ..., up to 10 CRT exponents... */ | |
266 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
267 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
268 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
269 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
270 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
271 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
272 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
273 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
274 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
275 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), | |
276 | /* ..., and up to 9 CRT coefficients */ | |
277 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
278 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
279 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
280 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
281 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
282 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
283 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
284 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
285 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), | |
286 | }; | |
287 | /* | |
288 | * We lied about the amount of factors, exponents and coefficients, the | |
289 | * export and import functions can really deal with an infinite amount | |
290 | * of these numbers. However, RSA keys with too many primes are futile, | |
291 | * so we at least pretend to have some limits. | |
292 | */ | |
293 | ||
273a67e3 | 294 | static const OSSL_PARAM *rsa_imexport_types(int selection) |
29be6023 | 295 | { |
273a67e3 | 296 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) |
8dd5c603 RL |
297 | return rsa_key_types; |
298 | return NULL; | |
29be6023 RL |
299 | } |
300 | ||
8dd5c603 | 301 | static const OSSL_PARAM *rsa_import_types(int selection) |
29be6023 | 302 | { |
273a67e3 RL |
303 | return rsa_imexport_types(selection); |
304 | } | |
305 | ||
306 | ||
307 | static const OSSL_PARAM *rsa_export_types(int selection) | |
308 | { | |
309 | return rsa_imexport_types(selection); | |
29be6023 RL |
310 | } |
311 | ||
8dd5c603 | 312 | static int rsa_get_params(void *key, OSSL_PARAM params[]) |
9e5aaf78 RL |
313 | { |
314 | RSA *rsa = key; | |
315 | OSSL_PARAM *p; | |
316 | ||
317 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL | |
318 | && !OSSL_PARAM_set_int(p, RSA_bits(rsa))) | |
319 | return 0; | |
320 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL | |
321 | && !OSSL_PARAM_set_int(p, RSA_security_bits(rsa))) | |
322 | return 0; | |
323 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL | |
324 | && !OSSL_PARAM_set_int(p, RSA_size(rsa))) | |
325 | return 0; | |
8baa49ae | 326 | |
afb638f1 | 327 | # if 0 /* TODO(3.0): PSS support pending */ |
8baa49ae RL |
328 | if ((p = OSSL_PARAM_locate(params, |
329 | OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL | |
330 | && RSA_get0_pss_params(rsa) != NULL) { | |
331 | const EVP_MD *md, *mgf1md; | |
332 | int min_saltlen; | |
333 | ||
334 | if (!rsa_pss_get_param(RSA_get0_pss_params(rsa), | |
335 | &md, &mgf1md, &min_saltlen)) { | |
336 | ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); | |
337 | return 0; | |
338 | } | |
339 | if (!OSSL_PARAM_set_utf8_string(p, EVP_MD_name(md))) | |
340 | return 0; | |
341 | } | |
342 | #endif | |
343 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL | |
afb638f1 MC |
344 | /* TODO(3.0): PSS support pending */ |
345 | #if 0 | |
346 | && RSA_get0_pss_params(rsa) == NULL | |
347 | #endif | |
348 | ) { | |
8baa49ae RL |
349 | if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD)) |
350 | return 0; | |
afb638f1 | 351 | } |
8baa49ae | 352 | |
9e5aaf78 RL |
353 | return 1; |
354 | } | |
355 | ||
273a67e3 RL |
356 | static const OSSL_PARAM rsa_params[] = { |
357 | OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), | |
358 | OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), | |
359 | OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), | |
360 | OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), | |
361 | OSSL_PARAM_END | |
362 | }; | |
363 | ||
364 | static const OSSL_PARAM *rsa_gettable_params(void) | |
365 | { | |
366 | return rsa_params; | |
367 | } | |
368 | ||
8dd5c603 | 369 | static int rsa_validate(void *keydata, int selection) |
12603de6 | 370 | { |
8dd5c603 RL |
371 | RSA *rsa = keydata; |
372 | int ok = 0; | |
373 | ||
374 | if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) | |
375 | ok = 1; | |
376 | ||
377 | /* If the whole key is selected, we do a pairwise validation */ | |
378 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) | |
379 | == OSSL_KEYMGMT_SELECT_KEYPAIR) { | |
380 | ok = ok && rsa_validate_pairwise(rsa); | |
381 | } else { | |
382 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) | |
383 | ok = ok && rsa_validate_private(rsa); | |
384 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) | |
385 | ok = ok && rsa_validate_public(rsa); | |
386 | } | |
387 | return ok; | |
12603de6 SL |
388 | } |
389 | ||
29be6023 | 390 | const OSSL_DISPATCH rsa_keymgmt_functions[] = { |
8dd5c603 RL |
391 | { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsa_newdata }, |
392 | { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata }, | |
273a67e3 RL |
393 | { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params }, |
394 | { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params }, | |
8dd5c603 | 395 | { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has }, |
273a67e3 | 396 | { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate }, |
8dd5c603 RL |
397 | { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import }, |
398 | { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types }, | |
399 | { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export }, | |
400 | { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types }, | |
29be6023 RL |
401 | { 0, NULL } |
402 | }; |