]>
Commit | Line | Data |
---|---|---|
8b84b075 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> | |
8b84b075 | 13 | #include <openssl/params.h> |
1640d48c | 14 | #include "internal/param_build.h" |
8dd5c603 | 15 | #include "crypto/dh.h" |
af3e7e1b | 16 | #include "prov/implementations.h" |
1640d48c | 17 | #include "prov/providercommon.h" |
8083fd3a SL |
18 | #include "prov/provider_ctx.h" |
19 | #include "crypto/dh.h" | |
8b84b075 | 20 | |
8dd5c603 RL |
21 | static OSSL_OP_keymgmt_new_fn dh_newdata; |
22 | static OSSL_OP_keymgmt_free_fn dh_freedata; | |
273a67e3 RL |
23 | static OSSL_OP_keymgmt_get_params_fn dh_get_params; |
24 | static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params; | |
8dd5c603 RL |
25 | static OSSL_OP_keymgmt_has_fn dh_has; |
26 | static OSSL_OP_keymgmt_import_fn dh_import; | |
273a67e3 | 27 | static OSSL_OP_keymgmt_import_types_fn dh_import_types; |
8dd5c603 | 28 | static OSSL_OP_keymgmt_export_fn dh_export; |
273a67e3 | 29 | static OSSL_OP_keymgmt_export_types_fn dh_export_types; |
8dd5c603 RL |
30 | |
31 | #define DH_POSSIBLE_SELECTIONS \ | |
273a67e3 | 32 | (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) |
8b84b075 | 33 | |
14e3e00f | 34 | static int params_to_domparams(DH *dh, const OSSL_PARAM params[]) |
8b84b075 | 35 | { |
14e3e00f RL |
36 | const OSSL_PARAM *param_p, *param_g; |
37 | BIGNUM *p = NULL, *g = NULL; | |
8b84b075 RL |
38 | |
39 | if (dh == NULL) | |
40 | return 0; | |
41 | ||
4889dadc MC |
42 | param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); |
43 | param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); | |
14e3e00f RL |
44 | |
45 | if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) | |
46 | || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))) | |
47 | goto err; | |
48 | ||
49 | if (!DH_set0_pqg(dh, p, NULL, g)) | |
50 | goto err; | |
51 | ||
52 | return 1; | |
53 | ||
54 | err: | |
55 | BN_free(p); | |
56 | BN_free(g); | |
57 | return 0; | |
58 | } | |
59 | ||
1640d48c | 60 | static int domparams_to_params(DH *dh, OSSL_PARAM_BLD *tmpl) |
c8f23016 | 61 | { |
c8f23016 RL |
62 | const BIGNUM *dh_p = NULL, *dh_g = NULL; |
63 | ||
64 | if (dh == NULL) | |
65 | return 0; | |
66 | ||
67 | DH_get0_pqg(dh, &dh_p, NULL, &dh_g); | |
1640d48c RL |
68 | if (dh_p != NULL |
69 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dh_p)) | |
c8f23016 | 70 | return 0; |
1640d48c RL |
71 | if (dh_g != NULL |
72 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dh_g)) | |
c8f23016 RL |
73 | return 0; |
74 | ||
75 | return 1; | |
76 | } | |
77 | ||
14e3e00f RL |
78 | static int params_to_key(DH *dh, const OSSL_PARAM params[]) |
79 | { | |
80 | const OSSL_PARAM *param_priv_key, *param_pub_key; | |
81 | BIGNUM *priv_key = NULL, *pub_key = NULL; | |
82 | ||
83 | if (dh == NULL) | |
84 | return 0; | |
85 | ||
86 | if (!params_to_domparams(dh, params)) | |
87 | return 0; | |
88 | ||
8b84b075 | 89 | param_priv_key = |
90d3cb57 | 90 | OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); |
8b84b075 | 91 | param_pub_key = |
90d3cb57 | 92 | OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); |
8b84b075 RL |
93 | |
94 | /* | |
95 | * DH documentation says that a public key must be present if a | |
96 | * private key is present. | |
97 | * We want to have at least a public key either way, so we end up | |
98 | * requiring it unconditionally. | |
99 | */ | |
100 | if (param_pub_key == NULL) | |
101 | return 0; | |
102 | ||
14e3e00f RL |
103 | if ((param_priv_key != NULL |
104 | && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) | |
8b84b075 RL |
105 | || !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) |
106 | goto err; | |
107 | ||
8b84b075 RL |
108 | if (!DH_set0_key(dh, pub_key, priv_key)) |
109 | goto err; | |
8b84b075 RL |
110 | |
111 | return 1; | |
112 | ||
113 | err: | |
afa2b389 | 114 | BN_clear_free(priv_key); |
8b84b075 RL |
115 | BN_free(pub_key); |
116 | return 0; | |
117 | } | |
118 | ||
1640d48c | 119 | static int key_to_params(DH *dh, OSSL_PARAM_BLD *tmpl) |
c8f23016 | 120 | { |
c8f23016 RL |
121 | const BIGNUM *priv_key = NULL, *pub_key = NULL; |
122 | ||
123 | if (dh == NULL) | |
124 | return 0; | |
1640d48c | 125 | if (!domparams_to_params(dh, tmpl)) |
c8f23016 RL |
126 | return 0; |
127 | ||
128 | DH_get0_key(dh, &pub_key, &priv_key); | |
1640d48c | 129 | if (priv_key != NULL |
90d3cb57 | 130 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key)) |
c8f23016 | 131 | return 0; |
1640d48c | 132 | if (pub_key != NULL |
90d3cb57 | 133 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key)) |
c8f23016 RL |
134 | return 0; |
135 | ||
136 | return 1; | |
137 | } | |
138 | ||
8dd5c603 | 139 | static void *dh_newdata(void *provctx) |
14e3e00f | 140 | { |
8083fd3a | 141 | return dh_new_with_ctx(PROV_LIBRARY_CONTEXT_OF(provctx)); |
14e3e00f RL |
142 | } |
143 | ||
8dd5c603 | 144 | static void dh_freedata(void *keydata) |
c8f23016 | 145 | { |
8dd5c603 RL |
146 | DH_free(keydata); |
147 | } | |
1640d48c | 148 | |
8dd5c603 RL |
149 | static int dh_has(void *keydata, int selection) |
150 | { | |
151 | DH *dh = keydata; | |
152 | int ok = 0; | |
153 | ||
154 | if ((selection & DH_POSSIBLE_SELECTIONS) != 0) | |
155 | ok = 1; | |
156 | ||
157 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) | |
158 | ok = ok && (DH_get0_pub_key(dh) != NULL); | |
159 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) | |
160 | ok = ok && (DH_get0_priv_key(dh) != NULL); | |
161 | if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) | |
162 | ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL); | |
163 | return ok; | |
c8f23016 RL |
164 | } |
165 | ||
8dd5c603 | 166 | static int dh_import(void *keydata, int selection, const OSSL_PARAM params[]) |
8b84b075 | 167 | { |
8dd5c603 RL |
168 | DH *dh = keydata; |
169 | int ok = 0; | |
170 | ||
171 | if (dh == NULL) | |
172 | return 0; | |
173 | ||
174 | if ((selection & DH_POSSIBLE_SELECTIONS) != 0) | |
175 | ok = 1; | |
176 | ||
177 | if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) | |
178 | ok = ok && params_to_domparams(dh, params); | |
179 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
180 | ok = ok && params_to_key(dh, params); | |
181 | ||
182 | return ok; | |
8b84b075 RL |
183 | } |
184 | ||
8dd5c603 RL |
185 | static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, |
186 | void *cbarg) | |
c8f23016 | 187 | { |
8dd5c603 | 188 | DH *dh = keydata; |
1640d48c RL |
189 | OSSL_PARAM_BLD tmpl; |
190 | OSSL_PARAM *params = NULL; | |
8dd5c603 RL |
191 | int ok = 1; |
192 | ||
193 | if (dh == NULL) | |
194 | return 0; | |
1640d48c RL |
195 | |
196 | ossl_param_bld_init(&tmpl); | |
8dd5c603 RL |
197 | |
198 | if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) | |
199 | ok = ok && domparams_to_params(dh, &tmpl); | |
200 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
201 | ok = ok && key_to_params(dh, &tmpl); | |
202 | ||
203 | if (!ok | |
1640d48c RL |
204 | || (params = ossl_param_bld_to_param(&tmpl)) == NULL) |
205 | return 0; | |
8dd5c603 RL |
206 | |
207 | ok = param_cb(params, cbarg); | |
1640d48c | 208 | ossl_param_bld_free(params); |
8dd5c603 | 209 | return ok; |
c8f23016 RL |
210 | } |
211 | ||
273a67e3 RL |
212 | /* IMEXPORT = IMPORT + EXPORT */ |
213 | ||
214 | # define DH_IMEXPORTABLE_PARAMETERS \ | |
215 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \ | |
216 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0) | |
217 | # define DH_IMEXPORTABLE_PUBLIC_KEY \ | |
90d3cb57 | 218 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0) |
273a67e3 | 219 | # define DH_IMEXPORTABLE_PRIVATE_KEY \ |
90d3cb57 | 220 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0) |
273a67e3 RL |
221 | static const OSSL_PARAM dh_all_types[] = { |
222 | DH_IMEXPORTABLE_PARAMETERS, | |
223 | DH_IMEXPORTABLE_PUBLIC_KEY, | |
224 | DH_IMEXPORTABLE_PRIVATE_KEY, | |
225 | OSSL_PARAM_END | |
226 | }; | |
227 | static const OSSL_PARAM dh_parameter_types[] = { | |
228 | DH_IMEXPORTABLE_PARAMETERS, | |
229 | OSSL_PARAM_END | |
230 | }; | |
231 | static const OSSL_PARAM dh_key_types[] = { | |
232 | DH_IMEXPORTABLE_PUBLIC_KEY, | |
233 | DH_IMEXPORTABLE_PRIVATE_KEY, | |
234 | OSSL_PARAM_END | |
235 | }; | |
236 | static const OSSL_PARAM *dh_types[] = { | |
237 | NULL, /* Index 0 = none of them */ | |
238 | dh_parameter_types, /* Index 1 = parameter types */ | |
239 | dh_key_types, /* Index 2 = key types */ | |
240 | dh_all_types /* Index 3 = 1 + 2 */ | |
241 | }; | |
242 | ||
243 | static const OSSL_PARAM *dh_imexport_types(int selection) | |
244 | { | |
245 | int type_select = 0; | |
246 | ||
247 | if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0) | |
248 | type_select += 1; | |
249 | if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) | |
250 | type_select += 2; | |
251 | return dh_types[type_select]; | |
252 | } | |
253 | ||
254 | static const OSSL_PARAM *dh_import_types(int selection) | |
255 | { | |
256 | return dh_imexport_types(selection); | |
257 | } | |
258 | ||
259 | static const OSSL_PARAM *dh_export_types(int selection) | |
260 | { | |
261 | return dh_imexport_types(selection); | |
262 | } | |
263 | ||
8dd5c603 | 264 | static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[]) |
9e5aaf78 RL |
265 | { |
266 | DH *dh = key; | |
267 | OSSL_PARAM *p; | |
268 | ||
269 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL | |
270 | && !OSSL_PARAM_set_int(p, DH_bits(dh))) | |
271 | return 0; | |
272 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL | |
273 | && !OSSL_PARAM_set_int(p, DH_security_bits(dh))) | |
274 | return 0; | |
275 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL | |
276 | && !OSSL_PARAM_set_int(p, DH_size(dh))) | |
277 | return 0; | |
278 | return 1; | |
279 | } | |
280 | ||
273a67e3 RL |
281 | static const OSSL_PARAM dh_params[] = { |
282 | OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), | |
283 | OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), | |
284 | OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), | |
285 | OSSL_PARAM_END | |
286 | }; | |
287 | ||
288 | static const OSSL_PARAM *dh_gettable_params(void) | |
289 | { | |
290 | return dh_params; | |
291 | } | |
292 | ||
8b84b075 | 293 | const OSSL_DISPATCH dh_keymgmt_functions[] = { |
8dd5c603 RL |
294 | { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata }, |
295 | { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata }, | |
273a67e3 RL |
296 | { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params }, |
297 | { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params }, | |
8dd5c603 RL |
298 | { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has }, |
299 | { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import }, | |
273a67e3 | 300 | { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types }, |
8dd5c603 | 301 | { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export }, |
273a67e3 | 302 | { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types }, |
8b84b075 RL |
303 | { 0, NULL } |
304 | }; |