/src/openssl30/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 |