Coverage Report

Created: 2025-06-13 06:58

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