xref: /openssl/crypto/evp/dh_ctrl.c (revision 87e4e9c4)
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