Coverage Report

Created: 2025-06-22 06:56

/src/openssl/crypto/dh/dh_pmeth.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2006-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
 * 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
84
static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
85
0
{
86
0
    DH_PKEY_CTX *dctx, *sctx;
87
88
0
    if (!pkey_dh_init(dst))
89
0
        return 0;
90
0
    sctx = src->data;
91
0
    dctx = dst->data;
92
0
    dctx->prime_len = sctx->prime_len;
93
0
    dctx->subprime_len = sctx->subprime_len;
94
0
    dctx->generator = sctx->generator;
95
0
    dctx->paramgen_type = sctx->paramgen_type;
96
0
    dctx->pad = sctx->pad;
97
0
    dctx->md = sctx->md;
98
0
    dctx->param_nid = sctx->param_nid;
99
100
0
    dctx->kdf_type = sctx->kdf_type;
101
0
    dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
102
0
    if (dctx->kdf_oid == NULL)
103
0
        return 0;
104
0
    dctx->kdf_md = sctx->kdf_md;
105
0
    if (sctx->kdf_ukm != NULL) {
106
0
        dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
107
0
        if (dctx->kdf_ukm == NULL)
108
0
          return 0;
109
0
        dctx->kdf_ukmlen = sctx->kdf_ukmlen;
110
0
    }
111
0
    dctx->kdf_outlen = sctx->kdf_outlen;
112
0
    return 1;
113
0
}
114
115
static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
116
0
{
117
0
    DH_PKEY_CTX *dctx = ctx->data;
118
0
    switch (type) {
119
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
120
0
        if (p1 < 256)
121
0
            return -2;
122
0
        dctx->prime_len = p1;
123
0
        return 1;
124
125
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
126
0
        if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
127
0
            return -2;
128
0
        dctx->subprime_len = p1;
129
0
        return 1;
130
131
0
    case EVP_PKEY_CTRL_DH_PAD:
132
0
        dctx->pad = p1;
133
0
        return 1;
134
135
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
136
0
        if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
137
0
            return -2;
138
0
        dctx->generator = p1;
139
0
        return 1;
140
141
0
    case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
142
#ifdef OPENSSL_NO_DSA
143
        if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
144
            return -2;
145
#else
146
0
        if (p1 < 0 || p1 > 2)
147
0
            return -2;
148
0
#endif
149
0
        dctx->paramgen_type = p1;
150
0
        return 1;
151
152
0
    case EVP_PKEY_CTRL_DH_RFC5114:
153
0
        if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
154
0
            return -2;
155
0
        dctx->param_nid = p1;
156
0
        return 1;
157
158
0
    case EVP_PKEY_CTRL_DH_NID:
159
0
        if (p1 <= 0 || dctx->param_nid != NID_undef)
160
0
            return -2;
161
0
        dctx->param_nid = p1;
162
0
        return 1;
163
164
0
    case EVP_PKEY_CTRL_PEER_KEY:
165
        /* Default behaviour is OK */
166
0
        return 1;
167
168
0
    case EVP_PKEY_CTRL_DH_KDF_TYPE:
169
0
        if (p1 == -2)
170
0
            return dctx->kdf_type;
171
0
        if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
172
0
            return -2;
173
0
        dctx->kdf_type = p1;
174
0
        return 1;
175
176
0
    case EVP_PKEY_CTRL_DH_KDF_MD:
177
0
        dctx->kdf_md = p2;
178
0
        return 1;
179
180
0
    case EVP_PKEY_CTRL_GET_DH_KDF_MD:
181
0
        *(const EVP_MD **)p2 = dctx->kdf_md;
182
0
        return 1;
183
184
0
    case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
185
0
        if (p1 <= 0)
186
0
            return -2;
187
0
        dctx->kdf_outlen = (size_t)p1;
188
0
        return 1;
189
190
0
    case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
191
0
        *(int *)p2 = dctx->kdf_outlen;
192
0
        return 1;
193
194
0
    case EVP_PKEY_CTRL_DH_KDF_UKM:
195
0
        OPENSSL_free(dctx->kdf_ukm);
196
0
        dctx->kdf_ukm = p2;
197
0
        if (p2)
198
0
            dctx->kdf_ukmlen = p1;
199
0
        else
200
0
            dctx->kdf_ukmlen = 0;
201
0
        return 1;
202
203
0
    case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
204
0
        *(unsigned char **)p2 = dctx->kdf_ukm;
205
0
        return dctx->kdf_ukmlen;
206
207
0
    case EVP_PKEY_CTRL_DH_KDF_OID:
208
0
        ASN1_OBJECT_free(dctx->kdf_oid);
209
0
        dctx->kdf_oid = p2;
210
0
        return 1;
211
212
0
    case EVP_PKEY_CTRL_GET_DH_KDF_OID:
213
0
        *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
214
0
        return 1;
215
216
0
    default:
217
0
        return -2;
218
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) {
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
    }
430
0
    else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
431
432
0
        unsigned char *Z = NULL;
433
0
        int Zlen = 0;
434
435
0
        if (!dctx->kdf_outlen || !dctx->kdf_oid)
436
0
            return 0;
437
0
        if (key == NULL) {
438
0
            *keylen = dctx->kdf_outlen;
439
0
            return 1;
440
0
        }
441
0
        if (*keylen != dctx->kdf_outlen)
442
0
            return 0;
443
0
        ret = 0;
444
0
        if ((Zlen = DH_size(dh)) <= 0)
445
0
            return 0;
446
0
        if ((Z = OPENSSL_malloc(Zlen)) == NULL)
447
0
            return 0;
448
0
        if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
449
0
            goto err;
450
0
        if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
451
0
                          dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
452
0
            goto err;
453
0
        *keylen = dctx->kdf_outlen;
454
0
        ret = 1;
455
0
 err:
456
0
        OPENSSL_clear_free(Z, Zlen);
457
0
        return ret;
458
0
    }
459
0
    return 0;
460
0
}
461
462
static const EVP_PKEY_METHOD dh_pkey_meth = {
463
    EVP_PKEY_DH,
464
    0,
465
    pkey_dh_init,
466
    pkey_dh_copy,
467
    pkey_dh_cleanup,
468
469
    0,
470
    pkey_dh_paramgen,
471
472
    0,
473
    pkey_dh_keygen,
474
475
    0,
476
    0,
477
478
    0,
479
    0,
480
481
    0, 0,
482
483
    0, 0, 0, 0,
484
485
    0, 0,
486
487
    0, 0,
488
489
    0,
490
    pkey_dh_derive,
491
492
    pkey_dh_ctrl,
493
    pkey_dh_ctrl_str
494
};
495
496
const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
497
0
{
498
0
    return &dh_pkey_meth;
499
0
}
500
501
static const EVP_PKEY_METHOD dhx_pkey_meth = {
502
    EVP_PKEY_DHX,
503
    0,
504
    pkey_dh_init,
505
    pkey_dh_copy,
506
    pkey_dh_cleanup,
507
508
    0,
509
    pkey_dh_paramgen,
510
511
    0,
512
    pkey_dh_keygen,
513
514
    0,
515
    0,
516
517
    0,
518
    0,
519
520
    0, 0,
521
522
    0, 0, 0, 0,
523
524
    0, 0,
525
526
    0, 0,
527
528
    0,
529
    pkey_dh_derive,
530
531
    pkey_dh_ctrl,
532
    pkey_dh_ctrl_str
533
};
534
535
const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
536
0
{
537
0
    return &dhx_pkey_meth;
538
0
}