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> |
13 | #include <openssl/rsa.h> |
14 | #include <openssl/params.h> |
15 | #include <openssl/types.h> |
16 | #include "internal/param_build.h" |
17 | #include "prov/implementations.h" |
18 | #include "prov/providercommon.h" |
19 | #include "crypto/rsa.h" |
20 | |
21 | static OSSL_OP_keymgmt_importkey_fn rsa_importkey; |
22 | static OSSL_OP_keymgmt_exportkey_fn rsa_exportkey; |
23 | |
24 | DEFINE_STACK_OF(BIGNUM) |
25 | DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) |
26 | |
27 | static int collect_numbers(STACK_OF(BIGNUM) *numbers, |
28 | const OSSL_PARAM params[], const char *key) |
29 | { |
30 | const OSSL_PARAM *p = NULL; |
31 | |
32 | if (numbers == NULL) |
33 | return 0; |
34 | |
35 | for (p = params; (p = OSSL_PARAM_locate_const(p, key)) != NULL; p++) { |
36 | BIGNUM *tmp = NULL; |
37 | |
38 | if (!OSSL_PARAM_get_BN(p, &tmp)) |
39 | return 0; |
40 | sk_BIGNUM_push(numbers, tmp); |
41 | } |
42 | |
43 | return 1; |
44 | } |
45 | |
46 | static int params_to_key(RSA *rsa, const OSSL_PARAM params[]) |
47 | { |
48 | const OSSL_PARAM *param_n, *param_e, *param_d; |
49 | BIGNUM *n = NULL, *e = NULL, *d = NULL; |
50 | STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; |
51 | int is_private = 0; |
52 | |
53 | if (rsa == NULL) |
54 | return 0; |
55 | |
56 | param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); |
57 | param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); |
58 | param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); |
59 | |
60 | if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) |
61 | || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) |
62 | || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d))) |
63 | goto err; |
64 | |
65 | is_private = (d != NULL); |
66 | |
67 | if (!RSA_set0_key(rsa, n, e, d)) |
68 | goto err; |
69 | n = e = d = NULL; |
70 | |
71 | if (is_private) { |
72 | if (!collect_numbers(factors = sk_BIGNUM_new_null(), params, |
73 | OSSL_PKEY_PARAM_RSA_FACTOR) |
74 | || !collect_numbers(exps = sk_BIGNUM_new_null(), params, |
75 | OSSL_PKEY_PARAM_RSA_EXPONENT) |
76 | || !collect_numbers(coeffs = sk_BIGNUM_new_null(), params, |
77 | OSSL_PKEY_PARAM_RSA_COEFFICIENT)) |
78 | goto err; |
79 | |
80 | /* It's ok if this private key just has n, e and d */ |
81 | if (sk_BIGNUM_num(factors) != 0 |
82 | && !rsa_set0_all_params(rsa, factors, exps, coeffs)) |
83 | goto err; |
84 | } |
85 | |
86 | sk_BIGNUM_free(factors); |
87 | sk_BIGNUM_free(exps); |
88 | sk_BIGNUM_free(coeffs); |
89 | return 1; |
90 | |
91 | err: |
92 | BN_free(n); |
93 | BN_free(e); |
94 | BN_free(d); |
95 | sk_BIGNUM_pop_free(factors, BN_free); |
96 | sk_BIGNUM_pop_free(exps, BN_free); |
97 | sk_BIGNUM_pop_free(coeffs, BN_free); |
98 | return 0; |
99 | } |
100 | |
101 | static int export_numbers(OSSL_PARAM_BLD *tmpl, const char *key, |
102 | STACK_OF(BIGNUM_const) *numbers) |
103 | { |
104 | int i, nnum; |
105 | |
106 | if (numbers == NULL) |
107 | return 0; |
108 | |
109 | nnum = sk_BIGNUM_const_num(numbers); |
110 | |
111 | for (i = 0; i < nnum; i++) { |
112 | if (!ossl_param_bld_push_BN(tmpl, key, |
113 | sk_BIGNUM_const_value(numbers, i))) |
114 | return 0; |
115 | } |
116 | |
117 | return 1; |
118 | } |
119 | |
120 | static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl) |
121 | { |
122 | int ret = 0; |
123 | const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; |
124 | STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); |
125 | STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); |
126 | STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); |
127 | |
128 | if (rsa == NULL || factors == NULL || exps == NULL || coeffs == NULL) |
129 | goto err; |
130 | |
131 | RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); |
132 | rsa_get0_all_params(rsa, factors, exps, coeffs); |
133 | |
134 | if (rsa_n != NULL |
135 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, rsa_n)) |
136 | goto err; |
137 | if (rsa_e != NULL |
138 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, rsa_e)) |
139 | goto err; |
140 | if (rsa_d != NULL |
141 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, rsa_d)) |
142 | goto err; |
143 | |
144 | if (!export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, factors) |
145 | || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, exps) |
146 | || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs)) |
147 | goto err; |
148 | |
149 | ret = 1; |
150 | err: |
151 | sk_BIGNUM_const_free(factors); |
152 | sk_BIGNUM_const_free(exps); |
153 | sk_BIGNUM_const_free(coeffs); |
154 | return ret; |
155 | } |
156 | |
157 | static void *rsa_importkey(void *provctx, const OSSL_PARAM params[]) |
158 | { |
159 | RSA *rsa; |
160 | |
161 | if ((rsa = RSA_new()) == NULL |
162 | || !params_to_key(rsa, params)) { |
163 | RSA_free(rsa); |
164 | rsa = NULL; |
165 | } |
166 | return rsa; |
167 | } |
168 | |
169 | static int rsa_exportkey(void *key, OSSL_CALLBACK *param_callback, void *cbarg) |
170 | { |
171 | RSA *rsa = key; |
172 | OSSL_PARAM_BLD tmpl; |
173 | OSSL_PARAM *params = NULL; |
174 | int ret; |
175 | |
176 | ossl_param_bld_init(&tmpl); |
177 | if (rsa == NULL |
178 | || !key_to_params(rsa, &tmpl) |
179 | || (params = ossl_param_bld_to_param(&tmpl)) == NULL) |
180 | return 0; |
181 | ret = param_callback(params, cbarg); |
182 | ossl_param_bld_free(params); |
183 | return ret; |
184 | } |
185 | |
186 | /* |
187 | * This provider can export everything in an RSA key, so we use the exact |
188 | * same type description for export as for import. Other providers might |
189 | * choose to import full keys, but only export the public parts, and will |
190 | * therefore have the importkey_types and importkey_types functions return |
191 | * different arrays. |
192 | */ |
193 | static const OSSL_PARAM rsa_key_types[] = { |
194 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_N, NULL, 0), |
195 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0), |
196 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_D, NULL, 0), |
197 | /* We tolerate up to 10 factors... */ |
198 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
199 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
200 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
201 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
202 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
203 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
204 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
205 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
206 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
207 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_FACTOR, NULL, 0), |
208 | /* ..., up to 10 CRT exponents... */ |
209 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
210 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
211 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
212 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
213 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
214 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
215 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
216 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
217 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
218 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_EXPONENT, NULL, 0), |
219 | /* ..., and up to 9 CRT coefficients */ |
220 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
221 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
222 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
223 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
224 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
225 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
226 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
227 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
228 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_COEFFICIENT, NULL, 0), |
229 | }; |
230 | /* |
231 | * We lied about the amount of factors, exponents and coefficients, the |
232 | * export and import functions can really deal with an infinite amount |
233 | * of these numbers. However, RSA keys with too many primes are futile, |
234 | * so we at least pretend to have some limits. |
235 | */ |
236 | |
237 | static const OSSL_PARAM *rsa_exportkey_types(void) |
238 | { |
239 | return rsa_key_types; |
240 | } |
241 | |
242 | static const OSSL_PARAM *rsa_importkey_types(void) |
243 | { |
244 | return rsa_key_types; |
245 | } |
246 | |
247 | const OSSL_DISPATCH rsa_keymgmt_functions[] = { |
248 | { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))rsa_importkey }, |
249 | { OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES, (void (*)(void))rsa_importkey_types }, |
250 | { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))rsa_exportkey }, |
251 | { OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES, (void (*)(void))rsa_exportkey_types }, |
252 | { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))RSA_free }, |
253 | { 0, NULL } |
254 | }; |
255 | |