c9aef88b16294587dcba7eae1647208effda4312
[openssl.git] / providers / implementations / keymgmt / dh_kmgmt.c
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/dh.h>
20 #include <openssl/params.h>
21 #include "prov/implementations.h"
22 #include "prov/providercommon.h"
23 #include "prov/provider_ctx.h"
24 #include "crypto/dh.h"
25 #include "internal/param_build.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_match_fn dh_match;
33 static OSSL_OP_keymgmt_validate_fn dh_validate;
34 static OSSL_OP_keymgmt_import_fn dh_import;
35 static OSSL_OP_keymgmt_import_types_fn dh_import_types;
36 static OSSL_OP_keymgmt_export_fn dh_export;
37 static OSSL_OP_keymgmt_export_types_fn dh_export_types;
38
39 #define DH_POSSIBLE_SELECTIONS                 \
40     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
41
42 static int params_to_domparams(DH *dh, const OSSL_PARAM params[])
43 {
44     const OSSL_PARAM *param_p, *param_g;
45     BIGNUM *p = NULL, *g = NULL;
46
47     if (dh == NULL)
48         return 0;
49
50     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
51     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
52
53     if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
54         || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
55         goto err;
56
57     if (!DH_set0_pqg(dh, p, NULL, g))
58         goto err;
59
60     return 1;
61
62  err:
63     BN_free(p);
64     BN_free(g);
65     return 0;
66 }
67
68 static int domparams_to_params(DH *dh, OSSL_PARAM_BLD *tmpl)
69 {
70     const BIGNUM *dh_p = NULL, *dh_g = NULL;
71
72     if (dh == NULL)
73         return 0;
74
75     DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
76     if (dh_p != NULL
77         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dh_p))
78         return 0;
79     if (dh_g != NULL
80         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dh_g))
81         return 0;
82
83     return 1;
84 }
85
86 static int params_to_key(DH *dh, const OSSL_PARAM params[])
87 {
88     const OSSL_PARAM *param_priv_key, *param_pub_key;
89     BIGNUM *priv_key = NULL, *pub_key = NULL;
90
91     if (dh == NULL)
92         return 0;
93
94     if (!params_to_domparams(dh, params))
95         return 0;
96
97     param_priv_key =
98         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
99     param_pub_key =
100         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
101
102     /*
103      * DH documentation says that a public key must be present if a
104      * private key is present.
105      * We want to have at least a public key either way, so we end up
106      * requiring it unconditionally.
107      */
108     if (param_pub_key == NULL)
109         return 0;
110
111     if ((param_priv_key != NULL
112          && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
113         || !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
114         goto err;
115
116     if (!DH_set0_key(dh, pub_key, priv_key))
117         goto err;
118
119     return 1;
120
121  err:
122     BN_clear_free(priv_key);
123     BN_free(pub_key);
124     return 0;
125 }
126
127 static int key_to_params(DH *dh, OSSL_PARAM_BLD *tmpl)
128 {
129     const BIGNUM *priv_key = NULL, *pub_key = NULL;
130
131     if (dh == NULL)
132         return 0;
133     if (!domparams_to_params(dh, tmpl))
134         return 0;
135
136     DH_get0_key(dh, &pub_key, &priv_key);
137     if (priv_key != NULL
138         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key))
139         return 0;
140     if (pub_key != NULL
141         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
142         return 0;
143
144     return 1;
145 }
146
147 static void *dh_newdata(void *provctx)
148 {
149     return dh_new_with_ctx(PROV_LIBRARY_CONTEXT_OF(provctx));
150 }
151
152 static void dh_freedata(void *keydata)
153 {
154     DH_free(keydata);
155 }
156
157 static int dh_has(void *keydata, int selection)
158 {
159     DH *dh = keydata;
160     int ok = 0;
161
162     if (dh != NULL) {
163         if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
164             ok = 1;
165
166         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
167             ok = ok && (DH_get0_pub_key(dh) != NULL);
168         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
169             ok = ok && (DH_get0_priv_key(dh) != NULL);
170         if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
171             ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
172     }
173     return ok;
174 }
175
176 static int dh_match(const void *keydata1, const void *keydata2, int selection)
177 {
178     const DH *dh1 = keydata1;
179     const DH *dh2 = keydata2;
180     int ok = 1;
181
182     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
183         ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0;
184     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
185         ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0;
186     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
187         FFC_PARAMS *dhparams1 = dh_get0_params((DH *)dh1);
188         FFC_PARAMS *dhparams2 = dh_get0_params((DH *)dh2);
189
190         ok = ok && ffc_params_cmp(dhparams1, dhparams2, 1);
191     }
192     return ok;
193 }
194
195 static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
196 {
197     DH *dh = keydata;
198     int ok = 0;
199
200     if (dh == NULL)
201         return 0;
202
203     if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
204         ok = 1;
205
206     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
207         ok = ok && params_to_domparams(dh, params);
208     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
209         ok = ok && params_to_key(dh, params);
210
211     return ok;
212 }
213
214 static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
215                      void *cbarg)
216 {
217     DH *dh = keydata;
218     OSSL_PARAM_BLD tmpl;
219     OSSL_PARAM *params = NULL;
220     int ok = 1;
221
222     if (dh == NULL)
223         return 0;
224
225     ossl_param_bld_init(&tmpl);
226
227     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
228         ok = ok && domparams_to_params(dh, &tmpl);
229     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
230         ok = ok && key_to_params(dh, &tmpl);
231
232     if (!ok
233         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
234         return 0;
235
236     ok = param_cb(params, cbarg);
237     ossl_param_bld_free(params);
238     return ok;
239 }
240
241 /* IMEXPORT = IMPORT + EXPORT */
242
243 # define DH_IMEXPORTABLE_PARAMETERS                     \
244     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0),      \
245     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0)
246 # define DH_IMEXPORTABLE_PUBLIC_KEY                     \
247     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
248 # define DH_IMEXPORTABLE_PRIVATE_KEY                    \
249     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
250 static const OSSL_PARAM dh_all_types[] = {
251     DH_IMEXPORTABLE_PARAMETERS,
252     DH_IMEXPORTABLE_PUBLIC_KEY,
253     DH_IMEXPORTABLE_PRIVATE_KEY,
254     OSSL_PARAM_END
255 };
256 static const OSSL_PARAM dh_parameter_types[] = {
257     DH_IMEXPORTABLE_PARAMETERS,
258     OSSL_PARAM_END
259 };
260 static const OSSL_PARAM dh_key_types[] = {
261     DH_IMEXPORTABLE_PUBLIC_KEY,
262     DH_IMEXPORTABLE_PRIVATE_KEY,
263     OSSL_PARAM_END
264 };
265 static const OSSL_PARAM *dh_types[] = {
266     NULL,                        /* Index 0 = none of them */
267     dh_parameter_types,          /* Index 1 = parameter types */
268     dh_key_types,                /* Index 2 = key types */
269     dh_all_types                 /* Index 3 = 1 + 2 */
270 };
271
272 static const OSSL_PARAM *dh_imexport_types(int selection)
273 {
274     int type_select = 0;
275
276     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
277         type_select += 1;
278     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
279         type_select += 2;
280     return dh_types[type_select];
281 }
282
283 static const OSSL_PARAM *dh_import_types(int selection)
284 {
285     return dh_imexport_types(selection);
286 }
287
288 static const OSSL_PARAM *dh_export_types(int selection)
289 {
290     return dh_imexport_types(selection);
291 }
292
293 static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])
294 {
295     DH *dh = key;
296     OSSL_PARAM *p;
297
298     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
299         && !OSSL_PARAM_set_int(p, DH_bits(dh)))
300         return 0;
301     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
302         && !OSSL_PARAM_set_int(p, DH_security_bits(dh)))
303         return 0;
304     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
305         && !OSSL_PARAM_set_int(p, DH_size(dh)))
306         return 0;
307     return 1;
308 }
309
310 static const OSSL_PARAM dh_params[] = {
311     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
312     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
313     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
314     OSSL_PARAM_END
315 };
316
317 static const OSSL_PARAM *dh_gettable_params(void)
318 {
319     return dh_params;
320 }
321
322 static int dh_validate_public(DH *dh)
323 {
324     const BIGNUM *pub_key = NULL;
325
326     DH_get0_key(dh, &pub_key, NULL);
327     return DH_check_pub_key_ex(dh, pub_key);
328 }
329
330 static int dh_validate_private(DH *dh)
331 {
332     int status = 0;
333     const BIGNUM *priv_key = NULL;
334
335     DH_get0_key(dh, NULL, &priv_key);
336     return dh_check_priv_key(dh, priv_key, &status);;
337 }
338
339 static int dh_validate(void *keydata, int selection)
340 {
341     DH *dh = keydata;
342     int ok = 0;
343
344     if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
345         ok = 1;
346
347     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
348         ok = ok && DH_check_params_ex(dh);
349
350     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
351         ok = ok && dh_validate_public(dh);
352
353     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
354         ok = ok && dh_validate_private(dh);
355
356     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
357             == OSSL_KEYMGMT_SELECT_KEYPAIR)
358         ok = ok && dh_check_pairwise(dh);
359     return ok;
360 }
361
362 const OSSL_DISPATCH dh_keymgmt_functions[] = {
363     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
364     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
365     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
366     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
367     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
368     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
369     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
370     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
371     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
372     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
373     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
374     { 0, NULL }
375 };