]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/ec_ctrl.c
ff0c55d0232098c9182ed72b637ae7054f4c9a79
[thirdparty/openssl.git] / crypto / evp / ec_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 <string.h>
13
14 #include <openssl/core_names.h>
15 #include <openssl/err.h>
16 #include <openssl/ec.h>
17 #include "crypto/evp.h"
18 #include "crypto/ec.h"
19
20 /*
21 * This file is meant to contain functions to provide EVP_PKEY support for EC
22 * keys.
23 */
24
25 static ossl_inline
26 int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
27 {
28 if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
29 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
30 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
31 return -2;
32 }
33
34 /* If key type not EC return error */
35 if (evp_pkey_ctx_is_legacy(ctx)
36 && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
37 return -1;
38
39 return 1;
40 }
41
42 int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
43 {
44 int ret;
45 OSSL_PARAM params[2], *p = params;
46
47 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
48 if (ret != 1)
49 return ret;
50
51 /*
52 * Valid input values are:
53 * * 0 for disable
54 * * 1 for enable
55 * * -1 for reset to default for associated priv key
56 */
57 if (cofactor_mode < -1 || cofactor_mode > 1) {
58 /* Uses the same return value of pkey_ec_ctrl() */
59 return -2;
60 }
61
62 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
63 &cofactor_mode);
64 *p++ = OSSL_PARAM_construct_end();
65
66 ret = evp_pkey_ctx_set_params_strict(ctx, params);
67 if (ret == -2)
68 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
69 return ret;
70 }
71
72 int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
73 {
74 int ret, mode;
75 OSSL_PARAM params[2], *p = params;
76
77 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
78 if (ret != 1)
79 return ret;
80
81 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
82 &mode);
83 *p++ = OSSL_PARAM_construct_end();
84
85 ret = evp_pkey_ctx_get_params_strict(ctx, params);
86
87 switch (ret) {
88 case -2:
89 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
90 break;
91 case 1:
92 ret = mode;
93 if (mode < 0 || mode > 1) {
94 /*
95 * The provider should return either 0 or 1, any other value is a
96 * provider error.
97 */
98 ret = -1;
99 }
100 break;
101 default:
102 ret = -1;
103 break;
104 }
105
106 return ret;
107 }
108
109 /*
110 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
111 * simply because that's easier.
112 */
113 int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
114 {
115 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
116 EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
117 }
118
119 /*
120 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
121 * simply because that's easier.
122 */
123 int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
124 {
125 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
126 EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
127 }
128
129 /*
130 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
131 * simply because that's easier.
132 * TODO(3.0) Should this be deprecated in favor of passing a name?
133 */
134 int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
135 {
136 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
137 EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
138 }
139
140 /*
141 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
142 * simply because that's easier.
143 * TODO(3.0) Should this be deprecated in favor of getting a name?
144 */
145 int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
146 {
147 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE,
148 EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
149 }
150
151 int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen)
152 {
153 int ret;
154 size_t len = outlen;
155 OSSL_PARAM params[2], *p = params;
156
157 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
158 if (ret != 1)
159 return ret;
160
161 if (outlen <= 0) {
162 /*
163 * This would ideally be -1 or 0, but we have to retain compatibility
164 * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
165 * in <= 0
166 */
167 return -2;
168 }
169
170 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
171 &len);
172 *p++ = OSSL_PARAM_construct_end();
173
174 ret = evp_pkey_ctx_set_params_strict(ctx, params);
175 if (ret == -2)
176 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
177 return ret;
178 }
179
180 int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
181 {
182 size_t len = UINT_MAX;
183 int ret;
184 OSSL_PARAM params[2], *p = params;
185
186 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
187 if (ret != 1)
188 return ret;
189
190 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
191 &len);
192 *p++ = OSSL_PARAM_construct_end();
193
194 ret = evp_pkey_ctx_get_params_strict(ctx, params);
195
196 switch (ret) {
197 case -2:
198 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
199 break;
200 case 1:
201 if (len <= INT_MAX)
202 *plen = (int)len;
203 else
204 ret = -1;
205 break;
206 default:
207 ret = -1;
208 break;
209 }
210
211 return ret;
212 }
213
214 int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
215 {
216 int ret;
217 OSSL_PARAM params[2], *p = params;
218
219 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
220 if (ret != 1)
221 return ret;
222
223 *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
224 /*
225 * Cast away the const. This is read
226 * only so should be safe
227 */
228 (void *)ukm,
229 (size_t)len);
230 *p++ = OSSL_PARAM_construct_end();
231
232 ret = evp_pkey_ctx_set_params_strict(ctx, params);
233
234 switch (ret) {
235 case -2:
236 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
237 break;
238 case 1:
239 OPENSSL_free(ukm);
240 break;
241 }
242
243 return ret;
244 }
245
246 #ifndef OPENSSL_NO_DEPRECATED_3_0
247 int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
248 {
249 size_t ukmlen;
250 int ret;
251 OSSL_PARAM params[2], *p = params;
252
253 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
254 if (ret != 1)
255 return ret;
256
257 /* TODO(3.0): Remove this eventually when no more legacy */
258 if (ctx->op.kex.exchprovctx == NULL)
259 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
260 EVP_PKEY_OP_DERIVE,
261 EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
262 (void *)(pukm));
263
264 *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
265 (void **)pukm, 0);
266 *p++ = OSSL_PARAM_construct_end();
267
268 ret = evp_pkey_ctx_get_params_strict(ctx, params);
269
270 switch (ret) {
271 case -2:
272 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
273 break;
274 case 1:
275 ret = -1;
276 ukmlen = params[0].return_size;
277 if (ukmlen <= INT_MAX)
278 ret = (int)ukmlen;
279 break;
280 default:
281 ret = -1;
282 break;
283 }
284
285 return ret;
286 }
287 #endif
288
289 #ifndef FIPS_MODULE
290 /*
291 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
292 * simply because that's easier.
293 * TODO(3.0) Should this be deprecated in favor of setting a name or an
294 * ASN1_OBJECT (which would be converted to text internally)?
295 */
296 int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
297 {
298 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
299 EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
300 nid, NULL);
301 }
302
303 /*
304 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper,
305 * simply because that's easier.
306 */
307 int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
308 {
309 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
310 EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
311 }
312 #endif