ssl/statem: Replace size_t with int and add the checks
[openssl.git] / crypto / evp / dh_ctrl.c
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 {
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
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
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
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  */
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
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
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
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  */
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
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  * TODO(3.0) Should this be deprecated in favor of passing a name or an
152  * ASN1_OBJECT (which can be converted to text internally)?
153  */
154 int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid)
155 {
156     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH,
157                              EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
158                              EVP_PKEY_CTRL_DH_NID, nid, NULL);
159 }
160
161 int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
162 {
163     OSSL_PARAM dh_pad_params[2];
164     unsigned int upad = pad;
165
166     /* We use EVP_PKEY_CTX_ctrl return values */
167     if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
168         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
169         return -2;
170     }
171
172     dh_pad_params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &upad);
173     dh_pad_params[1] = OSSL_PARAM_construct_end();
174
175     return evp_pkey_ctx_set_params_strict(ctx, dh_pad_params);
176 }
177
178 /*
179  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
180  * simply because that's easier.
181  * TODO(3.0) Should this be deprecated in favor of passing a name?
182  */
183 int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
184 {
185     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
186                              EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL);
187 }
188
189 /*
190  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
191  * simply because that's easier.
192  * TODO(3.0) Should this be deprecated in favor of getting a name?
193  */
194 int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx)
195 {
196     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
197                              EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL);
198 }
199
200 /*
201  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
202  * simply because that's easier.
203  */
204 int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid)
205 {
206     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
207                              EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid));
208 }
209
210 /*
211  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
212  * simply because that's easier.
213  */
214 int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid)
215 {
216     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
217                              EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(oid));
218 }
219
220 /*
221  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
222  * simply because that's easier.
223  * TODO(3.0) Should this be deprecated in favor of passing a name?
224  */
225 int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
226 {
227     return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
228                              EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md));
229 }
230
231 /*
232  * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
233  * simply because that's easier.
234  * TODO(3.0) Should this be deprecated in favor of getting a name?
235  */
236 int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
237 {
238         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
239                                  EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd));
240 }
241
242 int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
243 {
244     int ret;
245     size_t len = outlen;
246     OSSL_PARAM params[2], *p = params;
247
248     ret = dh_param_derive_check(ctx);
249     if (ret != 1)
250         return ret;
251
252     if (outlen <= 0) {
253         /*
254          * This would ideally be -1 or 0, but we have to retain compatibility
255          * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
256          * inlen <= 0
257          */
258         return -2;
259     }
260
261     *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
262                                        &len);
263     *p = OSSL_PARAM_construct_end();
264
265     ret = evp_pkey_ctx_set_params_strict(ctx, params);
266     if (ret == -2)
267         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
268     return ret;
269 }
270
271 int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
272 {
273     int ret;
274     size_t len = UINT_MAX;
275     OSSL_PARAM params[2], *p = params;
276
277     ret = dh_param_derive_check(ctx);
278     if (ret != 1)
279         return ret;
280
281     *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
282                                        &len);
283     *p = OSSL_PARAM_construct_end();
284
285     ret = evp_pkey_ctx_get_params_strict(ctx, params);
286     if (ret == -2)
287         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
288     if (ret != 1 || len > INT_MAX)
289         return -1;
290
291     *plen = (int)len;
292
293     return 1;
294 }
295
296 int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
297 {
298     int ret;
299     OSSL_PARAM params[2], *p = params;
300
301     if (len < 0)
302         return -1;
303
304     ret = dh_param_derive_check(ctx);
305     if (ret != 1)
306         return ret;
307
308     *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
309                                             /*
310                                              * Cast away the const. This is read
311                                              * only so should be safe
312                                              */
313                                             (void *)ukm,
314                                             (size_t)len);
315     *p = OSSL_PARAM_construct_end();
316
317     ret = evp_pkey_ctx_set_params_strict(ctx, params);
318     if (ret == -2)
319         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
320     if (ret == 1)
321         OPENSSL_free(ukm);
322     return ret;
323 }
324
325 #ifndef OPENSSL_NO_DEPRECATED_3_0
326 int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
327 {
328     int ret;
329     size_t ukmlen;
330     OSSL_PARAM params[2], *p = params;
331
332     ret = dh_param_derive_check(ctx);
333     if (ret != 1)
334         return ret;
335
336     *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
337                                           (void **)pukm, 0);
338     *p = OSSL_PARAM_construct_end();
339
340     ret = evp_pkey_ctx_get_params_strict(ctx, params);
341     if (ret == -2)
342         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
343     if (ret != 1)
344         return -1;
345
346     ukmlen = params[0].return_size;
347     if (ukmlen > INT_MAX)
348         return -1;
349
350     return (int)ukmlen;
351 }
352 #endif