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