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