1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2006-2021 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/* 11e1051a39Sopenharmony_ci * ECDH and ECDSA low level APIs are deprecated for public use, but still ok 12e1051a39Sopenharmony_ci * for internal use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <stdio.h> 17e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 18e1051a39Sopenharmony_ci#include <openssl/asn1t.h> 19e1051a39Sopenharmony_ci#include <openssl/x509.h> 20e1051a39Sopenharmony_ci#include <openssl/ec.h> 21e1051a39Sopenharmony_ci#include "ec_local.h" 22e1051a39Sopenharmony_ci#include <openssl/evp.h> 23e1051a39Sopenharmony_ci#include "crypto/evp.h" 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci/* EC pkey context structure */ 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_citypedef struct { 28e1051a39Sopenharmony_ci /* Key and paramgen group */ 29e1051a39Sopenharmony_ci EC_GROUP *gen_group; 30e1051a39Sopenharmony_ci /* message digest */ 31e1051a39Sopenharmony_ci const EVP_MD *md; 32e1051a39Sopenharmony_ci /* Duplicate key if custom cofactor needed */ 33e1051a39Sopenharmony_ci EC_KEY *co_key; 34e1051a39Sopenharmony_ci /* Cofactor mode */ 35e1051a39Sopenharmony_ci signed char cofactor_mode; 36e1051a39Sopenharmony_ci /* KDF (if any) to use for ECDH */ 37e1051a39Sopenharmony_ci char kdf_type; 38e1051a39Sopenharmony_ci /* Message digest to use for key derivation */ 39e1051a39Sopenharmony_ci const EVP_MD *kdf_md; 40e1051a39Sopenharmony_ci /* User key material */ 41e1051a39Sopenharmony_ci unsigned char *kdf_ukm; 42e1051a39Sopenharmony_ci size_t kdf_ukmlen; 43e1051a39Sopenharmony_ci /* KDF output length */ 44e1051a39Sopenharmony_ci size_t kdf_outlen; 45e1051a39Sopenharmony_ci} EC_PKEY_CTX; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_cistatic int pkey_ec_init(EVP_PKEY_CTX *ctx) 48e1051a39Sopenharmony_ci{ 49e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { 52e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 53e1051a39Sopenharmony_ci return 0; 54e1051a39Sopenharmony_ci } 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci dctx->cofactor_mode = -1; 57e1051a39Sopenharmony_ci dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; 58e1051a39Sopenharmony_ci ctx->data = dctx; 59e1051a39Sopenharmony_ci return 1; 60e1051a39Sopenharmony_ci} 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_cistatic int pkey_ec_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) 63e1051a39Sopenharmony_ci{ 64e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx, *sctx; 65e1051a39Sopenharmony_ci if (!pkey_ec_init(dst)) 66e1051a39Sopenharmony_ci return 0; 67e1051a39Sopenharmony_ci sctx = src->data; 68e1051a39Sopenharmony_ci dctx = dst->data; 69e1051a39Sopenharmony_ci if (sctx->gen_group) { 70e1051a39Sopenharmony_ci dctx->gen_group = EC_GROUP_dup(sctx->gen_group); 71e1051a39Sopenharmony_ci if (!dctx->gen_group) 72e1051a39Sopenharmony_ci return 0; 73e1051a39Sopenharmony_ci } 74e1051a39Sopenharmony_ci dctx->md = sctx->md; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci if (sctx->co_key) { 77e1051a39Sopenharmony_ci dctx->co_key = EC_KEY_dup(sctx->co_key); 78e1051a39Sopenharmony_ci if (!dctx->co_key) 79e1051a39Sopenharmony_ci return 0; 80e1051a39Sopenharmony_ci } 81e1051a39Sopenharmony_ci dctx->kdf_type = sctx->kdf_type; 82e1051a39Sopenharmony_ci dctx->kdf_md = sctx->kdf_md; 83e1051a39Sopenharmony_ci dctx->kdf_outlen = sctx->kdf_outlen; 84e1051a39Sopenharmony_ci if (sctx->kdf_ukm) { 85e1051a39Sopenharmony_ci dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); 86e1051a39Sopenharmony_ci if (!dctx->kdf_ukm) 87e1051a39Sopenharmony_ci return 0; 88e1051a39Sopenharmony_ci } else 89e1051a39Sopenharmony_ci dctx->kdf_ukm = NULL; 90e1051a39Sopenharmony_ci dctx->kdf_ukmlen = sctx->kdf_ukmlen; 91e1051a39Sopenharmony_ci return 1; 92e1051a39Sopenharmony_ci} 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_cistatic void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) 95e1051a39Sopenharmony_ci{ 96e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 97e1051a39Sopenharmony_ci if (dctx != NULL) { 98e1051a39Sopenharmony_ci EC_GROUP_free(dctx->gen_group); 99e1051a39Sopenharmony_ci EC_KEY_free(dctx->co_key); 100e1051a39Sopenharmony_ci OPENSSL_free(dctx->kdf_ukm); 101e1051a39Sopenharmony_ci OPENSSL_free(dctx); 102e1051a39Sopenharmony_ci ctx->data = NULL; 103e1051a39Sopenharmony_ci } 104e1051a39Sopenharmony_ci} 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_cistatic int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 107e1051a39Sopenharmony_ci const unsigned char *tbs, size_t tbslen) 108e1051a39Sopenharmony_ci{ 109e1051a39Sopenharmony_ci int ret, type; 110e1051a39Sopenharmony_ci unsigned int sltmp; 111e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 112e1051a39Sopenharmony_ci /* 113e1051a39Sopenharmony_ci * Discard const. Its marked as const because this may be a cached copy of 114e1051a39Sopenharmony_ci * the "real" key. These calls don't make any modifications that need to 115e1051a39Sopenharmony_ci * be reflected back in the "original" key. 116e1051a39Sopenharmony_ci */ 117e1051a39Sopenharmony_ci EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); 118e1051a39Sopenharmony_ci const int sig_sz = ECDSA_size(ec); 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci /* ensure cast to size_t is safe */ 121e1051a39Sopenharmony_ci if (!ossl_assert(sig_sz > 0)) 122e1051a39Sopenharmony_ci return 0; 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci if (sig == NULL) { 125e1051a39Sopenharmony_ci *siglen = (size_t)sig_sz; 126e1051a39Sopenharmony_ci return 1; 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci if (*siglen < (size_t)sig_sz) { 130e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); 131e1051a39Sopenharmony_ci return 0; 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci type = (dctx->md != NULL) ? EVP_MD_get_type(dctx->md) : NID_sha1; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci if (ret <= 0) 139e1051a39Sopenharmony_ci return ret; 140e1051a39Sopenharmony_ci *siglen = (size_t)sltmp; 141e1051a39Sopenharmony_ci return 1; 142e1051a39Sopenharmony_ci} 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_cistatic int pkey_ec_verify(EVP_PKEY_CTX *ctx, 145e1051a39Sopenharmony_ci const unsigned char *sig, size_t siglen, 146e1051a39Sopenharmony_ci const unsigned char *tbs, size_t tbslen) 147e1051a39Sopenharmony_ci{ 148e1051a39Sopenharmony_ci int ret, type; 149e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 150e1051a39Sopenharmony_ci /* 151e1051a39Sopenharmony_ci * Discard const. Its marked as const because this may be a cached copy of 152e1051a39Sopenharmony_ci * the "real" key. These calls don't make any modifications that need to 153e1051a39Sopenharmony_ci * be reflected back in the "original" key. 154e1051a39Sopenharmony_ci */ 155e1051a39Sopenharmony_ci EC_KEY *ec = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci if (dctx->md) 158e1051a39Sopenharmony_ci type = EVP_MD_get_type(dctx->md); 159e1051a39Sopenharmony_ci else 160e1051a39Sopenharmony_ci type = NID_sha1; 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci return ret; 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 168e1051a39Sopenharmony_cistatic int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) 169e1051a39Sopenharmony_ci{ 170e1051a39Sopenharmony_ci int ret; 171e1051a39Sopenharmony_ci size_t outlen; 172e1051a39Sopenharmony_ci const EC_POINT *pubkey = NULL; 173e1051a39Sopenharmony_ci EC_KEY *eckey; 174e1051a39Sopenharmony_ci const EC_KEY *eckeypub; 175e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci if (ctx->pkey == NULL || ctx->peerkey == NULL) { 178e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET); 179e1051a39Sopenharmony_ci return 0; 180e1051a39Sopenharmony_ci } 181e1051a39Sopenharmony_ci eckeypub = EVP_PKEY_get0_EC_KEY(ctx->peerkey); 182e1051a39Sopenharmony_ci if (eckeypub == NULL) { 183e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET); 184e1051a39Sopenharmony_ci return 0; 185e1051a39Sopenharmony_ci } 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci eckey = dctx->co_key ? dctx->co_key 188e1051a39Sopenharmony_ci : (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci if (!key) { 191e1051a39Sopenharmony_ci const EC_GROUP *group; 192e1051a39Sopenharmony_ci group = EC_KEY_get0_group(eckey); 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci if (group == NULL) 195e1051a39Sopenharmony_ci return 0; 196e1051a39Sopenharmony_ci *keylen = (EC_GROUP_get_degree(group) + 7) / 8; 197e1051a39Sopenharmony_ci return 1; 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci pubkey = EC_KEY_get0_public_key(eckeypub); 200e1051a39Sopenharmony_ci 201e1051a39Sopenharmony_ci /* 202e1051a39Sopenharmony_ci * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not 203e1051a39Sopenharmony_ci * an error, the result is truncated. 204e1051a39Sopenharmony_ci */ 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci outlen = *keylen; 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); 209e1051a39Sopenharmony_ci if (ret <= 0) 210e1051a39Sopenharmony_ci return 0; 211e1051a39Sopenharmony_ci *keylen = ret; 212e1051a39Sopenharmony_ci return 1; 213e1051a39Sopenharmony_ci} 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_cistatic int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, 216e1051a39Sopenharmony_ci unsigned char *key, size_t *keylen) 217e1051a39Sopenharmony_ci{ 218e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 219e1051a39Sopenharmony_ci unsigned char *ktmp = NULL; 220e1051a39Sopenharmony_ci size_t ktmplen; 221e1051a39Sopenharmony_ci int rv = 0; 222e1051a39Sopenharmony_ci if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) 223e1051a39Sopenharmony_ci return pkey_ec_derive(ctx, key, keylen); 224e1051a39Sopenharmony_ci if (!key) { 225e1051a39Sopenharmony_ci *keylen = dctx->kdf_outlen; 226e1051a39Sopenharmony_ci return 1; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci if (*keylen != dctx->kdf_outlen) 229e1051a39Sopenharmony_ci return 0; 230e1051a39Sopenharmony_ci if (!pkey_ec_derive(ctx, NULL, &ktmplen)) 231e1051a39Sopenharmony_ci return 0; 232e1051a39Sopenharmony_ci if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) { 233e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 234e1051a39Sopenharmony_ci return 0; 235e1051a39Sopenharmony_ci } 236e1051a39Sopenharmony_ci if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) 237e1051a39Sopenharmony_ci goto err; 238e1051a39Sopenharmony_ci /* Do KDF stuff */ 239e1051a39Sopenharmony_ci if (!ossl_ecdh_kdf_X9_63(key, *keylen, ktmp, ktmplen, 240e1051a39Sopenharmony_ci dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md, 241e1051a39Sopenharmony_ci ctx->libctx, ctx->propquery)) 242e1051a39Sopenharmony_ci goto err; 243e1051a39Sopenharmony_ci rv = 1; 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci err: 246e1051a39Sopenharmony_ci OPENSSL_clear_free(ktmp, ktmplen); 247e1051a39Sopenharmony_ci return rv; 248e1051a39Sopenharmony_ci} 249e1051a39Sopenharmony_ci#endif 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_cistatic int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 252e1051a39Sopenharmony_ci{ 253e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 254e1051a39Sopenharmony_ci EC_GROUP *group; 255e1051a39Sopenharmony_ci switch (type) { 256e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 257e1051a39Sopenharmony_ci group = EC_GROUP_new_by_curve_name(p1); 258e1051a39Sopenharmony_ci if (group == NULL) { 259e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); 260e1051a39Sopenharmony_ci return 0; 261e1051a39Sopenharmony_ci } 262e1051a39Sopenharmony_ci EC_GROUP_free(dctx->gen_group); 263e1051a39Sopenharmony_ci dctx->gen_group = group; 264e1051a39Sopenharmony_ci return 1; 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_PARAM_ENC: 267e1051a39Sopenharmony_ci if (!dctx->gen_group) { 268e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); 269e1051a39Sopenharmony_ci return 0; 270e1051a39Sopenharmony_ci } 271e1051a39Sopenharmony_ci EC_GROUP_set_asn1_flag(dctx->gen_group, p1); 272e1051a39Sopenharmony_ci return 1; 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 275e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_ECDH_COFACTOR: 276e1051a39Sopenharmony_ci if (p1 == -2) { 277e1051a39Sopenharmony_ci if (dctx->cofactor_mode != -1) 278e1051a39Sopenharmony_ci return dctx->cofactor_mode; 279e1051a39Sopenharmony_ci else { 280e1051a39Sopenharmony_ci const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ctx->pkey); 281e1051a39Sopenharmony_ci return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0; 282e1051a39Sopenharmony_ci } 283e1051a39Sopenharmony_ci } else if (p1 < -1 || p1 > 1) 284e1051a39Sopenharmony_ci return -2; 285e1051a39Sopenharmony_ci dctx->cofactor_mode = p1; 286e1051a39Sopenharmony_ci if (p1 != -1) { 287e1051a39Sopenharmony_ci EC_KEY *ec_key = (EC_KEY *)EVP_PKEY_get0_EC_KEY(ctx->pkey); 288e1051a39Sopenharmony_ci 289e1051a39Sopenharmony_ci /* 290e1051a39Sopenharmony_ci * We discarded the "const" above. This will only work if the key is 291e1051a39Sopenharmony_ci * a "real" legacy key, and not a cached copy of a provided key 292e1051a39Sopenharmony_ci */ 293e1051a39Sopenharmony_ci if (evp_pkey_is_provided(ctx->pkey)) { 294e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_UNSUPPORTED); 295e1051a39Sopenharmony_ci return 0; 296e1051a39Sopenharmony_ci } 297e1051a39Sopenharmony_ci if (!ec_key->group) 298e1051a39Sopenharmony_ci return -2; 299e1051a39Sopenharmony_ci /* If cofactor is 1 cofactor mode does nothing */ 300e1051a39Sopenharmony_ci if (BN_is_one(ec_key->group->cofactor)) 301e1051a39Sopenharmony_ci return 1; 302e1051a39Sopenharmony_ci if (!dctx->co_key) { 303e1051a39Sopenharmony_ci dctx->co_key = EC_KEY_dup(ec_key); 304e1051a39Sopenharmony_ci if (!dctx->co_key) 305e1051a39Sopenharmony_ci return 0; 306e1051a39Sopenharmony_ci } 307e1051a39Sopenharmony_ci if (p1) 308e1051a39Sopenharmony_ci EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); 309e1051a39Sopenharmony_ci else 310e1051a39Sopenharmony_ci EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH); 311e1051a39Sopenharmony_ci } else { 312e1051a39Sopenharmony_ci EC_KEY_free(dctx->co_key); 313e1051a39Sopenharmony_ci dctx->co_key = NULL; 314e1051a39Sopenharmony_ci } 315e1051a39Sopenharmony_ci return 1; 316e1051a39Sopenharmony_ci#endif 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_KDF_TYPE: 319e1051a39Sopenharmony_ci if (p1 == -2) 320e1051a39Sopenharmony_ci return dctx->kdf_type; 321e1051a39Sopenharmony_ci if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63) 322e1051a39Sopenharmony_ci return -2; 323e1051a39Sopenharmony_ci dctx->kdf_type = p1; 324e1051a39Sopenharmony_ci return 1; 325e1051a39Sopenharmony_ci 326e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_KDF_MD: 327e1051a39Sopenharmony_ci dctx->kdf_md = p2; 328e1051a39Sopenharmony_ci return 1; 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_GET_EC_KDF_MD: 331e1051a39Sopenharmony_ci *(const EVP_MD **)p2 = dctx->kdf_md; 332e1051a39Sopenharmony_ci return 1; 333e1051a39Sopenharmony_ci 334e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_KDF_OUTLEN: 335e1051a39Sopenharmony_ci if (p1 <= 0) 336e1051a39Sopenharmony_ci return -2; 337e1051a39Sopenharmony_ci dctx->kdf_outlen = (size_t)p1; 338e1051a39Sopenharmony_ci return 1; 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: 341e1051a39Sopenharmony_ci *(int *)p2 = dctx->kdf_outlen; 342e1051a39Sopenharmony_ci return 1; 343e1051a39Sopenharmony_ci 344e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_EC_KDF_UKM: 345e1051a39Sopenharmony_ci OPENSSL_free(dctx->kdf_ukm); 346e1051a39Sopenharmony_ci dctx->kdf_ukm = p2; 347e1051a39Sopenharmony_ci if (p2) 348e1051a39Sopenharmony_ci dctx->kdf_ukmlen = p1; 349e1051a39Sopenharmony_ci else 350e1051a39Sopenharmony_ci dctx->kdf_ukmlen = 0; 351e1051a39Sopenharmony_ci return 1; 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_GET_EC_KDF_UKM: 354e1051a39Sopenharmony_ci *(unsigned char **)p2 = dctx->kdf_ukm; 355e1051a39Sopenharmony_ci return dctx->kdf_ukmlen; 356e1051a39Sopenharmony_ci 357e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_MD: 358e1051a39Sopenharmony_ci if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 && 359e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && 360e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 && 361e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256 && 362e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha384 && 363e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha512 && 364e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_224 && 365e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_256 && 366e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_384 && 367e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_512 && 368e1051a39Sopenharmony_ci EVP_MD_get_type((const EVP_MD *)p2) != NID_sm3) { 369e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE); 370e1051a39Sopenharmony_ci return 0; 371e1051a39Sopenharmony_ci } 372e1051a39Sopenharmony_ci dctx->md = p2; 373e1051a39Sopenharmony_ci return 1; 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_GET_MD: 376e1051a39Sopenharmony_ci *(const EVP_MD **)p2 = dctx->md; 377e1051a39Sopenharmony_ci return 1; 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_PEER_KEY: 380e1051a39Sopenharmony_ci /* Default behaviour is OK */ 381e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_DIGESTINIT: 382e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_PKCS7_SIGN: 383e1051a39Sopenharmony_ci case EVP_PKEY_CTRL_CMS_SIGN: 384e1051a39Sopenharmony_ci return 1; 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_ci default: 387e1051a39Sopenharmony_ci return -2; 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci } 390e1051a39Sopenharmony_ci} 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_cistatic int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, 393e1051a39Sopenharmony_ci const char *type, const char *value) 394e1051a39Sopenharmony_ci{ 395e1051a39Sopenharmony_ci if (strcmp(type, "ec_paramgen_curve") == 0) { 396e1051a39Sopenharmony_ci int nid; 397e1051a39Sopenharmony_ci nid = EC_curve_nist2nid(value); 398e1051a39Sopenharmony_ci if (nid == NID_undef) 399e1051a39Sopenharmony_ci nid = OBJ_sn2nid(value); 400e1051a39Sopenharmony_ci if (nid == NID_undef) 401e1051a39Sopenharmony_ci nid = OBJ_ln2nid(value); 402e1051a39Sopenharmony_ci if (nid == NID_undef) { 403e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); 404e1051a39Sopenharmony_ci return 0; 405e1051a39Sopenharmony_ci } 406e1051a39Sopenharmony_ci return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); 407e1051a39Sopenharmony_ci } else if (strcmp(type, "ec_param_enc") == 0) { 408e1051a39Sopenharmony_ci int param_enc; 409e1051a39Sopenharmony_ci if (strcmp(value, "explicit") == 0) 410e1051a39Sopenharmony_ci param_enc = 0; 411e1051a39Sopenharmony_ci else if (strcmp(value, "named_curve") == 0) 412e1051a39Sopenharmony_ci param_enc = OPENSSL_EC_NAMED_CURVE; 413e1051a39Sopenharmony_ci else 414e1051a39Sopenharmony_ci return -2; 415e1051a39Sopenharmony_ci return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); 416e1051a39Sopenharmony_ci } else if (strcmp(type, "ecdh_kdf_md") == 0) { 417e1051a39Sopenharmony_ci const EVP_MD *md; 418e1051a39Sopenharmony_ci if ((md = EVP_get_digestbyname(value)) == NULL) { 419e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST); 420e1051a39Sopenharmony_ci return 0; 421e1051a39Sopenharmony_ci } 422e1051a39Sopenharmony_ci return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md); 423e1051a39Sopenharmony_ci } else if (strcmp(type, "ecdh_cofactor_mode") == 0) { 424e1051a39Sopenharmony_ci int co_mode; 425e1051a39Sopenharmony_ci co_mode = atoi(value); 426e1051a39Sopenharmony_ci return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode); 427e1051a39Sopenharmony_ci } 428e1051a39Sopenharmony_ci 429e1051a39Sopenharmony_ci return -2; 430e1051a39Sopenharmony_ci} 431e1051a39Sopenharmony_ci 432e1051a39Sopenharmony_cistatic int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 433e1051a39Sopenharmony_ci{ 434e1051a39Sopenharmony_ci EC_KEY *ec = NULL; 435e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 436e1051a39Sopenharmony_ci int ret; 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ci if (dctx->gen_group == NULL) { 439e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); 440e1051a39Sopenharmony_ci return 0; 441e1051a39Sopenharmony_ci } 442e1051a39Sopenharmony_ci ec = EC_KEY_new(); 443e1051a39Sopenharmony_ci if (ec == NULL) 444e1051a39Sopenharmony_ci return 0; 445e1051a39Sopenharmony_ci if (!(ret = EC_KEY_set_group(ec, dctx->gen_group)) 446e1051a39Sopenharmony_ci || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec))) 447e1051a39Sopenharmony_ci EC_KEY_free(ec); 448e1051a39Sopenharmony_ci return ret; 449e1051a39Sopenharmony_ci} 450e1051a39Sopenharmony_ci 451e1051a39Sopenharmony_cistatic int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 452e1051a39Sopenharmony_ci{ 453e1051a39Sopenharmony_ci EC_KEY *ec = NULL; 454e1051a39Sopenharmony_ci EC_PKEY_CTX *dctx = ctx->data; 455e1051a39Sopenharmony_ci int ret; 456e1051a39Sopenharmony_ci 457e1051a39Sopenharmony_ci if (ctx->pkey == NULL && dctx->gen_group == NULL) { 458e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET); 459e1051a39Sopenharmony_ci return 0; 460e1051a39Sopenharmony_ci } 461e1051a39Sopenharmony_ci ec = EC_KEY_new(); 462e1051a39Sopenharmony_ci if (ec == NULL) 463e1051a39Sopenharmony_ci return 0; 464e1051a39Sopenharmony_ci if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) { 465e1051a39Sopenharmony_ci EC_KEY_free(ec); 466e1051a39Sopenharmony_ci return 0; 467e1051a39Sopenharmony_ci } 468e1051a39Sopenharmony_ci /* Note: if error is returned, we count on caller to free pkey->pkey.ec */ 469e1051a39Sopenharmony_ci if (ctx->pkey != NULL) 470e1051a39Sopenharmony_ci ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey); 471e1051a39Sopenharmony_ci else 472e1051a39Sopenharmony_ci ret = EC_KEY_set_group(ec, dctx->gen_group); 473e1051a39Sopenharmony_ci 474e1051a39Sopenharmony_ci return ret ? EC_KEY_generate_key(ec) : 0; 475e1051a39Sopenharmony_ci} 476e1051a39Sopenharmony_ci 477e1051a39Sopenharmony_cistatic const EVP_PKEY_METHOD ec_pkey_meth = { 478e1051a39Sopenharmony_ci EVP_PKEY_EC, 479e1051a39Sopenharmony_ci 0, 480e1051a39Sopenharmony_ci pkey_ec_init, 481e1051a39Sopenharmony_ci pkey_ec_copy, 482e1051a39Sopenharmony_ci pkey_ec_cleanup, 483e1051a39Sopenharmony_ci 484e1051a39Sopenharmony_ci 0, 485e1051a39Sopenharmony_ci pkey_ec_paramgen, 486e1051a39Sopenharmony_ci 487e1051a39Sopenharmony_ci 0, 488e1051a39Sopenharmony_ci pkey_ec_keygen, 489e1051a39Sopenharmony_ci 490e1051a39Sopenharmony_ci 0, 491e1051a39Sopenharmony_ci pkey_ec_sign, 492e1051a39Sopenharmony_ci 493e1051a39Sopenharmony_ci 0, 494e1051a39Sopenharmony_ci pkey_ec_verify, 495e1051a39Sopenharmony_ci 496e1051a39Sopenharmony_ci 0, 0, 497e1051a39Sopenharmony_ci 498e1051a39Sopenharmony_ci 0, 0, 0, 0, 499e1051a39Sopenharmony_ci 500e1051a39Sopenharmony_ci 0, 501e1051a39Sopenharmony_ci 0, 502e1051a39Sopenharmony_ci 503e1051a39Sopenharmony_ci 0, 504e1051a39Sopenharmony_ci 0, 505e1051a39Sopenharmony_ci 506e1051a39Sopenharmony_ci 0, 507e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 508e1051a39Sopenharmony_ci pkey_ec_kdf_derive, 509e1051a39Sopenharmony_ci#else 510e1051a39Sopenharmony_ci 0, 511e1051a39Sopenharmony_ci#endif 512e1051a39Sopenharmony_ci pkey_ec_ctrl, 513e1051a39Sopenharmony_ci pkey_ec_ctrl_str 514e1051a39Sopenharmony_ci}; 515e1051a39Sopenharmony_ci 516e1051a39Sopenharmony_ciconst EVP_PKEY_METHOD *ossl_ec_pkey_method(void) 517e1051a39Sopenharmony_ci{ 518e1051a39Sopenharmony_ci return &ec_pkey_meth; 519e1051a39Sopenharmony_ci} 520