Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/dh/dh_pmeth.c
Line
Count
Source
1
/*
2
 * Copyright 2006-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
10
/*
11
 * DH & DSA low level APIs are deprecated for public use, but still ok for
12
 * internal use.
13
 */
14
#include "internal/deprecated.h"
15
16
#include <stdio.h>
17
#include "internal/cryptlib.h"
18
#include <openssl/asn1t.h>
19
#include <openssl/x509.h>
20
#include <openssl/evp.h>
21
#include "dh_local.h"
22
#include <openssl/bn.h>
23
#include <openssl/dsa.h>
24
#include <openssl/objects.h>
25
#include "crypto/evp.h"
26
27
/* DH pkey context structure */
28
29
typedef struct {
30
    /* Parameter gen parameters */
31
    int prime_len;
32
    int generator;
33
    int paramgen_type;
34
    int subprime_len;
35
    int pad;
36
    /* message digest used for parameter generation */
37
    const EVP_MD *md;
38
    int param_nid;
39
    /* Keygen callback info */
40
    int gentmp[2];
41
    /* KDF (if any) to use for DH */
42
    char kdf_type;
43
    /* OID to use for KDF */
44
    ASN1_OBJECT *kdf_oid;
45
    /* Message digest to use for key derivation */
46
    const EVP_MD *kdf_md;
47
    /* User key material */
48
    unsigned char *kdf_ukm;
49
    size_t kdf_ukmlen;
50
    /* KDF output length */
51
    size_t kdf_outlen;
52
} DH_PKEY_CTX;
53
54
static int pkey_dh_init(EVP_PKEY_CTX *ctx)
55
0
{
56
0
    DH_PKEY_CTX *dctx;
57
58
0
    if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL)
59
0
        return 0;
60
0
    dctx->prime_len = 2048;
61
0
    dctx->subprime_len = -1;
62
0
    dctx->generator = 2;
63
0
    dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
64
65
0
    ctx->data = dctx;
66
0
    ctx->keygen_info = dctx->gentmp;
67
0
    ctx->keygen_info_count = 2;
68
69
0
    return 1;
70
0
}
71
72
static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
73
0
{
74
0
    DH_PKEY_CTX *dctx = ctx->data;
75
76
0
    if (dctx != NULL) {
77
0
        OPENSSL_free(dctx->kdf_ukm);
78
0
        ASN1_OBJECT_free(dctx->kdf_oid);
79
0
        OPENSSL_free(dctx);
80
0
    }
81
0
}
82
83
static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
84
0
{
85
0
    DH_PKEY_CTX *dctx, *sctx;
86
87
0
    if (!pkey_dh_init(dst))
88
0
        return 0;
89
0
    sctx = src->data;
90
0
    dctx = dst->data;
91
0
    dctx->prime_len = sctx->prime_len;
92
0
    dctx->subprime_len = sctx->subprime_len;
93
0
    dctx->generator = sctx->generator;
94
0
    dctx->paramgen_type = sctx->paramgen_type;
95
0
    dctx->pad = sctx->pad;
96
0
    dctx->md = sctx->md;
97
0
    dctx->param_nid = sctx->param_nid;
98
99
0
    dctx->kdf_type = sctx->kdf_type;
100
0
    dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
101
0
    if (dctx->kdf_oid == NULL)
102
0
        return 0;
103
0
    dctx->kdf_md = sctx->kdf_md;
104
0
    if (sctx->kdf_ukm != NULL) {
105
0
        dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
106
0
        if (dctx->kdf_ukm == NULL)
107
0
            return 0;
108
0
        dctx->kdf_ukmlen = sctx->kdf_ukmlen;
109
0
    }
110
0
    dctx->kdf_outlen = sctx->kdf_outlen;
111
0
    return 1;
112
0
}
113
114
static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
115
0
{
116
0
    DH_PKEY_CTX *dctx = ctx->data;
117
0
    switch (type) {
118
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
119
0
        if (p1 < 256)
120
0
            return -2;
121
0
        dctx->prime_len = p1;
122
0
        return 1;
123
124
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
125
0
        if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
126
0
            return -2;
127
0
        dctx->subprime_len = p1;
128
0
        return 1;
129
130
0
    case EVP_PKEY_CTRL_DH_PAD:
131
0
        dctx->pad = p1;
132
0
        return 1;
133
134
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
135
0
        if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
136
0
            return -2;
137
0
        dctx->generator = p1;
138
0
        return 1;
139
140
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
141
#ifdef OPENSSL_NO_DSA
142
        if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
143
            return -2;
144
#else
145
0
        if (p1 < 0 || p1 > 2)
146
0
            return -2;
147
0
#endif
148
0
        dctx->paramgen_type = p1;
149
0
        return 1;
150
151
0
    case EVP_PKEY_CTRL_DH_RFC5114:
152
0
        if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
153
0
            return -2;
154
0
        dctx->param_nid = p1;
155
0
        return 1;
156
157
0
    case EVP_PKEY_CTRL_DH_NID:
158
0
        if (p1 <= 0 || dctx->param_nid != NID_undef)
159
0
            return -2;
160
0
        dctx->param_nid = p1;
161
0
        return 1;
162
163
0
    case EVP_PKEY_CTRL_PEER_KEY:
164
        /* Default behaviour is OK */
165
0
        return 1;
166
167
0
    case EVP_PKEY_CTRL_DH_KDF_TYPE:
168
0
        if (p1 == -2)
169
0
            return dctx->kdf_type;
170
0
        if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
171
0
            return -2;
172
0
        dctx->kdf_type = p1;
173
0
        return 1;
174
175
0
    case EVP_PKEY_CTRL_DH_KDF_MD:
176
0
        dctx->kdf_md = p2;
177
0
        return 1;
178
179
0
    case EVP_PKEY_CTRL_GET_DH_KDF_MD:
180
0
        *(const EVP_MD **)p2 = dctx->kdf_md;
181
0
        return 1;
182
183
0
    case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
184
0
        if (p1 <= 0)
185
0
            return -2;
186
0
        dctx->kdf_outlen = (size_t)p1;
187
0
        return 1;
188
189
0
    case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
190
0
        *(int *)p2 = (int)dctx->kdf_outlen;
191
0
        return 1;
192
193
0
    case EVP_PKEY_CTRL_DH_KDF_UKM:
194
0
        OPENSSL_free(dctx->kdf_ukm);
195
0
        dctx->kdf_ukm = p2;
196
0
        if (p2)
197
0
            dctx->kdf_ukmlen = p1;
198
0
        else
199
0
            dctx->kdf_ukmlen = 0;
200
0
        return 1;
201
202
0
    case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
203
0
        *(unsigned char **)p2 = dctx->kdf_ukm;
204
0
        return (int)dctx->kdf_ukmlen;
205
206
0
    case EVP_PKEY_CTRL_DH_KDF_OID:
207
0
        ASN1_OBJECT_free(dctx->kdf_oid);
208
0
        dctx->kdf_oid = p2;
209
0
        return 1;
210
211
0
    case EVP_PKEY_CTRL_GET_DH_KDF_OID:
212
0
        *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
213
0
        return 1;
214
215
0
    default:
216
0
        return -2;
217
0
    }
218
0
}
219
220
static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
221
    const char *type, const char *value)
222
0
{
223
0
    if (strcmp(type, "dh_paramgen_prime_len") == 0) {
224
0
        int len;
225
0
        len = atoi(value);
226
0
        return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
227
0
    }
228
0
    if (strcmp(type, "dh_rfc5114") == 0) {
229
0
        DH_PKEY_CTX *dctx = ctx->data;
230
0
        int id;
231
232
0
        id = atoi(value);
233
0
        if (id < 0 || id > 3)
234
0
            return -2;
235
0
        dctx->param_nid = id;
236
0
        return 1;
237
0
    }
238
0
    if (strcmp(type, "dh_param") == 0) {
239
0
        DH_PKEY_CTX *dctx = ctx->data;
240
0
        int nid = OBJ_sn2nid(value);
241
242
0
        if (nid == NID_undef) {
243
0
            ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
244
0
            return -2;
245
0
        }
246
0
        dctx->param_nid = nid;
247
0
        return 1;
248
0
    }
249
0
    if (strcmp(type, "dh_paramgen_generator") == 0) {
250
0
        int len;
251
0
        len = atoi(value);
252
0
        return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
253
0
    }
254
0
    if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
255
0
        int len;
256
0
        len = atoi(value);
257
0
        return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
258
0
    }
259
0
    if (strcmp(type, "dh_paramgen_type") == 0) {
260
0
        int typ;
261
0
        typ = atoi(value);
262
0
        return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
263
0
    }
264
0
    if (strcmp(type, "dh_pad") == 0) {
265
0
        int pad;
266
0
        pad = atoi(value);
267
0
        return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
268
0
    }
269
0
    return -2;
270
0
}
271
272
static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
273
    BN_GENCB *pcb)
274
0
{
275
0
    DH *ret;
276
0
    int rv = 0;
277
0
    int res;
278
0
    int prime_len = dctx->prime_len;
279
0
    int subprime_len = dctx->subprime_len;
280
281
0
    if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
282
0
        return NULL;
283
0
    ret = DH_new();
284
0
    if (ret == NULL)
285
0
        return NULL;
286
287
0
    if (subprime_len == -1) {
288
0
        if (prime_len >= 2048)
289
0
            subprime_len = 256;
290
0
        else
291
0
            subprime_len = 160;
292
0
    }
293
294
0
    if (dctx->md != NULL)
295
0
        ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
296
297
0
#ifndef FIPS_MODULE
298
0
    if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
299
0
        rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
300
0
            FFC_PARAM_TYPE_DH,
301
0
            prime_len, subprime_len, &res,
302
0
            pcb);
303
0
    else
304
0
#endif
305
        /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
306
0
        if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
307
0
            rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
308
0
                FFC_PARAM_TYPE_DH,
309
0
                prime_len, subprime_len, &res,
310
0
                pcb);
311
0
    if (rv <= 0) {
312
0
        DH_free(ret);
313
0
        return NULL;
314
0
    }
315
0
    return ret;
316
0
}
317
318
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
319
    EVP_PKEY *pkey)
320
0
{
321
0
    DH *dh = NULL;
322
0
    DH_PKEY_CTX *dctx = ctx->data;
323
0
    BN_GENCB *pcb = NULL;
324
0
    int ret;
325
326
    /*
327
     * Look for a safe prime group for key establishment. Which uses
328
     * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
329
     * RFC_5114 is also handled here for param_nid = (1..3)
330
     */
331
0
    if (dctx->param_nid != NID_undef) {
332
0
        int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
333
334
0
        if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
335
0
            return 0;
336
0
        EVP_PKEY_assign(pkey, type, dh);
337
0
        return 1;
338
0
    }
339
340
0
    if (ctx->pkey_gencb != NULL) {
341
0
        pcb = BN_GENCB_new();
342
0
        if (pcb == NULL)
343
0
            return 0;
344
0
        evp_pkey_set_cb_translate(pcb, ctx);
345
0
    }
346
#ifdef FIPS_MODULE
347
    dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
348
#endif /* FIPS_MODULE */
349
0
    if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
350
0
        dh = ffc_params_generate(NULL, dctx, pcb);
351
0
        BN_GENCB_free(pcb);
352
0
        if (dh == NULL)
353
0
            return 0;
354
0
        EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
355
0
        return 1;
356
0
    }
357
0
    dh = DH_new();
358
0
    if (dh == NULL) {
359
0
        BN_GENCB_free(pcb);
360
0
        return 0;
361
0
    }
362
0
    ret = DH_generate_parameters_ex(dh,
363
0
        dctx->prime_len, dctx->generator, pcb);
364
0
    BN_GENCB_free(pcb);
365
0
    if (ret)
366
0
        EVP_PKEY_assign_DH(pkey, dh);
367
0
    else
368
0
        DH_free(dh);
369
0
    return ret;
370
0
}
371
372
static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
373
0
{
374
0
    DH_PKEY_CTX *dctx = ctx->data;
375
0
    DH *dh = NULL;
376
377
0
    if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
378
0
        ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET);
379
0
        return 0;
380
0
    }
381
0
    if (dctx->param_nid != NID_undef)
382
0
        dh = DH_new_by_nid(dctx->param_nid);
383
0
    else
384
0
        dh = DH_new();
385
0
    if (dh == NULL)
386
0
        return 0;
387
0
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
388
    /* Note: if error return, pkey is freed by parent routine */
389
0
    if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
390
0
        return 0;
391
0
    return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
392
0
}
393
394
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
395
    size_t *keylen)
396
0
{
397
0
    int ret;
398
0
    DH *dh;
399
0
    const DH *dhpub;
400
0
    DH_PKEY_CTX *dctx = ctx->data;
401
0
    BIGNUM *dhpubbn;
402
403
0
    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
404
0
        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
405
0
        return 0;
406
0
    }
407
0
    dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
408
0
    dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
409
0
    if (dhpub == NULL || dh == NULL) {
410
0
        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
411
0
        return 0;
412
0
    }
413
0
    dhpubbn = dhpub->pub_key;
414
0
    if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
415
0
        if (key == NULL) {
416
0
            *keylen = DH_size(dh);
417
0
            return 1;
418
0
        }
419
0
        if (dctx->pad)
420
0
            ret = DH_compute_key_padded(key, dhpubbn, dh);
421
0
        else
422
0
            ret = DH_compute_key(key, dhpubbn, dh);
423
0
        if (ret <= 0)
424
0
            return ret;
425
0
        *keylen = ret;
426
0
        return 1;
427
0
    } else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
428
429
0
        unsigned char *Z = NULL;
430
0
        int Zlen = 0;
431
432
0
        if (!dctx->kdf_outlen || !dctx->kdf_oid)
433
0
            return 0;
434
0
        if (key == NULL) {
435
0
            *keylen = dctx->kdf_outlen;
436
0
            return 1;
437
0
        }
438
0
        if (*keylen != dctx->kdf_outlen)
439
0
            return 0;
440
0
        ret = 0;
441
0
        if ((Zlen = DH_size(dh)) <= 0)
442
0
            return 0;
443
0
        if ((Z = OPENSSL_malloc(Zlen)) == NULL)
444
0
            return 0;
445
0
        if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
446
0
            goto err;
447
0
        if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
448
0
                dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
449
0
            goto err;
450
0
        *keylen = dctx->kdf_outlen;
451
0
        ret = 1;
452
0
    err:
453
0
        OPENSSL_clear_free(Z, Zlen);
454
0
        return ret;
455
0
    }
456
0
    return 0;
457
0
}
458
459
static const EVP_PKEY_METHOD dh_pkey_meth = {
460
    EVP_PKEY_DH,
461
    0,
462
    pkey_dh_init,
463
    pkey_dh_copy,
464
    pkey_dh_cleanup,
465
466
    0,
467
    pkey_dh_paramgen,
468
469
    0,
470
    pkey_dh_keygen,
471
472
    0,
473
    0,
474
475
    0,
476
    0,
477
478
    0, 0,
479
480
    0, 0, 0, 0,
481
482
    0, 0,
483
484
    0, 0,
485
486
    0,
487
    pkey_dh_derive,
488
489
    pkey_dh_ctrl,
490
    pkey_dh_ctrl_str
491
};
492
493
const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
494
0
{
495
0
    return &dh_pkey_meth;
496
0
}
497
498
static const EVP_PKEY_METHOD dhx_pkey_meth = {
499
    EVP_PKEY_DHX,
500
    0,
501
    pkey_dh_init,
502
    pkey_dh_copy,
503
    pkey_dh_cleanup,
504
505
    0,
506
    pkey_dh_paramgen,
507
508
    0,
509
    pkey_dh_keygen,
510
511
    0,
512
    0,
513
514
    0,
515
    0,
516
517
    0, 0,
518
519
    0, 0, 0, 0,
520
521
    0, 0,
522
523
    0, 0,
524
525
    0,
526
    pkey_dh_derive,
527
528
    pkey_dh_ctrl,
529
    pkey_dh_ctrl_str
530
};
531
532
const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
533
0
{
534
0
    return &dhx_pkey_meth;
535
0
}