1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci/* 12e1051a39Sopenharmony_ci * EC_KEY low level APIs are deprecated for public use, but still ok for 13e1051a39Sopenharmony_ci * internal use. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci#include "internal/deprecated.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 18e1051a39Sopenharmony_ci#include <string.h> 19e1051a39Sopenharmony_ci#include "ec_local.h" 20e1051a39Sopenharmony_ci#include "internal/refcount.h" 21e1051a39Sopenharmony_ci#include <openssl/err.h> 22e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 23e1051a39Sopenharmony_ci# include <openssl/engine.h> 24e1051a39Sopenharmony_ci#endif 25e1051a39Sopenharmony_ci#include <openssl/self_test.h> 26e1051a39Sopenharmony_ci#include "prov/providercommon.h" 27e1051a39Sopenharmony_ci#include "crypto/bn.h" 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_cistatic int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, 30e1051a39Sopenharmony_ci void *cbarg); 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 33e1051a39Sopenharmony_ciEC_KEY *EC_KEY_new(void) 34e1051a39Sopenharmony_ci{ 35e1051a39Sopenharmony_ci return ossl_ec_key_new_method_int(NULL, NULL, NULL); 36e1051a39Sopenharmony_ci} 37e1051a39Sopenharmony_ci#endif 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ciEC_KEY *EC_KEY_new_ex(OSSL_LIB_CTX *ctx, const char *propq) 40e1051a39Sopenharmony_ci{ 41e1051a39Sopenharmony_ci return ossl_ec_key_new_method_int(ctx, propq, NULL); 42e1051a39Sopenharmony_ci} 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ciEC_KEY *EC_KEY_new_by_curve_name_ex(OSSL_LIB_CTX *ctx, const char *propq, 45e1051a39Sopenharmony_ci int nid) 46e1051a39Sopenharmony_ci{ 47e1051a39Sopenharmony_ci EC_KEY *ret = EC_KEY_new_ex(ctx, propq); 48e1051a39Sopenharmony_ci if (ret == NULL) 49e1051a39Sopenharmony_ci return NULL; 50e1051a39Sopenharmony_ci ret->group = EC_GROUP_new_by_curve_name_ex(ctx, propq, nid); 51e1051a39Sopenharmony_ci if (ret->group == NULL) { 52e1051a39Sopenharmony_ci EC_KEY_free(ret); 53e1051a39Sopenharmony_ci return NULL; 54e1051a39Sopenharmony_ci } 55e1051a39Sopenharmony_ci if (ret->meth->set_group != NULL 56e1051a39Sopenharmony_ci && ret->meth->set_group(ret, ret->group) == 0) { 57e1051a39Sopenharmony_ci EC_KEY_free(ret); 58e1051a39Sopenharmony_ci return NULL; 59e1051a39Sopenharmony_ci } 60e1051a39Sopenharmony_ci return ret; 61e1051a39Sopenharmony_ci} 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 64e1051a39Sopenharmony_ciEC_KEY *EC_KEY_new_by_curve_name(int nid) 65e1051a39Sopenharmony_ci{ 66e1051a39Sopenharmony_ci return EC_KEY_new_by_curve_name_ex(NULL, NULL, nid); 67e1051a39Sopenharmony_ci} 68e1051a39Sopenharmony_ci#endif 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_civoid EC_KEY_free(EC_KEY *r) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci int i; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci if (r == NULL) 75e1051a39Sopenharmony_ci return; 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci CRYPTO_DOWN_REF(&r->references, &i, r->lock); 78e1051a39Sopenharmony_ci REF_PRINT_COUNT("EC_KEY", r); 79e1051a39Sopenharmony_ci if (i > 0) 80e1051a39Sopenharmony_ci return; 81e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 0); 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci if (r->meth != NULL && r->meth->finish != NULL) 84e1051a39Sopenharmony_ci r->meth->finish(r); 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 87e1051a39Sopenharmony_ci ENGINE_finish(r->engine); 88e1051a39Sopenharmony_ci#endif 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci if (r->group && r->group->meth->keyfinish) 91e1051a39Sopenharmony_ci r->group->meth->keyfinish(r); 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 94e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); 95e1051a39Sopenharmony_ci#endif 96e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(r->lock); 97e1051a39Sopenharmony_ci EC_GROUP_free(r->group); 98e1051a39Sopenharmony_ci EC_POINT_free(r->pub_key); 99e1051a39Sopenharmony_ci BN_clear_free(r->priv_key); 100e1051a39Sopenharmony_ci OPENSSL_free(r->propq); 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci OPENSSL_clear_free((void *)r, sizeof(EC_KEY)); 103e1051a39Sopenharmony_ci} 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ciEC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) 106e1051a39Sopenharmony_ci{ 107e1051a39Sopenharmony_ci if (dest == NULL || src == NULL) { 108e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 109e1051a39Sopenharmony_ci return NULL; 110e1051a39Sopenharmony_ci } 111e1051a39Sopenharmony_ci if (src->meth != dest->meth) { 112e1051a39Sopenharmony_ci if (dest->meth->finish != NULL) 113e1051a39Sopenharmony_ci dest->meth->finish(dest); 114e1051a39Sopenharmony_ci if (dest->group && dest->group->meth->keyfinish) 115e1051a39Sopenharmony_ci dest->group->meth->keyfinish(dest); 116e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 117e1051a39Sopenharmony_ci if (ENGINE_finish(dest->engine) == 0) 118e1051a39Sopenharmony_ci return 0; 119e1051a39Sopenharmony_ci dest->engine = NULL; 120e1051a39Sopenharmony_ci#endif 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci dest->libctx = src->libctx; 123e1051a39Sopenharmony_ci /* copy the parameters */ 124e1051a39Sopenharmony_ci if (src->group != NULL) { 125e1051a39Sopenharmony_ci /* clear the old group */ 126e1051a39Sopenharmony_ci EC_GROUP_free(dest->group); 127e1051a39Sopenharmony_ci dest->group = ossl_ec_group_new_ex(src->libctx, src->propq, 128e1051a39Sopenharmony_ci src->group->meth); 129e1051a39Sopenharmony_ci if (dest->group == NULL) 130e1051a39Sopenharmony_ci return NULL; 131e1051a39Sopenharmony_ci if (!EC_GROUP_copy(dest->group, src->group)) 132e1051a39Sopenharmony_ci return NULL; 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci /* copy the public key */ 135e1051a39Sopenharmony_ci if (src->pub_key != NULL) { 136e1051a39Sopenharmony_ci EC_POINT_free(dest->pub_key); 137e1051a39Sopenharmony_ci dest->pub_key = EC_POINT_new(src->group); 138e1051a39Sopenharmony_ci if (dest->pub_key == NULL) 139e1051a39Sopenharmony_ci return NULL; 140e1051a39Sopenharmony_ci if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 141e1051a39Sopenharmony_ci return NULL; 142e1051a39Sopenharmony_ci } 143e1051a39Sopenharmony_ci /* copy the private key */ 144e1051a39Sopenharmony_ci if (src->priv_key != NULL) { 145e1051a39Sopenharmony_ci if (dest->priv_key == NULL) { 146e1051a39Sopenharmony_ci dest->priv_key = BN_new(); 147e1051a39Sopenharmony_ci if (dest->priv_key == NULL) 148e1051a39Sopenharmony_ci return NULL; 149e1051a39Sopenharmony_ci } 150e1051a39Sopenharmony_ci if (!BN_copy(dest->priv_key, src->priv_key)) 151e1051a39Sopenharmony_ci return NULL; 152e1051a39Sopenharmony_ci if (src->group->meth->keycopy 153e1051a39Sopenharmony_ci && src->group->meth->keycopy(dest, src) == 0) 154e1051a39Sopenharmony_ci return NULL; 155e1051a39Sopenharmony_ci } 156e1051a39Sopenharmony_ci } 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_ci /* copy the rest */ 160e1051a39Sopenharmony_ci dest->enc_flag = src->enc_flag; 161e1051a39Sopenharmony_ci dest->conv_form = src->conv_form; 162e1051a39Sopenharmony_ci dest->version = src->version; 163e1051a39Sopenharmony_ci dest->flags = src->flags; 164e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 165e1051a39Sopenharmony_ci if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, 166e1051a39Sopenharmony_ci &dest->ex_data, &src->ex_data)) 167e1051a39Sopenharmony_ci return NULL; 168e1051a39Sopenharmony_ci#endif 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci if (src->meth != dest->meth) { 171e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 172e1051a39Sopenharmony_ci if (src->engine != NULL && ENGINE_init(src->engine) == 0) 173e1051a39Sopenharmony_ci return NULL; 174e1051a39Sopenharmony_ci dest->engine = src->engine; 175e1051a39Sopenharmony_ci#endif 176e1051a39Sopenharmony_ci dest->meth = src->meth; 177e1051a39Sopenharmony_ci } 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) 180e1051a39Sopenharmony_ci return NULL; 181e1051a39Sopenharmony_ci 182e1051a39Sopenharmony_ci dest->dirty_cnt++; 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci return dest; 185e1051a39Sopenharmony_ci} 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ciEC_KEY *EC_KEY_dup(const EC_KEY *ec_key) 188e1051a39Sopenharmony_ci{ 189e1051a39Sopenharmony_ci return ossl_ec_key_dup(ec_key, OSSL_KEYMGMT_SELECT_ALL); 190e1051a39Sopenharmony_ci} 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ciint EC_KEY_up_ref(EC_KEY *r) 193e1051a39Sopenharmony_ci{ 194e1051a39Sopenharmony_ci int i; 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_ci if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) 197e1051a39Sopenharmony_ci return 0; 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_ci REF_PRINT_COUNT("EC_KEY", r); 200e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 2); 201e1051a39Sopenharmony_ci return ((i > 1) ? 1 : 0); 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ciENGINE *EC_KEY_get0_engine(const EC_KEY *eckey) 205e1051a39Sopenharmony_ci{ 206e1051a39Sopenharmony_ci return eckey->engine; 207e1051a39Sopenharmony_ci} 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ciint EC_KEY_generate_key(EC_KEY *eckey) 210e1051a39Sopenharmony_ci{ 211e1051a39Sopenharmony_ci if (eckey == NULL || eckey->group == NULL) { 212e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 213e1051a39Sopenharmony_ci return 0; 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci if (eckey->meth->keygen != NULL) { 216e1051a39Sopenharmony_ci int ret; 217e1051a39Sopenharmony_ci 218e1051a39Sopenharmony_ci ret = eckey->meth->keygen(eckey); 219e1051a39Sopenharmony_ci if (ret == 1) 220e1051a39Sopenharmony_ci eckey->dirty_cnt++; 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ci return ret; 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_OPERATION_NOT_SUPPORTED); 225e1051a39Sopenharmony_ci return 0; 226e1051a39Sopenharmony_ci} 227e1051a39Sopenharmony_ci 228e1051a39Sopenharmony_ciint ossl_ec_key_gen(EC_KEY *eckey) 229e1051a39Sopenharmony_ci{ 230e1051a39Sopenharmony_ci int ret; 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci ret = eckey->group->meth->keygen(eckey); 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ci if (ret == 1) 235e1051a39Sopenharmony_ci eckey->dirty_cnt++; 236e1051a39Sopenharmony_ci return ret; 237e1051a39Sopenharmony_ci} 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci/* 240e1051a39Sopenharmony_ci * ECC Key generation. 241e1051a39Sopenharmony_ci * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" 242e1051a39Sopenharmony_ci * 243e1051a39Sopenharmony_ci * Params: 244e1051a39Sopenharmony_ci * libctx A context containing an optional self test callback. 245e1051a39Sopenharmony_ci * eckey An EC key object that contains domain params. The generated keypair 246e1051a39Sopenharmony_ci * is stored in this object. 247e1051a39Sopenharmony_ci * pairwise_test Set to non zero to perform a pairwise test. If the test 248e1051a39Sopenharmony_ci * fails then the keypair is not generated, 249e1051a39Sopenharmony_ci * Returns 1 if the keypair was generated or 0 otherwise. 250e1051a39Sopenharmony_ci */ 251e1051a39Sopenharmony_cistatic int ec_generate_key(EC_KEY *eckey, int pairwise_test) 252e1051a39Sopenharmony_ci{ 253e1051a39Sopenharmony_ci int ok = 0; 254e1051a39Sopenharmony_ci BIGNUM *priv_key = NULL; 255e1051a39Sopenharmony_ci const BIGNUM *tmp = NULL; 256e1051a39Sopenharmony_ci BIGNUM *order = NULL; 257e1051a39Sopenharmony_ci EC_POINT *pub_key = NULL; 258e1051a39Sopenharmony_ci const EC_GROUP *group = eckey->group; 259e1051a39Sopenharmony_ci BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx); 260e1051a39Sopenharmony_ci int sm2 = EC_KEY_get_flags(eckey) & EC_FLAG_SM2_RANGE ? 1 : 0; 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci if (ctx == NULL) 263e1051a39Sopenharmony_ci goto err; 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci if (eckey->priv_key == NULL) { 266e1051a39Sopenharmony_ci priv_key = BN_secure_new(); 267e1051a39Sopenharmony_ci if (priv_key == NULL) 268e1051a39Sopenharmony_ci goto err; 269e1051a39Sopenharmony_ci } else 270e1051a39Sopenharmony_ci priv_key = eckey->priv_key; 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci /* 273e1051a39Sopenharmony_ci * Steps (1-2): Check domain parameters and security strength. 274e1051a39Sopenharmony_ci * These steps must be done by the user. This would need to be 275e1051a39Sopenharmony_ci * stated in the security policy. 276e1051a39Sopenharmony_ci */ 277e1051a39Sopenharmony_ci 278e1051a39Sopenharmony_ci tmp = EC_GROUP_get0_order(group); 279e1051a39Sopenharmony_ci if (tmp == NULL) 280e1051a39Sopenharmony_ci goto err; 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci /* 283e1051a39Sopenharmony_ci * Steps (3-7): priv_key = DRBG_RAND(order_n_bits) (range [1, n-1]). 284e1051a39Sopenharmony_ci * Although this is slightly different from the standard, it is effectively 285e1051a39Sopenharmony_ci * equivalent as it gives an unbiased result ranging from 1..n-1. It is also 286e1051a39Sopenharmony_ci * faster as the standard needs to retry more often. Also doing 287e1051a39Sopenharmony_ci * 1 + rand[0..n-2] would effect the way that tests feed dummy entropy into 288e1051a39Sopenharmony_ci * rand so the simpler backward compatible method has been used here. 289e1051a39Sopenharmony_ci */ 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ci /* range of SM2 private key is [1, n-1) */ 292e1051a39Sopenharmony_ci if (sm2) { 293e1051a39Sopenharmony_ci order = BN_new(); 294e1051a39Sopenharmony_ci if (order == NULL || !BN_sub(order, tmp, BN_value_one())) 295e1051a39Sopenharmony_ci goto err; 296e1051a39Sopenharmony_ci } else { 297e1051a39Sopenharmony_ci order = BN_dup(tmp); 298e1051a39Sopenharmony_ci if (order == NULL) 299e1051a39Sopenharmony_ci goto err; 300e1051a39Sopenharmony_ci } 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ci do 303e1051a39Sopenharmony_ci if (!BN_priv_rand_range_ex(priv_key, order, 0, ctx)) 304e1051a39Sopenharmony_ci goto err; 305e1051a39Sopenharmony_ci while (BN_is_zero(priv_key)) ; 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci if (eckey->pub_key == NULL) { 308e1051a39Sopenharmony_ci pub_key = EC_POINT_new(group); 309e1051a39Sopenharmony_ci if (pub_key == NULL) 310e1051a39Sopenharmony_ci goto err; 311e1051a39Sopenharmony_ci } else 312e1051a39Sopenharmony_ci pub_key = eckey->pub_key; 313e1051a39Sopenharmony_ci 314e1051a39Sopenharmony_ci /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */ 315e1051a39Sopenharmony_ci if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) 316e1051a39Sopenharmony_ci goto err; 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ci eckey->priv_key = priv_key; 319e1051a39Sopenharmony_ci eckey->pub_key = pub_key; 320e1051a39Sopenharmony_ci priv_key = NULL; 321e1051a39Sopenharmony_ci pub_key = NULL; 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci eckey->dirty_cnt++; 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 326e1051a39Sopenharmony_ci pairwise_test = 1; 327e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 328e1051a39Sopenharmony_ci 329e1051a39Sopenharmony_ci ok = 1; 330e1051a39Sopenharmony_ci if (pairwise_test) { 331e1051a39Sopenharmony_ci OSSL_CALLBACK *cb = NULL; 332e1051a39Sopenharmony_ci void *cbarg = NULL; 333e1051a39Sopenharmony_ci 334e1051a39Sopenharmony_ci OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg); 335e1051a39Sopenharmony_ci ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg); 336e1051a39Sopenharmony_ci } 337e1051a39Sopenharmony_cierr: 338e1051a39Sopenharmony_ci /* Step (9): If there is an error return an invalid keypair. */ 339e1051a39Sopenharmony_ci if (!ok) { 340e1051a39Sopenharmony_ci ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); 341e1051a39Sopenharmony_ci BN_clear(eckey->priv_key); 342e1051a39Sopenharmony_ci if (eckey->pub_key != NULL) 343e1051a39Sopenharmony_ci EC_POINT_set_to_infinity(group, eckey->pub_key); 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci EC_POINT_free(pub_key); 347e1051a39Sopenharmony_ci BN_clear_free(priv_key); 348e1051a39Sopenharmony_ci BN_CTX_free(ctx); 349e1051a39Sopenharmony_ci BN_free(order); 350e1051a39Sopenharmony_ci return ok; 351e1051a39Sopenharmony_ci} 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ciint ossl_ec_key_simple_generate_key(EC_KEY *eckey) 354e1051a39Sopenharmony_ci{ 355e1051a39Sopenharmony_ci return ec_generate_key(eckey, 0); 356e1051a39Sopenharmony_ci} 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ciint ossl_ec_key_simple_generate_public_key(EC_KEY *eckey) 359e1051a39Sopenharmony_ci{ 360e1051a39Sopenharmony_ci int ret; 361e1051a39Sopenharmony_ci BN_CTX *ctx = BN_CTX_new_ex(eckey->libctx); 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_ci if (ctx == NULL) 364e1051a39Sopenharmony_ci return 0; 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci /* 367e1051a39Sopenharmony_ci * See SP800-56AR3 5.6.1.2.2: Step (8) 368e1051a39Sopenharmony_ci * pub_key = priv_key * G (where G is a point on the curve) 369e1051a39Sopenharmony_ci */ 370e1051a39Sopenharmony_ci ret = EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, 371e1051a39Sopenharmony_ci NULL, ctx); 372e1051a39Sopenharmony_ci 373e1051a39Sopenharmony_ci BN_CTX_free(ctx); 374e1051a39Sopenharmony_ci if (ret == 1) 375e1051a39Sopenharmony_ci eckey->dirty_cnt++; 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ci return ret; 378e1051a39Sopenharmony_ci} 379e1051a39Sopenharmony_ci 380e1051a39Sopenharmony_ciint EC_KEY_check_key(const EC_KEY *eckey) 381e1051a39Sopenharmony_ci{ 382e1051a39Sopenharmony_ci if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { 383e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 384e1051a39Sopenharmony_ci return 0; 385e1051a39Sopenharmony_ci } 386e1051a39Sopenharmony_ci 387e1051a39Sopenharmony_ci if (eckey->group->meth->keycheck == NULL) { 388e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 389e1051a39Sopenharmony_ci return 0; 390e1051a39Sopenharmony_ci } 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci return eckey->group->meth->keycheck(eckey); 393e1051a39Sopenharmony_ci} 394e1051a39Sopenharmony_ci 395e1051a39Sopenharmony_ci/* 396e1051a39Sopenharmony_ci * Check the range of the EC public key. 397e1051a39Sopenharmony_ci * See SP800-56A R3 Section 5.6.2.3.3 (Part 2) 398e1051a39Sopenharmony_ci * i.e. 399e1051a39Sopenharmony_ci * - If q = odd prime p: Verify that xQ and yQ are integers in the 400e1051a39Sopenharmony_ci * interval[0, p - 1], OR 401e1051a39Sopenharmony_ci * - If q = 2m: Verify that xQ and yQ are bit strings of length m bits. 402e1051a39Sopenharmony_ci * Returns 1 if the public key has a valid range, otherwise it returns 0. 403e1051a39Sopenharmony_ci */ 404e1051a39Sopenharmony_cistatic int ec_key_public_range_check(BN_CTX *ctx, const EC_KEY *key) 405e1051a39Sopenharmony_ci{ 406e1051a39Sopenharmony_ci int ret = 0; 407e1051a39Sopenharmony_ci BIGNUM *x, *y; 408e1051a39Sopenharmony_ci 409e1051a39Sopenharmony_ci BN_CTX_start(ctx); 410e1051a39Sopenharmony_ci x = BN_CTX_get(ctx); 411e1051a39Sopenharmony_ci y = BN_CTX_get(ctx); 412e1051a39Sopenharmony_ci if (y == NULL) 413e1051a39Sopenharmony_ci goto err; 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ci if (!EC_POINT_get_affine_coordinates(key->group, key->pub_key, x, y, ctx)) 416e1051a39Sopenharmony_ci goto err; 417e1051a39Sopenharmony_ci 418e1051a39Sopenharmony_ci if (EC_GROUP_get_field_type(key->group) == NID_X9_62_prime_field) { 419e1051a39Sopenharmony_ci if (BN_is_negative(x) 420e1051a39Sopenharmony_ci || BN_cmp(x, key->group->field) >= 0 421e1051a39Sopenharmony_ci || BN_is_negative(y) 422e1051a39Sopenharmony_ci || BN_cmp(y, key->group->field) >= 0) { 423e1051a39Sopenharmony_ci goto err; 424e1051a39Sopenharmony_ci } 425e1051a39Sopenharmony_ci } else { 426e1051a39Sopenharmony_ci int m = EC_GROUP_get_degree(key->group); 427e1051a39Sopenharmony_ci if (BN_num_bits(x) > m || BN_num_bits(y) > m) { 428e1051a39Sopenharmony_ci goto err; 429e1051a39Sopenharmony_ci } 430e1051a39Sopenharmony_ci } 431e1051a39Sopenharmony_ci ret = 1; 432e1051a39Sopenharmony_cierr: 433e1051a39Sopenharmony_ci BN_CTX_end(ctx); 434e1051a39Sopenharmony_ci return ret; 435e1051a39Sopenharmony_ci} 436e1051a39Sopenharmony_ci 437e1051a39Sopenharmony_ci/* 438e1051a39Sopenharmony_ci * ECC Partial Public-Key Validation as specified in SP800-56A R3 439e1051a39Sopenharmony_ci * Section 5.6.2.3.4 ECC Partial Public-Key Validation Routine. 440e1051a39Sopenharmony_ci */ 441e1051a39Sopenharmony_ciint ossl_ec_key_public_check_quick(const EC_KEY *eckey, BN_CTX *ctx) 442e1051a39Sopenharmony_ci{ 443e1051a39Sopenharmony_ci if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { 444e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 445e1051a39Sopenharmony_ci return 0; 446e1051a39Sopenharmony_ci } 447e1051a39Sopenharmony_ci 448e1051a39Sopenharmony_ci /* 5.6.2.3.3 (Step 1): Q != infinity */ 449e1051a39Sopenharmony_ci if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 450e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); 451e1051a39Sopenharmony_ci return 0; 452e1051a39Sopenharmony_ci } 453e1051a39Sopenharmony_ci 454e1051a39Sopenharmony_ci /* 5.6.2.3.3 (Step 2) Test if the public key is in range */ 455e1051a39Sopenharmony_ci if (!ec_key_public_range_check(ctx, eckey)) { 456e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); 457e1051a39Sopenharmony_ci return 0; 458e1051a39Sopenharmony_ci } 459e1051a39Sopenharmony_ci 460e1051a39Sopenharmony_ci /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */ 461e1051a39Sopenharmony_ci if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { 462e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE); 463e1051a39Sopenharmony_ci return 0; 464e1051a39Sopenharmony_ci } 465e1051a39Sopenharmony_ci return 1; 466e1051a39Sopenharmony_ci} 467e1051a39Sopenharmony_ci 468e1051a39Sopenharmony_ci/* 469e1051a39Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3. 470e1051a39Sopenharmony_ci * Section 5.6.2.3.3 ECC Full Public-Key Validation Routine. 471e1051a39Sopenharmony_ci */ 472e1051a39Sopenharmony_ciint ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx) 473e1051a39Sopenharmony_ci{ 474e1051a39Sopenharmony_ci int ret = 0; 475e1051a39Sopenharmony_ci EC_POINT *point = NULL; 476e1051a39Sopenharmony_ci const BIGNUM *order = NULL; 477e1051a39Sopenharmony_ci 478e1051a39Sopenharmony_ci if (!ossl_ec_key_public_check_quick(eckey, ctx)) 479e1051a39Sopenharmony_ci return 0; 480e1051a39Sopenharmony_ci 481e1051a39Sopenharmony_ci point = EC_POINT_new(eckey->group); 482e1051a39Sopenharmony_ci if (point == NULL) 483e1051a39Sopenharmony_ci return 0; 484e1051a39Sopenharmony_ci 485e1051a39Sopenharmony_ci order = eckey->group->order; 486e1051a39Sopenharmony_ci if (BN_is_zero(order)) { 487e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); 488e1051a39Sopenharmony_ci goto err; 489e1051a39Sopenharmony_ci } 490e1051a39Sopenharmony_ci /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */ 491e1051a39Sopenharmony_ci if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { 492e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 493e1051a39Sopenharmony_ci goto err; 494e1051a39Sopenharmony_ci } 495e1051a39Sopenharmony_ci if (!EC_POINT_is_at_infinity(eckey->group, point)) { 496e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_WRONG_ORDER); 497e1051a39Sopenharmony_ci goto err; 498e1051a39Sopenharmony_ci } 499e1051a39Sopenharmony_ci ret = 1; 500e1051a39Sopenharmony_cierr: 501e1051a39Sopenharmony_ci EC_POINT_free(point); 502e1051a39Sopenharmony_ci return ret; 503e1051a39Sopenharmony_ci} 504e1051a39Sopenharmony_ci 505e1051a39Sopenharmony_ci/* 506e1051a39Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3. 507e1051a39Sopenharmony_ci * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity 508e1051a39Sopenharmony_ci * The private key is in the range [1, order-1] 509e1051a39Sopenharmony_ci */ 510e1051a39Sopenharmony_ciint ossl_ec_key_private_check(const EC_KEY *eckey) 511e1051a39Sopenharmony_ci{ 512e1051a39Sopenharmony_ci if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) { 513e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 514e1051a39Sopenharmony_ci return 0; 515e1051a39Sopenharmony_ci } 516e1051a39Sopenharmony_ci if (BN_cmp(eckey->priv_key, BN_value_one()) < 0 517e1051a39Sopenharmony_ci || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) { 518e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); 519e1051a39Sopenharmony_ci return 0; 520e1051a39Sopenharmony_ci } 521e1051a39Sopenharmony_ci return 1; 522e1051a39Sopenharmony_ci} 523e1051a39Sopenharmony_ci 524e1051a39Sopenharmony_ci/* 525e1051a39Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3. 526e1051a39Sopenharmony_ci * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b) 527e1051a39Sopenharmony_ci * Check if generator * priv_key = pub_key 528e1051a39Sopenharmony_ci */ 529e1051a39Sopenharmony_ciint ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx) 530e1051a39Sopenharmony_ci{ 531e1051a39Sopenharmony_ci int ret = 0; 532e1051a39Sopenharmony_ci EC_POINT *point = NULL; 533e1051a39Sopenharmony_ci 534e1051a39Sopenharmony_ci if (eckey == NULL 535e1051a39Sopenharmony_ci || eckey->group == NULL 536e1051a39Sopenharmony_ci || eckey->pub_key == NULL 537e1051a39Sopenharmony_ci || eckey->priv_key == NULL) { 538e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 539e1051a39Sopenharmony_ci return 0; 540e1051a39Sopenharmony_ci } 541e1051a39Sopenharmony_ci 542e1051a39Sopenharmony_ci point = EC_POINT_new(eckey->group); 543e1051a39Sopenharmony_ci if (point == NULL) 544e1051a39Sopenharmony_ci goto err; 545e1051a39Sopenharmony_ci 546e1051a39Sopenharmony_ci 547e1051a39Sopenharmony_ci if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { 548e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 549e1051a39Sopenharmony_ci goto err; 550e1051a39Sopenharmony_ci } 551e1051a39Sopenharmony_ci if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 552e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY); 553e1051a39Sopenharmony_ci goto err; 554e1051a39Sopenharmony_ci } 555e1051a39Sopenharmony_ci ret = 1; 556e1051a39Sopenharmony_cierr: 557e1051a39Sopenharmony_ci EC_POINT_free(point); 558e1051a39Sopenharmony_ci return ret; 559e1051a39Sopenharmony_ci} 560e1051a39Sopenharmony_ci 561e1051a39Sopenharmony_ci 562e1051a39Sopenharmony_ci/* 563e1051a39Sopenharmony_ci * ECC Key validation as specified in SP800-56A R3. 564e1051a39Sopenharmony_ci * Section 5.6.2.3.3 ECC Full Public-Key Validation 565e1051a39Sopenharmony_ci * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity 566e1051a39Sopenharmony_ci * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency 567e1051a39Sopenharmony_ci * NOTES: 568e1051a39Sopenharmony_ci * Before calling this method in fips mode, there should be an assurance that 569e1051a39Sopenharmony_ci * an approved elliptic-curve group is used. 570e1051a39Sopenharmony_ci * Returns 1 if the key is valid, otherwise it returns 0. 571e1051a39Sopenharmony_ci */ 572e1051a39Sopenharmony_ciint ossl_ec_key_simple_check_key(const EC_KEY *eckey) 573e1051a39Sopenharmony_ci{ 574e1051a39Sopenharmony_ci int ok = 0; 575e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 576e1051a39Sopenharmony_ci 577e1051a39Sopenharmony_ci if (eckey == NULL) { 578e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 579e1051a39Sopenharmony_ci return 0; 580e1051a39Sopenharmony_ci } 581e1051a39Sopenharmony_ci if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) 582e1051a39Sopenharmony_ci return 0; 583e1051a39Sopenharmony_ci 584e1051a39Sopenharmony_ci if (!ossl_ec_key_public_check(eckey, ctx)) 585e1051a39Sopenharmony_ci goto err; 586e1051a39Sopenharmony_ci 587e1051a39Sopenharmony_ci if (eckey->priv_key != NULL) { 588e1051a39Sopenharmony_ci if (!ossl_ec_key_private_check(eckey) 589e1051a39Sopenharmony_ci || !ossl_ec_key_pairwise_check(eckey, ctx)) 590e1051a39Sopenharmony_ci goto err; 591e1051a39Sopenharmony_ci } 592e1051a39Sopenharmony_ci ok = 1; 593e1051a39Sopenharmony_cierr: 594e1051a39Sopenharmony_ci BN_CTX_free(ctx); 595e1051a39Sopenharmony_ci return ok; 596e1051a39Sopenharmony_ci} 597e1051a39Sopenharmony_ci 598e1051a39Sopenharmony_ciint EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, 599e1051a39Sopenharmony_ci BIGNUM *y) 600e1051a39Sopenharmony_ci{ 601e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 602e1051a39Sopenharmony_ci BIGNUM *tx, *ty; 603e1051a39Sopenharmony_ci EC_POINT *point = NULL; 604e1051a39Sopenharmony_ci int ok = 0; 605e1051a39Sopenharmony_ci 606e1051a39Sopenharmony_ci if (key == NULL || key->group == NULL || x == NULL || y == NULL) { 607e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 608e1051a39Sopenharmony_ci return 0; 609e1051a39Sopenharmony_ci } 610e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(key->libctx); 611e1051a39Sopenharmony_ci if (ctx == NULL) 612e1051a39Sopenharmony_ci return 0; 613e1051a39Sopenharmony_ci 614e1051a39Sopenharmony_ci BN_CTX_start(ctx); 615e1051a39Sopenharmony_ci point = EC_POINT_new(key->group); 616e1051a39Sopenharmony_ci 617e1051a39Sopenharmony_ci if (point == NULL) 618e1051a39Sopenharmony_ci goto err; 619e1051a39Sopenharmony_ci 620e1051a39Sopenharmony_ci tx = BN_CTX_get(ctx); 621e1051a39Sopenharmony_ci ty = BN_CTX_get(ctx); 622e1051a39Sopenharmony_ci if (ty == NULL) 623e1051a39Sopenharmony_ci goto err; 624e1051a39Sopenharmony_ci 625e1051a39Sopenharmony_ci if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) 626e1051a39Sopenharmony_ci goto err; 627e1051a39Sopenharmony_ci if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) 628e1051a39Sopenharmony_ci goto err; 629e1051a39Sopenharmony_ci 630e1051a39Sopenharmony_ci /* 631e1051a39Sopenharmony_ci * Check if retrieved coordinates match originals. The range check is done 632e1051a39Sopenharmony_ci * inside EC_KEY_check_key(). 633e1051a39Sopenharmony_ci */ 634e1051a39Sopenharmony_ci if (BN_cmp(x, tx) || BN_cmp(y, ty)) { 635e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_COORDINATES_OUT_OF_RANGE); 636e1051a39Sopenharmony_ci goto err; 637e1051a39Sopenharmony_ci } 638e1051a39Sopenharmony_ci 639e1051a39Sopenharmony_ci /* EC_KEY_set_public_key updates dirty_cnt */ 640e1051a39Sopenharmony_ci if (!EC_KEY_set_public_key(key, point)) 641e1051a39Sopenharmony_ci goto err; 642e1051a39Sopenharmony_ci 643e1051a39Sopenharmony_ci if (EC_KEY_check_key(key) == 0) 644e1051a39Sopenharmony_ci goto err; 645e1051a39Sopenharmony_ci 646e1051a39Sopenharmony_ci ok = 1; 647e1051a39Sopenharmony_ci 648e1051a39Sopenharmony_ci err: 649e1051a39Sopenharmony_ci BN_CTX_end(ctx); 650e1051a39Sopenharmony_ci BN_CTX_free(ctx); 651e1051a39Sopenharmony_ci EC_POINT_free(point); 652e1051a39Sopenharmony_ci return ok; 653e1051a39Sopenharmony_ci 654e1051a39Sopenharmony_ci} 655e1051a39Sopenharmony_ci 656e1051a39Sopenharmony_ciOSSL_LIB_CTX *ossl_ec_key_get_libctx(const EC_KEY *key) 657e1051a39Sopenharmony_ci{ 658e1051a39Sopenharmony_ci return key->libctx; 659e1051a39Sopenharmony_ci} 660e1051a39Sopenharmony_ci 661e1051a39Sopenharmony_ciconst char *ossl_ec_key_get0_propq(const EC_KEY *key) 662e1051a39Sopenharmony_ci{ 663e1051a39Sopenharmony_ci return key->propq; 664e1051a39Sopenharmony_ci} 665e1051a39Sopenharmony_ci 666e1051a39Sopenharmony_civoid ossl_ec_key_set0_libctx(EC_KEY *key, OSSL_LIB_CTX *libctx) 667e1051a39Sopenharmony_ci{ 668e1051a39Sopenharmony_ci key->libctx = libctx; 669e1051a39Sopenharmony_ci /* Do we need to propagate this to the group? */ 670e1051a39Sopenharmony_ci} 671e1051a39Sopenharmony_ci 672e1051a39Sopenharmony_ciconst EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) 673e1051a39Sopenharmony_ci{ 674e1051a39Sopenharmony_ci return key->group; 675e1051a39Sopenharmony_ci} 676e1051a39Sopenharmony_ci 677e1051a39Sopenharmony_ciint EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) 678e1051a39Sopenharmony_ci{ 679e1051a39Sopenharmony_ci if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0) 680e1051a39Sopenharmony_ci return 0; 681e1051a39Sopenharmony_ci EC_GROUP_free(key->group); 682e1051a39Sopenharmony_ci key->group = EC_GROUP_dup(group); 683e1051a39Sopenharmony_ci if (key->group != NULL && EC_GROUP_get_curve_name(key->group) == NID_sm2) 684e1051a39Sopenharmony_ci EC_KEY_set_flags(key, EC_FLAG_SM2_RANGE); 685e1051a39Sopenharmony_ci 686e1051a39Sopenharmony_ci key->dirty_cnt++; 687e1051a39Sopenharmony_ci return (key->group == NULL) ? 0 : 1; 688e1051a39Sopenharmony_ci} 689e1051a39Sopenharmony_ci 690e1051a39Sopenharmony_ciconst BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) 691e1051a39Sopenharmony_ci{ 692e1051a39Sopenharmony_ci return key->priv_key; 693e1051a39Sopenharmony_ci} 694e1051a39Sopenharmony_ci 695e1051a39Sopenharmony_ciint EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) 696e1051a39Sopenharmony_ci{ 697e1051a39Sopenharmony_ci int fixed_top; 698e1051a39Sopenharmony_ci const BIGNUM *order = NULL; 699e1051a39Sopenharmony_ci BIGNUM *tmp_key = NULL; 700e1051a39Sopenharmony_ci 701e1051a39Sopenharmony_ci if (key->group == NULL || key->group->meth == NULL) 702e1051a39Sopenharmony_ci return 0; 703e1051a39Sopenharmony_ci 704e1051a39Sopenharmony_ci /* 705e1051a39Sopenharmony_ci * Not only should key->group be set, but it should also be in a valid 706e1051a39Sopenharmony_ci * fully initialized state. 707e1051a39Sopenharmony_ci * 708e1051a39Sopenharmony_ci * Specifically, to operate in constant time, we need that the group order 709e1051a39Sopenharmony_ci * is set, as we use its length as the fixed public size of any scalar used 710e1051a39Sopenharmony_ci * as an EC private key. 711e1051a39Sopenharmony_ci */ 712e1051a39Sopenharmony_ci order = EC_GROUP_get0_order(key->group); 713e1051a39Sopenharmony_ci if (order == NULL || BN_is_zero(order)) 714e1051a39Sopenharmony_ci return 0; /* This should never happen */ 715e1051a39Sopenharmony_ci 716e1051a39Sopenharmony_ci if (key->group->meth->set_private != NULL 717e1051a39Sopenharmony_ci && key->group->meth->set_private(key, priv_key) == 0) 718e1051a39Sopenharmony_ci return 0; 719e1051a39Sopenharmony_ci if (key->meth->set_private != NULL 720e1051a39Sopenharmony_ci && key->meth->set_private(key, priv_key) == 0) 721e1051a39Sopenharmony_ci return 0; 722e1051a39Sopenharmony_ci 723e1051a39Sopenharmony_ci /* 724e1051a39Sopenharmony_ci * Return `0` to comply with legacy behavior for this function, see 725e1051a39Sopenharmony_ci * https://github.com/openssl/openssl/issues/18744#issuecomment-1195175696 726e1051a39Sopenharmony_ci */ 727e1051a39Sopenharmony_ci if (priv_key == NULL) { 728e1051a39Sopenharmony_ci BN_clear_free(key->priv_key); 729e1051a39Sopenharmony_ci key->priv_key = NULL; 730e1051a39Sopenharmony_ci return 0; /* intentional for legacy compatibility */ 731e1051a39Sopenharmony_ci } 732e1051a39Sopenharmony_ci 733e1051a39Sopenharmony_ci /* 734e1051a39Sopenharmony_ci * We should never leak the bit length of the secret scalar in the key, 735e1051a39Sopenharmony_ci * so we always set the `BN_FLG_CONSTTIME` flag on the internal `BIGNUM` 736e1051a39Sopenharmony_ci * holding the secret scalar. 737e1051a39Sopenharmony_ci * 738e1051a39Sopenharmony_ci * This is important also because `BN_dup()` (and `BN_copy()`) do not 739e1051a39Sopenharmony_ci * propagate the `BN_FLG_CONSTTIME` flag from the source `BIGNUM`, and 740e1051a39Sopenharmony_ci * this brings an extra risk of inadvertently losing the flag, even when 741e1051a39Sopenharmony_ci * the caller specifically set it. 742e1051a39Sopenharmony_ci * 743e1051a39Sopenharmony_ci * The propagation has been turned on and off a few times in the past 744e1051a39Sopenharmony_ci * years because in some conditions has shown unintended consequences in 745e1051a39Sopenharmony_ci * some code paths, so at the moment we can't fix this in the BN layer. 746e1051a39Sopenharmony_ci * 747e1051a39Sopenharmony_ci * In `EC_KEY_set_private_key()` we can work around the propagation by 748e1051a39Sopenharmony_ci * manually setting the flag after `BN_dup()` as we know for sure that 749e1051a39Sopenharmony_ci * inside the EC module the `BN_FLG_CONSTTIME` is always treated 750e1051a39Sopenharmony_ci * correctly and should not generate unintended consequences. 751e1051a39Sopenharmony_ci * 752e1051a39Sopenharmony_ci * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have 753e1051a39Sopenharmony_ci * to preallocate the BIGNUM internal buffer to a fixed public size big 754e1051a39Sopenharmony_ci * enough that operations performed during the processing never trigger 755e1051a39Sopenharmony_ci * a realloc which would leak the size of the scalar through memory 756e1051a39Sopenharmony_ci * accesses. 757e1051a39Sopenharmony_ci * 758e1051a39Sopenharmony_ci * Fixed Length 759e1051a39Sopenharmony_ci * ------------ 760e1051a39Sopenharmony_ci * 761e1051a39Sopenharmony_ci * The order of the large prime subgroup of the curve is our choice for 762e1051a39Sopenharmony_ci * a fixed public size, as that is generally the upper bound for 763e1051a39Sopenharmony_ci * generating a private key in EC cryptosystems and should fit all valid 764e1051a39Sopenharmony_ci * secret scalars. 765e1051a39Sopenharmony_ci * 766e1051a39Sopenharmony_ci * For preallocating the BIGNUM storage we look at the number of "words" 767e1051a39Sopenharmony_ci * required for the internal representation of the order, and we 768e1051a39Sopenharmony_ci * preallocate 2 extra "words" in case any of the subsequent processing 769e1051a39Sopenharmony_ci * might temporarily overflow the order length. 770e1051a39Sopenharmony_ci */ 771e1051a39Sopenharmony_ci tmp_key = BN_dup(priv_key); 772e1051a39Sopenharmony_ci if (tmp_key == NULL) 773e1051a39Sopenharmony_ci return 0; 774e1051a39Sopenharmony_ci 775e1051a39Sopenharmony_ci BN_set_flags(tmp_key, BN_FLG_CONSTTIME); 776e1051a39Sopenharmony_ci 777e1051a39Sopenharmony_ci fixed_top = bn_get_top(order) + 2; 778e1051a39Sopenharmony_ci if (bn_wexpand(tmp_key, fixed_top) == NULL) { 779e1051a39Sopenharmony_ci BN_clear_free(tmp_key); 780e1051a39Sopenharmony_ci return 0; 781e1051a39Sopenharmony_ci } 782e1051a39Sopenharmony_ci 783e1051a39Sopenharmony_ci BN_clear_free(key->priv_key); 784e1051a39Sopenharmony_ci key->priv_key = tmp_key; 785e1051a39Sopenharmony_ci key->dirty_cnt++; 786e1051a39Sopenharmony_ci 787e1051a39Sopenharmony_ci return 1; 788e1051a39Sopenharmony_ci} 789e1051a39Sopenharmony_ci 790e1051a39Sopenharmony_ciconst EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) 791e1051a39Sopenharmony_ci{ 792e1051a39Sopenharmony_ci return key->pub_key; 793e1051a39Sopenharmony_ci} 794e1051a39Sopenharmony_ci 795e1051a39Sopenharmony_ciint EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) 796e1051a39Sopenharmony_ci{ 797e1051a39Sopenharmony_ci if (key->meth->set_public != NULL 798e1051a39Sopenharmony_ci && key->meth->set_public(key, pub_key) == 0) 799e1051a39Sopenharmony_ci return 0; 800e1051a39Sopenharmony_ci EC_POINT_free(key->pub_key); 801e1051a39Sopenharmony_ci key->pub_key = EC_POINT_dup(pub_key, key->group); 802e1051a39Sopenharmony_ci key->dirty_cnt++; 803e1051a39Sopenharmony_ci return (key->pub_key == NULL) ? 0 : 1; 804e1051a39Sopenharmony_ci} 805e1051a39Sopenharmony_ci 806e1051a39Sopenharmony_ciunsigned int EC_KEY_get_enc_flags(const EC_KEY *key) 807e1051a39Sopenharmony_ci{ 808e1051a39Sopenharmony_ci return key->enc_flag; 809e1051a39Sopenharmony_ci} 810e1051a39Sopenharmony_ci 811e1051a39Sopenharmony_civoid EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) 812e1051a39Sopenharmony_ci{ 813e1051a39Sopenharmony_ci key->enc_flag = flags; 814e1051a39Sopenharmony_ci} 815e1051a39Sopenharmony_ci 816e1051a39Sopenharmony_cipoint_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) 817e1051a39Sopenharmony_ci{ 818e1051a39Sopenharmony_ci return key->conv_form; 819e1051a39Sopenharmony_ci} 820e1051a39Sopenharmony_ci 821e1051a39Sopenharmony_civoid EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) 822e1051a39Sopenharmony_ci{ 823e1051a39Sopenharmony_ci key->conv_form = cform; 824e1051a39Sopenharmony_ci if (key->group != NULL) 825e1051a39Sopenharmony_ci EC_GROUP_set_point_conversion_form(key->group, cform); 826e1051a39Sopenharmony_ci} 827e1051a39Sopenharmony_ci 828e1051a39Sopenharmony_civoid EC_KEY_set_asn1_flag(EC_KEY *key, int flag) 829e1051a39Sopenharmony_ci{ 830e1051a39Sopenharmony_ci if (key->group != NULL) 831e1051a39Sopenharmony_ci EC_GROUP_set_asn1_flag(key->group, flag); 832e1051a39Sopenharmony_ci} 833e1051a39Sopenharmony_ci 834e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 835e1051a39Sopenharmony_ciint EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) 836e1051a39Sopenharmony_ci{ 837e1051a39Sopenharmony_ci if (key->group == NULL) 838e1051a39Sopenharmony_ci return 0; 839e1051a39Sopenharmony_ci return EC_GROUP_precompute_mult(key->group, ctx); 840e1051a39Sopenharmony_ci} 841e1051a39Sopenharmony_ci#endif 842e1051a39Sopenharmony_ci 843e1051a39Sopenharmony_ciint EC_KEY_get_flags(const EC_KEY *key) 844e1051a39Sopenharmony_ci{ 845e1051a39Sopenharmony_ci return key->flags; 846e1051a39Sopenharmony_ci} 847e1051a39Sopenharmony_ci 848e1051a39Sopenharmony_civoid EC_KEY_set_flags(EC_KEY *key, int flags) 849e1051a39Sopenharmony_ci{ 850e1051a39Sopenharmony_ci key->flags |= flags; 851e1051a39Sopenharmony_ci key->dirty_cnt++; 852e1051a39Sopenharmony_ci} 853e1051a39Sopenharmony_ci 854e1051a39Sopenharmony_civoid EC_KEY_clear_flags(EC_KEY *key, int flags) 855e1051a39Sopenharmony_ci{ 856e1051a39Sopenharmony_ci key->flags &= ~flags; 857e1051a39Sopenharmony_ci key->dirty_cnt++; 858e1051a39Sopenharmony_ci} 859e1051a39Sopenharmony_ci 860e1051a39Sopenharmony_ciint EC_KEY_decoded_from_explicit_params(const EC_KEY *key) 861e1051a39Sopenharmony_ci{ 862e1051a39Sopenharmony_ci if (key == NULL || key->group == NULL) 863e1051a39Sopenharmony_ci return -1; 864e1051a39Sopenharmony_ci return key->group->decoded_from_explicit_params; 865e1051a39Sopenharmony_ci} 866e1051a39Sopenharmony_ci 867e1051a39Sopenharmony_cisize_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, 868e1051a39Sopenharmony_ci unsigned char **pbuf, BN_CTX *ctx) 869e1051a39Sopenharmony_ci{ 870e1051a39Sopenharmony_ci if (key == NULL || key->pub_key == NULL || key->group == NULL) 871e1051a39Sopenharmony_ci return 0; 872e1051a39Sopenharmony_ci return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx); 873e1051a39Sopenharmony_ci} 874e1051a39Sopenharmony_ci 875e1051a39Sopenharmony_ciint EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, 876e1051a39Sopenharmony_ci BN_CTX *ctx) 877e1051a39Sopenharmony_ci{ 878e1051a39Sopenharmony_ci if (key == NULL || key->group == NULL) 879e1051a39Sopenharmony_ci return 0; 880e1051a39Sopenharmony_ci if (key->pub_key == NULL) 881e1051a39Sopenharmony_ci key->pub_key = EC_POINT_new(key->group); 882e1051a39Sopenharmony_ci if (key->pub_key == NULL) 883e1051a39Sopenharmony_ci return 0; 884e1051a39Sopenharmony_ci if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0) 885e1051a39Sopenharmony_ci return 0; 886e1051a39Sopenharmony_ci key->dirty_cnt++; 887e1051a39Sopenharmony_ci /* 888e1051a39Sopenharmony_ci * Save the point conversion form. 889e1051a39Sopenharmony_ci * For non-custom curves the first octet of the buffer (excluding 890e1051a39Sopenharmony_ci * the last significant bit) contains the point conversion form. 891e1051a39Sopenharmony_ci * EC_POINT_oct2point() has already performed sanity checking of 892e1051a39Sopenharmony_ci * the buffer so we know it is valid. 893e1051a39Sopenharmony_ci */ 894e1051a39Sopenharmony_ci if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) 895e1051a39Sopenharmony_ci key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01); 896e1051a39Sopenharmony_ci return 1; 897e1051a39Sopenharmony_ci} 898e1051a39Sopenharmony_ci 899e1051a39Sopenharmony_cisize_t EC_KEY_priv2oct(const EC_KEY *eckey, 900e1051a39Sopenharmony_ci unsigned char *buf, size_t len) 901e1051a39Sopenharmony_ci{ 902e1051a39Sopenharmony_ci if (eckey->group == NULL || eckey->group->meth == NULL) 903e1051a39Sopenharmony_ci return 0; 904e1051a39Sopenharmony_ci if (eckey->group->meth->priv2oct == NULL) { 905e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 906e1051a39Sopenharmony_ci return 0; 907e1051a39Sopenharmony_ci } 908e1051a39Sopenharmony_ci 909e1051a39Sopenharmony_ci return eckey->group->meth->priv2oct(eckey, buf, len); 910e1051a39Sopenharmony_ci} 911e1051a39Sopenharmony_ci 912e1051a39Sopenharmony_cisize_t ossl_ec_key_simple_priv2oct(const EC_KEY *eckey, 913e1051a39Sopenharmony_ci unsigned char *buf, size_t len) 914e1051a39Sopenharmony_ci{ 915e1051a39Sopenharmony_ci size_t buf_len; 916e1051a39Sopenharmony_ci 917e1051a39Sopenharmony_ci buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8; 918e1051a39Sopenharmony_ci if (eckey->priv_key == NULL) 919e1051a39Sopenharmony_ci return 0; 920e1051a39Sopenharmony_ci if (buf == NULL) 921e1051a39Sopenharmony_ci return buf_len; 922e1051a39Sopenharmony_ci else if (len < buf_len) 923e1051a39Sopenharmony_ci return 0; 924e1051a39Sopenharmony_ci 925e1051a39Sopenharmony_ci /* Octetstring may need leading zeros if BN is to short */ 926e1051a39Sopenharmony_ci 927e1051a39Sopenharmony_ci if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) { 928e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); 929e1051a39Sopenharmony_ci return 0; 930e1051a39Sopenharmony_ci } 931e1051a39Sopenharmony_ci 932e1051a39Sopenharmony_ci return buf_len; 933e1051a39Sopenharmony_ci} 934e1051a39Sopenharmony_ci 935e1051a39Sopenharmony_ciint EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) 936e1051a39Sopenharmony_ci{ 937e1051a39Sopenharmony_ci int ret; 938e1051a39Sopenharmony_ci 939e1051a39Sopenharmony_ci if (eckey->group == NULL || eckey->group->meth == NULL) 940e1051a39Sopenharmony_ci return 0; 941e1051a39Sopenharmony_ci if (eckey->group->meth->oct2priv == NULL) { 942e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 943e1051a39Sopenharmony_ci return 0; 944e1051a39Sopenharmony_ci } 945e1051a39Sopenharmony_ci ret = eckey->group->meth->oct2priv(eckey, buf, len); 946e1051a39Sopenharmony_ci if (ret == 1) 947e1051a39Sopenharmony_ci eckey->dirty_cnt++; 948e1051a39Sopenharmony_ci return ret; 949e1051a39Sopenharmony_ci} 950e1051a39Sopenharmony_ci 951e1051a39Sopenharmony_ciint ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, 952e1051a39Sopenharmony_ci size_t len) 953e1051a39Sopenharmony_ci{ 954e1051a39Sopenharmony_ci if (eckey->priv_key == NULL) 955e1051a39Sopenharmony_ci eckey->priv_key = BN_secure_new(); 956e1051a39Sopenharmony_ci if (eckey->priv_key == NULL) { 957e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 958e1051a39Sopenharmony_ci return 0; 959e1051a39Sopenharmony_ci } 960e1051a39Sopenharmony_ci if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) { 961e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 962e1051a39Sopenharmony_ci return 0; 963e1051a39Sopenharmony_ci } 964e1051a39Sopenharmony_ci eckey->dirty_cnt++; 965e1051a39Sopenharmony_ci return 1; 966e1051a39Sopenharmony_ci} 967e1051a39Sopenharmony_ci 968e1051a39Sopenharmony_cisize_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) 969e1051a39Sopenharmony_ci{ 970e1051a39Sopenharmony_ci size_t len; 971e1051a39Sopenharmony_ci unsigned char *buf; 972e1051a39Sopenharmony_ci 973e1051a39Sopenharmony_ci len = EC_KEY_priv2oct(eckey, NULL, 0); 974e1051a39Sopenharmony_ci if (len == 0) 975e1051a39Sopenharmony_ci return 0; 976e1051a39Sopenharmony_ci if ((buf = OPENSSL_malloc(len)) == NULL) { 977e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 978e1051a39Sopenharmony_ci return 0; 979e1051a39Sopenharmony_ci } 980e1051a39Sopenharmony_ci len = EC_KEY_priv2oct(eckey, buf, len); 981e1051a39Sopenharmony_ci if (len == 0) { 982e1051a39Sopenharmony_ci OPENSSL_free(buf); 983e1051a39Sopenharmony_ci return 0; 984e1051a39Sopenharmony_ci } 985e1051a39Sopenharmony_ci *pbuf = buf; 986e1051a39Sopenharmony_ci return len; 987e1051a39Sopenharmony_ci} 988e1051a39Sopenharmony_ci 989e1051a39Sopenharmony_ciint EC_KEY_can_sign(const EC_KEY *eckey) 990e1051a39Sopenharmony_ci{ 991e1051a39Sopenharmony_ci if (eckey->group == NULL || eckey->group->meth == NULL 992e1051a39Sopenharmony_ci || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN)) 993e1051a39Sopenharmony_ci return 0; 994e1051a39Sopenharmony_ci return 1; 995e1051a39Sopenharmony_ci} 996e1051a39Sopenharmony_ci 997e1051a39Sopenharmony_ci/* 998e1051a39Sopenharmony_ci * FIPS 140-2 IG 9.9 AS09.33 999e1051a39Sopenharmony_ci * Perform a sign/verify operation. 1000e1051a39Sopenharmony_ci * 1001e1051a39Sopenharmony_ci * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9 1002e1051a39Sopenharmony_ci * states that no additional pairwise tests are required (apart from the tests 1003e1051a39Sopenharmony_ci * specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are 1004e1051a39Sopenharmony_ci * omitted here. 1005e1051a39Sopenharmony_ci */ 1006e1051a39Sopenharmony_cistatic int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, 1007e1051a39Sopenharmony_ci void *cbarg) 1008e1051a39Sopenharmony_ci{ 1009e1051a39Sopenharmony_ci int ret = 0; 1010e1051a39Sopenharmony_ci unsigned char dgst[16] = {0}; 1011e1051a39Sopenharmony_ci int dgst_len = (int)sizeof(dgst); 1012e1051a39Sopenharmony_ci ECDSA_SIG *sig = NULL; 1013e1051a39Sopenharmony_ci OSSL_SELF_TEST *st = NULL; 1014e1051a39Sopenharmony_ci 1015e1051a39Sopenharmony_ci st = OSSL_SELF_TEST_new(cb, cbarg); 1016e1051a39Sopenharmony_ci if (st == NULL) 1017e1051a39Sopenharmony_ci return 0; 1018e1051a39Sopenharmony_ci 1019e1051a39Sopenharmony_ci OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, 1020e1051a39Sopenharmony_ci OSSL_SELF_TEST_DESC_PCT_ECDSA); 1021e1051a39Sopenharmony_ci 1022e1051a39Sopenharmony_ci sig = ECDSA_do_sign(dgst, dgst_len, eckey); 1023e1051a39Sopenharmony_ci if (sig == NULL) 1024e1051a39Sopenharmony_ci goto err; 1025e1051a39Sopenharmony_ci 1026e1051a39Sopenharmony_ci OSSL_SELF_TEST_oncorrupt_byte(st, dgst); 1027e1051a39Sopenharmony_ci 1028e1051a39Sopenharmony_ci if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1) 1029e1051a39Sopenharmony_ci goto err; 1030e1051a39Sopenharmony_ci 1031e1051a39Sopenharmony_ci ret = 1; 1032e1051a39Sopenharmony_cierr: 1033e1051a39Sopenharmony_ci OSSL_SELF_TEST_onend(st, ret); 1034e1051a39Sopenharmony_ci OSSL_SELF_TEST_free(st); 1035e1051a39Sopenharmony_ci ECDSA_SIG_free(sig); 1036e1051a39Sopenharmony_ci return ret; 1037e1051a39Sopenharmony_ci} 1038