2 * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <openssl/err.h>
13 #include <openssl/opensslv.h>
15 #include <openssl/core_names.h>
16 #include "crypto/evp.h"
21 * This file is meant to contain functions to provide EVP_PKEY support for EC
26 int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
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 */
34 /* If key type not EC return error */
35 if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
41 int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
44 OSSL_PARAM params[2], *p = params;
46 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
51 * Valid input values are:
54 * * -1 for reset to default for associated priv key
56 if (cofactor_mode < -1 || cofactor_mode > 1) {
57 /* Uses the same return value of pkey_ec_ctrl() */
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,
65 EVP_PKEY_CTRL_EC_ECDH_COFACTOR,
68 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
70 *p++ = OSSL_PARAM_construct_end();
72 ret = evp_pkey_ctx_set_params_strict(ctx, params);
74 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
75 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
82 int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
85 OSSL_PARAM params[2], *p = params;
87 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
95 EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL);
97 *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
99 *p++ = OSSL_PARAM_construct_end();
101 ret = evp_pkey_ctx_get_params_strict(ctx, params);
103 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
104 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
106 } else if (ret != 1) {
110 if (mode < 0 || mode > 1) {
112 * The provider should return either 0 or 1, any other value is a
121 int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
124 const char *kdf_type;
125 OSSL_PARAM params[2], *p = params;
127 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
132 case EVP_PKEY_ECDH_KDF_NONE:
135 case EVP_PKEY_ECDH_KDF_X9_63:
136 kdf_type = OSSL_KDF_NAME_X963KDF;
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,
146 EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
148 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
150 * Cast away the const. This is read
151 * only so should be safe
153 (char *)kdf_type, 0);
154 *p++ = OSSL_PARAM_construct_end();
156 ret = evp_pkey_ctx_set_params_strict(ctx, params);
158 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
159 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
166 int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
169 /* 80 should be big enough */
171 OSSL_PARAM params[2], *p = params;
173 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
181 EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
183 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
184 kdf_type, sizeof(kdf_type));
185 *p++ = OSSL_PARAM_construct_end();
187 ret = evp_pkey_ctx_get_params_strict(ctx, params);
189 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
190 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
192 } else if (ret != 1) {
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;
204 int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
207 OSSL_PARAM params[2], *p = params;
208 const char *md_name = NULL;
210 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
218 EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
220 md_name = (md == NULL) ? "" : EVP_MD_name(md);
222 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
224 * Cast away the const. This is read
225 * only so should be safe
228 *p++ = OSSL_PARAM_construct_end();
230 ret = evp_pkey_ctx_set_params_strict(ctx, params);
232 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
233 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
239 int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
241 /* 80 should be big enough */
244 OSSL_PARAM params[2], *p = params;
246 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
254 EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
256 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
258 *p++ = OSSL_PARAM_construct_end();
260 ret = evp_pkey_ctx_get_params_strict(ctx, params);
262 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
263 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
265 } else if (ret != 1) {
269 /* May be NULL meaning "unknown" */
270 *pmd = EVP_get_digestbyname(name);
275 int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int in)
279 OSSL_PARAM params[2], *p = params;
281 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
289 EVP_PKEY_CTRL_EC_KDF_OUTLEN, in, NULL);
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
300 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
302 *p++ = OSSL_PARAM_construct_end();
304 ret = evp_pkey_ctx_set_params_strict(ctx, params);
306 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
307 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
313 int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
315 size_t len = UINT_MAX;
317 OSSL_PARAM params[2], *p = params;
319 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
327 EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0,
330 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
332 *p++ = OSSL_PARAM_construct_end();
334 ret = evp_pkey_ctx_get_params_strict(ctx, params);
336 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
337 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
339 } else if (ret != 1) {
351 int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
354 OSSL_PARAM params[2], *p = params;
356 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
364 EVP_PKEY_CTRL_EC_KDF_UKM, len, (void *)(ukm));
366 *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
368 * Cast away the const. This is read
369 * only so should be safe
373 *p++ = OSSL_PARAM_construct_end();
375 ret = evp_pkey_ctx_set_params_strict(ctx, params);
377 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
378 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
386 int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
390 OSSL_PARAM params[3], *p = params;
392 ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
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,
400 EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
403 *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
405 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN,
407 *p++ = OSSL_PARAM_construct_end();
409 ret = evp_pkey_ctx_get_params_strict(ctx, params);
411 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
412 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
414 } else if (ret != 1) {
418 if (ukmlen > INT_MAX)
424 int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
427 OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
428 OSSL_PARAM *p = params;
430 if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
431 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
432 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
439 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
441 return EVP_PKEY_CTX_set_params(ctx, params);
444 int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
445 char *name, size_t namelen)
447 OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
448 OSSL_PARAM *p = params;
450 if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
451 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
452 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
459 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
461 if (!EVP_PKEY_CTX_get_params(ctx, params))
467 int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
469 if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
470 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
471 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
475 /* Legacy: if key type not EC return error */
476 if (ctx->pmeth != NULL
477 && EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC)
480 if (ctx->op.keymgmt.genctx == NULL)
481 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
482 EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
483 EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
486 return EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, OBJ_nid2sn(nid));