Coverage Report

Created: 2025-12-31 06:58

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