3eeac98497527db2a09cf6e45067d3cd8ea90daa
[openssl.git] / providers / implementations / exchange / dh_exch.c
1 /*
2  * Copyright 2019-2020 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 <string.h>
17 #include <openssl/crypto.h>
18 #include <openssl/core_dispatch.h>
19 #include <openssl/core_names.h>
20 #include <openssl/dh.h>
21 #include <openssl/err.h>
22 #include <openssl/params.h>
23 #include "prov/providercommon.h"
24 #include "prov/implementations.h"
25 #include "prov/provider_ctx.h"
26 #include "prov/securitycheck.h"
27 #include "crypto/dh.h"
28
29 static OSSL_FUNC_keyexch_newctx_fn dh_newctx;
30 static OSSL_FUNC_keyexch_init_fn dh_init;
31 static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer;
32 static OSSL_FUNC_keyexch_derive_fn dh_derive;
33 static OSSL_FUNC_keyexch_freectx_fn dh_freectx;
34 static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx;
35 static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params;
36 static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params;
37 static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params;
38 static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params;
39
40 /*
41  * This type is only really used to handle some legacy related functionality.
42  * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
43  * here and then create and run a KDF after the key is derived.
44  * Note that X942 has 2 variants of key derivation:
45  *   (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
46  *   the counter embedded in it.
47  *   (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
48  *       done by creating a "X963KDF".
49  */
50 enum kdf_type {
51     PROV_DH_KDF_NONE = 0,
52     PROV_DH_KDF_X9_42_ASN1
53 };
54
55 /*
56  * What's passed as an actual key is defined by the KEYMGMT interface.
57  * We happen to know that our KEYMGMT simply passes DH structures, so
58  * we use that here too.
59  */
60
61 typedef struct {
62     OSSL_LIB_CTX *libctx;
63     DH *dh;
64     DH *dhpeer;
65     unsigned int pad : 1;
66
67     /* DH KDF */
68     /* KDF (if any) to use for DH */
69     enum kdf_type kdf_type;
70     /* Message digest to use for key derivation */
71     EVP_MD *kdf_md;
72     /* User key material */
73     unsigned char *kdf_ukm;
74     size_t kdf_ukmlen;
75     /* KDF output length */
76     size_t kdf_outlen;
77     char *kdf_cekalg;
78 } PROV_DH_CTX;
79
80 static void *dh_newctx(void *provctx)
81 {
82     PROV_DH_CTX *pdhctx;
83
84     if (!ossl_prov_is_running())
85         return NULL;
86
87     pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX));
88     if (pdhctx == NULL)
89         return NULL;
90     pdhctx->libctx = PROV_LIBCTX_OF(provctx);
91     pdhctx->kdf_type = PROV_DH_KDF_NONE;
92     return pdhctx;
93 }
94
95 static int dh_init(void *vpdhctx, void *vdh)
96 {
97     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
98
99     if (!ossl_prov_is_running()
100             || pdhctx == NULL
101             || vdh == NULL
102             || !DH_up_ref(vdh))
103         return 0;
104     DH_free(pdhctx->dh);
105     pdhctx->dh = vdh;
106     pdhctx->kdf_type = PROV_DH_KDF_NONE;
107     return dh_check_key(vdh);
108 }
109
110 static int dh_set_peer(void *vpdhctx, void *vdh)
111 {
112     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
113
114     if (!ossl_prov_is_running()
115             || pdhctx == NULL
116             || vdh == NULL
117             || !DH_up_ref(vdh))
118         return 0;
119     DH_free(pdhctx->dhpeer);
120     pdhctx->dhpeer = vdh;
121     return 1;
122 }
123
124 static int dh_plain_derive(void *vpdhctx,
125                            unsigned char *secret, size_t *secretlen,
126                            size_t outlen)
127 {
128     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
129     int ret;
130     size_t dhsize;
131     const BIGNUM *pub_key = NULL;
132
133     /* TODO(3.0): Add errors to stack */
134     if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL)
135         return 0;
136
137     dhsize = (size_t)DH_size(pdhctx->dh);
138     if (secret == NULL) {
139         *secretlen = dhsize;
140         return 1;
141     }
142     if (outlen < dhsize)
143         return 0;
144
145     DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
146     if (pdhctx->pad)
147         ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh);
148     else
149         ret = DH_compute_key(secret, pub_key, pdhctx->dh);
150     if (ret <= 0)
151         return 0;
152
153     *secretlen = ret;
154     return 1;
155 }
156
157 static int dh_X9_42_kdf_derive(void *vpdhctx, unsigned char *secret,
158                                size_t *secretlen, size_t outlen)
159 {
160     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
161     unsigned char *stmp = NULL;
162     size_t stmplen;
163     int ret = 0;
164
165     if (secret == NULL) {
166         *secretlen = pdhctx->kdf_outlen;
167         return 1;
168     }
169
170     if (pdhctx->kdf_outlen > outlen)
171         return 0;
172     if (!dh_plain_derive(pdhctx, NULL, &stmplen, 0))
173         return 0;
174     if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
175         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
176         return 0;
177     }
178     if (!dh_plain_derive(pdhctx, stmp, &stmplen, stmplen))
179         goto err;
180
181     /* Do KDF stuff */
182     if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) {
183         if (!dh_KDF_X9_42_asn1(secret, pdhctx->kdf_outlen,
184                                stmp, stmplen,
185                                pdhctx->kdf_cekalg,
186                                pdhctx->kdf_ukm,
187                                pdhctx->kdf_ukmlen,
188                                pdhctx->kdf_md,
189                                pdhctx->libctx, NULL))
190             goto err;
191     }
192     *secretlen = pdhctx->kdf_outlen;
193     ret = 1;
194 err:
195     OPENSSL_secure_clear_free(stmp, stmplen);
196     return ret;
197 }
198
199 static int dh_derive(void *vpdhctx, unsigned char *secret,
200                      size_t *psecretlen, size_t outlen)
201 {
202     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
203
204     if (!ossl_prov_is_running())
205         return 0;
206
207     switch (pdhctx->kdf_type) {
208         case PROV_DH_KDF_NONE:
209             return dh_plain_derive(pdhctx, secret, psecretlen, outlen);
210         case PROV_DH_KDF_X9_42_ASN1:
211             return dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen);
212         default:
213             break;
214     }
215     return 0;
216 }
217
218
219 static void dh_freectx(void *vpdhctx)
220 {
221     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
222
223     OPENSSL_free(pdhctx->kdf_cekalg);
224     DH_free(pdhctx->dh);
225     DH_free(pdhctx->dhpeer);
226     EVP_MD_free(pdhctx->kdf_md);
227     OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen);
228
229     OPENSSL_free(pdhctx);
230 }
231
232 static void *dh_dupctx(void *vpdhctx)
233 {
234     PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
235     PROV_DH_CTX *dstctx;
236
237     if (!ossl_prov_is_running())
238         return NULL;
239
240     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
241     if (dstctx == NULL)
242         return NULL;
243
244     *dstctx = *srcctx;
245     dstctx->dh = NULL;
246     dstctx->dhpeer = NULL;
247     dstctx->kdf_md = NULL;
248     dstctx->kdf_ukm = NULL;
249     dstctx->kdf_cekalg = NULL;
250
251     if (dstctx->dh != NULL && !DH_up_ref(srcctx->dh))
252         goto err;
253     else
254         dstctx->dh = srcctx->dh;
255
256     if (dstctx->dhpeer != NULL && !DH_up_ref(srcctx->dhpeer))
257         goto err;
258     else
259         dstctx->dhpeer = srcctx->dhpeer;
260
261     if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
262         goto err;
263     else
264         dstctx->kdf_md = srcctx->kdf_md;
265
266     /* Duplicate UKM data if present */
267     if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
268         dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
269                                          srcctx->kdf_ukmlen);
270         if (dstctx->kdf_ukm == NULL)
271             goto err;
272     }
273     dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg);
274
275     return dstctx;
276 err:
277     dh_freectx(dstctx);
278     return NULL;
279 }
280
281 static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
282 {
283     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
284     const OSSL_PARAM *p;
285     unsigned int pad;
286     char name[80] = { '\0' }; /* should be big enough */
287     char *str = NULL;
288
289     if (pdhctx == NULL || params == NULL)
290         return 0;
291
292     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
293     if (p != NULL) {
294         str = name;
295         if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
296             return 0;
297
298         if (name[0] == '\0')
299             pdhctx->kdf_type = PROV_DH_KDF_NONE;
300         else if (strcmp(name, OSSL_KDF_NAME_X942KDF) == 0)
301             pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1;
302         else
303             return 0;
304     }
305     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
306     if (p != NULL) {
307         char mdprops[80] = { '\0' }; /* should be big enough */
308
309         str = name;
310         if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
311             return 0;
312
313         str = mdprops;
314         p = OSSL_PARAM_locate_const(params,
315                                     OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
316
317         if (p != NULL) {
318             if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
319                 return 0;
320         }
321
322         EVP_MD_free(pdhctx->kdf_md);
323         pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
324         if (!digest_is_allowed(pdhctx->kdf_md)) {
325             EVP_MD_free(pdhctx->kdf_md);
326             pdhctx->kdf_md = NULL;
327         }
328         if (pdhctx->kdf_md == NULL)
329             return 0;
330     }
331
332     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
333     if (p != NULL) {
334         size_t outlen;
335
336         if (!OSSL_PARAM_get_size_t(p, &outlen))
337             return 0;
338         pdhctx->kdf_outlen = outlen;
339     }
340
341     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
342     if (p != NULL) {
343         void *tmp_ukm = NULL;
344         size_t tmp_ukmlen;
345
346         OPENSSL_free(pdhctx->kdf_ukm);
347         pdhctx->kdf_ukm = NULL;
348         pdhctx->kdf_ukmlen = 0;
349         /* ukm is an optional field so it can be NULL */
350         if (p->data != NULL && p->data_size != 0) {
351             if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
352                 return 0;
353             pdhctx->kdf_ukm = tmp_ukm;
354             pdhctx->kdf_ukmlen = tmp_ukmlen;
355         }
356     }
357
358     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
359     if (p != NULL) {
360         if (!OSSL_PARAM_get_uint(p, &pad))
361             return 0;
362         pdhctx->pad = pad ? 1 : 0;
363     }
364
365     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG);
366     if (p != NULL) {
367         str = name;
368         if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
369             return 0;
370         pdhctx->kdf_cekalg = OPENSSL_strdup(name);
371     }
372     return 1;
373 }
374
375 static const OSSL_PARAM known_settable_ctx_params[] = {
376     OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
377     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
378     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
379     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
380     OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
381     OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
382     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
383     OSSL_PARAM_END
384 };
385
386 static const OSSL_PARAM *dh_settable_ctx_params(ossl_unused void *provctx)
387 {
388     return known_settable_ctx_params;
389 }
390
391 static const OSSL_PARAM known_gettable_ctx_params[] = {
392     OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
393     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
394     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
395     OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
396     OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
397                     NULL, 0),
398     OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN, NULL),
399     OSSL_PARAM_END
400 };
401
402 static const OSSL_PARAM *dh_gettable_ctx_params(ossl_unused void *provctx)
403 {
404     return known_gettable_ctx_params;
405 }
406
407 static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[])
408 {
409     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
410     OSSL_PARAM *p;
411
412     if (pdhctx == NULL || params == NULL)
413         return 0;
414
415     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
416     if (p != NULL) {
417         const char *kdf_type = NULL;
418
419         switch (pdhctx->kdf_type) {
420             case PROV_DH_KDF_NONE:
421                 kdf_type = "";
422                 break;
423             case PROV_DH_KDF_X9_42_ASN1:
424                 kdf_type = OSSL_KDF_NAME_X942KDF;
425                 break;
426             default:
427                 return 0;
428         }
429
430         if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
431             return 0;
432     }
433
434     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
435     if (p != NULL
436             && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL
437                                            ? ""
438                                            : EVP_MD_name(pdhctx->kdf_md))){
439         return 0;
440     }
441
442     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
443     if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen))
444         return 0;
445
446     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
447     if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, 0))
448         return 0;
449
450     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM_LEN);
451     if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_ukmlen))
452         return 0;
453
454     p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG);
455     if (p != NULL
456             && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL
457                                            ? "" :  pdhctx->kdf_cekalg))
458         return 0;
459
460     return 1;
461 }
462
463 const OSSL_DISPATCH ossl_dh_keyexch_functions[] = {
464     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
465     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
466     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
467     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
468     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
469     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
470     { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params },
471     { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
472       (void (*)(void))dh_settable_ctx_params },
473     { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))dh_get_ctx_params },
474     { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
475       (void (*)(void))dh_gettable_ctx_params },
476     { 0, NULL }
477 };