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