1240116Smarcel/* 2240116Smarcel * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. 3240116Smarcel * 4240116Smarcel * Licensed under the Apache License 2.0 (the "License"). You may not use 5240116Smarcel * this file except in compliance with the License. You can obtain a copy 6240116Smarcel * in the file LICENSE in the source distribution or at 7240116Smarcel * https://www.openssl.org/source/license.html 8240116Smarcel */ 9240116Smarcel 10240116Smarcel#include "internal/deprecated.h" 11240116Smarcel 12240116Smarcel#include <openssl/core_names.h> 13240116Smarcel#include <openssl/err.h> 14240116Smarcel#include <openssl/ec.h> 15240116Smarcel#include "crypto/evp.h" 16240116Smarcel#include "crypto/ec.h" 17240116Smarcel 18240116Smarcel/* 19240116Smarcel * This file is meant to contain functions to provide EVP_PKEY support for EC 20240116Smarcel * keys. 21240116Smarcel */ 22240116Smarcel 23240116Smarcelstatic ossl_inline 24240116Smarcelint evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx) 25240116Smarcel{ 26240116Smarcel if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { 27240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 28240116Smarcel /* Uses the same return values as EVP_PKEY_CTX_ctrl */ 29240116Smarcel return -2; 30240116Smarcel } 31240116Smarcel 32240116Smarcel /* If key type not EC return error */ 33240116Smarcel if (evp_pkey_ctx_is_legacy(ctx) 34240116Smarcel && ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC) 35240116Smarcel return -1; 36240116Smarcel 37240116Smarcel return 1; 38240116Smarcel} 39240116Smarcel 40240116Smarcelint EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode) 41240116Smarcel{ 42240116Smarcel int ret; 43240116Smarcel OSSL_PARAM params[2], *p = params; 44240116Smarcel 45240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 46240116Smarcel if (ret != 1) 47240116Smarcel return ret; 48240116Smarcel 49240116Smarcel /* 50240116Smarcel * Valid input values are: 51240116Smarcel * * 0 for disable 52240116Smarcel * * 1 for enable 53260029Sjmmv * * -1 for reset to default for associated priv key 54240116Smarcel */ 55240116Smarcel if (cofactor_mode < -1 || cofactor_mode > 1) { 56260029Sjmmv /* Uses the same return value of pkey_ec_ctrl() */ 57240116Smarcel return -2; 58240116Smarcel } 59240116Smarcel 60240116Smarcel *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, 61240116Smarcel &cofactor_mode); 62240116Smarcel *p++ = OSSL_PARAM_construct_end(); 63240116Smarcel 64240116Smarcel ret = evp_pkey_ctx_set_params_strict(ctx, params); 65240116Smarcel if (ret == -2) 66240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 67240116Smarcel return ret; 68240116Smarcel} 69240116Smarcel 70240116Smarcelint EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx) 71240116Smarcel{ 72240116Smarcel int ret, mode; 73240116Smarcel OSSL_PARAM params[2], *p = params; 74240116Smarcel 75240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 76240116Smarcel if (ret != 1) 77240116Smarcel return ret; 78240116Smarcel 79240116Smarcel *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, 80240116Smarcel &mode); 81240116Smarcel *p++ = OSSL_PARAM_construct_end(); 82240116Smarcel 83240116Smarcel ret = evp_pkey_ctx_get_params_strict(ctx, params); 84240116Smarcel 85240116Smarcel switch (ret) { 86240116Smarcel case -2: 87240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 88240116Smarcel break; 89240116Smarcel case 1: 90240116Smarcel ret = mode; 91240116Smarcel if (mode < 0 || mode > 1) { 92240116Smarcel /* 93240116Smarcel * The provider should return either 0 or 1, any other value is a 94240116Smarcel * provider error. 95240116Smarcel */ 96240116Smarcel ret = -1; 97240116Smarcel } 98240116Smarcel break; 99240116Smarcel default: 100240116Smarcel ret = -1; 101240116Smarcel break; 102240116Smarcel } 103240116Smarcel 104240116Smarcel return ret; 105240116Smarcel} 106240116Smarcel 107240116Smarcel/* 108240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 109240116Smarcel * simply because that's easier. 110240116Smarcel */ 111240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf) 112240116Smarcel{ 113240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE, 114240116Smarcel EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL); 115240116Smarcel} 116240116Smarcel 117240116Smarcel/* 118240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 119240116Smarcel * simply because that's easier. 120240116Smarcel */ 121240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx) 122240116Smarcel{ 123240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE, 124240116Smarcel EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL); 125240116Smarcel} 126240116Smarcel 127240116Smarcel/* 128240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 129240116Smarcel * simply because that's easier. 130240116Smarcel */ 131240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) 132240116Smarcel{ 133240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE, 134240116Smarcel EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md)); 135240116Smarcel} 136240116Smarcel 137240116Smarcel/* 138240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 139240116Smarcel * simply because that's easier. 140240116Smarcel */ 141240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd) 142240116Smarcel{ 143240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_DERIVE, 144240116Smarcel EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd)); 145240116Smarcel} 146240116Smarcel 147240116Smarcelint EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen) 148240116Smarcel{ 149240116Smarcel int ret; 150240116Smarcel size_t len = outlen; 151240116Smarcel OSSL_PARAM params[2], *p = params; 152240116Smarcel 153240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 154240116Smarcel if (ret != 1) 155240116Smarcel return ret; 156240116Smarcel 157240116Smarcel if (outlen <= 0) { 158240116Smarcel /* 159240116Smarcel * This would ideally be -1 or 0, but we have to retain compatibility 160240116Smarcel * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if 161240116Smarcel * in <= 0 162240116Smarcel */ 163240116Smarcel return -2; 164240116Smarcel } 165240116Smarcel 166240116Smarcel *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, 167240116Smarcel &len); 168240116Smarcel *p++ = OSSL_PARAM_construct_end(); 169240116Smarcel 170240116Smarcel ret = evp_pkey_ctx_set_params_strict(ctx, params); 171240116Smarcel if (ret == -2) 172240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 173240116Smarcel return ret; 174240116Smarcel} 175240116Smarcel 176240116Smarcelint EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen) 177240116Smarcel{ 178240116Smarcel size_t len = UINT_MAX; 179240116Smarcel int ret; 180240116Smarcel OSSL_PARAM params[2], *p = params; 181240116Smarcel 182240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 183240116Smarcel if (ret != 1) 184240116Smarcel return ret; 185240116Smarcel 186240116Smarcel *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, 187240116Smarcel &len); 188240116Smarcel *p++ = OSSL_PARAM_construct_end(); 189240116Smarcel 190240116Smarcel ret = evp_pkey_ctx_get_params_strict(ctx, params); 191240116Smarcel 192240116Smarcel switch (ret) { 193240116Smarcel case -2: 194240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 195240116Smarcel break; 196240116Smarcel case 1: 197240116Smarcel if (len <= INT_MAX) 198240116Smarcel *plen = (int)len; 199240116Smarcel else 200240116Smarcel ret = -1; 201240116Smarcel break; 202240116Smarcel default: 203240116Smarcel ret = -1; 204240116Smarcel break; 205240116Smarcel } 206240116Smarcel 207240116Smarcel return ret; 208240116Smarcel} 209240116Smarcel 210240116Smarcelint EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len) 211240116Smarcel{ 212240116Smarcel int ret; 213240116Smarcel OSSL_PARAM params[2], *p = params; 214240116Smarcel 215240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 216240116Smarcel if (ret != 1) 217240116Smarcel return ret; 218240116Smarcel 219240116Smarcel *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, 220240116Smarcel /* 221240116Smarcel * Cast away the const. This is read 222240116Smarcel * only so should be safe 223240116Smarcel */ 224240116Smarcel (void *)ukm, 225240116Smarcel (size_t)len); 226240116Smarcel *p++ = OSSL_PARAM_construct_end(); 227240116Smarcel 228240116Smarcel ret = evp_pkey_ctx_set_params_strict(ctx, params); 229240116Smarcel 230240116Smarcel switch (ret) { 231240116Smarcel case -2: 232240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 233240116Smarcel break; 234240116Smarcel case 1: 235240116Smarcel OPENSSL_free(ukm); 236240116Smarcel break; 237240116Smarcel } 238240116Smarcel 239240116Smarcel return ret; 240240116Smarcel} 241240116Smarcel 242240116Smarcel#ifndef OPENSSL_NO_DEPRECATED_3_0 243240116Smarcelint EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm) 244240116Smarcel{ 245240116Smarcel size_t ukmlen; 246240116Smarcel int ret; 247240116Smarcel OSSL_PARAM params[2], *p = params; 248240116Smarcel 249240116Smarcel ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx); 250240116Smarcel if (ret != 1) 251240116Smarcel return ret; 252240116Smarcel 253240116Smarcel *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM, 254240116Smarcel (void **)pukm, 0); 255240116Smarcel *p++ = OSSL_PARAM_construct_end(); 256240116Smarcel 257240116Smarcel ret = evp_pkey_ctx_get_params_strict(ctx, params); 258240116Smarcel 259240116Smarcel switch (ret) { 260240116Smarcel case -2: 261240116Smarcel ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 262240116Smarcel break; 263240116Smarcel case 1: 264240116Smarcel ret = -1; 265240116Smarcel ukmlen = params[0].return_size; 266240116Smarcel if (ukmlen <= INT_MAX) 267240116Smarcel ret = (int)ukmlen; 268240116Smarcel break; 269240116Smarcel default: 270240116Smarcel ret = -1; 271240116Smarcel break; 272240116Smarcel } 273240116Smarcel 274240116Smarcel return ret; 275240116Smarcel} 276240116Smarcel#endif 277240116Smarcel 278240116Smarcel#ifndef FIPS_MODULE 279240116Smarcel/* 280240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 281240116Smarcel * simply because that's easier. 282240116Smarcel * ASN1_OBJECT (which would be converted to text internally)? 283240116Smarcel */ 284240116Smarcelint EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) 285240116Smarcel{ 286240116Smarcel int keytype = nid == EVP_PKEY_SM2 ? EVP_PKEY_SM2 : EVP_PKEY_EC; 287240116Smarcel 288240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, keytype, EVP_PKEY_OP_TYPE_GEN, 289240116Smarcel EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, 290240116Smarcel nid, NULL); 291240116Smarcel} 292240116Smarcel 293240116Smarcel/* 294240116Smarcel * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 295240116Smarcel * simply because that's easier. 296240116Smarcel */ 297240116Smarcelint EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int param_enc) 298240116Smarcel{ 299240116Smarcel return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN, 300240116Smarcel EVP_PKEY_CTRL_EC_PARAM_ENC, param_enc, NULL); 301240116Smarcel} 302240116Smarcel#endif 303240116Smarcel