1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2001-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_GROUP 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 <string.h> 18e1051a39Sopenharmony_ci#include <openssl/params.h> 19e1051a39Sopenharmony_ci#include <openssl/core_names.h> 20e1051a39Sopenharmony_ci#include <openssl/err.h> 21e1051a39Sopenharmony_ci#include <openssl/opensslv.h> 22e1051a39Sopenharmony_ci#include "crypto/ec.h" 23e1051a39Sopenharmony_ci#include "internal/nelem.h" 24e1051a39Sopenharmony_ci#include "ec_local.h" 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci/* functions for EC_GROUP objects */ 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ciEC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq, 29e1051a39Sopenharmony_ci const EC_METHOD *meth) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci EC_GROUP *ret; 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_ci if (meth == NULL) { 34e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL); 35e1051a39Sopenharmony_ci return NULL; 36e1051a39Sopenharmony_ci } 37e1051a39Sopenharmony_ci if (meth->group_init == 0) { 38e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 39e1051a39Sopenharmony_ci return NULL; 40e1051a39Sopenharmony_ci } 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci ret = OPENSSL_zalloc(sizeof(*ret)); 43e1051a39Sopenharmony_ci if (ret == NULL) { 44e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 45e1051a39Sopenharmony_ci return NULL; 46e1051a39Sopenharmony_ci } 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci ret->libctx = libctx; 49e1051a39Sopenharmony_ci if (propq != NULL) { 50e1051a39Sopenharmony_ci ret->propq = OPENSSL_strdup(propq); 51e1051a39Sopenharmony_ci if (ret->propq == NULL) { 52e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 53e1051a39Sopenharmony_ci goto err; 54e1051a39Sopenharmony_ci } 55e1051a39Sopenharmony_ci } 56e1051a39Sopenharmony_ci ret->meth = meth; 57e1051a39Sopenharmony_ci if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { 58e1051a39Sopenharmony_ci ret->order = BN_new(); 59e1051a39Sopenharmony_ci if (ret->order == NULL) 60e1051a39Sopenharmony_ci goto err; 61e1051a39Sopenharmony_ci ret->cofactor = BN_new(); 62e1051a39Sopenharmony_ci if (ret->cofactor == NULL) 63e1051a39Sopenharmony_ci goto err; 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE; 66e1051a39Sopenharmony_ci ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 67e1051a39Sopenharmony_ci if (!meth->group_init(ret)) 68e1051a39Sopenharmony_ci goto err; 69e1051a39Sopenharmony_ci return ret; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci err: 72e1051a39Sopenharmony_ci BN_free(ret->order); 73e1051a39Sopenharmony_ci BN_free(ret->cofactor); 74e1051a39Sopenharmony_ci OPENSSL_free(ret->propq); 75e1051a39Sopenharmony_ci OPENSSL_free(ret); 76e1051a39Sopenharmony_ci return NULL; 77e1051a39Sopenharmony_ci} 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 80e1051a39Sopenharmony_ci# ifndef FIPS_MODULE 81e1051a39Sopenharmony_ciEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci return ossl_ec_group_new_ex(NULL, NULL, meth); 84e1051a39Sopenharmony_ci} 85e1051a39Sopenharmony_ci# endif 86e1051a39Sopenharmony_ci#endif 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_civoid EC_pre_comp_free(EC_GROUP *group) 89e1051a39Sopenharmony_ci{ 90e1051a39Sopenharmony_ci switch (group->pre_comp_type) { 91e1051a39Sopenharmony_ci case PCT_none: 92e1051a39Sopenharmony_ci break; 93e1051a39Sopenharmony_ci case PCT_nistz256: 94e1051a39Sopenharmony_ci#ifdef ECP_NISTZ256_ASM 95e1051a39Sopenharmony_ci EC_nistz256_pre_comp_free(group->pre_comp.nistz256); 96e1051a39Sopenharmony_ci#endif 97e1051a39Sopenharmony_ci break; 98e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 99e1051a39Sopenharmony_ci case PCT_nistp224: 100e1051a39Sopenharmony_ci EC_nistp224_pre_comp_free(group->pre_comp.nistp224); 101e1051a39Sopenharmony_ci break; 102e1051a39Sopenharmony_ci case PCT_nistp256: 103e1051a39Sopenharmony_ci EC_nistp256_pre_comp_free(group->pre_comp.nistp256); 104e1051a39Sopenharmony_ci break; 105e1051a39Sopenharmony_ci case PCT_nistp521: 106e1051a39Sopenharmony_ci EC_nistp521_pre_comp_free(group->pre_comp.nistp521); 107e1051a39Sopenharmony_ci break; 108e1051a39Sopenharmony_ci#else 109e1051a39Sopenharmony_ci case PCT_nistp224: 110e1051a39Sopenharmony_ci case PCT_nistp256: 111e1051a39Sopenharmony_ci case PCT_nistp521: 112e1051a39Sopenharmony_ci break; 113e1051a39Sopenharmony_ci#endif 114e1051a39Sopenharmony_ci case PCT_ec: 115e1051a39Sopenharmony_ci EC_ec_pre_comp_free(group->pre_comp.ec); 116e1051a39Sopenharmony_ci break; 117e1051a39Sopenharmony_ci } 118e1051a39Sopenharmony_ci group->pre_comp.ec = NULL; 119e1051a39Sopenharmony_ci} 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_civoid EC_GROUP_free(EC_GROUP *group) 122e1051a39Sopenharmony_ci{ 123e1051a39Sopenharmony_ci if (!group) 124e1051a39Sopenharmony_ci return; 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ci if (group->meth->group_finish != 0) 127e1051a39Sopenharmony_ci group->meth->group_finish(group); 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci EC_pre_comp_free(group); 130e1051a39Sopenharmony_ci BN_MONT_CTX_free(group->mont_data); 131e1051a39Sopenharmony_ci EC_POINT_free(group->generator); 132e1051a39Sopenharmony_ci BN_free(group->order); 133e1051a39Sopenharmony_ci BN_free(group->cofactor); 134e1051a39Sopenharmony_ci OPENSSL_free(group->seed); 135e1051a39Sopenharmony_ci OPENSSL_free(group->propq); 136e1051a39Sopenharmony_ci OPENSSL_free(group); 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 140e1051a39Sopenharmony_civoid EC_GROUP_clear_free(EC_GROUP *group) 141e1051a39Sopenharmony_ci{ 142e1051a39Sopenharmony_ci if (!group) 143e1051a39Sopenharmony_ci return; 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (group->meth->group_clear_finish != 0) 146e1051a39Sopenharmony_ci group->meth->group_clear_finish(group); 147e1051a39Sopenharmony_ci else if (group->meth->group_finish != 0) 148e1051a39Sopenharmony_ci group->meth->group_finish(group); 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci EC_pre_comp_free(group); 151e1051a39Sopenharmony_ci BN_MONT_CTX_free(group->mont_data); 152e1051a39Sopenharmony_ci EC_POINT_clear_free(group->generator); 153e1051a39Sopenharmony_ci BN_clear_free(group->order); 154e1051a39Sopenharmony_ci BN_clear_free(group->cofactor); 155e1051a39Sopenharmony_ci OPENSSL_clear_free(group->seed, group->seed_len); 156e1051a39Sopenharmony_ci OPENSSL_clear_free(group, sizeof(*group)); 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci#endif 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ciint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 161e1051a39Sopenharmony_ci{ 162e1051a39Sopenharmony_ci if (dest->meth->group_copy == 0) { 163e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 164e1051a39Sopenharmony_ci return 0; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci if (dest->meth != src->meth) { 167e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 168e1051a39Sopenharmony_ci return 0; 169e1051a39Sopenharmony_ci } 170e1051a39Sopenharmony_ci if (dest == src) 171e1051a39Sopenharmony_ci return 1; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci dest->libctx = src->libctx; 174e1051a39Sopenharmony_ci dest->curve_name = src->curve_name; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci /* Copy precomputed */ 177e1051a39Sopenharmony_ci dest->pre_comp_type = src->pre_comp_type; 178e1051a39Sopenharmony_ci switch (src->pre_comp_type) { 179e1051a39Sopenharmony_ci case PCT_none: 180e1051a39Sopenharmony_ci dest->pre_comp.ec = NULL; 181e1051a39Sopenharmony_ci break; 182e1051a39Sopenharmony_ci case PCT_nistz256: 183e1051a39Sopenharmony_ci#ifdef ECP_NISTZ256_ASM 184e1051a39Sopenharmony_ci dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256); 185e1051a39Sopenharmony_ci#endif 186e1051a39Sopenharmony_ci break; 187e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 188e1051a39Sopenharmony_ci case PCT_nistp224: 189e1051a39Sopenharmony_ci dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224); 190e1051a39Sopenharmony_ci break; 191e1051a39Sopenharmony_ci case PCT_nistp256: 192e1051a39Sopenharmony_ci dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256); 193e1051a39Sopenharmony_ci break; 194e1051a39Sopenharmony_ci case PCT_nistp521: 195e1051a39Sopenharmony_ci dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521); 196e1051a39Sopenharmony_ci break; 197e1051a39Sopenharmony_ci#else 198e1051a39Sopenharmony_ci case PCT_nistp224: 199e1051a39Sopenharmony_ci case PCT_nistp256: 200e1051a39Sopenharmony_ci case PCT_nistp521: 201e1051a39Sopenharmony_ci break; 202e1051a39Sopenharmony_ci#endif 203e1051a39Sopenharmony_ci case PCT_ec: 204e1051a39Sopenharmony_ci dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec); 205e1051a39Sopenharmony_ci break; 206e1051a39Sopenharmony_ci } 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci if (src->mont_data != NULL) { 209e1051a39Sopenharmony_ci if (dest->mont_data == NULL) { 210e1051a39Sopenharmony_ci dest->mont_data = BN_MONT_CTX_new(); 211e1051a39Sopenharmony_ci if (dest->mont_data == NULL) 212e1051a39Sopenharmony_ci return 0; 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) 215e1051a39Sopenharmony_ci return 0; 216e1051a39Sopenharmony_ci } else { 217e1051a39Sopenharmony_ci /* src->generator == NULL */ 218e1051a39Sopenharmony_ci BN_MONT_CTX_free(dest->mont_data); 219e1051a39Sopenharmony_ci dest->mont_data = NULL; 220e1051a39Sopenharmony_ci } 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ci if (src->generator != NULL) { 223e1051a39Sopenharmony_ci if (dest->generator == NULL) { 224e1051a39Sopenharmony_ci dest->generator = EC_POINT_new(dest); 225e1051a39Sopenharmony_ci if (dest->generator == NULL) 226e1051a39Sopenharmony_ci return 0; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci if (!EC_POINT_copy(dest->generator, src->generator)) 229e1051a39Sopenharmony_ci return 0; 230e1051a39Sopenharmony_ci } else { 231e1051a39Sopenharmony_ci /* src->generator == NULL */ 232e1051a39Sopenharmony_ci EC_POINT_clear_free(dest->generator); 233e1051a39Sopenharmony_ci dest->generator = NULL; 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { 237e1051a39Sopenharmony_ci if (!BN_copy(dest->order, src->order)) 238e1051a39Sopenharmony_ci return 0; 239e1051a39Sopenharmony_ci if (!BN_copy(dest->cofactor, src->cofactor)) 240e1051a39Sopenharmony_ci return 0; 241e1051a39Sopenharmony_ci } 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci dest->asn1_flag = src->asn1_flag; 244e1051a39Sopenharmony_ci dest->asn1_form = src->asn1_form; 245e1051a39Sopenharmony_ci dest->decoded_from_explicit_params = src->decoded_from_explicit_params; 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ci if (src->seed) { 248e1051a39Sopenharmony_ci OPENSSL_free(dest->seed); 249e1051a39Sopenharmony_ci if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) { 250e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 251e1051a39Sopenharmony_ci return 0; 252e1051a39Sopenharmony_ci } 253e1051a39Sopenharmony_ci if (!memcpy(dest->seed, src->seed, src->seed_len)) 254e1051a39Sopenharmony_ci return 0; 255e1051a39Sopenharmony_ci dest->seed_len = src->seed_len; 256e1051a39Sopenharmony_ci } else { 257e1051a39Sopenharmony_ci OPENSSL_free(dest->seed); 258e1051a39Sopenharmony_ci dest->seed = NULL; 259e1051a39Sopenharmony_ci dest->seed_len = 0; 260e1051a39Sopenharmony_ci } 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci return dest->meth->group_copy(dest, src); 263e1051a39Sopenharmony_ci} 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ciEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 266e1051a39Sopenharmony_ci{ 267e1051a39Sopenharmony_ci EC_GROUP *t = NULL; 268e1051a39Sopenharmony_ci int ok = 0; 269e1051a39Sopenharmony_ci 270e1051a39Sopenharmony_ci if (a == NULL) 271e1051a39Sopenharmony_ci return NULL; 272e1051a39Sopenharmony_ci 273e1051a39Sopenharmony_ci if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL) 274e1051a39Sopenharmony_ci return NULL; 275e1051a39Sopenharmony_ci if (!EC_GROUP_copy(t, a)) 276e1051a39Sopenharmony_ci goto err; 277e1051a39Sopenharmony_ci 278e1051a39Sopenharmony_ci ok = 1; 279e1051a39Sopenharmony_ci 280e1051a39Sopenharmony_ci err: 281e1051a39Sopenharmony_ci if (!ok) { 282e1051a39Sopenharmony_ci EC_GROUP_free(t); 283e1051a39Sopenharmony_ci return NULL; 284e1051a39Sopenharmony_ci } 285e1051a39Sopenharmony_ci return t; 286e1051a39Sopenharmony_ci} 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 289e1051a39Sopenharmony_ciconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 290e1051a39Sopenharmony_ci{ 291e1051a39Sopenharmony_ci return group->meth; 292e1051a39Sopenharmony_ci} 293e1051a39Sopenharmony_ci 294e1051a39Sopenharmony_ciint EC_METHOD_get_field_type(const EC_METHOD *meth) 295e1051a39Sopenharmony_ci{ 296e1051a39Sopenharmony_ci return meth->field_type; 297e1051a39Sopenharmony_ci} 298e1051a39Sopenharmony_ci#endif 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_cistatic int ec_precompute_mont_data(EC_GROUP *); 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ci/*- 303e1051a39Sopenharmony_ci * Try computing cofactor from the generator order (n) and field cardinality (q). 304e1051a39Sopenharmony_ci * This works for all curves of cryptographic interest. 305e1051a39Sopenharmony_ci * 306e1051a39Sopenharmony_ci * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q) 307e1051a39Sopenharmony_ci * h_min = (q + 1 - 2*sqrt(q))/n 308e1051a39Sopenharmony_ci * h_max = (q + 1 + 2*sqrt(q))/n 309e1051a39Sopenharmony_ci * h_max - h_min = 4*sqrt(q)/n 310e1051a39Sopenharmony_ci * So if n > 4*sqrt(q) holds, there is only one possible value for h: 311e1051a39Sopenharmony_ci * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil 312e1051a39Sopenharmony_ci * 313e1051a39Sopenharmony_ci * Otherwise, zero cofactor and return success. 314e1051a39Sopenharmony_ci */ 315e1051a39Sopenharmony_cistatic int ec_guess_cofactor(EC_GROUP *group) { 316e1051a39Sopenharmony_ci int ret = 0; 317e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 318e1051a39Sopenharmony_ci BIGNUM *q = NULL; 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci /*- 321e1051a39Sopenharmony_ci * If the cofactor is too large, we cannot guess it. 322e1051a39Sopenharmony_ci * The RHS of below is a strict overestimate of lg(4 * sqrt(q)) 323e1051a39Sopenharmony_ci */ 324e1051a39Sopenharmony_ci if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) { 325e1051a39Sopenharmony_ci /* default to 0 */ 326e1051a39Sopenharmony_ci BN_zero(group->cofactor); 327e1051a39Sopenharmony_ci /* return success */ 328e1051a39Sopenharmony_ci return 1; 329e1051a39Sopenharmony_ci } 330e1051a39Sopenharmony_ci 331e1051a39Sopenharmony_ci if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL) 332e1051a39Sopenharmony_ci return 0; 333e1051a39Sopenharmony_ci 334e1051a39Sopenharmony_ci BN_CTX_start(ctx); 335e1051a39Sopenharmony_ci if ((q = BN_CTX_get(ctx)) == NULL) 336e1051a39Sopenharmony_ci goto err; 337e1051a39Sopenharmony_ci 338e1051a39Sopenharmony_ci /* set q = 2**m for binary fields; q = p otherwise */ 339e1051a39Sopenharmony_ci if (group->meth->field_type == NID_X9_62_characteristic_two_field) { 340e1051a39Sopenharmony_ci BN_zero(q); 341e1051a39Sopenharmony_ci if (!BN_set_bit(q, BN_num_bits(group->field) - 1)) 342e1051a39Sopenharmony_ci goto err; 343e1051a39Sopenharmony_ci } else { 344e1051a39Sopenharmony_ci if (!BN_copy(q, group->field)) 345e1051a39Sopenharmony_ci goto err; 346e1051a39Sopenharmony_ci } 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */ 349e1051a39Sopenharmony_ci if (!BN_rshift1(group->cofactor, group->order) /* n/2 */ 350e1051a39Sopenharmony_ci || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */ 351e1051a39Sopenharmony_ci /* q + 1 + n/2 */ 352e1051a39Sopenharmony_ci || !BN_add(group->cofactor, group->cofactor, BN_value_one()) 353e1051a39Sopenharmony_ci /* (q + 1 + n/2)/n */ 354e1051a39Sopenharmony_ci || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx)) 355e1051a39Sopenharmony_ci goto err; 356e1051a39Sopenharmony_ci ret = 1; 357e1051a39Sopenharmony_ci err: 358e1051a39Sopenharmony_ci BN_CTX_end(ctx); 359e1051a39Sopenharmony_ci BN_CTX_free(ctx); 360e1051a39Sopenharmony_ci return ret; 361e1051a39Sopenharmony_ci} 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_ciint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 364e1051a39Sopenharmony_ci const BIGNUM *order, const BIGNUM *cofactor) 365e1051a39Sopenharmony_ci{ 366e1051a39Sopenharmony_ci if (generator == NULL) { 367e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 368e1051a39Sopenharmony_ci return 0; 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci /* require group->field >= 1 */ 372e1051a39Sopenharmony_ci if (group->field == NULL || BN_is_zero(group->field) 373e1051a39Sopenharmony_ci || BN_is_negative(group->field)) { 374e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); 375e1051a39Sopenharmony_ci return 0; 376e1051a39Sopenharmony_ci } 377e1051a39Sopenharmony_ci 378e1051a39Sopenharmony_ci /*- 379e1051a39Sopenharmony_ci * - require order >= 1 380e1051a39Sopenharmony_ci * - enforce upper bound due to Hasse thm: order can be no more than one bit 381e1051a39Sopenharmony_ci * longer than field cardinality 382e1051a39Sopenharmony_ci */ 383e1051a39Sopenharmony_ci if (order == NULL || BN_is_zero(order) || BN_is_negative(order) 384e1051a39Sopenharmony_ci || BN_num_bits(order) > BN_num_bits(group->field) + 1) { 385e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); 386e1051a39Sopenharmony_ci return 0; 387e1051a39Sopenharmony_ci } 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci /*- 390e1051a39Sopenharmony_ci * Unfortunately the cofactor is an optional field in many standards. 391e1051a39Sopenharmony_ci * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor". 392e1051a39Sopenharmony_ci * So accept cofactor == NULL or cofactor >= 0. 393e1051a39Sopenharmony_ci */ 394e1051a39Sopenharmony_ci if (cofactor != NULL && BN_is_negative(cofactor)) { 395e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR); 396e1051a39Sopenharmony_ci return 0; 397e1051a39Sopenharmony_ci } 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci if (group->generator == NULL) { 400e1051a39Sopenharmony_ci group->generator = EC_POINT_new(group); 401e1051a39Sopenharmony_ci if (group->generator == NULL) 402e1051a39Sopenharmony_ci return 0; 403e1051a39Sopenharmony_ci } 404e1051a39Sopenharmony_ci if (!EC_POINT_copy(group->generator, generator)) 405e1051a39Sopenharmony_ci return 0; 406e1051a39Sopenharmony_ci 407e1051a39Sopenharmony_ci if (!BN_copy(group->order, order)) 408e1051a39Sopenharmony_ci return 0; 409e1051a39Sopenharmony_ci 410e1051a39Sopenharmony_ci /* Either take the provided positive cofactor, or try to compute it */ 411e1051a39Sopenharmony_ci if (cofactor != NULL && !BN_is_zero(cofactor)) { 412e1051a39Sopenharmony_ci if (!BN_copy(group->cofactor, cofactor)) 413e1051a39Sopenharmony_ci return 0; 414e1051a39Sopenharmony_ci } else if (!ec_guess_cofactor(group)) { 415e1051a39Sopenharmony_ci BN_zero(group->cofactor); 416e1051a39Sopenharmony_ci return 0; 417e1051a39Sopenharmony_ci } 418e1051a39Sopenharmony_ci 419e1051a39Sopenharmony_ci /* 420e1051a39Sopenharmony_ci * Some groups have an order with 421e1051a39Sopenharmony_ci * factors of two, which makes the Montgomery setup fail. 422e1051a39Sopenharmony_ci * |group->mont_data| will be NULL in this case. 423e1051a39Sopenharmony_ci */ 424e1051a39Sopenharmony_ci if (BN_is_odd(group->order)) { 425e1051a39Sopenharmony_ci return ec_precompute_mont_data(group); 426e1051a39Sopenharmony_ci } 427e1051a39Sopenharmony_ci 428e1051a39Sopenharmony_ci BN_MONT_CTX_free(group->mont_data); 429e1051a39Sopenharmony_ci group->mont_data = NULL; 430e1051a39Sopenharmony_ci return 1; 431e1051a39Sopenharmony_ci} 432e1051a39Sopenharmony_ci 433e1051a39Sopenharmony_ciconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 434e1051a39Sopenharmony_ci{ 435e1051a39Sopenharmony_ci return group->generator; 436e1051a39Sopenharmony_ci} 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ciBN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) 439e1051a39Sopenharmony_ci{ 440e1051a39Sopenharmony_ci return group->mont_data; 441e1051a39Sopenharmony_ci} 442e1051a39Sopenharmony_ci 443e1051a39Sopenharmony_ciint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 444e1051a39Sopenharmony_ci{ 445e1051a39Sopenharmony_ci if (group->order == NULL) 446e1051a39Sopenharmony_ci return 0; 447e1051a39Sopenharmony_ci if (!BN_copy(order, group->order)) 448e1051a39Sopenharmony_ci return 0; 449e1051a39Sopenharmony_ci 450e1051a39Sopenharmony_ci return !BN_is_zero(order); 451e1051a39Sopenharmony_ci} 452e1051a39Sopenharmony_ci 453e1051a39Sopenharmony_ciconst BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) 454e1051a39Sopenharmony_ci{ 455e1051a39Sopenharmony_ci return group->order; 456e1051a39Sopenharmony_ci} 457e1051a39Sopenharmony_ci 458e1051a39Sopenharmony_ciint EC_GROUP_order_bits(const EC_GROUP *group) 459e1051a39Sopenharmony_ci{ 460e1051a39Sopenharmony_ci return group->meth->group_order_bits(group); 461e1051a39Sopenharmony_ci} 462e1051a39Sopenharmony_ci 463e1051a39Sopenharmony_ciint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 464e1051a39Sopenharmony_ci BN_CTX *ctx) 465e1051a39Sopenharmony_ci{ 466e1051a39Sopenharmony_ci 467e1051a39Sopenharmony_ci if (group->cofactor == NULL) 468e1051a39Sopenharmony_ci return 0; 469e1051a39Sopenharmony_ci if (!BN_copy(cofactor, group->cofactor)) 470e1051a39Sopenharmony_ci return 0; 471e1051a39Sopenharmony_ci 472e1051a39Sopenharmony_ci return !BN_is_zero(group->cofactor); 473e1051a39Sopenharmony_ci} 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ciconst BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group) 476e1051a39Sopenharmony_ci{ 477e1051a39Sopenharmony_ci return group->cofactor; 478e1051a39Sopenharmony_ci} 479e1051a39Sopenharmony_ci 480e1051a39Sopenharmony_civoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 481e1051a39Sopenharmony_ci{ 482e1051a39Sopenharmony_ci group->curve_name = nid; 483e1051a39Sopenharmony_ci group->asn1_flag = 484e1051a39Sopenharmony_ci (nid != NID_undef) 485e1051a39Sopenharmony_ci ? OPENSSL_EC_NAMED_CURVE 486e1051a39Sopenharmony_ci : OPENSSL_EC_EXPLICIT_CURVE; 487e1051a39Sopenharmony_ci} 488e1051a39Sopenharmony_ci 489e1051a39Sopenharmony_ciint EC_GROUP_get_curve_name(const EC_GROUP *group) 490e1051a39Sopenharmony_ci{ 491e1051a39Sopenharmony_ci return group->curve_name; 492e1051a39Sopenharmony_ci} 493e1051a39Sopenharmony_ci 494e1051a39Sopenharmony_ciconst BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group) 495e1051a39Sopenharmony_ci{ 496e1051a39Sopenharmony_ci return group->field; 497e1051a39Sopenharmony_ci} 498e1051a39Sopenharmony_ci 499e1051a39Sopenharmony_ciint EC_GROUP_get_field_type(const EC_GROUP *group) 500e1051a39Sopenharmony_ci{ 501e1051a39Sopenharmony_ci return group->meth->field_type; 502e1051a39Sopenharmony_ci} 503e1051a39Sopenharmony_ci 504e1051a39Sopenharmony_civoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 505e1051a39Sopenharmony_ci{ 506e1051a39Sopenharmony_ci group->asn1_flag = flag; 507e1051a39Sopenharmony_ci} 508e1051a39Sopenharmony_ci 509e1051a39Sopenharmony_ciint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 510e1051a39Sopenharmony_ci{ 511e1051a39Sopenharmony_ci return group->asn1_flag; 512e1051a39Sopenharmony_ci} 513e1051a39Sopenharmony_ci 514e1051a39Sopenharmony_civoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 515e1051a39Sopenharmony_ci point_conversion_form_t form) 516e1051a39Sopenharmony_ci{ 517e1051a39Sopenharmony_ci group->asn1_form = form; 518e1051a39Sopenharmony_ci} 519e1051a39Sopenharmony_ci 520e1051a39Sopenharmony_cipoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 521e1051a39Sopenharmony_ci *group) 522e1051a39Sopenharmony_ci{ 523e1051a39Sopenharmony_ci return group->asn1_form; 524e1051a39Sopenharmony_ci} 525e1051a39Sopenharmony_ci 526e1051a39Sopenharmony_cisize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 527e1051a39Sopenharmony_ci{ 528e1051a39Sopenharmony_ci OPENSSL_free(group->seed); 529e1051a39Sopenharmony_ci group->seed = NULL; 530e1051a39Sopenharmony_ci group->seed_len = 0; 531e1051a39Sopenharmony_ci 532e1051a39Sopenharmony_ci if (!len || !p) 533e1051a39Sopenharmony_ci return 1; 534e1051a39Sopenharmony_ci 535e1051a39Sopenharmony_ci if ((group->seed = OPENSSL_malloc(len)) == NULL) { 536e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 537e1051a39Sopenharmony_ci return 0; 538e1051a39Sopenharmony_ci } 539e1051a39Sopenharmony_ci memcpy(group->seed, p, len); 540e1051a39Sopenharmony_ci group->seed_len = len; 541e1051a39Sopenharmony_ci 542e1051a39Sopenharmony_ci return len; 543e1051a39Sopenharmony_ci} 544e1051a39Sopenharmony_ci 545e1051a39Sopenharmony_ciunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 546e1051a39Sopenharmony_ci{ 547e1051a39Sopenharmony_ci return group->seed; 548e1051a39Sopenharmony_ci} 549e1051a39Sopenharmony_ci 550e1051a39Sopenharmony_cisize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 551e1051a39Sopenharmony_ci{ 552e1051a39Sopenharmony_ci return group->seed_len; 553e1051a39Sopenharmony_ci} 554e1051a39Sopenharmony_ci 555e1051a39Sopenharmony_ciint EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 556e1051a39Sopenharmony_ci const BIGNUM *b, BN_CTX *ctx) 557e1051a39Sopenharmony_ci{ 558e1051a39Sopenharmony_ci if (group->meth->group_set_curve == 0) { 559e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 560e1051a39Sopenharmony_ci return 0; 561e1051a39Sopenharmony_ci } 562e1051a39Sopenharmony_ci return group->meth->group_set_curve(group, p, a, b, ctx); 563e1051a39Sopenharmony_ci} 564e1051a39Sopenharmony_ci 565e1051a39Sopenharmony_ciint EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, 566e1051a39Sopenharmony_ci BN_CTX *ctx) 567e1051a39Sopenharmony_ci{ 568e1051a39Sopenharmony_ci if (group->meth->group_get_curve == NULL) { 569e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 570e1051a39Sopenharmony_ci return 0; 571e1051a39Sopenharmony_ci } 572e1051a39Sopenharmony_ci return group->meth->group_get_curve(group, p, a, b, ctx); 573e1051a39Sopenharmony_ci} 574e1051a39Sopenharmony_ci 575e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 576e1051a39Sopenharmony_ciint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 577e1051a39Sopenharmony_ci const BIGNUM *b, BN_CTX *ctx) 578e1051a39Sopenharmony_ci{ 579e1051a39Sopenharmony_ci return EC_GROUP_set_curve(group, p, a, b, ctx); 580e1051a39Sopenharmony_ci} 581e1051a39Sopenharmony_ci 582e1051a39Sopenharmony_ciint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 583e1051a39Sopenharmony_ci BIGNUM *b, BN_CTX *ctx) 584e1051a39Sopenharmony_ci{ 585e1051a39Sopenharmony_ci return EC_GROUP_get_curve(group, p, a, b, ctx); 586e1051a39Sopenharmony_ci} 587e1051a39Sopenharmony_ci 588e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_EC2M 589e1051a39Sopenharmony_ciint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 590e1051a39Sopenharmony_ci const BIGNUM *b, BN_CTX *ctx) 591e1051a39Sopenharmony_ci{ 592e1051a39Sopenharmony_ci return EC_GROUP_set_curve(group, p, a, b, ctx); 593e1051a39Sopenharmony_ci} 594e1051a39Sopenharmony_ci 595e1051a39Sopenharmony_ciint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 596e1051a39Sopenharmony_ci BIGNUM *b, BN_CTX *ctx) 597e1051a39Sopenharmony_ci{ 598e1051a39Sopenharmony_ci return EC_GROUP_get_curve(group, p, a, b, ctx); 599e1051a39Sopenharmony_ci} 600e1051a39Sopenharmony_ci# endif 601e1051a39Sopenharmony_ci#endif 602e1051a39Sopenharmony_ci 603e1051a39Sopenharmony_ciint EC_GROUP_get_degree(const EC_GROUP *group) 604e1051a39Sopenharmony_ci{ 605e1051a39Sopenharmony_ci if (group->meth->group_get_degree == 0) { 606e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 607e1051a39Sopenharmony_ci return 0; 608e1051a39Sopenharmony_ci } 609e1051a39Sopenharmony_ci return group->meth->group_get_degree(group); 610e1051a39Sopenharmony_ci} 611e1051a39Sopenharmony_ci 612e1051a39Sopenharmony_ciint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 613e1051a39Sopenharmony_ci{ 614e1051a39Sopenharmony_ci if (group->meth->group_check_discriminant == 0) { 615e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 616e1051a39Sopenharmony_ci return 0; 617e1051a39Sopenharmony_ci } 618e1051a39Sopenharmony_ci return group->meth->group_check_discriminant(group, ctx); 619e1051a39Sopenharmony_ci} 620e1051a39Sopenharmony_ci 621e1051a39Sopenharmony_ciint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 622e1051a39Sopenharmony_ci{ 623e1051a39Sopenharmony_ci int r = 0; 624e1051a39Sopenharmony_ci BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 625e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 626e1051a39Sopenharmony_ci BN_CTX *ctx_new = NULL; 627e1051a39Sopenharmony_ci#endif 628e1051a39Sopenharmony_ci 629e1051a39Sopenharmony_ci /* compare the field types */ 630e1051a39Sopenharmony_ci if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b)) 631e1051a39Sopenharmony_ci return 1; 632e1051a39Sopenharmony_ci /* compare the curve name (if present in both) */ 633e1051a39Sopenharmony_ci if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 634e1051a39Sopenharmony_ci EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 635e1051a39Sopenharmony_ci return 1; 636e1051a39Sopenharmony_ci if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE) 637e1051a39Sopenharmony_ci return 0; 638e1051a39Sopenharmony_ci 639e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 640e1051a39Sopenharmony_ci if (ctx == NULL) 641e1051a39Sopenharmony_ci ctx_new = ctx = BN_CTX_new(); 642e1051a39Sopenharmony_ci#endif 643e1051a39Sopenharmony_ci if (ctx == NULL) 644e1051a39Sopenharmony_ci return -1; 645e1051a39Sopenharmony_ci 646e1051a39Sopenharmony_ci BN_CTX_start(ctx); 647e1051a39Sopenharmony_ci a1 = BN_CTX_get(ctx); 648e1051a39Sopenharmony_ci a2 = BN_CTX_get(ctx); 649e1051a39Sopenharmony_ci a3 = BN_CTX_get(ctx); 650e1051a39Sopenharmony_ci b1 = BN_CTX_get(ctx); 651e1051a39Sopenharmony_ci b2 = BN_CTX_get(ctx); 652e1051a39Sopenharmony_ci b3 = BN_CTX_get(ctx); 653e1051a39Sopenharmony_ci if (b3 == NULL) { 654e1051a39Sopenharmony_ci BN_CTX_end(ctx); 655e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 656e1051a39Sopenharmony_ci BN_CTX_free(ctx_new); 657e1051a39Sopenharmony_ci#endif 658e1051a39Sopenharmony_ci return -1; 659e1051a39Sopenharmony_ci } 660e1051a39Sopenharmony_ci 661e1051a39Sopenharmony_ci /* 662e1051a39Sopenharmony_ci * XXX This approach assumes that the external representation of curves 663e1051a39Sopenharmony_ci * over the same field type is the same. 664e1051a39Sopenharmony_ci */ 665e1051a39Sopenharmony_ci if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 666e1051a39Sopenharmony_ci !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 667e1051a39Sopenharmony_ci r = 1; 668e1051a39Sopenharmony_ci 669e1051a39Sopenharmony_ci /* return 1 if the curve parameters are different */ 670e1051a39Sopenharmony_ci if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0) 671e1051a39Sopenharmony_ci r = 1; 672e1051a39Sopenharmony_ci 673e1051a39Sopenharmony_ci /* XXX EC_POINT_cmp() assumes that the methods are equal */ 674e1051a39Sopenharmony_ci /* return 1 if the generators are different */ 675e1051a39Sopenharmony_ci if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 676e1051a39Sopenharmony_ci EC_GROUP_get0_generator(b), ctx) != 0) 677e1051a39Sopenharmony_ci r = 1; 678e1051a39Sopenharmony_ci 679e1051a39Sopenharmony_ci if (!r) { 680e1051a39Sopenharmony_ci const BIGNUM *ao, *bo, *ac, *bc; 681e1051a39Sopenharmony_ci /* compare the orders */ 682e1051a39Sopenharmony_ci ao = EC_GROUP_get0_order(a); 683e1051a39Sopenharmony_ci bo = EC_GROUP_get0_order(b); 684e1051a39Sopenharmony_ci if (ao == NULL || bo == NULL) { 685e1051a39Sopenharmony_ci /* return an error if either order is NULL */ 686e1051a39Sopenharmony_ci r = -1; 687e1051a39Sopenharmony_ci goto end; 688e1051a39Sopenharmony_ci } 689e1051a39Sopenharmony_ci if (BN_cmp(ao, bo) != 0) { 690e1051a39Sopenharmony_ci /* return 1 if orders are different */ 691e1051a39Sopenharmony_ci r = 1; 692e1051a39Sopenharmony_ci goto end; 693e1051a39Sopenharmony_ci } 694e1051a39Sopenharmony_ci /* 695e1051a39Sopenharmony_ci * It gets here if the curve parameters and generator matched. 696e1051a39Sopenharmony_ci * Now check the optional cofactors (if both are present). 697e1051a39Sopenharmony_ci */ 698e1051a39Sopenharmony_ci ac = EC_GROUP_get0_cofactor(a); 699e1051a39Sopenharmony_ci bc = EC_GROUP_get0_cofactor(b); 700e1051a39Sopenharmony_ci /* Returns 1 (mismatch) if both cofactors are specified and different */ 701e1051a39Sopenharmony_ci if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0) 702e1051a39Sopenharmony_ci r = 1; 703e1051a39Sopenharmony_ci /* Returns 0 if the parameters matched */ 704e1051a39Sopenharmony_ci } 705e1051a39Sopenharmony_ciend: 706e1051a39Sopenharmony_ci BN_CTX_end(ctx); 707e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 708e1051a39Sopenharmony_ci BN_CTX_free(ctx_new); 709e1051a39Sopenharmony_ci#endif 710e1051a39Sopenharmony_ci return r; 711e1051a39Sopenharmony_ci} 712e1051a39Sopenharmony_ci 713e1051a39Sopenharmony_ci/* functions for EC_POINT objects */ 714e1051a39Sopenharmony_ci 715e1051a39Sopenharmony_ciEC_POINT *EC_POINT_new(const EC_GROUP *group) 716e1051a39Sopenharmony_ci{ 717e1051a39Sopenharmony_ci EC_POINT *ret; 718e1051a39Sopenharmony_ci 719e1051a39Sopenharmony_ci if (group == NULL) { 720e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); 721e1051a39Sopenharmony_ci return NULL; 722e1051a39Sopenharmony_ci } 723e1051a39Sopenharmony_ci if (group->meth->point_init == NULL) { 724e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 725e1051a39Sopenharmony_ci return NULL; 726e1051a39Sopenharmony_ci } 727e1051a39Sopenharmony_ci 728e1051a39Sopenharmony_ci ret = OPENSSL_zalloc(sizeof(*ret)); 729e1051a39Sopenharmony_ci if (ret == NULL) { 730e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 731e1051a39Sopenharmony_ci return NULL; 732e1051a39Sopenharmony_ci } 733e1051a39Sopenharmony_ci 734e1051a39Sopenharmony_ci ret->meth = group->meth; 735e1051a39Sopenharmony_ci ret->curve_name = group->curve_name; 736e1051a39Sopenharmony_ci 737e1051a39Sopenharmony_ci if (!ret->meth->point_init(ret)) { 738e1051a39Sopenharmony_ci OPENSSL_free(ret); 739e1051a39Sopenharmony_ci return NULL; 740e1051a39Sopenharmony_ci } 741e1051a39Sopenharmony_ci 742e1051a39Sopenharmony_ci return ret; 743e1051a39Sopenharmony_ci} 744e1051a39Sopenharmony_ci 745e1051a39Sopenharmony_civoid EC_POINT_free(EC_POINT *point) 746e1051a39Sopenharmony_ci{ 747e1051a39Sopenharmony_ci if (point == NULL) 748e1051a39Sopenharmony_ci return; 749e1051a39Sopenharmony_ci 750e1051a39Sopenharmony_ci if (point->meth->point_finish != 0) 751e1051a39Sopenharmony_ci point->meth->point_finish(point); 752e1051a39Sopenharmony_ci OPENSSL_free(point); 753e1051a39Sopenharmony_ci} 754e1051a39Sopenharmony_ci 755e1051a39Sopenharmony_civoid EC_POINT_clear_free(EC_POINT *point) 756e1051a39Sopenharmony_ci{ 757e1051a39Sopenharmony_ci if (point == NULL) 758e1051a39Sopenharmony_ci return; 759e1051a39Sopenharmony_ci 760e1051a39Sopenharmony_ci if (point->meth->point_clear_finish != 0) 761e1051a39Sopenharmony_ci point->meth->point_clear_finish(point); 762e1051a39Sopenharmony_ci else if (point->meth->point_finish != 0) 763e1051a39Sopenharmony_ci point->meth->point_finish(point); 764e1051a39Sopenharmony_ci OPENSSL_clear_free(point, sizeof(*point)); 765e1051a39Sopenharmony_ci} 766e1051a39Sopenharmony_ci 767e1051a39Sopenharmony_ciint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 768e1051a39Sopenharmony_ci{ 769e1051a39Sopenharmony_ci if (dest->meth->point_copy == 0) { 770e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 771e1051a39Sopenharmony_ci return 0; 772e1051a39Sopenharmony_ci } 773e1051a39Sopenharmony_ci if (dest->meth != src->meth 774e1051a39Sopenharmony_ci || (dest->curve_name != src->curve_name 775e1051a39Sopenharmony_ci && dest->curve_name != 0 776e1051a39Sopenharmony_ci && src->curve_name != 0)) { 777e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 778e1051a39Sopenharmony_ci return 0; 779e1051a39Sopenharmony_ci } 780e1051a39Sopenharmony_ci if (dest == src) 781e1051a39Sopenharmony_ci return 1; 782e1051a39Sopenharmony_ci return dest->meth->point_copy(dest, src); 783e1051a39Sopenharmony_ci} 784e1051a39Sopenharmony_ci 785e1051a39Sopenharmony_ciEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 786e1051a39Sopenharmony_ci{ 787e1051a39Sopenharmony_ci EC_POINT *t; 788e1051a39Sopenharmony_ci int r; 789e1051a39Sopenharmony_ci 790e1051a39Sopenharmony_ci if (a == NULL) 791e1051a39Sopenharmony_ci return NULL; 792e1051a39Sopenharmony_ci 793e1051a39Sopenharmony_ci t = EC_POINT_new(group); 794e1051a39Sopenharmony_ci if (t == NULL) 795e1051a39Sopenharmony_ci return NULL; 796e1051a39Sopenharmony_ci r = EC_POINT_copy(t, a); 797e1051a39Sopenharmony_ci if (!r) { 798e1051a39Sopenharmony_ci EC_POINT_free(t); 799e1051a39Sopenharmony_ci return NULL; 800e1051a39Sopenharmony_ci } 801e1051a39Sopenharmony_ci return t; 802e1051a39Sopenharmony_ci} 803e1051a39Sopenharmony_ci 804e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 805e1051a39Sopenharmony_ciconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 806e1051a39Sopenharmony_ci{ 807e1051a39Sopenharmony_ci return point->meth; 808e1051a39Sopenharmony_ci} 809e1051a39Sopenharmony_ci#endif 810e1051a39Sopenharmony_ci 811e1051a39Sopenharmony_ciint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 812e1051a39Sopenharmony_ci{ 813e1051a39Sopenharmony_ci if (group->meth->point_set_to_infinity == 0) { 814e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 815e1051a39Sopenharmony_ci return 0; 816e1051a39Sopenharmony_ci } 817e1051a39Sopenharmony_ci if (group->meth != point->meth) { 818e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 819e1051a39Sopenharmony_ci return 0; 820e1051a39Sopenharmony_ci } 821e1051a39Sopenharmony_ci return group->meth->point_set_to_infinity(group, point); 822e1051a39Sopenharmony_ci} 823e1051a39Sopenharmony_ci 824e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 825e1051a39Sopenharmony_ciint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 826e1051a39Sopenharmony_ci EC_POINT *point, const BIGNUM *x, 827e1051a39Sopenharmony_ci const BIGNUM *y, const BIGNUM *z, 828e1051a39Sopenharmony_ci BN_CTX *ctx) 829e1051a39Sopenharmony_ci{ 830e1051a39Sopenharmony_ci if (group->meth->field_type != NID_X9_62_prime_field) { 831e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 832e1051a39Sopenharmony_ci return 0; 833e1051a39Sopenharmony_ci } 834e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 835e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 836e1051a39Sopenharmony_ci return 0; 837e1051a39Sopenharmony_ci } 838e1051a39Sopenharmony_ci return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, 839e1051a39Sopenharmony_ci x, y, z, ctx); 840e1051a39Sopenharmony_ci} 841e1051a39Sopenharmony_ci 842e1051a39Sopenharmony_ciint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 843e1051a39Sopenharmony_ci const EC_POINT *point, BIGNUM *x, 844e1051a39Sopenharmony_ci BIGNUM *y, BIGNUM *z, 845e1051a39Sopenharmony_ci BN_CTX *ctx) 846e1051a39Sopenharmony_ci{ 847e1051a39Sopenharmony_ci if (group->meth->field_type != NID_X9_62_prime_field) { 848e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 849e1051a39Sopenharmony_ci return 0; 850e1051a39Sopenharmony_ci } 851e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 852e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 853e1051a39Sopenharmony_ci return 0; 854e1051a39Sopenharmony_ci } 855e1051a39Sopenharmony_ci return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point, 856e1051a39Sopenharmony_ci x, y, z, ctx); 857e1051a39Sopenharmony_ci} 858e1051a39Sopenharmony_ci#endif 859e1051a39Sopenharmony_ci 860e1051a39Sopenharmony_ciint EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, 861e1051a39Sopenharmony_ci const BIGNUM *x, const BIGNUM *y, 862e1051a39Sopenharmony_ci BN_CTX *ctx) 863e1051a39Sopenharmony_ci{ 864e1051a39Sopenharmony_ci if (group->meth->point_set_affine_coordinates == NULL) { 865e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 866e1051a39Sopenharmony_ci return 0; 867e1051a39Sopenharmony_ci } 868e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 869e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 870e1051a39Sopenharmony_ci return 0; 871e1051a39Sopenharmony_ci } 872e1051a39Sopenharmony_ci if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) 873e1051a39Sopenharmony_ci return 0; 874e1051a39Sopenharmony_ci 875e1051a39Sopenharmony_ci if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 876e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE); 877e1051a39Sopenharmony_ci return 0; 878e1051a39Sopenharmony_ci } 879e1051a39Sopenharmony_ci return 1; 880e1051a39Sopenharmony_ci} 881e1051a39Sopenharmony_ci 882e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 883e1051a39Sopenharmony_ciint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 884e1051a39Sopenharmony_ci EC_POINT *point, const BIGNUM *x, 885e1051a39Sopenharmony_ci const BIGNUM *y, BN_CTX *ctx) 886e1051a39Sopenharmony_ci{ 887e1051a39Sopenharmony_ci return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); 888e1051a39Sopenharmony_ci} 889e1051a39Sopenharmony_ci 890e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_EC2M 891e1051a39Sopenharmony_ciint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 892e1051a39Sopenharmony_ci EC_POINT *point, const BIGNUM *x, 893e1051a39Sopenharmony_ci const BIGNUM *y, BN_CTX *ctx) 894e1051a39Sopenharmony_ci{ 895e1051a39Sopenharmony_ci return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); 896e1051a39Sopenharmony_ci} 897e1051a39Sopenharmony_ci# endif 898e1051a39Sopenharmony_ci#endif 899e1051a39Sopenharmony_ci 900e1051a39Sopenharmony_ciint EC_POINT_get_affine_coordinates(const EC_GROUP *group, 901e1051a39Sopenharmony_ci const EC_POINT *point, BIGNUM *x, BIGNUM *y, 902e1051a39Sopenharmony_ci BN_CTX *ctx) 903e1051a39Sopenharmony_ci{ 904e1051a39Sopenharmony_ci if (group->meth->point_get_affine_coordinates == NULL) { 905e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 906e1051a39Sopenharmony_ci return 0; 907e1051a39Sopenharmony_ci } 908e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 909e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 910e1051a39Sopenharmony_ci return 0; 911e1051a39Sopenharmony_ci } 912e1051a39Sopenharmony_ci if (EC_POINT_is_at_infinity(group, point)) { 913e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); 914e1051a39Sopenharmony_ci return 0; 915e1051a39Sopenharmony_ci } 916e1051a39Sopenharmony_ci return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 917e1051a39Sopenharmony_ci} 918e1051a39Sopenharmony_ci 919e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 920e1051a39Sopenharmony_ciint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 921e1051a39Sopenharmony_ci const EC_POINT *point, BIGNUM *x, 922e1051a39Sopenharmony_ci BIGNUM *y, BN_CTX *ctx) 923e1051a39Sopenharmony_ci{ 924e1051a39Sopenharmony_ci return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); 925e1051a39Sopenharmony_ci} 926e1051a39Sopenharmony_ci 927e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_EC2M 928e1051a39Sopenharmony_ciint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 929e1051a39Sopenharmony_ci const EC_POINT *point, BIGNUM *x, 930e1051a39Sopenharmony_ci BIGNUM *y, BN_CTX *ctx) 931e1051a39Sopenharmony_ci{ 932e1051a39Sopenharmony_ci return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); 933e1051a39Sopenharmony_ci} 934e1051a39Sopenharmony_ci# endif 935e1051a39Sopenharmony_ci#endif 936e1051a39Sopenharmony_ci 937e1051a39Sopenharmony_ciint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 938e1051a39Sopenharmony_ci const EC_POINT *b, BN_CTX *ctx) 939e1051a39Sopenharmony_ci{ 940e1051a39Sopenharmony_ci if (group->meth->add == 0) { 941e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 942e1051a39Sopenharmony_ci return 0; 943e1051a39Sopenharmony_ci } 944e1051a39Sopenharmony_ci if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group) 945e1051a39Sopenharmony_ci || !ec_point_is_compat(b, group)) { 946e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 947e1051a39Sopenharmony_ci return 0; 948e1051a39Sopenharmony_ci } 949e1051a39Sopenharmony_ci return group->meth->add(group, r, a, b, ctx); 950e1051a39Sopenharmony_ci} 951e1051a39Sopenharmony_ci 952e1051a39Sopenharmony_ciint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 953e1051a39Sopenharmony_ci BN_CTX *ctx) 954e1051a39Sopenharmony_ci{ 955e1051a39Sopenharmony_ci if (group->meth->dbl == 0) { 956e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 957e1051a39Sopenharmony_ci return 0; 958e1051a39Sopenharmony_ci } 959e1051a39Sopenharmony_ci if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) { 960e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 961e1051a39Sopenharmony_ci return 0; 962e1051a39Sopenharmony_ci } 963e1051a39Sopenharmony_ci return group->meth->dbl(group, r, a, ctx); 964e1051a39Sopenharmony_ci} 965e1051a39Sopenharmony_ci 966e1051a39Sopenharmony_ciint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 967e1051a39Sopenharmony_ci{ 968e1051a39Sopenharmony_ci if (group->meth->invert == 0) { 969e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 970e1051a39Sopenharmony_ci return 0; 971e1051a39Sopenharmony_ci } 972e1051a39Sopenharmony_ci if (!ec_point_is_compat(a, group)) { 973e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 974e1051a39Sopenharmony_ci return 0; 975e1051a39Sopenharmony_ci } 976e1051a39Sopenharmony_ci return group->meth->invert(group, a, ctx); 977e1051a39Sopenharmony_ci} 978e1051a39Sopenharmony_ci 979e1051a39Sopenharmony_ciint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 980e1051a39Sopenharmony_ci{ 981e1051a39Sopenharmony_ci if (group->meth->is_at_infinity == 0) { 982e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 983e1051a39Sopenharmony_ci return 0; 984e1051a39Sopenharmony_ci } 985e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 986e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 987e1051a39Sopenharmony_ci return 0; 988e1051a39Sopenharmony_ci } 989e1051a39Sopenharmony_ci return group->meth->is_at_infinity(group, point); 990e1051a39Sopenharmony_ci} 991e1051a39Sopenharmony_ci 992e1051a39Sopenharmony_ci/* 993e1051a39Sopenharmony_ci * Check whether an EC_POINT is on the curve or not. Note that the return 994e1051a39Sopenharmony_ci * value for this function should NOT be treated as a boolean. Return values: 995e1051a39Sopenharmony_ci * 1: The point is on the curve 996e1051a39Sopenharmony_ci * 0: The point is not on the curve 997e1051a39Sopenharmony_ci * -1: An error occurred 998e1051a39Sopenharmony_ci */ 999e1051a39Sopenharmony_ciint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 1000e1051a39Sopenharmony_ci BN_CTX *ctx) 1001e1051a39Sopenharmony_ci{ 1002e1051a39Sopenharmony_ci if (group->meth->is_on_curve == 0) { 1003e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1004e1051a39Sopenharmony_ci return 0; 1005e1051a39Sopenharmony_ci } 1006e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 1007e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1008e1051a39Sopenharmony_ci return 0; 1009e1051a39Sopenharmony_ci } 1010e1051a39Sopenharmony_ci return group->meth->is_on_curve(group, point, ctx); 1011e1051a39Sopenharmony_ci} 1012e1051a39Sopenharmony_ci 1013e1051a39Sopenharmony_ciint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 1014e1051a39Sopenharmony_ci BN_CTX *ctx) 1015e1051a39Sopenharmony_ci{ 1016e1051a39Sopenharmony_ci if (group->meth->point_cmp == 0) { 1017e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1018e1051a39Sopenharmony_ci return -1; 1019e1051a39Sopenharmony_ci } 1020e1051a39Sopenharmony_ci if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) { 1021e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1022e1051a39Sopenharmony_ci return -1; 1023e1051a39Sopenharmony_ci } 1024e1051a39Sopenharmony_ci return group->meth->point_cmp(group, a, b, ctx); 1025e1051a39Sopenharmony_ci} 1026e1051a39Sopenharmony_ci 1027e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 1028e1051a39Sopenharmony_ciint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 1029e1051a39Sopenharmony_ci{ 1030e1051a39Sopenharmony_ci if (group->meth->make_affine == 0) { 1031e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1032e1051a39Sopenharmony_ci return 0; 1033e1051a39Sopenharmony_ci } 1034e1051a39Sopenharmony_ci if (!ec_point_is_compat(point, group)) { 1035e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1036e1051a39Sopenharmony_ci return 0; 1037e1051a39Sopenharmony_ci } 1038e1051a39Sopenharmony_ci return group->meth->make_affine(group, point, ctx); 1039e1051a39Sopenharmony_ci} 1040e1051a39Sopenharmony_ci 1041e1051a39Sopenharmony_ciint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 1042e1051a39Sopenharmony_ci EC_POINT *points[], BN_CTX *ctx) 1043e1051a39Sopenharmony_ci{ 1044e1051a39Sopenharmony_ci size_t i; 1045e1051a39Sopenharmony_ci 1046e1051a39Sopenharmony_ci if (group->meth->points_make_affine == 0) { 1047e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1048e1051a39Sopenharmony_ci return 0; 1049e1051a39Sopenharmony_ci } 1050e1051a39Sopenharmony_ci for (i = 0; i < num; i++) { 1051e1051a39Sopenharmony_ci if (!ec_point_is_compat(points[i], group)) { 1052e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1053e1051a39Sopenharmony_ci return 0; 1054e1051a39Sopenharmony_ci } 1055e1051a39Sopenharmony_ci } 1056e1051a39Sopenharmony_ci return group->meth->points_make_affine(group, num, points, ctx); 1057e1051a39Sopenharmony_ci} 1058e1051a39Sopenharmony_ci#endif 1059e1051a39Sopenharmony_ci 1060e1051a39Sopenharmony_ci/* 1061e1051a39Sopenharmony_ci * Functions for point multiplication. If group->meth->mul is 0, we use the 1062e1051a39Sopenharmony_ci * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1063e1051a39Sopenharmony_ci * methods. 1064e1051a39Sopenharmony_ci */ 1065e1051a39Sopenharmony_ci 1066e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 1067e1051a39Sopenharmony_ciint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1068e1051a39Sopenharmony_ci size_t num, const EC_POINT *points[], 1069e1051a39Sopenharmony_ci const BIGNUM *scalars[], BN_CTX *ctx) 1070e1051a39Sopenharmony_ci{ 1071e1051a39Sopenharmony_ci int ret = 0; 1072e1051a39Sopenharmony_ci size_t i = 0; 1073e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1074e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 1075e1051a39Sopenharmony_ci#endif 1076e1051a39Sopenharmony_ci 1077e1051a39Sopenharmony_ci if (!ec_point_is_compat(r, group)) { 1078e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1079e1051a39Sopenharmony_ci return 0; 1080e1051a39Sopenharmony_ci } 1081e1051a39Sopenharmony_ci 1082e1051a39Sopenharmony_ci if (scalar == NULL && num == 0) 1083e1051a39Sopenharmony_ci return EC_POINT_set_to_infinity(group, r); 1084e1051a39Sopenharmony_ci 1085e1051a39Sopenharmony_ci for (i = 0; i < num; i++) { 1086e1051a39Sopenharmony_ci if (!ec_point_is_compat(points[i], group)) { 1087e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1088e1051a39Sopenharmony_ci return 0; 1089e1051a39Sopenharmony_ci } 1090e1051a39Sopenharmony_ci } 1091e1051a39Sopenharmony_ci 1092e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1093e1051a39Sopenharmony_ci if (ctx == NULL) 1094e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_secure_new(); 1095e1051a39Sopenharmony_ci#endif 1096e1051a39Sopenharmony_ci if (ctx == NULL) { 1097e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 1098e1051a39Sopenharmony_ci return 0; 1099e1051a39Sopenharmony_ci } 1100e1051a39Sopenharmony_ci 1101e1051a39Sopenharmony_ci if (group->meth->mul != NULL) 1102e1051a39Sopenharmony_ci ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1103e1051a39Sopenharmony_ci else 1104e1051a39Sopenharmony_ci /* use default */ 1105e1051a39Sopenharmony_ci ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1106e1051a39Sopenharmony_ci 1107e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1108e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 1109e1051a39Sopenharmony_ci#endif 1110e1051a39Sopenharmony_ci return ret; 1111e1051a39Sopenharmony_ci} 1112e1051a39Sopenharmony_ci#endif 1113e1051a39Sopenharmony_ci 1114e1051a39Sopenharmony_ciint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1115e1051a39Sopenharmony_ci const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1116e1051a39Sopenharmony_ci{ 1117e1051a39Sopenharmony_ci int ret = 0; 1118e1051a39Sopenharmony_ci size_t num; 1119e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1120e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 1121e1051a39Sopenharmony_ci#endif 1122e1051a39Sopenharmony_ci 1123e1051a39Sopenharmony_ci if (!ec_point_is_compat(r, group) 1124e1051a39Sopenharmony_ci || (point != NULL && !ec_point_is_compat(point, group))) { 1125e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS); 1126e1051a39Sopenharmony_ci return 0; 1127e1051a39Sopenharmony_ci } 1128e1051a39Sopenharmony_ci 1129e1051a39Sopenharmony_ci if (g_scalar == NULL && p_scalar == NULL) 1130e1051a39Sopenharmony_ci return EC_POINT_set_to_infinity(group, r); 1131e1051a39Sopenharmony_ci 1132e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1133e1051a39Sopenharmony_ci if (ctx == NULL) 1134e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_secure_new(); 1135e1051a39Sopenharmony_ci#endif 1136e1051a39Sopenharmony_ci if (ctx == NULL) { 1137e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 1138e1051a39Sopenharmony_ci return 0; 1139e1051a39Sopenharmony_ci } 1140e1051a39Sopenharmony_ci 1141e1051a39Sopenharmony_ci num = (point != NULL && p_scalar != NULL) ? 1 : 0; 1142e1051a39Sopenharmony_ci if (group->meth->mul != NULL) 1143e1051a39Sopenharmony_ci ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx); 1144e1051a39Sopenharmony_ci else 1145e1051a39Sopenharmony_ci /* use default */ 1146e1051a39Sopenharmony_ci ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx); 1147e1051a39Sopenharmony_ci 1148e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1149e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 1150e1051a39Sopenharmony_ci#endif 1151e1051a39Sopenharmony_ci return ret; 1152e1051a39Sopenharmony_ci} 1153e1051a39Sopenharmony_ci 1154e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 1155e1051a39Sopenharmony_ciint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1156e1051a39Sopenharmony_ci{ 1157e1051a39Sopenharmony_ci if (group->meth->mul == 0) 1158e1051a39Sopenharmony_ci /* use default */ 1159e1051a39Sopenharmony_ci return ossl_ec_wNAF_precompute_mult(group, ctx); 1160e1051a39Sopenharmony_ci 1161e1051a39Sopenharmony_ci if (group->meth->precompute_mult != 0) 1162e1051a39Sopenharmony_ci return group->meth->precompute_mult(group, ctx); 1163e1051a39Sopenharmony_ci else 1164e1051a39Sopenharmony_ci return 1; /* nothing to do, so report success */ 1165e1051a39Sopenharmony_ci} 1166e1051a39Sopenharmony_ci 1167e1051a39Sopenharmony_ciint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1168e1051a39Sopenharmony_ci{ 1169e1051a39Sopenharmony_ci if (group->meth->mul == 0) 1170e1051a39Sopenharmony_ci /* use default */ 1171e1051a39Sopenharmony_ci return ossl_ec_wNAF_have_precompute_mult(group); 1172e1051a39Sopenharmony_ci 1173e1051a39Sopenharmony_ci if (group->meth->have_precompute_mult != 0) 1174e1051a39Sopenharmony_ci return group->meth->have_precompute_mult(group); 1175e1051a39Sopenharmony_ci else 1176e1051a39Sopenharmony_ci return 0; /* cannot tell whether precomputation has 1177e1051a39Sopenharmony_ci * been performed */ 1178e1051a39Sopenharmony_ci} 1179e1051a39Sopenharmony_ci#endif 1180e1051a39Sopenharmony_ci 1181e1051a39Sopenharmony_ci/* 1182e1051a39Sopenharmony_ci * ec_precompute_mont_data sets |group->mont_data| from |group->order| and 1183e1051a39Sopenharmony_ci * returns one on success. On error it returns zero. 1184e1051a39Sopenharmony_ci */ 1185e1051a39Sopenharmony_cistatic int ec_precompute_mont_data(EC_GROUP *group) 1186e1051a39Sopenharmony_ci{ 1187e1051a39Sopenharmony_ci BN_CTX *ctx = BN_CTX_new_ex(group->libctx); 1188e1051a39Sopenharmony_ci int ret = 0; 1189e1051a39Sopenharmony_ci 1190e1051a39Sopenharmony_ci BN_MONT_CTX_free(group->mont_data); 1191e1051a39Sopenharmony_ci group->mont_data = NULL; 1192e1051a39Sopenharmony_ci 1193e1051a39Sopenharmony_ci if (ctx == NULL) 1194e1051a39Sopenharmony_ci goto err; 1195e1051a39Sopenharmony_ci 1196e1051a39Sopenharmony_ci group->mont_data = BN_MONT_CTX_new(); 1197e1051a39Sopenharmony_ci if (group->mont_data == NULL) 1198e1051a39Sopenharmony_ci goto err; 1199e1051a39Sopenharmony_ci 1200e1051a39Sopenharmony_ci if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) { 1201e1051a39Sopenharmony_ci BN_MONT_CTX_free(group->mont_data); 1202e1051a39Sopenharmony_ci group->mont_data = NULL; 1203e1051a39Sopenharmony_ci goto err; 1204e1051a39Sopenharmony_ci } 1205e1051a39Sopenharmony_ci 1206e1051a39Sopenharmony_ci ret = 1; 1207e1051a39Sopenharmony_ci 1208e1051a39Sopenharmony_ci err: 1209e1051a39Sopenharmony_ci 1210e1051a39Sopenharmony_ci BN_CTX_free(ctx); 1211e1051a39Sopenharmony_ci return ret; 1212e1051a39Sopenharmony_ci} 1213e1051a39Sopenharmony_ci 1214e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1215e1051a39Sopenharmony_ciint EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg) 1216e1051a39Sopenharmony_ci{ 1217e1051a39Sopenharmony_ci return CRYPTO_set_ex_data(&key->ex_data, idx, arg); 1218e1051a39Sopenharmony_ci} 1219e1051a39Sopenharmony_ci 1220e1051a39Sopenharmony_civoid *EC_KEY_get_ex_data(const EC_KEY *key, int idx) 1221e1051a39Sopenharmony_ci{ 1222e1051a39Sopenharmony_ci return CRYPTO_get_ex_data(&key->ex_data, idx); 1223e1051a39Sopenharmony_ci} 1224e1051a39Sopenharmony_ci#endif 1225e1051a39Sopenharmony_ci 1226e1051a39Sopenharmony_ciint ossl_ec_group_simple_order_bits(const EC_GROUP *group) 1227e1051a39Sopenharmony_ci{ 1228e1051a39Sopenharmony_ci if (group->order == NULL) 1229e1051a39Sopenharmony_ci return 0; 1230e1051a39Sopenharmony_ci return BN_num_bits(group->order); 1231e1051a39Sopenharmony_ci} 1232e1051a39Sopenharmony_ci 1233e1051a39Sopenharmony_cistatic int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, 1234e1051a39Sopenharmony_ci const BIGNUM *x, BN_CTX *ctx) 1235e1051a39Sopenharmony_ci{ 1236e1051a39Sopenharmony_ci BIGNUM *e = NULL; 1237e1051a39Sopenharmony_ci int ret = 0; 1238e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1239e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 1240e1051a39Sopenharmony_ci#endif 1241e1051a39Sopenharmony_ci 1242e1051a39Sopenharmony_ci if (group->mont_data == NULL) 1243e1051a39Sopenharmony_ci return 0; 1244e1051a39Sopenharmony_ci 1245e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1246e1051a39Sopenharmony_ci if (ctx == NULL) 1247e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_secure_new(); 1248e1051a39Sopenharmony_ci#endif 1249e1051a39Sopenharmony_ci if (ctx == NULL) 1250e1051a39Sopenharmony_ci return 0; 1251e1051a39Sopenharmony_ci 1252e1051a39Sopenharmony_ci BN_CTX_start(ctx); 1253e1051a39Sopenharmony_ci if ((e = BN_CTX_get(ctx)) == NULL) 1254e1051a39Sopenharmony_ci goto err; 1255e1051a39Sopenharmony_ci 1256e1051a39Sopenharmony_ci /*- 1257e1051a39Sopenharmony_ci * We want inverse in constant time, therefore we utilize the fact 1258e1051a39Sopenharmony_ci * order must be prime and use Fermats Little Theorem instead. 1259e1051a39Sopenharmony_ci */ 1260e1051a39Sopenharmony_ci if (!BN_set_word(e, 2)) 1261e1051a39Sopenharmony_ci goto err; 1262e1051a39Sopenharmony_ci if (!BN_sub(e, group->order, e)) 1263e1051a39Sopenharmony_ci goto err; 1264e1051a39Sopenharmony_ci /*- 1265e1051a39Sopenharmony_ci * Exponent e is public. 1266e1051a39Sopenharmony_ci * No need for scatter-gather or BN_FLG_CONSTTIME. 1267e1051a39Sopenharmony_ci */ 1268e1051a39Sopenharmony_ci if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data)) 1269e1051a39Sopenharmony_ci goto err; 1270e1051a39Sopenharmony_ci 1271e1051a39Sopenharmony_ci ret = 1; 1272e1051a39Sopenharmony_ci 1273e1051a39Sopenharmony_ci err: 1274e1051a39Sopenharmony_ci BN_CTX_end(ctx); 1275e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1276e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 1277e1051a39Sopenharmony_ci#endif 1278e1051a39Sopenharmony_ci return ret; 1279e1051a39Sopenharmony_ci} 1280e1051a39Sopenharmony_ci 1281e1051a39Sopenharmony_ci/*- 1282e1051a39Sopenharmony_ci * Default behavior, if group->meth->field_inverse_mod_ord is NULL: 1283e1051a39Sopenharmony_ci * - When group->order is even, this function returns an error. 1284e1051a39Sopenharmony_ci * - When group->order is otherwise composite, the correctness 1285e1051a39Sopenharmony_ci * of the output is not guaranteed. 1286e1051a39Sopenharmony_ci * - When x is outside the range [1, group->order), the correctness 1287e1051a39Sopenharmony_ci * of the output is not guaranteed. 1288e1051a39Sopenharmony_ci * - Otherwise, this function returns the multiplicative inverse in the 1289e1051a39Sopenharmony_ci * range [1, group->order). 1290e1051a39Sopenharmony_ci * 1291e1051a39Sopenharmony_ci * EC_METHODs must implement their own field_inverse_mod_ord for 1292e1051a39Sopenharmony_ci * other functionality. 1293e1051a39Sopenharmony_ci */ 1294e1051a39Sopenharmony_ciint ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res, 1295e1051a39Sopenharmony_ci const BIGNUM *x, BN_CTX *ctx) 1296e1051a39Sopenharmony_ci{ 1297e1051a39Sopenharmony_ci if (group->meth->field_inverse_mod_ord != NULL) 1298e1051a39Sopenharmony_ci return group->meth->field_inverse_mod_ord(group, res, x, ctx); 1299e1051a39Sopenharmony_ci else 1300e1051a39Sopenharmony_ci return ec_field_inverse_mod_ord(group, res, x, ctx); 1301e1051a39Sopenharmony_ci} 1302e1051a39Sopenharmony_ci 1303e1051a39Sopenharmony_ci/*- 1304e1051a39Sopenharmony_ci * Coordinate blinding for EC_POINT. 1305e1051a39Sopenharmony_ci * 1306e1051a39Sopenharmony_ci * The underlying EC_METHOD can optionally implement this function: 1307e1051a39Sopenharmony_ci * underlying implementations should return 0 on errors, or 1 on 1308e1051a39Sopenharmony_ci * success. 1309e1051a39Sopenharmony_ci * 1310e1051a39Sopenharmony_ci * This wrapper returns 1 in case the underlying EC_METHOD does not 1311e1051a39Sopenharmony_ci * support coordinate blinding. 1312e1051a39Sopenharmony_ci */ 1313e1051a39Sopenharmony_ciint ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, 1314e1051a39Sopenharmony_ci BN_CTX *ctx) 1315e1051a39Sopenharmony_ci{ 1316e1051a39Sopenharmony_ci if (group->meth->blind_coordinates == NULL) 1317e1051a39Sopenharmony_ci return 1; /* ignore if not implemented */ 1318e1051a39Sopenharmony_ci 1319e1051a39Sopenharmony_ci return group->meth->blind_coordinates(group, p, ctx); 1320e1051a39Sopenharmony_ci} 1321e1051a39Sopenharmony_ci 1322e1051a39Sopenharmony_ciint EC_GROUP_get_basis_type(const EC_GROUP *group) 1323e1051a39Sopenharmony_ci{ 1324e1051a39Sopenharmony_ci int i; 1325e1051a39Sopenharmony_ci 1326e1051a39Sopenharmony_ci if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field) 1327e1051a39Sopenharmony_ci /* everything else is currently not supported */ 1328e1051a39Sopenharmony_ci return 0; 1329e1051a39Sopenharmony_ci 1330e1051a39Sopenharmony_ci /* Find the last non-zero element of group->poly[] */ 1331e1051a39Sopenharmony_ci for (i = 0; 1332e1051a39Sopenharmony_ci i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0; 1333e1051a39Sopenharmony_ci i++) 1334e1051a39Sopenharmony_ci continue; 1335e1051a39Sopenharmony_ci 1336e1051a39Sopenharmony_ci if (i == 4) 1337e1051a39Sopenharmony_ci return NID_X9_62_ppBasis; 1338e1051a39Sopenharmony_ci else if (i == 2) 1339e1051a39Sopenharmony_ci return NID_X9_62_tpBasis; 1340e1051a39Sopenharmony_ci else 1341e1051a39Sopenharmony_ci /* everything else is currently not supported */ 1342e1051a39Sopenharmony_ci return 0; 1343e1051a39Sopenharmony_ci} 1344e1051a39Sopenharmony_ci 1345e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC2M 1346e1051a39Sopenharmony_ciint EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) 1347e1051a39Sopenharmony_ci{ 1348e1051a39Sopenharmony_ci if (group == NULL) 1349e1051a39Sopenharmony_ci return 0; 1350e1051a39Sopenharmony_ci 1351e1051a39Sopenharmony_ci if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field 1352e1051a39Sopenharmony_ci || !((group->poly[0] != 0) && (group->poly[1] != 0) 1353e1051a39Sopenharmony_ci && (group->poly[2] == 0))) { 1354e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1355e1051a39Sopenharmony_ci return 0; 1356e1051a39Sopenharmony_ci } 1357e1051a39Sopenharmony_ci 1358e1051a39Sopenharmony_ci if (k) 1359e1051a39Sopenharmony_ci *k = group->poly[1]; 1360e1051a39Sopenharmony_ci 1361e1051a39Sopenharmony_ci return 1; 1362e1051a39Sopenharmony_ci} 1363e1051a39Sopenharmony_ci 1364e1051a39Sopenharmony_ciint EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, 1365e1051a39Sopenharmony_ci unsigned int *k2, unsigned int *k3) 1366e1051a39Sopenharmony_ci{ 1367e1051a39Sopenharmony_ci if (group == NULL) 1368e1051a39Sopenharmony_ci return 0; 1369e1051a39Sopenharmony_ci 1370e1051a39Sopenharmony_ci if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field 1371e1051a39Sopenharmony_ci || !((group->poly[0] != 0) && (group->poly[1] != 0) 1372e1051a39Sopenharmony_ci && (group->poly[2] != 0) && (group->poly[3] != 0) 1373e1051a39Sopenharmony_ci && (group->poly[4] == 0))) { 1374e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1375e1051a39Sopenharmony_ci return 0; 1376e1051a39Sopenharmony_ci } 1377e1051a39Sopenharmony_ci 1378e1051a39Sopenharmony_ci if (k1) 1379e1051a39Sopenharmony_ci *k1 = group->poly[3]; 1380e1051a39Sopenharmony_ci if (k2) 1381e1051a39Sopenharmony_ci *k2 = group->poly[2]; 1382e1051a39Sopenharmony_ci if (k3) 1383e1051a39Sopenharmony_ci *k3 = group->poly[1]; 1384e1051a39Sopenharmony_ci 1385e1051a39Sopenharmony_ci return 1; 1386e1051a39Sopenharmony_ci} 1387e1051a39Sopenharmony_ci#endif 1388e1051a39Sopenharmony_ci 1389e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1390e1051a39Sopenharmony_ci/* 1391e1051a39Sopenharmony_ci * Check if the explicit parameters group matches any built-in curves. 1392e1051a39Sopenharmony_ci * 1393e1051a39Sopenharmony_ci * We create a copy of the group just built, so that we can remove optional 1394e1051a39Sopenharmony_ci * fields for the lookup: we do this to avoid the possibility that one of 1395e1051a39Sopenharmony_ci * the optional parameters is used to force the library into using a less 1396e1051a39Sopenharmony_ci * performant and less secure EC_METHOD instead of the specialized one. 1397e1051a39Sopenharmony_ci * In any case, `seed` is not really used in any computation, while a 1398e1051a39Sopenharmony_ci * cofactor different from the one in the built-in table is just 1399e1051a39Sopenharmony_ci * mathematically wrong anyway and should not be used. 1400e1051a39Sopenharmony_ci */ 1401e1051a39Sopenharmony_cistatic EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group, 1402e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, 1403e1051a39Sopenharmony_ci const char *propq, 1404e1051a39Sopenharmony_ci BN_CTX *ctx) 1405e1051a39Sopenharmony_ci{ 1406e1051a39Sopenharmony_ci EC_GROUP *ret_group = NULL, *dup = NULL; 1407e1051a39Sopenharmony_ci int curve_name_nid; 1408e1051a39Sopenharmony_ci 1409e1051a39Sopenharmony_ci const EC_POINT *point = EC_GROUP_get0_generator(group); 1410e1051a39Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 1411e1051a39Sopenharmony_ci int no_seed = (EC_GROUP_get0_seed(group) == NULL); 1412e1051a39Sopenharmony_ci 1413e1051a39Sopenharmony_ci if ((dup = EC_GROUP_dup(group)) == NULL 1414e1051a39Sopenharmony_ci || EC_GROUP_set_seed(dup, NULL, 0) != 1 1415e1051a39Sopenharmony_ci || !EC_GROUP_set_generator(dup, point, order, NULL)) 1416e1051a39Sopenharmony_ci goto err; 1417e1051a39Sopenharmony_ci if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) { 1418e1051a39Sopenharmony_ci /* 1419e1051a39Sopenharmony_ci * The input explicit parameters successfully matched one of the 1420e1051a39Sopenharmony_ci * built-in curves: often for built-in curves we have specialized 1421e1051a39Sopenharmony_ci * methods with better performance and hardening. 1422e1051a39Sopenharmony_ci * 1423e1051a39Sopenharmony_ci * In this case we replace the `EC_GROUP` created through explicit 1424e1051a39Sopenharmony_ci * parameters with one created from a named group. 1425e1051a39Sopenharmony_ci */ 1426e1051a39Sopenharmony_ci 1427e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 1428e1051a39Sopenharmony_ci /* 1429e1051a39Sopenharmony_ci * NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for 1430e1051a39Sopenharmony_ci * the same curve, we prefer the SECP nid when matching explicit 1431e1051a39Sopenharmony_ci * parameters as that is associated with a specialized EC_METHOD. 1432e1051a39Sopenharmony_ci */ 1433e1051a39Sopenharmony_ci if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12) 1434e1051a39Sopenharmony_ci curve_name_nid = NID_secp224r1; 1435e1051a39Sopenharmony_ci# endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */ 1436e1051a39Sopenharmony_ci 1437e1051a39Sopenharmony_ci ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid); 1438e1051a39Sopenharmony_ci if (ret_group == NULL) 1439e1051a39Sopenharmony_ci goto err; 1440e1051a39Sopenharmony_ci 1441e1051a39Sopenharmony_ci /* 1442e1051a39Sopenharmony_ci * Set the flag so that EC_GROUPs created from explicit parameters are 1443e1051a39Sopenharmony_ci * serialized using explicit parameters by default. 1444e1051a39Sopenharmony_ci */ 1445e1051a39Sopenharmony_ci EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE); 1446e1051a39Sopenharmony_ci 1447e1051a39Sopenharmony_ci /* 1448e1051a39Sopenharmony_ci * If the input params do not contain the optional seed field we make 1449e1051a39Sopenharmony_ci * sure it is not added to the returned group. 1450e1051a39Sopenharmony_ci * 1451e1051a39Sopenharmony_ci * The seed field is not really used inside libcrypto anyway, and 1452e1051a39Sopenharmony_ci * adding it to parsed explicit parameter keys would alter their DER 1453e1051a39Sopenharmony_ci * encoding output (because of the extra field) which could impact 1454e1051a39Sopenharmony_ci * applications fingerprinting keys by their DER encoding. 1455e1051a39Sopenharmony_ci */ 1456e1051a39Sopenharmony_ci if (no_seed) { 1457e1051a39Sopenharmony_ci if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1) 1458e1051a39Sopenharmony_ci goto err; 1459e1051a39Sopenharmony_ci } 1460e1051a39Sopenharmony_ci } else { 1461e1051a39Sopenharmony_ci ret_group = (EC_GROUP *)group; 1462e1051a39Sopenharmony_ci } 1463e1051a39Sopenharmony_ci EC_GROUP_free(dup); 1464e1051a39Sopenharmony_ci return ret_group; 1465e1051a39Sopenharmony_cierr: 1466e1051a39Sopenharmony_ci EC_GROUP_free(dup); 1467e1051a39Sopenharmony_ci EC_GROUP_free(ret_group); 1468e1051a39Sopenharmony_ci return NULL; 1469e1051a39Sopenharmony_ci} 1470e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 1471e1051a39Sopenharmony_ci 1472e1051a39Sopenharmony_cistatic EC_GROUP *group_new_from_name(const OSSL_PARAM *p, 1473e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 1474e1051a39Sopenharmony_ci{ 1475e1051a39Sopenharmony_ci int ok = 0, nid; 1476e1051a39Sopenharmony_ci const char *curve_name = NULL; 1477e1051a39Sopenharmony_ci 1478e1051a39Sopenharmony_ci switch (p->data_type) { 1479e1051a39Sopenharmony_ci case OSSL_PARAM_UTF8_STRING: 1480e1051a39Sopenharmony_ci /* The OSSL_PARAM functions have no support for this */ 1481e1051a39Sopenharmony_ci curve_name = p->data; 1482e1051a39Sopenharmony_ci ok = (curve_name != NULL); 1483e1051a39Sopenharmony_ci break; 1484e1051a39Sopenharmony_ci case OSSL_PARAM_UTF8_PTR: 1485e1051a39Sopenharmony_ci ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name); 1486e1051a39Sopenharmony_ci break; 1487e1051a39Sopenharmony_ci } 1488e1051a39Sopenharmony_ci 1489e1051a39Sopenharmony_ci if (ok) { 1490e1051a39Sopenharmony_ci nid = ossl_ec_curve_name2nid(curve_name); 1491e1051a39Sopenharmony_ci if (nid == NID_undef) { 1492e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE); 1493e1051a39Sopenharmony_ci return NULL; 1494e1051a39Sopenharmony_ci } else { 1495e1051a39Sopenharmony_ci return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid); 1496e1051a39Sopenharmony_ci } 1497e1051a39Sopenharmony_ci } 1498e1051a39Sopenharmony_ci return NULL; 1499e1051a39Sopenharmony_ci} 1500e1051a39Sopenharmony_ci 1501e1051a39Sopenharmony_ci/* These parameters can be set directly into an EC_GROUP */ 1502e1051a39Sopenharmony_ciint ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]) 1503e1051a39Sopenharmony_ci{ 1504e1051a39Sopenharmony_ci int encoding_flag = -1, format = -1; 1505e1051a39Sopenharmony_ci const OSSL_PARAM *p; 1506e1051a39Sopenharmony_ci 1507e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); 1508e1051a39Sopenharmony_ci if (p != NULL) { 1509e1051a39Sopenharmony_ci if (!ossl_ec_pt_format_param2id(p, &format)) { 1510e1051a39Sopenharmony_ci ECerr(0, EC_R_INVALID_FORM); 1511e1051a39Sopenharmony_ci return 0; 1512e1051a39Sopenharmony_ci } 1513e1051a39Sopenharmony_ci EC_GROUP_set_point_conversion_form(group, format); 1514e1051a39Sopenharmony_ci } 1515e1051a39Sopenharmony_ci 1516e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING); 1517e1051a39Sopenharmony_ci if (p != NULL) { 1518e1051a39Sopenharmony_ci if (!ossl_ec_encoding_param2id(p, &encoding_flag)) { 1519e1051a39Sopenharmony_ci ECerr(0, EC_R_INVALID_FORM); 1520e1051a39Sopenharmony_ci return 0; 1521e1051a39Sopenharmony_ci } 1522e1051a39Sopenharmony_ci EC_GROUP_set_asn1_flag(group, encoding_flag); 1523e1051a39Sopenharmony_ci } 1524e1051a39Sopenharmony_ci /* Optional seed */ 1525e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED); 1526e1051a39Sopenharmony_ci if (p != NULL) { 1527e1051a39Sopenharmony_ci /* The seed is allowed to be NULL */ 1528e1051a39Sopenharmony_ci if (p->data_type != OSSL_PARAM_OCTET_STRING 1529e1051a39Sopenharmony_ci || !EC_GROUP_set_seed(group, p->data, p->data_size)) { 1530e1051a39Sopenharmony_ci ECerr(0, EC_R_INVALID_SEED); 1531e1051a39Sopenharmony_ci return 0; 1532e1051a39Sopenharmony_ci } 1533e1051a39Sopenharmony_ci } 1534e1051a39Sopenharmony_ci return 1; 1535e1051a39Sopenharmony_ci} 1536e1051a39Sopenharmony_ci 1537e1051a39Sopenharmony_ciEC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], 1538e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 1539e1051a39Sopenharmony_ci{ 1540e1051a39Sopenharmony_ci const OSSL_PARAM *ptmp; 1541e1051a39Sopenharmony_ci EC_GROUP *group = NULL; 1542e1051a39Sopenharmony_ci 1543e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 1544e1051a39Sopenharmony_ci const OSSL_PARAM *pa, *pb; 1545e1051a39Sopenharmony_ci int ok = 0; 1546e1051a39Sopenharmony_ci EC_GROUP *named_group = NULL; 1547e1051a39Sopenharmony_ci BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL; 1548e1051a39Sopenharmony_ci EC_POINT *point = NULL; 1549e1051a39Sopenharmony_ci int field_bits = 0; 1550e1051a39Sopenharmony_ci int is_prime_field = 1; 1551e1051a39Sopenharmony_ci BN_CTX *bnctx = NULL; 1552e1051a39Sopenharmony_ci const unsigned char *buf = NULL; 1553e1051a39Sopenharmony_ci int encoding_flag = -1; 1554e1051a39Sopenharmony_ci#endif 1555e1051a39Sopenharmony_ci 1556e1051a39Sopenharmony_ci /* This is the simple named group case */ 1557e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); 1558e1051a39Sopenharmony_ci if (ptmp != NULL) { 1559e1051a39Sopenharmony_ci int decoded = 0; 1560e1051a39Sopenharmony_ci 1561e1051a39Sopenharmony_ci if ((group = group_new_from_name(ptmp, libctx, propq)) == NULL) 1562e1051a39Sopenharmony_ci return NULL; 1563e1051a39Sopenharmony_ci if (!ossl_ec_group_set_params(group, params)) { 1564e1051a39Sopenharmony_ci EC_GROUP_free(group); 1565e1051a39Sopenharmony_ci return NULL; 1566e1051a39Sopenharmony_ci } 1567e1051a39Sopenharmony_ci 1568e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, 1569e1051a39Sopenharmony_ci OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS); 1570e1051a39Sopenharmony_ci if (ptmp != NULL && !OSSL_PARAM_get_int(ptmp, &decoded)) { 1571e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); 1572e1051a39Sopenharmony_ci EC_GROUP_free(group); 1573e1051a39Sopenharmony_ci return NULL; 1574e1051a39Sopenharmony_ci } 1575e1051a39Sopenharmony_ci group->decoded_from_explicit_params = decoded > 0; 1576e1051a39Sopenharmony_ci return group; 1577e1051a39Sopenharmony_ci } 1578e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 1579e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED); 1580e1051a39Sopenharmony_ci return NULL; 1581e1051a39Sopenharmony_ci#else 1582e1051a39Sopenharmony_ci /* If it gets here then we are trying explicit parameters */ 1583e1051a39Sopenharmony_ci bnctx = BN_CTX_new_ex(libctx); 1584e1051a39Sopenharmony_ci if (bnctx == NULL) { 1585e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 1586e1051a39Sopenharmony_ci return 0; 1587e1051a39Sopenharmony_ci } 1588e1051a39Sopenharmony_ci BN_CTX_start(bnctx); 1589e1051a39Sopenharmony_ci 1590e1051a39Sopenharmony_ci p = BN_CTX_get(bnctx); 1591e1051a39Sopenharmony_ci a = BN_CTX_get(bnctx); 1592e1051a39Sopenharmony_ci b = BN_CTX_get(bnctx); 1593e1051a39Sopenharmony_ci order = BN_CTX_get(bnctx); 1594e1051a39Sopenharmony_ci if (order == NULL) { 1595e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 1596e1051a39Sopenharmony_ci goto err; 1597e1051a39Sopenharmony_ci } 1598e1051a39Sopenharmony_ci 1599e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE); 1600e1051a39Sopenharmony_ci if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) { 1601e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD); 1602e1051a39Sopenharmony_ci goto err; 1603e1051a39Sopenharmony_ci } 1604e1051a39Sopenharmony_ci if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) { 1605e1051a39Sopenharmony_ci is_prime_field = 1; 1606e1051a39Sopenharmony_ci } else if (OPENSSL_strcasecmp(ptmp->data, 1607e1051a39Sopenharmony_ci SN_X9_62_characteristic_two_field) == 0) { 1608e1051a39Sopenharmony_ci is_prime_field = 0; 1609e1051a39Sopenharmony_ci } else { 1610e1051a39Sopenharmony_ci /* Invalid field */ 1611e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD); 1612e1051a39Sopenharmony_ci goto err; 1613e1051a39Sopenharmony_ci } 1614e1051a39Sopenharmony_ci 1615e1051a39Sopenharmony_ci pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A); 1616e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_BN(pa, &a)) { 1617e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_A); 1618e1051a39Sopenharmony_ci goto err; 1619e1051a39Sopenharmony_ci } 1620e1051a39Sopenharmony_ci pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B); 1621e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_BN(pb, &b)) { 1622e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_B); 1623e1051a39Sopenharmony_ci goto err; 1624e1051a39Sopenharmony_ci } 1625e1051a39Sopenharmony_ci 1626e1051a39Sopenharmony_ci /* extract the prime number or irreducible polynomial */ 1627e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P); 1628e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_BN(ptmp, &p)) { 1629e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_P); 1630e1051a39Sopenharmony_ci goto err; 1631e1051a39Sopenharmony_ci } 1632e1051a39Sopenharmony_ci 1633e1051a39Sopenharmony_ci if (is_prime_field) { 1634e1051a39Sopenharmony_ci if (BN_is_negative(p) || BN_is_zero(p)) { 1635e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_P); 1636e1051a39Sopenharmony_ci goto err; 1637e1051a39Sopenharmony_ci } 1638e1051a39Sopenharmony_ci field_bits = BN_num_bits(p); 1639e1051a39Sopenharmony_ci if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { 1640e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); 1641e1051a39Sopenharmony_ci goto err; 1642e1051a39Sopenharmony_ci } 1643e1051a39Sopenharmony_ci 1644e1051a39Sopenharmony_ci /* create the EC_GROUP structure */ 1645e1051a39Sopenharmony_ci group = EC_GROUP_new_curve_GFp(p, a, b, bnctx); 1646e1051a39Sopenharmony_ci } else { 1647e1051a39Sopenharmony_ci# ifdef OPENSSL_NO_EC2M 1648e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED); 1649e1051a39Sopenharmony_ci goto err; 1650e1051a39Sopenharmony_ci# else 1651e1051a39Sopenharmony_ci /* create the EC_GROUP structure */ 1652e1051a39Sopenharmony_ci group = EC_GROUP_new_curve_GF2m(p, a, b, NULL); 1653e1051a39Sopenharmony_ci if (group != NULL) { 1654e1051a39Sopenharmony_ci field_bits = EC_GROUP_get_degree(group); 1655e1051a39Sopenharmony_ci if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { 1656e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE); 1657e1051a39Sopenharmony_ci goto err; 1658e1051a39Sopenharmony_ci } 1659e1051a39Sopenharmony_ci } 1660e1051a39Sopenharmony_ci# endif /* OPENSSL_NO_EC2M */ 1661e1051a39Sopenharmony_ci } 1662e1051a39Sopenharmony_ci 1663e1051a39Sopenharmony_ci if (group == NULL) { 1664e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 1665e1051a39Sopenharmony_ci goto err; 1666e1051a39Sopenharmony_ci } 1667e1051a39Sopenharmony_ci 1668e1051a39Sopenharmony_ci /* Optional seed */ 1669e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED); 1670e1051a39Sopenharmony_ci if (ptmp != NULL) { 1671e1051a39Sopenharmony_ci if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) { 1672e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED); 1673e1051a39Sopenharmony_ci goto err; 1674e1051a39Sopenharmony_ci } 1675e1051a39Sopenharmony_ci if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size)) 1676e1051a39Sopenharmony_ci goto err; 1677e1051a39Sopenharmony_ci } 1678e1051a39Sopenharmony_ci 1679e1051a39Sopenharmony_ci /* generator base point */ 1680e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR); 1681e1051a39Sopenharmony_ci if (ptmp == NULL 1682e1051a39Sopenharmony_ci || ptmp->data_type != OSSL_PARAM_OCTET_STRING) { 1683e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); 1684e1051a39Sopenharmony_ci goto err; 1685e1051a39Sopenharmony_ci } 1686e1051a39Sopenharmony_ci buf = (const unsigned char *)(ptmp->data); 1687e1051a39Sopenharmony_ci if ((point = EC_POINT_new(group)) == NULL) 1688e1051a39Sopenharmony_ci goto err; 1689e1051a39Sopenharmony_ci EC_GROUP_set_point_conversion_form(group, 1690e1051a39Sopenharmony_ci (point_conversion_form_t)buf[0] & ~0x01); 1691e1051a39Sopenharmony_ci if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) { 1692e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); 1693e1051a39Sopenharmony_ci goto err; 1694e1051a39Sopenharmony_ci } 1695e1051a39Sopenharmony_ci 1696e1051a39Sopenharmony_ci /* order */ 1697e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER); 1698e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_BN(ptmp, &order) 1699e1051a39Sopenharmony_ci || (BN_is_negative(order) || BN_is_zero(order)) 1700e1051a39Sopenharmony_ci || (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */ 1701e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER); 1702e1051a39Sopenharmony_ci goto err; 1703e1051a39Sopenharmony_ci } 1704e1051a39Sopenharmony_ci 1705e1051a39Sopenharmony_ci /* Optional cofactor */ 1706e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR); 1707e1051a39Sopenharmony_ci if (ptmp != NULL) { 1708e1051a39Sopenharmony_ci cofactor = BN_CTX_get(bnctx); 1709e1051a39Sopenharmony_ci if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) { 1710e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR); 1711e1051a39Sopenharmony_ci goto err; 1712e1051a39Sopenharmony_ci } 1713e1051a39Sopenharmony_ci } 1714e1051a39Sopenharmony_ci 1715e1051a39Sopenharmony_ci /* set the generator, order and cofactor (if present) */ 1716e1051a39Sopenharmony_ci if (!EC_GROUP_set_generator(group, point, order, cofactor)) { 1717e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR); 1718e1051a39Sopenharmony_ci goto err; 1719e1051a39Sopenharmony_ci } 1720e1051a39Sopenharmony_ci 1721e1051a39Sopenharmony_ci named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx); 1722e1051a39Sopenharmony_ci if (named_group == NULL) { 1723e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION); 1724e1051a39Sopenharmony_ci goto err; 1725e1051a39Sopenharmony_ci } 1726e1051a39Sopenharmony_ci if (named_group == group) { 1727e1051a39Sopenharmony_ci /* 1728e1051a39Sopenharmony_ci * If we did not find a named group then the encoding should be explicit 1729e1051a39Sopenharmony_ci * if it was specified 1730e1051a39Sopenharmony_ci */ 1731e1051a39Sopenharmony_ci ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING); 1732e1051a39Sopenharmony_ci if (ptmp != NULL 1733e1051a39Sopenharmony_ci && !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) { 1734e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 1735e1051a39Sopenharmony_ci goto err; 1736e1051a39Sopenharmony_ci } 1737e1051a39Sopenharmony_ci if (encoding_flag == OPENSSL_EC_NAMED_CURVE) { 1738e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 1739e1051a39Sopenharmony_ci goto err; 1740e1051a39Sopenharmony_ci } 1741e1051a39Sopenharmony_ci EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE); 1742e1051a39Sopenharmony_ci } else { 1743e1051a39Sopenharmony_ci EC_GROUP_free(group); 1744e1051a39Sopenharmony_ci group = named_group; 1745e1051a39Sopenharmony_ci } 1746e1051a39Sopenharmony_ci /* We've imported the group from explicit parameters, set it so. */ 1747e1051a39Sopenharmony_ci group->decoded_from_explicit_params = 1; 1748e1051a39Sopenharmony_ci ok = 1; 1749e1051a39Sopenharmony_ci err: 1750e1051a39Sopenharmony_ci if (!ok) { 1751e1051a39Sopenharmony_ci EC_GROUP_free(group); 1752e1051a39Sopenharmony_ci group = NULL; 1753e1051a39Sopenharmony_ci } 1754e1051a39Sopenharmony_ci EC_POINT_free(point); 1755e1051a39Sopenharmony_ci BN_CTX_end(bnctx); 1756e1051a39Sopenharmony_ci BN_CTX_free(bnctx); 1757e1051a39Sopenharmony_ci 1758e1051a39Sopenharmony_ci return group; 1759e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 1760e1051a39Sopenharmony_ci} 1761