Coverage Report

Created: 2025-06-13 06:58

/src/openssl31/crypto/evp/dh_ctrl.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2020-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
#include "internal/deprecated.h"
11
12
#include <openssl/core_names.h>
13
#include <openssl/params.h>
14
#include <openssl/err.h>
15
#include <openssl/dh.h>
16
#include "crypto/dh.h"
17
#include "crypto/evp.h"
18
19
static int dh_paramgen_check(EVP_PKEY_CTX *ctx)
20
0
{
21
0
    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
22
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
23
        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
24
0
        return -2;
25
0
    }
26
    /* If key type not DH return error */
27
0
    if (evp_pkey_ctx_is_legacy(ctx)
28
0
        && ctx->pmeth->pkey_id != EVP_PKEY_DH
29
0
        && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
30
0
        return -1;
31
0
    return 1;
32
0
}
33
34
static int dh_param_derive_check(EVP_PKEY_CTX *ctx)
35
0
{
36
0
    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
37
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
38
        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
39
0
        return -2;
40
0
    }
41
    /* If key type not DH return error */
42
0
    if (evp_pkey_ctx_is_legacy(ctx)
43
0
        && ctx->pmeth->pkey_id != EVP_PKEY_DH
44
0
        && ctx->pmeth->pkey_id != EVP_PKEY_DHX)
45
0
        return -1;
46
0
    return 1;
47
0
}
48
49
int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
50
0
{
51
0
    int ret;
52
0
    OSSL_PARAM params[2], *p = params;
53
54
0
    if ((ret = dh_paramgen_check(ctx)) <= 0)
55
0
        return ret;
56
57
0
    *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
58
0
    *p = OSSL_PARAM_construct_end();
59
60
0
    return evp_pkey_ctx_set_params_strict(ctx, params);
61
0
}
62
63
int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
64
                                      const unsigned char *seed,
65
                                      size_t seedlen)
66
0
{
67
0
    int ret;
68
0
    OSSL_PARAM params[2], *p = params;
69
70
0
    if ((ret = dh_paramgen_check(ctx)) <= 0)
71
0
        return ret;
72
73
0
    *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
74
0
                                             (void *)seed, seedlen);
75
0
    *p = OSSL_PARAM_construct_end();
76
77
0
    return evp_pkey_ctx_set_params_strict(ctx, params);
78
0
}
79
80
/*
81
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
82
 * simply because that's easier.
83
 */
84
int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int typ)
85
0
{
86
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
87
0
                             EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL);
88
0
}
89
90
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits)
91
0
{
92
0
    int ret;
93
0
    OSSL_PARAM params[2], *p = params;
94
0
    size_t bits = pbits;
95
96
0
    if ((ret = dh_paramgen_check(ctx)) <= 0)
97
0
        return ret;
98
99
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
100
0
    *p = OSSL_PARAM_construct_end();
101
0
    return evp_pkey_ctx_set_params_strict(ctx, params);
102
0
}
103
104
int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int qbits)
105
0
{
106
0
    int ret;
107
0
    OSSL_PARAM params[2], *p = params;
108
0
    size_t bits2 = qbits;
109
110
0
    if ((ret = dh_paramgen_check(ctx)) <= 0)
111
0
        return ret;
112
113
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
114
0
    *p = OSSL_PARAM_construct_end();
115
116
0
    return evp_pkey_ctx_set_params_strict(ctx, params);
117
0
}
118
119
int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen)
120
0
{
121
0
    int ret;
122
0
    OSSL_PARAM params[2], *p = params;
123
124
0
    if ((ret = dh_paramgen_check(ctx)) <= 0)
125
0
        return ret;
126
127
0
    *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_DH_GENERATOR, &gen);
128
0
    *p = OSSL_PARAM_construct_end();
129
130
0
    return evp_pkey_ctx_set_params_strict(ctx, params);
131
0
}
132
133
/*
134
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
135
 * simply because that's easier.
136
 */
137
int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int gen)
138
0
{
139
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN,
140
0
                             EVP_PKEY_CTRL_DH_RFC5114, gen, NULL);
141
0
}
142
143
int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int gen)
144
0
{
145
0
    return EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen);
146
0
}
147
148
/*
149
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
150
 * simply because that's easier.
151
 */
152
int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid)
153
0
{
154
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH,
155
0
                             EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
156
0
                             EVP_PKEY_CTRL_DH_NID, nid, NULL);
157
0
}
158
159
int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
160
{
161
    OSSL_PARAM dh_pad_params[2];
162
    unsigned int upad = pad;
163
164
    /* We use EVP_PKEY_CTX_ctrl return values */
165
    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
166
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
167
        return -2;
168
    }
169
170
    dh_pad_params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &upad);
171
    dh_pad_params[1] = OSSL_PARAM_construct_end();
172
173
    return evp_pkey_ctx_set_params_strict(ctx, dh_pad_params);
174
}
175
176
/*
177
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
178
 * simply because that's easier.
179
 */
180
int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
181
0
{
182
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
183
0
                             EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL);
184
0
}
185
186
/*
187
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
188
 * simply because that's easier.
189
 */
190
int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx)
191
0
{
192
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
193
0
                             EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL);
194
0
}
195
196
/*
197
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
198
 * simply because that's easier.
199
 */
200
int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid)
201
0
{
202
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
203
0
                             EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid));
204
0
}
205
206
/*
207
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
208
 * simply because that's easier.
209
 */
210
int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid)
211
0
{
212
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
213
0
                             EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(oid));
214
0
}
215
216
/*
217
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
218
 * simply because that's easier.
219
 */
220
int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
221
0
{
222
0
    return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
223
0
                             EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md));
224
0
}
225
226
/*
227
 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
228
 * simply because that's easier.
229
 */
230
int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
231
0
{
232
0
        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
233
0
                                 EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd));
234
0
}
235
236
int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
237
0
{
238
0
    int ret;
239
0
    size_t len = outlen;
240
0
    OSSL_PARAM params[2], *p = params;
241
242
0
    ret = dh_param_derive_check(ctx);
243
0
    if (ret != 1)
244
0
        return ret;
245
246
0
    if (outlen <= 0) {
247
        /*
248
         * This would ideally be -1 or 0, but we have to retain compatibility
249
         * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
250
         * inlen <= 0
251
         */
252
0
        return -2;
253
0
    }
254
255
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
256
0
                                       &len);
257
0
    *p = OSSL_PARAM_construct_end();
258
259
0
    ret = evp_pkey_ctx_set_params_strict(ctx, params);
260
0
    if (ret == -2)
261
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
262
0
    return ret;
263
0
}
264
265
int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
266
0
{
267
0
    int ret;
268
0
    size_t len = UINT_MAX;
269
0
    OSSL_PARAM params[2], *p = params;
270
271
0
    ret = dh_param_derive_check(ctx);
272
0
    if (ret != 1)
273
0
        return ret;
274
275
0
    *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
276
0
                                       &len);
277
0
    *p = OSSL_PARAM_construct_end();
278
279
0
    ret = evp_pkey_ctx_get_params_strict(ctx, params);
280
0
    if (ret == -2)
281
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
282
0
    if (ret != 1 || len > INT_MAX)
283
0
        return -1;
284
285
0
    *plen = (int)len;
286
287
0
    return 1;
288
0
}
289
290
int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
291
0
{
292
0
    int ret;
293
0
    OSSL_PARAM params[2], *p = params;
294
295
0
    if (len < 0)
296
0
        return -1;
297
298
0
    ret = dh_param_derive_check(ctx);
299
0
    if (ret != 1)
300
0
        return ret;
301
302
0
    *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
303
                                            /*
304
                                             * Cast away the const. This is read
305
                                             * only so should be safe
306
                                             */
307
0
                                            (void *)ukm,
308
0
                                            (size_t)len);
309
0
    *p = OSSL_PARAM_construct_end();
310
311
0
    ret = evp_pkey_ctx_set_params_strict(ctx, params);
312
0
    if (ret == -2)
313
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
314
0
    if (ret == 1)
315
0
        OPENSSL_free(ukm);
316
0
    return ret;
317
0
}
318
319
#ifndef OPENSSL_NO_DEPRECATED_3_0
320
int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
321
0
{
322
0
    int ret;
323
0
    size_t ukmlen;
324
0
    OSSL_PARAM params[2], *p = params;
325
326
0
    ret = dh_param_derive_check(ctx);
327
0
    if (ret != 1)
328
0
        return ret;
329
330
0
    *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
331
0
                                          (void **)pukm, 0);
332
0
    *p = OSSL_PARAM_construct_end();
333
334
0
    ret = evp_pkey_ctx_get_params_strict(ctx, params);
335
0
    if (ret == -2)
336
0
        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
337
0
    if (ret != 1)
338
0
        return -1;
339
340
0
    ukmlen = params[0].return_size;
341
0
    if (ukmlen > INT_MAX)
342
0
        return -1;
343
344
0
    return (int)ukmlen;
345
0
}
346
#endif