Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl30/providers/implementations/exchange/ecdh_exch.c
Line
Count
Source
1
/*
2
 * Copyright 2020-2021 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
 * ECDH 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/evp.h>
19
#include <openssl/core_dispatch.h>
20
#include <openssl/core_names.h>
21
#include <openssl/ec.h>
22
#include <openssl/params.h>
23
#include <openssl/err.h>
24
#include <openssl/proverr.h>
25
#include "prov/provider_ctx.h"
26
#include "prov/providercommon.h"
27
#include "prov/implementations.h"
28
#include "prov/securitycheck.h"
29
#include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */
30
31
static OSSL_FUNC_keyexch_newctx_fn ecdh_newctx;
32
static OSSL_FUNC_keyexch_init_fn ecdh_init;
33
static OSSL_FUNC_keyexch_set_peer_fn ecdh_set_peer;
34
static OSSL_FUNC_keyexch_derive_fn ecdh_derive;
35
static OSSL_FUNC_keyexch_freectx_fn ecdh_freectx;
36
static OSSL_FUNC_keyexch_dupctx_fn ecdh_dupctx;
37
static OSSL_FUNC_keyexch_set_ctx_params_fn ecdh_set_ctx_params;
38
static OSSL_FUNC_keyexch_settable_ctx_params_fn ecdh_settable_ctx_params;
39
static OSSL_FUNC_keyexch_get_ctx_params_fn ecdh_get_ctx_params;
40
static OSSL_FUNC_keyexch_gettable_ctx_params_fn ecdh_gettable_ctx_params;
41
42
enum kdf_type {
43
    PROV_ECDH_KDF_NONE = 0,
44
    PROV_ECDH_KDF_X9_63
45
};
46
47
/*
48
 * What's passed as an actual key is defined by the KEYMGMT interface.
49
 * We happen to know that our KEYMGMT simply passes EC_KEY structures, so
50
 * we use that here too.
51
 */
52
53
typedef struct {
54
    OSSL_LIB_CTX *libctx;
55
56
    EC_KEY *k;
57
    EC_KEY *peerk;
58
59
    /*
60
     * ECDH cofactor mode:
61
     *
62
     *  . 0  disabled
63
     *  . 1  enabled
64
     *  . -1 use cofactor mode set for k
65
     */
66
    int cofactor_mode;
67
68
    /************
69
     * ECDH KDF *
70
     ************/
71
    /* KDF (if any) to use for ECDH */
72
    enum kdf_type kdf_type;
73
    /* Message digest to use for key derivation */
74
    EVP_MD *kdf_md;
75
    /* User key material */
76
    unsigned char *kdf_ukm;
77
    size_t kdf_ukmlen;
78
    /* KDF output length */
79
    size_t kdf_outlen;
80
} PROV_ECDH_CTX;
81
82
static void *ecdh_newctx(void *provctx)
83
4.31k
{
84
4.31k
    PROV_ECDH_CTX *pectx;
85
86
4.31k
    if (!ossl_prov_is_running())
87
0
        return NULL;
88
89
4.31k
    pectx = OPENSSL_zalloc(sizeof(*pectx));
90
4.31k
    if (pectx == NULL)
91
0
        return NULL;
92
93
4.31k
    pectx->libctx = PROV_LIBCTX_OF(provctx);
94
4.31k
    pectx->cofactor_mode = -1;
95
4.31k
    pectx->kdf_type = PROV_ECDH_KDF_NONE;
96
97
4.31k
    return (void *)pectx;
98
4.31k
}
99
100
static int ecdh_init(void *vpecdhctx, void *vecdh, const OSSL_PARAM params[])
101
1.27k
{
102
1.27k
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
103
104
1.27k
    if (!ossl_prov_is_running()
105
1.27k
        || pecdhctx == NULL
106
1.27k
        || vecdh == NULL
107
1.27k
        || !EC_KEY_up_ref(vecdh))
108
0
        return 0;
109
1.27k
    EC_KEY_free(pecdhctx->k);
110
1.27k
    pecdhctx->k = vecdh;
111
1.27k
    pecdhctx->cofactor_mode = -1;
112
1.27k
    pecdhctx->kdf_type = PROV_ECDH_KDF_NONE;
113
1.27k
    return ecdh_set_ctx_params(pecdhctx, params)
114
1.27k
        && ossl_ec_check_key(pecdhctx->libctx, vecdh, 1);
115
1.27k
}
116
117
static int ecdh_match_params(const EC_KEY *priv, const EC_KEY *peer)
118
4.28k
{
119
4.28k
    int ret;
120
4.28k
    BN_CTX *ctx = NULL;
121
4.28k
    const EC_GROUP *group_priv = EC_KEY_get0_group(priv);
122
4.28k
    const EC_GROUP *group_peer = EC_KEY_get0_group(peer);
123
124
4.28k
    ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(priv));
125
4.28k
    if (ctx == NULL) {
126
0
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
127
0
        return 0;
128
0
    }
129
4.28k
    ret = group_priv != NULL
130
4.28k
        && group_peer != NULL
131
4.28k
        && EC_GROUP_cmp(group_priv, group_peer, ctx) == 0;
132
4.28k
    if (!ret)
133
4.28k
        ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
134
4.28k
    BN_CTX_free(ctx);
135
4.28k
    return ret;
136
4.28k
}
137
138
static int ecdh_set_peer(void *vpecdhctx, void *vecdh)
139
1.26k
{
140
1.26k
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
141
142
1.26k
    if (!ossl_prov_is_running()
143
1.26k
        || pecdhctx == NULL
144
1.26k
        || vecdh == NULL
145
1.26k
        || !ecdh_match_params(pecdhctx->k, vecdh)
146
1.26k
        || !ossl_ec_check_key(pecdhctx->libctx, vecdh, 1)
147
1.26k
        || !EC_KEY_up_ref(vecdh))
148
0
        return 0;
149
150
1.26k
    EC_KEY_free(pecdhctx->peerk);
151
1.26k
    pecdhctx->peerk = vecdh;
152
1.26k
    return 1;
153
1.26k
}
154
155
static void ecdh_freectx(void *vpecdhctx)
156
4.31k
{
157
4.31k
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
158
159
4.31k
    EC_KEY_free(pecdhctx->k);
160
4.31k
    EC_KEY_free(pecdhctx->peerk);
161
162
4.31k
    EVP_MD_free(pecdhctx->kdf_md);
163
4.31k
    OPENSSL_clear_free(pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen);
164
165
4.31k
    OPENSSL_free(pecdhctx);
166
4.31k
}
167
168
static void *ecdh_dupctx(void *vpecdhctx)
169
0
{
170
0
    PROV_ECDH_CTX *srcctx = (PROV_ECDH_CTX *)vpecdhctx;
171
0
    PROV_ECDH_CTX *dstctx;
172
173
0
    if (!ossl_prov_is_running())
174
0
        return NULL;
175
176
0
    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
177
0
    if (dstctx == NULL)
178
0
        return NULL;
179
180
0
    *dstctx = *srcctx;
181
182
    /* clear all pointers */
183
184
0
    dstctx->k = NULL;
185
0
    dstctx->peerk = NULL;
186
0
    dstctx->kdf_md = NULL;
187
0
    dstctx->kdf_ukm = NULL;
188
189
    /* up-ref all ref-counted objects referenced in dstctx */
190
191
0
    if (srcctx->k != NULL && !EC_KEY_up_ref(srcctx->k))
192
0
        goto err;
193
0
    else
194
0
        dstctx->k = srcctx->k;
195
196
0
    if (srcctx->peerk != NULL && !EC_KEY_up_ref(srcctx->peerk))
197
0
        goto err;
198
0
    else
199
0
        dstctx->peerk = srcctx->peerk;
200
201
0
    if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
202
0
        goto err;
203
0
    else
204
0
        dstctx->kdf_md = srcctx->kdf_md;
205
206
    /* Duplicate UKM data if present */
207
0
    if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
208
0
        dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
209
0
            srcctx->kdf_ukmlen);
210
0
        if (dstctx->kdf_ukm == NULL)
211
0
            goto err;
212
0
    }
213
214
0
    return dstctx;
215
216
0
err:
217
0
    ecdh_freectx(dstctx);
218
0
    return NULL;
219
0
}
220
221
static int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[])
222
616
{
223
616
    char name[80] = { '\0' }; /* should be big enough */
224
616
    char *str = NULL;
225
616
    PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
226
616
    const OSSL_PARAM *p;
227
228
616
    if (pectx == NULL)
229
0
        return 0;
230
616
    if (params == NULL)
231
616
        return 1;
232
233
0
    p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
234
0
    if (p != NULL) {
235
0
        int mode;
236
237
0
        if (!OSSL_PARAM_get_int(p, &mode))
238
0
            return 0;
239
240
0
        if (mode < -1 || mode > 1)
241
0
            return 0;
242
243
0
        pectx->cofactor_mode = mode;
244
0
    }
245
246
0
    p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
247
0
    if (p != NULL) {
248
0
        str = name;
249
0
        if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
250
0
            return 0;
251
252
0
        if (name[0] == '\0')
253
0
            pectx->kdf_type = PROV_ECDH_KDF_NONE;
254
0
        else if (strcmp(name, OSSL_KDF_NAME_X963KDF) == 0)
255
0
            pectx->kdf_type = PROV_ECDH_KDF_X9_63;
256
0
        else
257
0
            return 0;
258
0
    }
259
260
0
    p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
261
0
    if (p != NULL) {
262
0
        char mdprops[80] = { '\0' }; /* should be big enough */
263
264
0
        str = name;
265
0
        if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
266
0
            return 0;
267
268
0
        str = mdprops;
269
0
        p = OSSL_PARAM_locate_const(params,
270
0
            OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
271
272
0
        if (p != NULL) {
273
0
            if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
274
0
                return 0;
275
0
        }
276
277
0
        EVP_MD_free(pectx->kdf_md);
278
0
        pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops);
279
0
        if (!ossl_digest_is_allowed(pectx->libctx, pectx->kdf_md)) {
280
0
            EVP_MD_free(pectx->kdf_md);
281
0
            pectx->kdf_md = NULL;
282
0
        }
283
0
        if (pectx->kdf_md == NULL)
284
0
            return 0;
285
0
    }
286
287
0
    p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
288
0
    if (p != NULL) {
289
0
        size_t outlen;
290
291
0
        if (!OSSL_PARAM_get_size_t(p, &outlen))
292
0
            return 0;
293
0
        pectx->kdf_outlen = outlen;
294
0
    }
295
296
0
    p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
297
0
    if (p != NULL) {
298
0
        void *tmp_ukm = NULL;
299
0
        size_t tmp_ukmlen;
300
301
0
        if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
302
0
            return 0;
303
0
        OPENSSL_free(pectx->kdf_ukm);
304
0
        pectx->kdf_ukm = tmp_ukm;
305
0
        pectx->kdf_ukmlen = tmp_ukmlen;
306
0
    }
307
308
0
    return 1;
309
0
}
310
311
static const OSSL_PARAM known_settable_ctx_params[] = {
312
    OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
313
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
314
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
315
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
316
    OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
317
    OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
318
    OSSL_PARAM_END
319
};
320
321
static const OSSL_PARAM *ecdh_settable_ctx_params(ossl_unused void *vpecdhctx,
322
    ossl_unused void *provctx)
323
25
{
324
25
    return known_settable_ctx_params;
325
25
}
326
327
static int ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[])
328
0
{
329
0
    PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
330
0
    OSSL_PARAM *p;
331
332
0
    if (pectx == NULL)
333
0
        return 0;
334
335
0
    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
336
0
    if (p != NULL) {
337
0
        int mode = pectx->cofactor_mode;
338
339
0
        if (mode == -1) {
340
            /* check what is the default for pecdhctx->k */
341
0
            mode = EC_KEY_get_flags(pectx->k) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
342
0
        }
343
344
0
        if (!OSSL_PARAM_set_int(p, mode))
345
0
            return 0;
346
0
    }
347
348
0
    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
349
0
    if (p != NULL) {
350
0
        const char *kdf_type = NULL;
351
352
0
        switch (pectx->kdf_type) {
353
0
        case PROV_ECDH_KDF_NONE:
354
0
            kdf_type = "";
355
0
            break;
356
0
        case PROV_ECDH_KDF_X9_63:
357
0
            kdf_type = OSSL_KDF_NAME_X963KDF;
358
0
            break;
359
0
        default:
360
0
            return 0;
361
0
        }
362
363
0
        if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
364
0
            return 0;
365
0
    }
366
367
0
    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
368
0
    if (p != NULL
369
0
        && !OSSL_PARAM_set_utf8_string(p, pectx->kdf_md == NULL ? "" : EVP_MD_get0_name(pectx->kdf_md))) {
370
0
        return 0;
371
0
    }
372
373
0
    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
374
0
    if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_outlen))
375
0
        return 0;
376
377
0
    p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
378
0
    if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, pectx->kdf_ukmlen))
379
0
        return 0;
380
381
0
    return 1;
382
0
}
383
384
static const OSSL_PARAM known_gettable_ctx_params[] = {
385
    OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
386
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
387
    OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
388
    OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
389
    OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
390
        NULL, 0),
391
    OSSL_PARAM_END
392
};
393
394
static const OSSL_PARAM *ecdh_gettable_ctx_params(ossl_unused void *vpecdhctx,
395
    ossl_unused void *provctx)
396
0
{
397
0
    return known_gettable_ctx_params;
398
0
}
399
400
static ossl_inline
401
    size_t
402
    ecdh_size(const EC_KEY *k)
403
8.57k
{
404
8.57k
    size_t degree = 0;
405
8.57k
    const EC_GROUP *group;
406
407
8.57k
    if (k == NULL
408
8.57k
        || (group = EC_KEY_get0_group(k)) == NULL)
409
0
        return 0;
410
411
8.57k
    degree = EC_GROUP_get_degree(group);
412
413
8.57k
    return (degree + 7) / 8;
414
8.57k
}
415
416
static ossl_inline int ecdh_plain_derive(void *vpecdhctx, unsigned char *secret,
417
    size_t *psecretlen, size_t outlen)
418
2.53k
{
419
2.53k
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
420
2.53k
    int retlen, ret = 0;
421
2.53k
    size_t ecdhsize, size;
422
2.53k
    const EC_POINT *ppubkey = NULL;
423
2.53k
    EC_KEY *privk = NULL;
424
2.53k
    const EC_GROUP *group;
425
2.53k
    const BIGNUM *cofactor;
426
2.53k
    int key_cofactor_mode;
427
428
2.53k
    if (pecdhctx->k == NULL || pecdhctx->peerk == NULL) {
429
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
430
0
        return 0;
431
0
    }
432
433
2.53k
    ecdhsize = ecdh_size(pecdhctx->k);
434
2.53k
    if (secret == NULL) {
435
1.26k
        *psecretlen = ecdhsize;
436
1.26k
        return 1;
437
1.26k
    }
438
439
1.26k
    if ((group = EC_KEY_get0_group(pecdhctx->k)) == NULL
440
1.26k
        || (cofactor = EC_GROUP_get0_cofactor(group)) == NULL)
441
0
        return 0;
442
443
    /*
444
     * NB: unlike PKCS#3 DH, if outlen is less than maximum size this is not
445
     * an error, the result is truncated.
446
     */
447
1.26k
    size = outlen < ecdhsize ? outlen : ecdhsize;
448
449
    /*
450
     * The ctx->cofactor_mode flag has precedence over the
451
     * cofactor_mode flag set on ctx->k.
452
     *
453
     * - if ctx->cofactor_mode == -1, use ctx->k directly
454
     * - if ctx->cofactor_mode == key_cofactor_mode, use ctx->k directly
455
     * - if ctx->cofactor_mode != key_cofactor_mode:
456
     *     - if ctx->k->cofactor == 1, the cofactor_mode flag is irrelevant, use
457
     *          ctx->k directly
458
     *     - if ctx->k->cofactor != 1, use a duplicate of ctx->k with the flag
459
     *          set to ctx->cofactor_mode
460
     */
461
1.26k
    key_cofactor_mode = (EC_KEY_get_flags(pecdhctx->k) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
462
1.26k
    if (pecdhctx->cofactor_mode != -1
463
0
        && pecdhctx->cofactor_mode != key_cofactor_mode
464
0
        && !BN_is_one(cofactor)) {
465
0
        if ((privk = EC_KEY_dup(pecdhctx->k)) == NULL)
466
0
            return 0;
467
468
0
        if (pecdhctx->cofactor_mode == 1)
469
0
            EC_KEY_set_flags(privk, EC_FLAG_COFACTOR_ECDH);
470
0
        else
471
0
            EC_KEY_clear_flags(privk, EC_FLAG_COFACTOR_ECDH);
472
1.26k
    } else {
473
1.26k
        privk = pecdhctx->k;
474
1.26k
    }
475
476
1.26k
    ppubkey = EC_KEY_get0_public_key(pecdhctx->peerk);
477
478
1.26k
    retlen = ECDH_compute_key(secret, size, ppubkey, privk, NULL);
479
480
1.26k
    if (retlen <= 0)
481
0
        goto end;
482
483
1.26k
    *psecretlen = retlen;
484
1.26k
    ret = 1;
485
486
1.26k
end:
487
1.26k
    if (privk != pecdhctx->k)
488
0
        EC_KEY_free(privk);
489
1.26k
    return ret;
490
1.26k
}
491
492
static ossl_inline int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
493
    size_t *psecretlen, size_t outlen)
494
0
{
495
0
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
496
0
    unsigned char *stmp = NULL;
497
0
    size_t stmplen;
498
0
    int ret = 0;
499
500
0
    if (secret == NULL) {
501
0
        *psecretlen = pecdhctx->kdf_outlen;
502
0
        return 1;
503
0
    }
504
505
0
    if (pecdhctx->kdf_outlen > outlen) {
506
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
507
0
        return 0;
508
0
    }
509
0
    if (!ecdh_plain_derive(vpecdhctx, NULL, &stmplen, 0))
510
0
        return 0;
511
0
    if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
512
0
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
513
0
        return 0;
514
0
    }
515
0
    if (!ecdh_plain_derive(vpecdhctx, stmp, &stmplen, stmplen))
516
0
        goto err;
517
518
    /* Do KDF stuff */
519
0
    if (!ossl_ecdh_kdf_X9_63(secret, pecdhctx->kdf_outlen,
520
0
            stmp, stmplen,
521
0
            pecdhctx->kdf_ukm,
522
0
            pecdhctx->kdf_ukmlen,
523
0
            pecdhctx->kdf_md,
524
0
            pecdhctx->libctx, NULL))
525
0
        goto err;
526
0
    *psecretlen = pecdhctx->kdf_outlen;
527
0
    ret = 1;
528
529
0
err:
530
0
    OPENSSL_secure_clear_free(stmp, stmplen);
531
0
    return ret;
532
0
}
533
534
static int ecdh_derive(void *vpecdhctx, unsigned char *secret,
535
    size_t *psecretlen, size_t outlen)
536
8.57k
{
537
8.57k
    PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
538
539
8.57k
    switch (pecdhctx->kdf_type) {
540
8.57k
    case PROV_ECDH_KDF_NONE:
541
8.57k
        return ecdh_plain_derive(vpecdhctx, secret, psecretlen, outlen);
542
0
    case PROV_ECDH_KDF_X9_63:
543
0
        return ecdh_X9_63_kdf_derive(vpecdhctx, secret, psecretlen, outlen);
544
0
    default:
545
0
        break;
546
8.57k
    }
547
0
    return 0;
548
8.57k
}
549
550
const OSSL_DISPATCH ossl_ecdh_keyexch_functions[] = {
551
    { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ecdh_newctx },
552
    { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecdh_init },
553
    { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecdh_derive },
554
    { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecdh_set_peer },
555
    { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecdh_freectx },
556
    { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecdh_dupctx },
557
    { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ecdh_set_ctx_params },
558
    { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
559
        (void (*)(void))ecdh_settable_ctx_params },
560
    { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecdh_get_ctx_params },
561
    { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
562
        (void (*)(void))ecdh_gettable_ctx_params },
563
    { 0, NULL }
564
};