]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/ec_ctrl.c
Deprecate EC_KEY + Update ec apps to use EVP_PKEY
[thirdparty/openssl.git] / crypto / evp / ec_ctrl.c
1 /*
2 * Copyright 2020 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 (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
36 return -1;
37
38 return 1;
39 }
40
41 int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
42 {
43 int ret;
44 OSSL_PARAM params[2], *p = params;
45
46 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
47 if (ret != 1)
48 return ret;
49
50 /*
51 * Valid input values are:
52 * * 0 for disable
53 * * 1 for enable
54 * * -1 for reset to default for associated priv key
55 */
56 if (cofactor_mode < -1 || cofactor_mode > 1) {
57 /* Uses the same return value of pkey_ec_ctrl() */
58 return -2;
59 }
60
61 /* TODO(3.0): Remove this eventually when no more legacy */
62 if (ctx->op.kex.exchprovctx == NULL)
63 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
64 EVP_PKEY_OP_DERIVE,
65 EVP_PKEY_CTRL_EC_ECDH_COFACTOR,
66 cofactor_mode, NULL);
67
68 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
69 &cofactor_mode);
70 *p++ = OSSL_PARAM_construct_end();
71
72 ret = evp_pkey_ctx_set_params_strict(ctx, params);
73 if (ret == -2) {
74 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
75 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
76 return -2;
77 }
78
79 return ret;
80 }
81
82 int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
83 {
84 int ret, mode;
85 OSSL_PARAM params[2], *p = params;
86
87 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
88 if (ret != 1)
89 return ret;
90
91 /* TODO(3.0): Remove this eventually when no more legacy */
92 if (ctx->op.kex.exchprovctx == NULL)
93 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
94 EVP_PKEY_OP_DERIVE,
95 EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL);
96
97 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
98 &mode);
99 *p++ = OSSL_PARAM_construct_end();
100
101 ret = evp_pkey_ctx_get_params_strict(ctx, params);
102 if (ret == -2) {
103 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
104 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
105 return -2;
106 } else if (ret != 1) {
107 return -1;
108 }
109
110 if (mode < 0 || mode > 1) {
111 /*
112 * The provider should return either 0 or 1, any other value is a
113 * provider error.
114 */
115 return -1;
116 }
117
118 return mode;
119 }
120
121 int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
122 {
123 int ret;
124 const char *kdf_type;
125 OSSL_PARAM params[2], *p = params;
126
127 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
128 if (ret != 1)
129 return ret;
130
131 switch (kdf) {
132 case EVP_PKEY_ECDH_KDF_NONE:
133 kdf_type = "";
134 break;
135 case EVP_PKEY_ECDH_KDF_X9_63:
136 kdf_type = OSSL_KDF_NAME_X963KDF;
137 break;
138 default:
139 return -2;
140 }
141
142 /* TODO(3.0): Remove this eventually when no more legacy */
143 if (ctx->op.kex.exchprovctx == NULL)
144 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
145 EVP_PKEY_OP_DERIVE,
146 EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
147
148 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
149 /*
150 * Cast away the const. This is read
151 * only so should be safe
152 */
153 (char *)kdf_type, 0);
154 *p++ = OSSL_PARAM_construct_end();
155
156 ret = evp_pkey_ctx_set_params_strict(ctx, params);
157 if (ret == -2) {
158 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
159 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
160 return -2;
161 }
162
163 return ret;
164 }
165
166 int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
167 {
168 int ret;
169 /* 80 should be big enough */
170 char kdf_type[80];
171 OSSL_PARAM params[2], *p = params;
172
173 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
174 if (ret != 1)
175 return ret;
176
177 /* TODO(3.0): Remove this eventually when no more legacy */
178 if (ctx->op.kex.exchprovctx == NULL)
179 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
180 EVP_PKEY_OP_DERIVE,
181 EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
182
183 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
184 kdf_type, sizeof(kdf_type));
185 *p++ = OSSL_PARAM_construct_end();
186
187 ret = evp_pkey_ctx_get_params_strict(ctx, params);
188 if (ret == -2) {
189 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
190 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
191 return -2;
192 } else if (ret != 1) {
193 return -1;
194 }
195
196 if (kdf_type[0] == '\0')
197 return EVP_PKEY_ECDH_KDF_NONE;
198 else if (strcmp(kdf_type, OSSL_KDF_NAME_X963KDF) == 0)
199 return EVP_PKEY_ECDH_KDF_X9_63;
200
201 return -1;
202 }
203
204 int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
205 {
206 int ret;
207 OSSL_PARAM params[2], *p = params;
208 const char *md_name = NULL;
209
210 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
211 if (ret != 1)
212 return ret;
213
214 /* TODO(3.0): Remove this eventually when no more legacy */
215 if (ctx->op.kex.exchprovctx == NULL)
216 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
217 EVP_PKEY_OP_DERIVE,
218 EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
219
220 md_name = (md == NULL) ? "" : EVP_MD_name(md);
221
222 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
223 /*
224 * Cast away the const. This is read
225 * only so should be safe
226 */
227 (char *)md_name, 0);
228 *p++ = OSSL_PARAM_construct_end();
229
230 ret = evp_pkey_ctx_set_params_strict(ctx, params);
231 if (ret == -2) {
232 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
233 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
234 return -2;
235 }
236 return ret;
237 }
238
239 int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
240 {
241 /* 80 should be big enough */
242 char name[80] = "";
243 int ret;
244 OSSL_PARAM params[2], *p = params;
245
246 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
247 if (ret != 1)
248 return ret;
249
250 /* TODO(3.0): Remove this eventually when no more legacy */
251 if (ctx->op.kex.exchprovctx == NULL)
252 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
253 EVP_PKEY_OP_DERIVE,
254 EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
255
256 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
257 name, sizeof(name));
258 *p++ = OSSL_PARAM_construct_end();
259
260 ret = evp_pkey_ctx_get_params_strict(ctx, params);
261 if (ret == -2) {
262 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
263 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
264 return -2;
265 } else if (ret != 1) {
266 return -1;
267 }
268
269 /* May be NULL meaning "unknown" */
270 *pmd = EVP_get_digestbyname(name);
271
272 return 1;
273 }
274
275 int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int in)
276 {
277 int ret;
278 size_t len = in;
279 OSSL_PARAM params[2], *p = params;
280
281 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
282 if (ret != 1)
283 return ret;
284
285 /* TODO(3.0): Remove this eventually when no more legacy */
286 if (ctx->op.kex.exchprovctx == NULL)
287 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
288 EVP_PKEY_OP_DERIVE,
289 EVP_PKEY_CTRL_EC_KDF_OUTLEN, in, NULL);
290
291 if (in <= 0) {
292 /*
293 * This would ideally be -1 or 0, but we have to retain compatibility
294 * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
295 * in <= 0
296 */
297 return -2;
298 }
299
300 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
301 &len);
302 *p++ = OSSL_PARAM_construct_end();
303
304 ret = evp_pkey_ctx_set_params_strict(ctx, params);
305 if (ret == -2) {
306 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
307 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
308 return -2;
309 }
310 return ret;
311 }
312
313 int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
314 {
315 size_t len = UINT_MAX;
316 int ret;
317 OSSL_PARAM params[2], *p = params;
318
319 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
320 if (ret != 1)
321 return ret;
322
323 /* TODO(3.0): Remove this eventually when no more legacy */
324 if (ctx->op.kex.exchprovctx == NULL)
325 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
326 EVP_PKEY_OP_DERIVE,
327 EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0,
328 (void *)(plen));
329
330 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
331 &len);
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 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
338 return -2;
339 } else if (ret != 1) {
340 return -1;
341 }
342
343 if (len > INT_MAX)
344 return -1;
345
346 *plen = (int)len;
347
348 return 1;
349 }
350
351 int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
352 {
353 int ret;
354 OSSL_PARAM params[2], *p = params;
355
356 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
357 if (ret != 1)
358 return ret;
359
360 /* TODO(3.0): Remove this eventually when no more legacy */
361 if (ctx->op.kex.exchprovctx == NULL)
362 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
363 EVP_PKEY_OP_DERIVE,
364 EVP_PKEY_CTRL_EC_KDF_UKM, len, (void *)(ukm));
365
366 *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
367 /*
368 * Cast away the const. This is read
369 * only so should be safe
370 */
371 (void *)ukm,
372 (size_t)len);
373 *p++ = OSSL_PARAM_construct_end();
374
375 ret = evp_pkey_ctx_set_params_strict(ctx, params);
376 if (ret == -2) {
377 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
378 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
379 return -2;
380 }
381 if (ret == 1)
382 OPENSSL_free(ukm);
383 return ret;
384 }
385
386 int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
387 {
388 size_t ukmlen;
389 int ret;
390 OSSL_PARAM params[3], *p = params;
391
392 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
393 if (ret != 1)
394 return ret;
395
396 /* TODO(3.0): Remove this eventually when no more legacy */
397 if (ctx->op.kex.exchprovctx == NULL)
398 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
399 EVP_PKEY_OP_DERIVE,
400 EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
401 (void *)(pukm));
402
403 *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
404 (void **)pukm, 0);
405 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN,
406 &ukmlen);
407 *p++ = OSSL_PARAM_construct_end();
408
409 ret = evp_pkey_ctx_get_params_strict(ctx, params);
410 if (ret == -2) {
411 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
412 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
413 return -2;
414 } else if (ret != 1) {
415 return -1;
416 }
417
418 if (ukmlen > INT_MAX)
419 return -1;
420
421 return (int)ukmlen;
422 }
423
424 #ifndef FIPS_MODULE
425 int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
426 {
427 if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
428 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
429 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
430 return -2;
431 }
432
433 /* Legacy: if key type not EC return error */
434 if (ctx->pmeth != NULL
435 && EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC)
436 return -1;
437
438 if (ctx->op.keymgmt.genctx == NULL)
439 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
440 EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
441 EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
442 nid, NULL);
443
444 return EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(nid));
445 }
446
447 int evp_pkey_ctx_set_ec_param_enc_prov(EVP_PKEY_CTX *ctx, int param_enc)
448 {
449 const char *enc = NULL;
450 OSSL_PARAM params[2], *p = params;
451 int ret = -2; /* Assume unsupported */
452
453 if (ctx == NULL
454 || !EVP_PKEY_CTX_IS_GEN_OP(ctx)
455 || ctx->op.keymgmt.genctx == NULL)
456 goto end;
457
458 switch (param_enc) {
459 case OPENSSL_EC_EXPLICIT_CURVE:
460 enc = OSSL_PKEY_EC_ENCODING_EXPLICIT;
461 break;
462 case OPENSSL_EC_NAMED_CURVE:
463 enc = OSSL_PKEY_EC_ENCODING_GROUP;
464 break;
465 default:
466 goto end;
467 }
468
469 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
470 (char *)enc, 0);
471 *p = OSSL_PARAM_construct_end();
472
473 ret = evp_pkey_ctx_set_params_strict(ctx, params);
474 end:
475 if (ret == -2)
476 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
477 return ret;
478 }
479
480 int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc)
481 {
482 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
483 EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
484 EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL);
485 }
486 #endif