Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/providers/implementations/exchange/dh_exch.c
Line
Count
Source
1
/*
2
 * Copyright 2019-2025 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
/* clang-format off */
10
11
/* clang-format on */
12
13
/*
14
 * DH low level APIs are deprecated for public use, but still ok for
15
 * internal use.
16
 */
17
#include "internal/deprecated.h"
18
19
#include <string.h>
20
#include <openssl/crypto.h>
21
#include <openssl/core_dispatch.h>
22
#include <openssl/core_names.h>
23
#include <openssl/dh.h>
24
#include <openssl/err.h>
25
#include <openssl/proverr.h>
26
#include <openssl/params.h>
27
#include "internal/cryptlib.h"
28
#include "prov/providercommon.h"
29
#include "prov/implementations.h"
30
#include "prov/provider_ctx.h"
31
#include "prov/securitycheck.h"
32
#include "crypto/dh.h"
33
34
static OSSL_FUNC_keyexch_newctx_fn dh_newctx;
35
static OSSL_FUNC_keyexch_init_fn dh_init;
36
static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer;
37
static OSSL_FUNC_keyexch_derive_fn dh_derive;
38
static OSSL_FUNC_keyexch_freectx_fn dh_freectx;
39
static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx;
40
static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params;
41
static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params;
42
static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params;
43
static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params;
44
45
/*
46
 * This type is only really used to handle some legacy related functionality.
47
 * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
48
 * here and then create and run a KDF after the key is derived.
49
 * Note that X942 has 2 variants of key derivation:
50
 *   (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
51
 *   the counter embedded in it.
52
 *   (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
53
 *       done by creating a "X963KDF".
54
 */
55
enum kdf_type {
56
    PROV_DH_KDF_NONE = 0,
57
    PROV_DH_KDF_X9_42_ASN1
58
};
59
60
/*
61
 * What's passed as an actual key is defined by the KEYMGMT interface.
62
 * We happen to know that our KEYMGMT simply passes DH structures, so
63
 * we use that here too.
64
 */
65
66
typedef struct {
67
    OSSL_LIB_CTX *libctx;
68
    DH *dh;
69
    DH *dhpeer;
70
    unsigned int pad : 1;
71
72
    /* DH KDF */
73
    /* KDF (if any) to use for DH */
74
    enum kdf_type kdf_type;
75
    /* Message digest to use for key derivation */
76
    EVP_MD *kdf_md;
77
    /* User key material */
78
    unsigned char *kdf_ukm;
79
    size_t kdf_ukmlen;
80
    /* KDF output length */
81
    size_t kdf_outlen;
82
    char *kdf_cekalg;
83
    OSSL_FIPS_IND_DECLARE
84
} PROV_DH_CTX;
85
86
static void *dh_newctx(void *provctx)
87
5.13k
{
88
5.13k
    PROV_DH_CTX *pdhctx;
89
90
5.13k
    if (!ossl_prov_is_running())
91
0
        return NULL;
92
93
5.13k
    pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX));
94
5.13k
    if (pdhctx == NULL)
95
0
        return NULL;
96
5.13k
    OSSL_FIPS_IND_INIT(pdhctx)
97
5.13k
    pdhctx->libctx = PROV_LIBCTX_OF(provctx);
98
5.13k
    pdhctx->kdf_type = PROV_DH_KDF_NONE;
99
5.13k
    return pdhctx;
100
5.13k
}
101
102
#ifdef FIPS_MODULE
103
static int dh_check_key(PROV_DH_CTX *ctx)
104
{
105
    int key_approved = ossl_dh_check_key(ctx->dh);
106
107
    if (!key_approved) {
108
        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
109
                ctx->libctx, "DH Init", "DH Key",
110
                ossl_fips_config_securitycheck_enabled)) {
111
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
112
            return 0;
113
        }
114
    }
115
    return 1;
116
}
117
118
static int digest_check(PROV_DH_CTX *ctx, const EVP_MD *md)
119
{
120
    return ossl_fips_ind_digest_exch_check(OSSL_FIPS_IND_GET(ctx),
121
        OSSL_FIPS_IND_SETTABLE1, ctx->libctx,
122
        md, "DH Set Ctx");
123
}
124
#endif
125
126
static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[])
127
3.11k
{
128
3.11k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
129
130
3.11k
    if (!ossl_prov_is_running()
131
3.11k
        || pdhctx == NULL
132
3.11k
        || vdh == NULL
133
3.11k
        || !DH_up_ref(vdh))
134
0
        return 0;
135
3.11k
    DH_free(pdhctx->dh);
136
3.11k
    pdhctx->dh = vdh;
137
3.11k
    pdhctx->kdf_type = PROV_DH_KDF_NONE;
138
139
3.11k
    OSSL_FIPS_IND_SET_APPROVED(pdhctx)
140
3.11k
    if (!dh_set_ctx_params(pdhctx, params))
141
0
        return 0;
142
#ifdef FIPS_MODULE
143
    if (!dh_check_key(pdhctx))
144
        return 0;
145
#endif
146
3.11k
    return 1;
147
3.11k
}
148
149
/* The 2 parties must share the same domain parameters */
150
static int dh_match_params(DH *priv, DH *peer)
151
4.81k
{
152
4.81k
    int ret;
153
4.81k
    FFC_PARAMS *dhparams_priv = ossl_dh_get0_params(priv);
154
4.81k
    FFC_PARAMS *dhparams_peer = ossl_dh_get0_params(peer);
155
156
4.81k
    ret = dhparams_priv != NULL
157
4.81k
        && dhparams_peer != NULL
158
4.81k
        && ossl_ffc_params_cmp(dhparams_priv, dhparams_peer, 1);
159
4.81k
    if (!ret)
160
4.81k
        ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
161
4.81k
    return ret;
162
4.81k
}
163
164
static int dh_set_peer(void *vpdhctx, void *vdh)
165
4.81k
{
166
4.81k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
167
168
4.81k
    if (!ossl_prov_is_running()
169
4.81k
        || pdhctx == NULL
170
4.81k
        || vdh == NULL
171
4.81k
        || !dh_match_params(vdh, pdhctx->dh)
172
4.81k
        || !DH_up_ref(vdh))
173
0
        return 0;
174
4.81k
    DH_free(pdhctx->dhpeer);
175
4.81k
    pdhctx->dhpeer = vdh;
176
4.81k
    return 1;
177
4.81k
}
178
179
static int dh_plain_derive(void *vpdhctx,
180
    unsigned char *secret, size_t *secretlen,
181
    size_t outlen, unsigned int pad)
182
9.62k
{
183
9.62k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
184
9.62k
    int ret;
185
9.62k
    size_t dhsize;
186
9.62k
    const BIGNUM *pub_key = NULL;
187
188
9.62k
    if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) {
189
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
190
0
        return 0;
191
0
    }
192
193
9.62k
    dhsize = (size_t)DH_size(pdhctx->dh);
194
9.62k
    if (secret == NULL) {
195
4.81k
        *secretlen = dhsize;
196
4.81k
        return 1;
197
4.81k
    }
198
4.81k
    if (outlen < dhsize) {
199
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
200
0
        return 0;
201
0
    }
202
203
4.81k
    DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
204
4.81k
    if (pad)
205
146
        ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh);
206
4.66k
    else
207
4.66k
        ret = DH_compute_key(secret, pub_key, pdhctx->dh);
208
4.81k
    if (ret <= 0)
209
0
        return 0;
210
211
4.81k
    *secretlen = ret;
212
4.81k
    return 1;
213
4.81k
}
214
215
static int dh_X9_42_kdf_derive(void *vpdhctx, unsigned char *secret,
216
    size_t *secretlen, size_t outlen)
217
0
{
218
0
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
219
0
    unsigned char *stmp = NULL;
220
0
    size_t stmplen;
221
0
    int ret = 0;
222
223
0
    if (secret == NULL) {
224
0
        *secretlen = pdhctx->kdf_outlen;
225
0
        return 1;
226
0
    }
227
228
0
    if (pdhctx->kdf_outlen > outlen) {
229
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
230
0
        return 0;
231
0
    }
232
0
    if (!dh_plain_derive(pdhctx, NULL, &stmplen, 0, 1))
233
0
        return 0;
234
0
    if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL)
235
0
        return 0;
236
0
    if (!dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, 1))
237
0
        goto err;
238
239
    /* Do KDF stuff */
240
0
    if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) {
241
0
        if (!ossl_dh_kdf_X9_42_asn1(secret, pdhctx->kdf_outlen,
242
0
                stmp, stmplen,
243
0
                pdhctx->kdf_cekalg,
244
0
                pdhctx->kdf_ukm,
245
0
                pdhctx->kdf_ukmlen,
246
0
                pdhctx->kdf_md,
247
0
                pdhctx->libctx, NULL))
248
0
            goto err;
249
0
    }
250
0
    *secretlen = pdhctx->kdf_outlen;
251
0
    ret = 1;
252
0
err:
253
0
    OPENSSL_secure_clear_free(stmp, stmplen);
254
0
    return ret;
255
0
}
256
257
static int dh_derive(void *vpdhctx, unsigned char *secret,
258
    size_t *psecretlen, size_t outlen)
259
9.62k
{
260
9.62k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
261
262
9.62k
    if (!ossl_prov_is_running())
263
0
        return 0;
264
265
9.62k
    switch (pdhctx->kdf_type) {
266
9.62k
    case PROV_DH_KDF_NONE:
267
9.62k
        return dh_plain_derive(pdhctx, secret, psecretlen, outlen,
268
9.62k
            pdhctx->pad);
269
0
    case PROV_DH_KDF_X9_42_ASN1:
270
0
        return dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen);
271
0
    default:
272
0
        break;
273
9.62k
    }
274
0
    return 0;
275
9.62k
}
276
277
static void dh_freectx(void *vpdhctx)
278
5.13k
{
279
5.13k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
280
281
5.13k
    OPENSSL_free(pdhctx->kdf_cekalg);
282
5.13k
    DH_free(pdhctx->dh);
283
5.13k
    DH_free(pdhctx->dhpeer);
284
5.13k
    EVP_MD_free(pdhctx->kdf_md);
285
5.13k
    OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen);
286
287
5.13k
    OPENSSL_free(pdhctx);
288
5.13k
}
289
290
static void *dh_dupctx(void *vpdhctx)
291
0
{
292
0
    PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
293
0
    PROV_DH_CTX *dstctx;
294
295
0
    if (!ossl_prov_is_running())
296
0
        return NULL;
297
298
0
    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
299
0
    if (dstctx == NULL)
300
0
        return NULL;
301
302
0
    *dstctx = *srcctx;
303
0
    dstctx->dh = NULL;
304
0
    dstctx->dhpeer = NULL;
305
0
    dstctx->kdf_md = NULL;
306
0
    dstctx->kdf_ukm = NULL;
307
0
    dstctx->kdf_cekalg = NULL;
308
309
0
    if (srcctx->dh != NULL && !DH_up_ref(srcctx->dh))
310
0
        goto err;
311
0
    else
312
0
        dstctx->dh = srcctx->dh;
313
314
0
    if (srcctx->dhpeer != NULL && !DH_up_ref(srcctx->dhpeer))
315
0
        goto err;
316
0
    else
317
0
        dstctx->dhpeer = srcctx->dhpeer;
318
319
0
    if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
320
0
        goto err;
321
0
    else
322
0
        dstctx->kdf_md = srcctx->kdf_md;
323
324
    /* Duplicate UKM data if present */
325
0
    if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
326
0
        dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
327
0
            srcctx->kdf_ukmlen);
328
0
        if (dstctx->kdf_ukm == NULL)
329
0
            goto err;
330
0
    }
331
332
0
    if (srcctx->kdf_cekalg != NULL) {
333
0
        dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg);
334
0
        if (dstctx->kdf_cekalg == NULL)
335
0
            goto err;
336
0
    }
337
338
0
    return dstctx;
339
0
err:
340
0
    dh_freectx(dstctx);
341
0
    return NULL;
342
0
}
343
344
/* clang-format off */
345
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
346
#ifndef dh_set_ctx_params_list
347
static const OSSL_PARAM dh_set_ctx_params_list[] = {
348
    OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
349
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
350
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
351
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
352
    OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
353
    OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
354
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
355
# if defined(FIPS_MODULE)
356
    OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK, NULL),
357
# endif
358
# if defined(FIPS_MODULE)
359
    OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK, NULL),
360
# endif
361
    OSSL_PARAM_END
362
};
363
#endif
364
365
#ifndef dh_set_ctx_params_st
366
struct dh_set_ctx_params_st {
367
    OSSL_PARAM *cekalg;
368
    OSSL_PARAM *digest;
369
# if defined(FIPS_MODULE)
370
    OSSL_PARAM *ind_d;
371
# endif
372
# if defined(FIPS_MODULE)
373
    OSSL_PARAM *ind_k;
374
# endif
375
    OSSL_PARAM *kdf;
376
    OSSL_PARAM *len;
377
    OSSL_PARAM *pad;
378
    OSSL_PARAM *propq;
379
    OSSL_PARAM *ukm;
380
};
381
#endif
382
383
#ifndef dh_set_ctx_params_decoder
384
static int dh_set_ctx_params_decoder
385
    (const OSSL_PARAM *p, struct dh_set_ctx_params_st *r)
386
1.75k
{
387
1.75k
    const char *s;
388
389
1.75k
    memset(r, 0, sizeof(*r));
390
1.75k
    if (p != NULL)
391
292
        for (; (s = p->key) != NULL; p++)
392
146
            switch(s[0]) {
393
0
            default:
394
0
                break;
395
0
            case 'c':
396
0
                if (ossl_likely(strcmp("ekalg", s + 1) == 0)) {
397
                    /* OSSL_KDF_PARAM_CEK_ALG */
398
0
                    if (ossl_unlikely(r->cekalg != NULL)) {
399
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
400
0
                                       "param %s is repeated", s);
401
0
                        return 0;
402
0
                    }
403
0
                    r->cekalg = (OSSL_PARAM *)p;
404
0
                }
405
0
                break;
406
0
            case 'd':
407
# if defined(FIPS_MODULE)
408
                if (ossl_likely(strcmp("igest-check", s + 1) == 0)) {
409
                    /* OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK */
410
                    if (ossl_unlikely(r->ind_d != NULL)) {
411
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
412
                                       "param %s is repeated", s);
413
                        return 0;
414
                    }
415
                    r->ind_d = (OSSL_PARAM *)p;
416
                }
417
# endif
418
0
                break;
419
0
            case 'k':
420
0
                switch(s[1]) {
421
0
                default:
422
0
                    break;
423
0
                case 'd':
424
0
                    switch(s[2]) {
425
0
                    default:
426
0
                        break;
427
0
                    case 'f':
428
0
                        switch(s[3]) {
429
0
                        default:
430
0
                            break;
431
0
                        case '-':
432
0
                            switch(s[4]) {
433
0
                            default:
434
0
                                break;
435
0
                            case 'd':
436
0
                                switch(s[5]) {
437
0
                                default:
438
0
                                    break;
439
0
                                case 'i':
440
0
                                    switch(s[6]) {
441
0
                                    default:
442
0
                                        break;
443
0
                                    case 'g':
444
0
                                        switch(s[7]) {
445
0
                                        default:
446
0
                                            break;
447
0
                                        case 'e':
448
0
                                            switch(s[8]) {
449
0
                                            default:
450
0
                                                break;
451
0
                                            case 's':
452
0
                                                switch(s[9]) {
453
0
                                                default:
454
0
                                                    break;
455
0
                                                case 't':
456
0
                                                    switch(s[10]) {
457
0
                                                    default:
458
0
                                                        break;
459
0
                                                    case '-':
460
0
                                                        if (ossl_likely(strcmp("props", s + 11) == 0)) {
461
                                                            /* OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS */
462
0
                                                            if (ossl_unlikely(r->propq != NULL)) {
463
0
                                                                ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
464
0
                                                                               "param %s is repeated", s);
465
0
                                                                return 0;
466
0
                                                            }
467
0
                                                            r->propq = (OSSL_PARAM *)p;
468
0
                                                        }
469
0
                                                        break;
470
0
                                                    case '\0':
471
0
                                                        if (ossl_unlikely(r->digest != NULL)) {
472
0
                                                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
473
0
                                                                           "param %s is repeated", s);
474
0
                                                            return 0;
475
0
                                                        }
476
0
                                                        r->digest = (OSSL_PARAM *)p;
477
0
                                                    }
478
0
                                                }
479
0
                                            }
480
0
                                        }
481
0
                                    }
482
0
                                }
483
0
                                break;
484
0
                            case 'o':
485
0
                                if (ossl_likely(strcmp("utlen", s + 5) == 0)) {
486
                                    /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */
487
0
                                    if (ossl_unlikely(r->len != NULL)) {
488
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
489
0
                                                       "param %s is repeated", s);
490
0
                                        return 0;
491
0
                                    }
492
0
                                    r->len = (OSSL_PARAM *)p;
493
0
                                }
494
0
                                break;
495
0
                            case 't':
496
0
                                if (ossl_likely(strcmp("ype", s + 5) == 0)) {
497
                                    /* OSSL_EXCHANGE_PARAM_KDF_TYPE */
498
0
                                    if (ossl_unlikely(r->kdf != NULL)) {
499
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
500
0
                                                       "param %s is repeated", s);
501
0
                                        return 0;
502
0
                                    }
503
0
                                    r->kdf = (OSSL_PARAM *)p;
504
0
                                }
505
0
                                break;
506
0
                            case 'u':
507
0
                                if (ossl_likely(strcmp("km", s + 5) == 0)) {
508
                                    /* OSSL_EXCHANGE_PARAM_KDF_UKM */
509
0
                                    if (ossl_unlikely(r->ukm != NULL)) {
510
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
511
0
                                                       "param %s is repeated", s);
512
0
                                        return 0;
513
0
                                    }
514
0
                                    r->ukm = (OSSL_PARAM *)p;
515
0
                                }
516
0
                            }
517
0
                        }
518
0
                    }
519
0
                    break;
520
0
                case 'e':
521
# if defined(FIPS_MODULE)
522
                    if (ossl_likely(strcmp("y-check", s + 2) == 0)) {
523
                        /* OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK */
524
                        if (ossl_unlikely(r->ind_k != NULL)) {
525
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
526
                                           "param %s is repeated", s);
527
                            return 0;
528
                        }
529
                        r->ind_k = (OSSL_PARAM *)p;
530
                    }
531
# endif
532
0
                    break;
533
0
                }
534
0
                break;
535
146
            case 'p':
536
146
                if (ossl_likely(strcmp("ad", s + 1) == 0)) {
537
                    /* OSSL_EXCHANGE_PARAM_PAD */
538
146
                    if (ossl_unlikely(r->pad != NULL)) {
539
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
540
0
                                       "param %s is repeated", s);
541
0
                        return 0;
542
0
                    }
543
146
                    r->pad = (OSSL_PARAM *)p;
544
146
                }
545
146
            }
546
1.75k
    return 1;
547
1.75k
}
548
#endif
549
/* End of machine generated */
550
/* clang-format on */
551
552
static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
553
1.75k
{
554
1.75k
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
555
1.75k
    struct dh_set_ctx_params_st p;
556
1.75k
    unsigned int pad;
557
1.75k
    char name[80] = { '\0' }; /* should be big enough */
558
1.75k
    char *str = NULL;
559
560
1.75k
    if (pdhctx == NULL || !dh_set_ctx_params_decoder(params, &p))
561
0
        return 0;
562
563
1.75k
    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(pdhctx, OSSL_FIPS_IND_SETTABLE0, p.ind_k))
564
0
        return 0;
565
1.75k
    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(pdhctx, OSSL_FIPS_IND_SETTABLE1, p.ind_d))
566
0
        return 0;
567
568
1.75k
    if (p.kdf != NULL) {
569
0
        str = name;
570
0
        if (!OSSL_PARAM_get_utf8_string(p.kdf, &str, sizeof(name)))
571
0
            return 0;
572
573
0
        if (name[0] == '\0')
574
0
            pdhctx->kdf_type = PROV_DH_KDF_NONE;
575
0
        else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0)
576
0
            pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1;
577
0
        else
578
0
            return 0;
579
0
    }
580
581
1.75k
    if (p.digest != NULL) {
582
0
        char mdprops[80] = { '\0' }; /* should be big enough */
583
584
0
        str = name;
585
0
        if (!OSSL_PARAM_get_utf8_string(p.digest, &str, sizeof(name)))
586
0
            return 0;
587
588
0
        str = mdprops;
589
0
        if (p.propq != NULL) {
590
0
            if (!OSSL_PARAM_get_utf8_string(p.propq, &str, sizeof(mdprops)))
591
0
                return 0;
592
0
        }
593
594
0
        EVP_MD_free(pdhctx->kdf_md);
595
0
        pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
596
0
        if (pdhctx->kdf_md == NULL)
597
0
            return 0;
598
        /* XOF digests are not allowed */
599
0
        if (EVP_MD_xof(pdhctx->kdf_md)) {
600
0
            ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
601
0
            return 0;
602
0
        }
603
#ifdef FIPS_MODULE
604
        if (!digest_check(pdhctx, pdhctx->kdf_md)) {
605
            EVP_MD_free(pdhctx->kdf_md);
606
            pdhctx->kdf_md = NULL;
607
            return 0;
608
        }
609
#endif
610
0
    }
611
612
1.75k
    if (p.len != NULL) {
613
0
        size_t outlen;
614
615
0
        if (!OSSL_PARAM_get_size_t(p.len, &outlen))
616
0
            return 0;
617
0
        pdhctx->kdf_outlen = outlen;
618
0
    }
619
620
1.75k
    if (p.ukm != NULL) {
621
0
        void *tmp_ukm = NULL;
622
0
        size_t tmp_ukmlen;
623
624
0
        OPENSSL_free(pdhctx->kdf_ukm);
625
0
        pdhctx->kdf_ukm = NULL;
626
0
        pdhctx->kdf_ukmlen = 0;
627
        /* ukm is an optional field so it can be NULL */
628
0
        if (p.ukm->data != NULL && p.ukm->data_size != 0) {
629
0
            if (!OSSL_PARAM_get_octet_string(p.ukm, &tmp_ukm, 0, &tmp_ukmlen))
630
0
                return 0;
631
0
            pdhctx->kdf_ukm = tmp_ukm;
632
0
            pdhctx->kdf_ukmlen = tmp_ukmlen;
633
0
        }
634
0
    }
635
636
1.75k
    if (p.pad != NULL) {
637
146
        if (!OSSL_PARAM_get_uint(p.pad, &pad))
638
0
            return 0;
639
146
        pdhctx->pad = pad ? 1 : 0;
640
146
    }
641
642
1.75k
    if (p.cekalg != NULL) {
643
0
        str = name;
644
645
0
        OPENSSL_free(pdhctx->kdf_cekalg);
646
0
        pdhctx->kdf_cekalg = NULL;
647
0
        if (p.cekalg->data != NULL && p.cekalg->data_size != 0) {
648
0
            if (!OSSL_PARAM_get_utf8_string(p.cekalg, &str, sizeof(name)))
649
0
                return 0;
650
0
            pdhctx->kdf_cekalg = OPENSSL_strdup(name);
651
0
            if (pdhctx->kdf_cekalg == NULL)
652
0
                return 0;
653
0
        }
654
0
    }
655
1.75k
    return 1;
656
1.75k
}
657
658
static const OSSL_PARAM *dh_settable_ctx_params(ossl_unused void *vpdhctx,
659
    ossl_unused void *provctx)
660
166
{
661
166
    return dh_set_ctx_params_list;
662
166
}
663
664
/* clang-format off */
665
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
666
#ifndef dh_get_ctx_params_list
667
static const OSSL_PARAM dh_get_ctx_params_list[] = {
668
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
669
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
670
    OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
671
    OSSL_PARAM_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
672
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
673
# if defined(FIPS_MODULE)
674
    OSSL_PARAM_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR, NULL),
675
# endif
676
    OSSL_PARAM_END
677
};
678
#endif
679
680
#ifndef dh_get_ctx_params_st
681
struct dh_get_ctx_params_st {
682
    OSSL_PARAM *cekalg;
683
    OSSL_PARAM *digest;
684
# if defined(FIPS_MODULE)
685
    OSSL_PARAM *ind;
686
# endif
687
    OSSL_PARAM *kdf;
688
    OSSL_PARAM *len;
689
    OSSL_PARAM *ukm;
690
};
691
#endif
692
693
#ifndef dh_get_ctx_params_decoder
694
static int dh_get_ctx_params_decoder
695
    (const OSSL_PARAM *p, struct dh_get_ctx_params_st *r)
696
0
{
697
0
    const char *s;
698
699
0
    memset(r, 0, sizeof(*r));
700
0
    if (p != NULL)
701
0
        for (; (s = p->key) != NULL; p++)
702
0
            switch(s[0]) {
703
0
            default:
704
0
                break;
705
0
            case 'c':
706
0
                if (ossl_likely(strcmp("ekalg", s + 1) == 0)) {
707
                    /* OSSL_KDF_PARAM_CEK_ALG */
708
0
                    if (ossl_unlikely(r->cekalg != NULL)) {
709
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
710
0
                                       "param %s is repeated", s);
711
0
                        return 0;
712
0
                    }
713
0
                    r->cekalg = (OSSL_PARAM *)p;
714
0
                }
715
0
                break;
716
0
            case 'f':
717
# if defined(FIPS_MODULE)
718
                if (ossl_likely(strcmp("ips-indicator", s + 1) == 0)) {
719
                    /* OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR */
720
                    if (ossl_unlikely(r->ind != NULL)) {
721
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
722
                                       "param %s is repeated", s);
723
                        return 0;
724
                    }
725
                    r->ind = (OSSL_PARAM *)p;
726
                }
727
# endif
728
0
                break;
729
0
            case 'k':
730
0
                switch(s[1]) {
731
0
                default:
732
0
                    break;
733
0
                case 'd':
734
0
                    switch(s[2]) {
735
0
                    default:
736
0
                        break;
737
0
                    case 'f':
738
0
                        switch(s[3]) {
739
0
                        default:
740
0
                            break;
741
0
                        case '-':
742
0
                            switch(s[4]) {
743
0
                            default:
744
0
                                break;
745
0
                            case 'd':
746
0
                                if (ossl_likely(strcmp("igest", s + 5) == 0)) {
747
                                    /* OSSL_EXCHANGE_PARAM_KDF_DIGEST */
748
0
                                    if (ossl_unlikely(r->digest != NULL)) {
749
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
750
0
                                                       "param %s is repeated", s);
751
0
                                        return 0;
752
0
                                    }
753
0
                                    r->digest = (OSSL_PARAM *)p;
754
0
                                }
755
0
                                break;
756
0
                            case 'o':
757
0
                                if (ossl_likely(strcmp("utlen", s + 5) == 0)) {
758
                                    /* OSSL_EXCHANGE_PARAM_KDF_OUTLEN */
759
0
                                    if (ossl_unlikely(r->len != NULL)) {
760
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
761
0
                                                       "param %s is repeated", s);
762
0
                                        return 0;
763
0
                                    }
764
0
                                    r->len = (OSSL_PARAM *)p;
765
0
                                }
766
0
                                break;
767
0
                            case 't':
768
0
                                if (ossl_likely(strcmp("ype", s + 5) == 0)) {
769
                                    /* OSSL_EXCHANGE_PARAM_KDF_TYPE */
770
0
                                    if (ossl_unlikely(r->kdf != NULL)) {
771
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
772
0
                                                       "param %s is repeated", s);
773
0
                                        return 0;
774
0
                                    }
775
0
                                    r->kdf = (OSSL_PARAM *)p;
776
0
                                }
777
0
                                break;
778
0
                            case 'u':
779
0
                                if (ossl_likely(strcmp("km", s + 5) == 0)) {
780
                                    /* OSSL_EXCHANGE_PARAM_KDF_UKM */
781
0
                                    if (ossl_unlikely(r->ukm != NULL)) {
782
0
                                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
783
0
                                                       "param %s is repeated", s);
784
0
                                        return 0;
785
0
                                    }
786
0
                                    r->ukm = (OSSL_PARAM *)p;
787
0
                                }
788
0
                            }
789
0
                        }
790
0
                    }
791
0
                }
792
0
            }
793
0
    return 1;
794
0
}
795
#endif
796
/* End of machine generated */
797
/* clang-format on */
798
799
static const OSSL_PARAM *dh_gettable_ctx_params(ossl_unused void *vpdhctx,
800
    ossl_unused void *provctx)
801
0
{
802
0
    return dh_get_ctx_params_list;
803
0
}
804
805
static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[])
806
0
{
807
0
    PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
808
0
    struct dh_get_ctx_params_st p;
809
810
0
    if (pdhctx == NULL || !dh_get_ctx_params_decoder(params, &p))
811
0
        return 0;
812
813
0
    if (p.kdf != NULL) {
814
0
        const char *kdf_type = NULL;
815
816
0
        switch (pdhctx->kdf_type) {
817
0
        case PROV_DH_KDF_NONE:
818
0
            kdf_type = "";
819
0
            break;
820
0
        case PROV_DH_KDF_X9_42_ASN1:
821
0
            kdf_type = OSSL_KDF_NAME_X942KDF_ASN1;
822
0
            break;
823
0
        default:
824
0
            return 0;
825
0
        }
826
827
0
        if (!OSSL_PARAM_set_utf8_string(p.kdf, kdf_type))
828
0
            return 0;
829
0
    }
830
831
0
    if (p.digest != NULL
832
0
        && !OSSL_PARAM_set_utf8_string(p.digest, pdhctx->kdf_md == NULL ? "" : EVP_MD_get0_name(pdhctx->kdf_md))) {
833
0
        return 0;
834
0
    }
835
836
0
    if (p.len != NULL && !OSSL_PARAM_set_size_t(p.len, pdhctx->kdf_outlen))
837
0
        return 0;
838
839
0
    if (p.ukm != NULL
840
0
        && !OSSL_PARAM_set_octet_ptr(p.ukm, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen))
841
0
        return 0;
842
843
0
    if (p.cekalg != NULL
844
0
        && !OSSL_PARAM_set_utf8_string(p.cekalg, pdhctx->kdf_cekalg == NULL ? "" : pdhctx->kdf_cekalg))
845
0
        return 0;
846
847
0
    if (!OSSL_FIPS_IND_GET_CTX_FROM_PARAM(pdhctx, p.ind))
848
0
        return 0;
849
0
    return 1;
850
0
}
851
852
const OSSL_DISPATCH ossl_dh_keyexch_functions[] = {
853
    { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
854
    { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
855
    { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
856
    { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
857
    { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
858
    { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
859
    { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params },
860
    { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
861
        (void (*)(void))dh_settable_ctx_params },
862
    { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))dh_get_ctx_params },
863
    { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
864
        (void (*)(void))dh_gettable_ctx_params },
865
    OSSL_DISPATCH_END
866
};