Coverage Report

Created: 2025-06-13 06:58

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