Coverage Report

Created: 2023-09-25 06:45

/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
1.83k
{
56
1.83k
    DH_PKEY_CTX *dctx;
57
58
1.83k
    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
1.83k
    dctx->prime_len = 2048;
63
1.83k
    dctx->subprime_len = -1;
64
1.83k
    dctx->generator = 2;
65
1.83k
    dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
66
67
1.83k
    ctx->data = dctx;
68
1.83k
    ctx->keygen_info = dctx->gentmp;
69
1.83k
    ctx->keygen_info_count = 2;
70
71
1.83k
    return 1;
72
1.83k
}
73
74
static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
75
1.83k
{
76
1.83k
    DH_PKEY_CTX *dctx = ctx->data;
77
78
1.83k
    if (dctx != NULL) {
79
1.83k
        OPENSSL_free(dctx->kdf_ukm);
80
1.83k
        ASN1_OBJECT_free(dctx->kdf_oid);
81
1.83k
        OPENSSL_free(dctx);
82
1.83k
    }
83
1.83k
}
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
{
119
    DH_PKEY_CTX *dctx = ctx->data;
120
    switch (type) {
121
    case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
122
        if (p1 < 256)
123
            return -2;
124
        dctx->prime_len = p1;
125
        return 1;
126
127
    case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
128
        if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
129
            return -2;
130
        dctx->subprime_len = p1;
131
        return 1;
132
133
    case EVP_PKEY_CTRL_DH_PAD:
134
        dctx->pad = p1;
135
        return 1;
136
137
    case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
138
        if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
139
            return -2;
140
        dctx->generator = p1;
141
        return 1;
142
143
    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
        if (p1 < 0 || p1 > 2)
149
            return -2;
150
#endif
151
        dctx->paramgen_type = p1;
152
        return 1;
153
154
    case EVP_PKEY_CTRL_DH_RFC5114:
155
        if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
156
            return -2;
157
        dctx->param_nid = p1;
158
        return 1;
159
160
    case EVP_PKEY_CTRL_DH_NID:
161
        if (p1 <= 0 || dctx->param_nid != NID_undef)
162
            return -2;
163
        dctx->param_nid = p1;
164
        return 1;
165
166
    case EVP_PKEY_CTRL_PEER_KEY:
167
        /* Default behaviour is OK */
168
        return 1;
169
170
    case EVP_PKEY_CTRL_DH_KDF_TYPE:
171
        if (p1 == -2)
172
            return dctx->kdf_type;
173
        if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
174
            return -2;
175
        dctx->kdf_type = p1;
176
        return 1;
177
178
    case EVP_PKEY_CTRL_DH_KDF_MD:
179
        dctx->kdf_md = p2;
180
        return 1;
181
182
    case EVP_PKEY_CTRL_GET_DH_KDF_MD:
183
        *(const EVP_MD **)p2 = dctx->kdf_md;
184
        return 1;
185
186
    case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
187
        if (p1 <= 0)
188
            return -2;
189
        dctx->kdf_outlen = (size_t)p1;
190
        return 1;
191
192
    case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
193
        *(int *)p2 = dctx->kdf_outlen;
194
        return 1;
195
196
    case EVP_PKEY_CTRL_DH_KDF_UKM:
197
        OPENSSL_free(dctx->kdf_ukm);
198
        dctx->kdf_ukm = p2;
199
        if (p2)
200
            dctx->kdf_ukmlen = p1;
201
        else
202
            dctx->kdf_ukmlen = 0;
203
        return 1;
204
205
    case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
206
        *(unsigned char **)p2 = dctx->kdf_ukm;
207
        return dctx->kdf_ukmlen;
208
209
    case EVP_PKEY_CTRL_DH_KDF_OID:
210
        ASN1_OBJECT_free(dctx->kdf_oid);
211
        dctx->kdf_oid = p2;
212
        return 1;
213
214
    case EVP_PKEY_CTRL_GET_DH_KDF_OID:
215
        *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
216
        return 1;
217
218
    default:
219
        return -2;
220
221
    }
222
}
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
918
{
378
918
    DH_PKEY_CTX *dctx = ctx->data;
379
918
    DH *dh = NULL;
380
381
918
    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
918
    if (dctx->param_nid != NID_undef)
386
0
        dh = DH_new_by_nid(dctx->param_nid);
387
918
    else
388
918
        dh = DH_new();
389
918
    if (dh == NULL)
390
0
        return 0;
391
918
    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
392
    /* Note: if error return, pkey is freed by parent routine */
393
918
    if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
394
0
        return 0;
395
918
    return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
396
918
}
397
398
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
399
                          size_t *keylen)
400
{
401
    int ret;
402
    DH *dh;
403
    const DH *dhpub;
404
    DH_PKEY_CTX *dctx = ctx->data;
405
    BIGNUM *dhpubbn;
406
407
    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
408
        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
409
        return 0;
410
    }
411
    dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
412
    dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
413
    if (dhpub == NULL) {
414
        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
415
        return 0;
416
    }
417
    dhpubbn = dhpub->pub_key;
418
    if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
419
        if (key == NULL) {
420
            *keylen = DH_size(dh);
421
            return 1;
422
        }
423
        if (dctx->pad)
424
            ret = DH_compute_key_padded(key, dhpubbn, dh);
425
        else
426
            ret = DH_compute_key(key, dhpubbn, dh);
427
        if (ret < 0)
428
            return ret;
429
        *keylen = ret;
430
        return 1;
431
    }
432
    else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
433
434
        unsigned char *Z = NULL;
435
        int Zlen = 0;
436
437
        if (!dctx->kdf_outlen || !dctx->kdf_oid)
438
            return 0;
439
        if (key == NULL) {
440
            *keylen = dctx->kdf_outlen;
441
            return 1;
442
        }
443
        if (*keylen != dctx->kdf_outlen)
444
            return 0;
445
        ret = 0;
446
        if ((Zlen = DH_size(dh)) <= 0)
447
            return 0;
448
        if ((Z = OPENSSL_malloc(Zlen)) == NULL) {
449
            ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
450
            return 0;
451
        }
452
        if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
453
            goto err;
454
        if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
455
                          dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
456
            goto err;
457
        *keylen = dctx->kdf_outlen;
458
        ret = 1;
459
 err:
460
        OPENSSL_clear_free(Z, Zlen);
461
        return ret;
462
    }
463
    return 0;
464
}
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
}