1*a9bbc4f7Stb /* $OpenBSD: ec_lib.c,v 1.116 2025/01/25 13:13:57 tb Exp $ */ 24fcf65c5Sdjm /* 34fcf65c5Sdjm * Originally written by Bodo Moeller for the OpenSSL project. 44fcf65c5Sdjm */ 5da347917Sbeck /* ==================================================================== 64fcf65c5Sdjm * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 7da347917Sbeck * 8da347917Sbeck * Redistribution and use in source and binary forms, with or without 9da347917Sbeck * modification, are permitted provided that the following conditions 10da347917Sbeck * are met: 11da347917Sbeck * 12da347917Sbeck * 1. Redistributions of source code must retain the above copyright 13da347917Sbeck * notice, this list of conditions and the following disclaimer. 14da347917Sbeck * 15da347917Sbeck * 2. Redistributions in binary form must reproduce the above copyright 16da347917Sbeck * notice, this list of conditions and the following disclaimer in 17da347917Sbeck * the documentation and/or other materials provided with the 18da347917Sbeck * distribution. 19da347917Sbeck * 20da347917Sbeck * 3. All advertising materials mentioning features or use of this 21da347917Sbeck * software must display the following acknowledgment: 22da347917Sbeck * "This product includes software developed by the OpenSSL Project 23da347917Sbeck * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24da347917Sbeck * 25da347917Sbeck * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26da347917Sbeck * endorse or promote products derived from this software without 27da347917Sbeck * prior written permission. For written permission, please contact 28da347917Sbeck * openssl-core@openssl.org. 29da347917Sbeck * 30da347917Sbeck * 5. Products derived from this software may not be called "OpenSSL" 31da347917Sbeck * nor may "OpenSSL" appear in their names without prior written 32da347917Sbeck * permission of the OpenSSL Project. 33da347917Sbeck * 34da347917Sbeck * 6. Redistributions of any form whatsoever must retain the following 35da347917Sbeck * acknowledgment: 36da347917Sbeck * "This product includes software developed by the OpenSSL Project 37da347917Sbeck * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38da347917Sbeck * 39da347917Sbeck * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40da347917Sbeck * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41da347917Sbeck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42da347917Sbeck * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43da347917Sbeck * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44da347917Sbeck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45da347917Sbeck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46da347917Sbeck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47da347917Sbeck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48da347917Sbeck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49da347917Sbeck * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50da347917Sbeck * OF THE POSSIBILITY OF SUCH DAMAGE. 51da347917Sbeck * ==================================================================== 52da347917Sbeck * 53da347917Sbeck * This product includes cryptographic software written by Eric Young 54da347917Sbeck * (eay@cryptsoft.com). This product includes software written by Tim 55da347917Sbeck * Hudson (tjh@cryptsoft.com). 56da347917Sbeck * 57da347917Sbeck */ 584fcf65c5Sdjm /* ==================================================================== 594fcf65c5Sdjm * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 604fcf65c5Sdjm * Binary polynomial ECC support in OpenSSL originally developed by 614fcf65c5Sdjm * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 624fcf65c5Sdjm */ 63da347917Sbeck 64587ebde5Stb #include <stdlib.h> 65da347917Sbeck #include <string.h> 66da347917Sbeck 678cf4d6a6Sjsing #include <openssl/opensslconf.h> 688cf4d6a6Sjsing 69587ebde5Stb #include <openssl/bn.h> 70587ebde5Stb #include <openssl/ec.h> 71da347917Sbeck #include <openssl/err.h> 72587ebde5Stb #include <openssl/objects.h> 73da347917Sbeck #include <openssl/opensslv.h> 74da347917Sbeck 75c9675a23Stb #include "bn_local.h" 76c9675a23Stb #include "ec_local.h" 77da347917Sbeck 78f67ac449Stedu EC_GROUP * 79f67ac449Stedu EC_GROUP_new(const EC_METHOD *meth) 80da347917Sbeck { 8121332710Stb EC_GROUP *group = NULL; 82da347917Sbeck 83f67ac449Stedu if (meth == NULL) { 845067ae9fSbeck ECerror(EC_R_SLOT_FULL); 8521332710Stb goto err; 86da347917Sbeck } 8721332710Stb if ((group = calloc(1, sizeof(*group))) == NULL) { 885067ae9fSbeck ECerror(ERR_R_MALLOC_FAILURE); 8921332710Stb goto err; 90da347917Sbeck } 91da347917Sbeck 9221332710Stb group->meth = meth; 934fcf65c5Sdjm 9421332710Stb group->asn1_flag = OPENSSL_EC_NAMED_CURVE; 9521332710Stb group->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 96da347917Sbeck 973c2cb882Stb if ((group->p = BN_new()) == NULL) 983c2cb882Stb goto err; 993c2cb882Stb if ((group->a = BN_new()) == NULL) 1003c2cb882Stb goto err; 1013c2cb882Stb if ((group->b = BN_new()) == NULL) 1023c2cb882Stb goto err; 1033c2cb882Stb 1043c2cb882Stb if ((group->order = BN_new()) == NULL) 1053c2cb882Stb goto err; 1063c2cb882Stb if ((group->cofactor = BN_new()) == NULL) 1073c2cb882Stb goto err; 1083c2cb882Stb 1093c2cb882Stb /* 1101c80ffcfStb * generator, seed and mont_ctx are optional. 1113c2cb882Stb */ 1123c2cb882Stb 11321332710Stb return group; 11421332710Stb 11521332710Stb err: 11621332710Stb EC_GROUP_free(group); 11721332710Stb 118da347917Sbeck return NULL; 119da347917Sbeck } 120ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_new); 121da347917Sbeck 122f67ac449Stedu void 123f67ac449Stedu EC_GROUP_free(EC_GROUP *group) 124da347917Sbeck { 125d7292987Sjsing if (group == NULL) 126f67ac449Stedu return; 127c58501deSbeck 1283c2cb882Stb BN_free(group->p); 1293c2cb882Stb BN_free(group->a); 1303c2cb882Stb BN_free(group->b); 13121084e45Stb 13221084e45Stb BN_MONT_CTX_free(group->mont_ctx); 133da347917Sbeck 134a7854573Sjsing EC_POINT_free(group->generator); 1353c2cb882Stb BN_free(group->order); 1363c2cb882Stb BN_free(group->cofactor); 1374fcf65c5Sdjm 1387de8a684Sderaadt freezero(group->seed, group->seed_len); 1397de8a684Sderaadt freezero(group, sizeof *group); 140da347917Sbeck } 141ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_free); 142da347917Sbeck 143a7854573Sjsing void 144a7854573Sjsing EC_GROUP_clear_free(EC_GROUP *group) 145a7854573Sjsing { 146d7292987Sjsing EC_GROUP_free(group); 147a7854573Sjsing } 1488a552917Sbeck LCRYPTO_ALIAS(EC_GROUP_clear_free); 149da347917Sbeck 150f67ac449Stedu int 151428f68d0Stb EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src) 152da347917Sbeck { 153428f68d0Stb if (dst->meth != src->meth) { 1545067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 155da347917Sbeck return 0; 156da347917Sbeck } 157428f68d0Stb if (dst == src) 158da347917Sbeck return 1; 159da347917Sbeck 160428f68d0Stb if (!bn_copy(dst->p, src->p)) 161f67ac449Stedu return 0; 162428f68d0Stb if (!bn_copy(dst->a, src->a)) 1632ab5ac8dStb return 0; 164428f68d0Stb if (!bn_copy(dst->b, src->b)) 1652ab5ac8dStb return 0; 1662ab5ac8dStb 167428f68d0Stb dst->a_is_minus3 = src->a_is_minus3; 1682ab5ac8dStb 169428f68d0Stb BN_MONT_CTX_free(dst->mont_ctx); 170428f68d0Stb dst->mont_ctx = NULL; 1712ab5ac8dStb if (src->mont_ctx != NULL) { 172428f68d0Stb if ((dst->mont_ctx = BN_MONT_CTX_new()) == NULL) 1732ab5ac8dStb return 0; 174428f68d0Stb if (!BN_MONT_CTX_copy(dst->mont_ctx, src->mont_ctx)) 1752ab5ac8dStb return 0; 1762ab5ac8dStb } 177cf85019eStb 178428f68d0Stb EC_POINT_free(dst->generator); 179428f68d0Stb dst->generator = NULL; 180cf85019eStb if (src->generator != NULL) { 181428f68d0Stb if (!EC_GROUP_set_generator(dst, src->generator, src->order, 1823c2cb882Stb src->cofactor)) 183cf85019eStb return 0; 184cf85019eStb } else { 185cf85019eStb /* XXX - should do the sanity checks as in set_generator() */ 186428f68d0Stb if (!bn_copy(dst->order, src->order)) 187f67ac449Stedu return 0; 188428f68d0Stb if (!bn_copy(dst->cofactor, src->cofactor)) 189f67ac449Stedu return 0; 190cf85019eStb } 1914fcf65c5Sdjm 192428f68d0Stb dst->nid = src->nid; 193428f68d0Stb dst->asn1_flag = src->asn1_flag; 194428f68d0Stb dst->asn1_form = src->asn1_form; 1954fcf65c5Sdjm 196428f68d0Stb if (!EC_GROUP_set_seed(dst, src->seed, src->seed_len)) 1974fcf65c5Sdjm return 0; 1984fcf65c5Sdjm 1992ab5ac8dStb return 1; 200da347917Sbeck } 201ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_copy); 202da347917Sbeck 203f67ac449Stedu EC_GROUP * 20426b186dbStb EC_GROUP_dup(const EC_GROUP *in_group) 2054fcf65c5Sdjm { 20626b186dbStb EC_GROUP *group = NULL; 2074fcf65c5Sdjm 20826b186dbStb if (in_group == NULL) 20926b186dbStb goto err; 21026b186dbStb 21126b186dbStb if ((group = EC_GROUP_new(in_group->meth)) == NULL) 21226b186dbStb goto err; 21326b186dbStb if (!EC_GROUP_copy(group, in_group)) 21426b186dbStb goto err; 21526b186dbStb 21626b186dbStb return group; 21726b186dbStb 21826b186dbStb err: 21926b186dbStb EC_GROUP_free(group); 22026b186dbStb 2218b4d06edStb return NULL; 2224fcf65c5Sdjm } 223ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_dup); 2244fcf65c5Sdjm 225baf7262aStb /* 22615f1f9a3Stb * If there is a user-provided cofactor, sanity check and use it. Otherwise 227823dae7dStb * try computing the cofactor from generator order n and field cardinality p. 228baf7262aStb * This works for all curves of cryptographic interest. 229baf7262aStb * 230823dae7dStb * Hasse's theorem: | h * n - (p + 1) | <= 2 * sqrt(p) 231baf7262aStb * 232823dae7dStb * So: h_min = (p + 1 - 2*sqrt(p)) / n and h_max = (p + 1 + 2*sqrt(p)) / n and 233823dae7dStb * therefore h_max - h_min = 4*sqrt(p) / n. So if n > 4*sqrt(p) holds, there is 234baf7262aStb * only one possible value for h: 235baf7262aStb * 236823dae7dStb * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (p + 1)/n \rceil 237baf7262aStb * 238baf7262aStb * Otherwise, zero cofactor and return success. 239baf7262aStb */ 240baf7262aStb static int 24115f1f9a3Stb ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) 242baf7262aStb { 243baf7262aStb BN_CTX *ctx = NULL; 24415f1f9a3Stb BIGNUM *cofactor; 245baf7262aStb int ret = 0; 246baf7262aStb 2473c2cb882Stb BN_zero(group->cofactor); 24815f1f9a3Stb 24915f1f9a3Stb if ((ctx = BN_CTX_new()) == NULL) 25015f1f9a3Stb goto err; 25115f1f9a3Stb 25215f1f9a3Stb BN_CTX_start(ctx); 25315f1f9a3Stb if ((cofactor = BN_CTX_get(ctx)) == NULL) 25415f1f9a3Stb goto err; 25515f1f9a3Stb 25615f1f9a3Stb /* 25715f1f9a3Stb * Unfortunately, the cofactor is an optional field in many standards. 25815f1f9a3Stb * Internally, the library uses a 0 cofactor as a marker for "unknown 25915f1f9a3Stb * cofactor". So accept in_cofactor == NULL or in_cofactor >= 0. 26015f1f9a3Stb */ 26115f1f9a3Stb if (in_cofactor != NULL && !BN_is_zero(in_cofactor)) { 26215f1f9a3Stb if (BN_is_negative(in_cofactor)) { 26315f1f9a3Stb ECerror(EC_R_UNKNOWN_COFACTOR); 26415f1f9a3Stb goto err; 26515f1f9a3Stb } 26615f1f9a3Stb if (!bn_copy(cofactor, in_cofactor)) 26715f1f9a3Stb goto err; 26815f1f9a3Stb goto done; 26915f1f9a3Stb } 27015f1f9a3Stb 271baf7262aStb /* 272baf7262aStb * If the cofactor is too large, we cannot guess it and default to zero. 273823dae7dStb * The RHS of below is a strict overestimate of log(4 * sqrt(p)). 274baf7262aStb */ 2753c2cb882Stb if (BN_num_bits(group->order) <= (BN_num_bits(group->p) + 1) / 2 + 3) 27615f1f9a3Stb goto done; 277baf7262aStb 278baf7262aStb /* 279baf7262aStb * Compute 280823dae7dStb * h = \lfloor (p + 1)/n \rceil = \lfloor (p + 1 + n/2) / n \rfloor. 281baf7262aStb */ 282baf7262aStb 283baf7262aStb /* h = n/2 */ 2843c2cb882Stb if (!BN_rshift1(cofactor, group->order)) 285baf7262aStb goto err; 286baf7262aStb /* h = 1 + n/2 */ 28715f1f9a3Stb if (!BN_add_word(cofactor, 1)) 288baf7262aStb goto err; 289823dae7dStb /* h = p + 1 + n/2 */ 2903c2cb882Stb if (!BN_add(cofactor, cofactor, group->p)) 291baf7262aStb goto err; 292823dae7dStb /* h = (p + 1 + n/2) / n */ 2933c2cb882Stb if (!BN_div_ct(cofactor, NULL, cofactor, group->order, ctx)) 29415f1f9a3Stb goto err; 29515f1f9a3Stb 29615f1f9a3Stb done: 29715f1f9a3Stb /* Use Hasse's theorem to bound the cofactor. */ 2983c2cb882Stb if (BN_num_bits(cofactor) > BN_num_bits(group->p) + 1) { 29915f1f9a3Stb ECerror(EC_R_INVALID_GROUP_ORDER); 30015f1f9a3Stb goto err; 30115f1f9a3Stb } 30215f1f9a3Stb 3033c2cb882Stb if (!bn_copy(group->cofactor, cofactor)) 304baf7262aStb goto err; 305baf7262aStb 306baf7262aStb ret = 1; 307e2787e9fStb 308baf7262aStb err: 309baf7262aStb BN_CTX_end(ctx); 310baf7262aStb BN_CTX_free(ctx); 311e2787e9fStb 312baf7262aStb return ret; 313baf7262aStb } 314da347917Sbeck 315f67ac449Stedu int 316f67ac449Stedu EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 317f67ac449Stedu const BIGNUM *order, const BIGNUM *cofactor) 318da347917Sbeck { 319f67ac449Stedu if (generator == NULL) { 3205067ae9fSbeck ECerror(ERR_R_PASSED_NULL_PARAMETER); 321da347917Sbeck return 0; 322da347917Sbeck } 323baf7262aStb 3243fd2f05cStb /* Require p >= 1. */ 3253c2cb882Stb if (BN_is_zero(group->p) || BN_is_negative(group->p)) { 326baf7262aStb ECerror(EC_R_INVALID_FIELD); 327baf7262aStb return 0; 328baf7262aStb } 329baf7262aStb 330baf7262aStb /* 3313cc94d96Stb * Require order > 1 and enforce an upper bound of at most one bit more 332baf7262aStb * than the field cardinality due to Hasse's theorem. 333baf7262aStb */ 3343cc94d96Stb if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 || 3353c2cb882Stb BN_num_bits(order) > BN_num_bits(group->p) + 1) { 336baf7262aStb ECerror(EC_R_INVALID_GROUP_ORDER); 337baf7262aStb return 0; 338baf7262aStb } 339baf7262aStb 34026dd3e34Stb if (group->generator == NULL) 3414fcf65c5Sdjm group->generator = EC_POINT_new(group); 342f67ac449Stedu if (group->generator == NULL) 343f67ac449Stedu return 0; 34426dd3e34Stb 345f67ac449Stedu if (!EC_POINT_copy(group->generator, generator)) 346f67ac449Stedu return 0; 3474fcf65c5Sdjm 3483c2cb882Stb if (!bn_copy(group->order, order)) 349f67ac449Stedu return 0; 3504fcf65c5Sdjm 35115f1f9a3Stb if (!ec_set_cofactor(group, cofactor)) 352f67ac449Stedu return 0; 353206d4dd0Stb 3544fcf65c5Sdjm return 1; 355da347917Sbeck } 356ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_generator); 357da347917Sbeck 358f67ac449Stedu const EC_POINT * 359f67ac449Stedu EC_GROUP_get0_generator(const EC_GROUP *group) 360da347917Sbeck { 3614fcf65c5Sdjm return group->generator; 362da347917Sbeck } 363ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get0_generator); 364da347917Sbeck 365f67ac449Stedu int 366f67ac449Stedu EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 367da347917Sbeck { 3683c2cb882Stb if (!bn_copy(order, group->order)) 369da347917Sbeck return 0; 3704fcf65c5Sdjm 3714fcf65c5Sdjm return !BN_is_zero(order); 372da347917Sbeck } 373ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_order); 374da347917Sbeck 3757fd74d8bStb const BIGNUM * 3767fd74d8bStb EC_GROUP_get0_order(const EC_GROUP *group) 3777fd74d8bStb { 3783c2cb882Stb return group->order; 3797fd74d8bStb } 3807fd74d8bStb 38170b8897aStb int 38270b8897aStb EC_GROUP_order_bits(const EC_GROUP *group) 38370b8897aStb { 384be018b2cStb return BN_num_bits(group->order); 38570b8897aStb } 386ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_order_bits); 387da347917Sbeck 388f67ac449Stedu int 389f67ac449Stedu EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 390da347917Sbeck { 3913c2cb882Stb if (!bn_copy(cofactor, group->cofactor)) 3924fcf65c5Sdjm return 0; 3934fcf65c5Sdjm 3943c2cb882Stb return !BN_is_zero(group->cofactor); 3954fcf65c5Sdjm } 396ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_cofactor); 3974fcf65c5Sdjm 398b072588bStb const BIGNUM * 399b072588bStb EC_GROUP_get0_cofactor(const EC_GROUP *group) 400b072588bStb { 4013c2cb882Stb return group->cofactor; 402b072588bStb } 403b072588bStb 404f67ac449Stedu void 405f67ac449Stedu EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 406da347917Sbeck { 40749eaabcdStb group->nid = nid; 4084fcf65c5Sdjm } 409ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_curve_name); 4104fcf65c5Sdjm 411f67ac449Stedu int 412f67ac449Stedu EC_GROUP_get_curve_name(const EC_GROUP *group) 4134fcf65c5Sdjm { 41449eaabcdStb return group->nid; 4154fcf65c5Sdjm } 416ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_curve_name); 4174fcf65c5Sdjm 418f67ac449Stedu void 419f67ac449Stedu EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 4204fcf65c5Sdjm { 4214fcf65c5Sdjm group->asn1_flag = flag; 4224fcf65c5Sdjm } 423ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_asn1_flag); 4244fcf65c5Sdjm 425f67ac449Stedu int 426f67ac449Stedu EC_GROUP_get_asn1_flag(const EC_GROUP *group) 4274fcf65c5Sdjm { 4284fcf65c5Sdjm return group->asn1_flag; 4294fcf65c5Sdjm } 430ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_asn1_flag); 4314fcf65c5Sdjm 432f67ac449Stedu void 433f67ac449Stedu EC_GROUP_set_point_conversion_form(EC_GROUP *group, 4344fcf65c5Sdjm point_conversion_form_t form) 4354fcf65c5Sdjm { 4364fcf65c5Sdjm group->asn1_form = form; 4374fcf65c5Sdjm } 438ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_point_conversion_form); 4394fcf65c5Sdjm 440f67ac449Stedu point_conversion_form_t 441f67ac449Stedu EC_GROUP_get_point_conversion_form(const EC_GROUP *group) 4424fcf65c5Sdjm { 4434fcf65c5Sdjm return group->asn1_form; 4444fcf65c5Sdjm } 445ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_point_conversion_form); 4464fcf65c5Sdjm 447f67ac449Stedu size_t 448b5448e3dStb EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *seed, size_t len) 4494fcf65c5Sdjm { 4506f3a6cb1Sbeck free(group->seed); 4514fcf65c5Sdjm group->seed = NULL; 4524fcf65c5Sdjm group->seed_len = 0; 453b5448e3dStb 454c715fd08Stb if (seed == NULL || len == 0) 4554fcf65c5Sdjm return 1; 4564fcf65c5Sdjm 4576f3a6cb1Sbeck if ((group->seed = malloc(len)) == NULL) 4584fcf65c5Sdjm return 0; 459b5448e3dStb memcpy(group->seed, seed, len); 4604fcf65c5Sdjm group->seed_len = len; 4614fcf65c5Sdjm 4624fcf65c5Sdjm return len; 4634fcf65c5Sdjm } 464ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_seed); 4654fcf65c5Sdjm 466f67ac449Stedu unsigned char * 467f67ac449Stedu EC_GROUP_get0_seed(const EC_GROUP *group) 4684fcf65c5Sdjm { 4694fcf65c5Sdjm return group->seed; 4704fcf65c5Sdjm } 471ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get0_seed); 4724fcf65c5Sdjm 473f67ac449Stedu size_t 474f67ac449Stedu EC_GROUP_get_seed_len(const EC_GROUP *group) 4754fcf65c5Sdjm { 4764fcf65c5Sdjm return group->seed_len; 4774fcf65c5Sdjm } 478ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_seed_len); 4794fcf65c5Sdjm 480f67ac449Stedu int 4810b15d7eeStb EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 4821f65bd71Sjsing const BIGNUM *b, BN_CTX *ctx_in) 4834fcf65c5Sdjm { 4841f65bd71Sjsing BN_CTX *ctx; 4851f65bd71Sjsing int ret = 0; 4861f65bd71Sjsing 4871f65bd71Sjsing if ((ctx = ctx_in) == NULL) 4881f65bd71Sjsing ctx = BN_CTX_new(); 4891f65bd71Sjsing if (ctx == NULL) 4901f65bd71Sjsing goto err; 4911f65bd71Sjsing 49260ca3fa5Stb if (group->meth->group_set_curve == NULL) { 4935067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 4941f65bd71Sjsing goto err; 495da347917Sbeck } 4961f65bd71Sjsing ret = group->meth->group_set_curve(group, p, a, b, ctx); 4971f65bd71Sjsing 4981f65bd71Sjsing err: 4991f65bd71Sjsing if (ctx != ctx_in) 5001f65bd71Sjsing BN_CTX_free(ctx); 5011f65bd71Sjsing 5021f65bd71Sjsing return ret; 5034fcf65c5Sdjm } 504ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_set_curve); 5054fcf65c5Sdjm 506f67ac449Stedu int 5070b15d7eeStb EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, 5081f65bd71Sjsing BN_CTX *ctx_in) 5094fcf65c5Sdjm { 5101f65bd71Sjsing BN_CTX *ctx; 5111f65bd71Sjsing int ret = 0; 5121f65bd71Sjsing 5131f65bd71Sjsing if ((ctx = ctx_in) == NULL) 5141f65bd71Sjsing ctx = BN_CTX_new(); 5151f65bd71Sjsing if (ctx == NULL) 5161f65bd71Sjsing goto err; 5171f65bd71Sjsing 51860ca3fa5Stb if (group->meth->group_get_curve == NULL) { 5195067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 5207b871452Stb goto err; 5214fcf65c5Sdjm } 5221f65bd71Sjsing ret = group->meth->group_get_curve(group, p, a, b, ctx); 5231f65bd71Sjsing 5241f65bd71Sjsing err: 5251f65bd71Sjsing if (ctx != ctx_in) 5261f65bd71Sjsing BN_CTX_free(ctx); 5271f65bd71Sjsing 5281f65bd71Sjsing return ret; 5294fcf65c5Sdjm } 530ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_curve); 5314fcf65c5Sdjm 5320b15d7eeStb int 5330b15d7eeStb EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 5340b15d7eeStb const BIGNUM *b, BN_CTX *ctx) 5350b15d7eeStb { 5360b15d7eeStb return EC_GROUP_set_curve(group, p, a, b, ctx); 5370b15d7eeStb } 5388a552917Sbeck LCRYPTO_ALIAS(EC_GROUP_set_curve_GFp); 5390b15d7eeStb 5400b15d7eeStb int 5410b15d7eeStb EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, 5420b15d7eeStb BN_CTX *ctx) 5430b15d7eeStb { 5440b15d7eeStb return EC_GROUP_get_curve(group, p, a, b, ctx); 5450b15d7eeStb } 5468a552917Sbeck LCRYPTO_ALIAS(EC_GROUP_get_curve_GFp); 5470b15d7eeStb 5482567856aStb EC_GROUP * 5492567856aStb EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, 5502567856aStb BN_CTX *ctx) 5512567856aStb { 5522567856aStb EC_GROUP *group; 5532567856aStb 5542567856aStb if ((group = EC_GROUP_new(EC_GFp_mont_method())) == NULL) 5552567856aStb goto err; 5562567856aStb 5572567856aStb if (!EC_GROUP_set_curve(group, p, a, b, ctx)) 5582567856aStb goto err; 5592567856aStb 5602567856aStb return group; 5612567856aStb 5622567856aStb err: 5632567856aStb EC_GROUP_free(group); 5642567856aStb 5652567856aStb return NULL; 5662567856aStb } 5672567856aStb LCRYPTO_ALIAS(EC_GROUP_new_curve_GFp); 5682567856aStb 569f67ac449Stedu int 570f67ac449Stedu EC_GROUP_get_degree(const EC_GROUP *group) 5714fcf65c5Sdjm { 572be018b2cStb return BN_num_bits(group->p); 5734fcf65c5Sdjm } 574ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_get_degree); 5754fcf65c5Sdjm 576f67ac449Stedu int 5771f65bd71Sjsing EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx_in) 5784fcf65c5Sdjm { 5791f65bd71Sjsing BN_CTX *ctx; 580a537a13eStb BIGNUM *p, *a, *b, *discriminant; 5811f65bd71Sjsing int ret = 0; 5821f65bd71Sjsing 5831f65bd71Sjsing if ((ctx = ctx_in) == NULL) 5841f65bd71Sjsing ctx = BN_CTX_new(); 5851f65bd71Sjsing if (ctx == NULL) 5861f65bd71Sjsing goto err; 5871f65bd71Sjsing 588a537a13eStb BN_CTX_start(ctx); 589a537a13eStb 590a537a13eStb if ((p = BN_CTX_get(ctx)) == NULL) 5917b871452Stb goto err; 592a537a13eStb if ((a = BN_CTX_get(ctx)) == NULL) 593a537a13eStb goto err; 594a537a13eStb if ((b = BN_CTX_get(ctx)) == NULL) 595a537a13eStb goto err; 596a537a13eStb if ((discriminant = BN_CTX_get(ctx)) == NULL) 597a537a13eStb goto err; 598a537a13eStb 599a537a13eStb if (!EC_GROUP_get_curve(group, p, a, b, ctx)) 600a537a13eStb goto err; 601a537a13eStb 602a537a13eStb /* 603742574bfStb * Check that the discriminant 4a^3 + 27b^2 is non-zero modulo p 604742574bfStb * assuming that p > 3 is prime and that a and b are in [0, p). 605a537a13eStb */ 606a537a13eStb 607a537a13eStb if (BN_is_zero(a) && BN_is_zero(b)) 608a537a13eStb goto err; 609a537a13eStb if (BN_is_zero(a) || BN_is_zero(b)) 610a537a13eStb goto done; 611a537a13eStb 612a537a13eStb /* Compute the discriminant: first 4a^3, then 27b^2, then their sum. */ 613a537a13eStb if (!BN_mod_sqr(discriminant, a, p, ctx)) 614a537a13eStb goto err; 615a537a13eStb if (!BN_mod_mul(discriminant, discriminant, a, p, ctx)) 616a537a13eStb goto err; 617a537a13eStb if (!BN_lshift(discriminant, discriminant, 2)) 618a537a13eStb goto err; 619a537a13eStb 620a537a13eStb if (!BN_mod_sqr(b, b, p, ctx)) 621a537a13eStb goto err; 622a537a13eStb if (!BN_mul_word(b, 27)) 623a537a13eStb goto err; 624a537a13eStb 625a537a13eStb if (!BN_mod_add(discriminant, discriminant, b, p, ctx)) 626a537a13eStb goto err; 627a537a13eStb 628a537a13eStb if (BN_is_zero(discriminant)) 629a537a13eStb goto err; 630a537a13eStb 631a537a13eStb done: 632a537a13eStb ret = 1; 6331f65bd71Sjsing 6341f65bd71Sjsing err: 6351f65bd71Sjsing if (ctx != ctx_in) 6361f65bd71Sjsing BN_CTX_free(ctx); 6371f65bd71Sjsing 6381f65bd71Sjsing return ret; 6394fcf65c5Sdjm } 640ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_check_discriminant); 6414fcf65c5Sdjm 642f67ac449Stedu int 643c827a8a4Stb EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx_in) 644c827a8a4Stb { 645c827a8a4Stb BN_CTX *ctx; 646c827a8a4Stb EC_POINT *point = NULL; 647ba47179bStb const EC_POINT *generator; 648c827a8a4Stb const BIGNUM *order; 649c827a8a4Stb int ret = 0; 650c827a8a4Stb 651c827a8a4Stb if ((ctx = ctx_in) == NULL) 652c827a8a4Stb ctx = BN_CTX_new(); 653c827a8a4Stb if (ctx == NULL) 654c827a8a4Stb goto err; 655c827a8a4Stb 656c827a8a4Stb if (!EC_GROUP_check_discriminant(group, ctx)) { 657c827a8a4Stb ECerror(EC_R_DISCRIMINANT_IS_ZERO); 658c827a8a4Stb goto err; 659c827a8a4Stb } 660c6fb1b70Stb 661ba47179bStb if ((generator = EC_GROUP_get0_generator(group)) == NULL) { 662c827a8a4Stb ECerror(EC_R_UNDEFINED_GENERATOR); 663c827a8a4Stb goto err; 664c827a8a4Stb } 665ba47179bStb if (EC_POINT_is_on_curve(group, generator, ctx) <= 0) { 666c827a8a4Stb ECerror(EC_R_POINT_IS_NOT_ON_CURVE); 667c827a8a4Stb goto err; 668c827a8a4Stb } 669c6fb1b70Stb 670c827a8a4Stb if ((point = EC_POINT_new(group)) == NULL) 671c827a8a4Stb goto err; 672c827a8a4Stb if ((order = EC_GROUP_get0_order(group)) == NULL) 673c827a8a4Stb goto err; 674c827a8a4Stb if (BN_is_zero(order)) { 675c827a8a4Stb ECerror(EC_R_UNDEFINED_ORDER); 676c827a8a4Stb goto err; 677c827a8a4Stb } 678c827a8a4Stb if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) 679c827a8a4Stb goto err; 68009b27144Stb if (!EC_POINT_is_at_infinity(group, point)) { 681c827a8a4Stb ECerror(EC_R_INVALID_GROUP_ORDER); 682c827a8a4Stb goto err; 683c827a8a4Stb } 684c827a8a4Stb 685c827a8a4Stb ret = 1; 686c827a8a4Stb 687c827a8a4Stb err: 688c827a8a4Stb if (ctx != ctx_in) 689c827a8a4Stb BN_CTX_free(ctx); 690c827a8a4Stb 691c827a8a4Stb EC_POINT_free(point); 692c827a8a4Stb 693c827a8a4Stb return ret; 694c827a8a4Stb } 695c827a8a4Stb LCRYPTO_ALIAS(EC_GROUP_check); 696c827a8a4Stb 6977e8924c8Stb /* 6987e8924c8Stb * Returns -1 on error, 0 if the groups are equal, 1 if they are distinct. 6997e8924c8Stb */ 700c827a8a4Stb int 7017e8924c8Stb EC_GROUP_cmp(const EC_GROUP *group1, const EC_GROUP *group2, BN_CTX *ctx_in) 7024fcf65c5Sdjm { 7037e8924c8Stb BN_CTX *ctx = NULL; 7047e8924c8Stb BIGNUM *p1, *a1, *b1, *p2, *a2, *b2; 7057e8924c8Stb const EC_POINT *generator1, *generator2; 7067e8924c8Stb const BIGNUM *order1, *order2, *cofactor1, *cofactor2; 7077e8924c8Stb int nid1, nid2; 7087e8924c8Stb int cmp = 1; 7097e8924c8Stb int ret = -1; 7104fcf65c5Sdjm 7117e8924c8Stb if ((ctx = ctx_in) == NULL) 7127e8924c8Stb ctx = BN_CTX_new(); 7137e8924c8Stb if (ctx == NULL) 7147e8924c8Stb goto err; 7154fcf65c5Sdjm 7164fcf65c5Sdjm BN_CTX_start(ctx); 7177e8924c8Stb 7187e8924c8Stb if ((nid1 = EC_GROUP_get_curve_name(group1)) != NID_undef && 7197e8924c8Stb (nid2 = EC_GROUP_get_curve_name(group2)) != NID_undef) { 7207e8924c8Stb if (nid1 != nid2) 7217e8924c8Stb goto distinct; 7227e8924c8Stb } 7237e8924c8Stb 7247e8924c8Stb if ((p1 = BN_CTX_get(ctx)) == NULL) 7257e8924c8Stb goto err; 726aa389b8cSjsing if ((a1 = BN_CTX_get(ctx)) == NULL) 727aa389b8cSjsing goto err; 728aa389b8cSjsing if ((b1 = BN_CTX_get(ctx)) == NULL) 729aa389b8cSjsing goto err; 7307e8924c8Stb if ((p2 = BN_CTX_get(ctx)) == NULL) 731aa389b8cSjsing goto err; 7327e8924c8Stb if ((a2 = BN_CTX_get(ctx)) == NULL) 7337e8924c8Stb goto err; 7347e8924c8Stb if ((b2 = BN_CTX_get(ctx)) == NULL) 735aa389b8cSjsing goto err; 736aa389b8cSjsing 737f67ac449Stedu /* 7387e8924c8Stb * If we ever support curves in non-Weierstrass form, this check needs 7397e8924c8Stb * to be adjusted. The comparison of the generators will fail anyway. 7404fcf65c5Sdjm */ 7417e8924c8Stb if (!EC_GROUP_get_curve(group1, p1, a1, b1, ctx)) 7424c1eb2ebSdoug goto err; 7437e8924c8Stb if (!EC_GROUP_get_curve(group2, p2, a2, b2, ctx)) 7447e8924c8Stb goto err; 7454fcf65c5Sdjm 7467e8924c8Stb if (BN_cmp(p1, p2) != 0 || BN_cmp(a1, a2) != 0 || BN_cmp(b1, b2) != 0) 7477e8924c8Stb goto distinct; 7487e8924c8Stb 7497e8924c8Stb if ((generator1 = EC_GROUP_get0_generator(group1)) == NULL) 7507e8924c8Stb goto err; 7517e8924c8Stb if ((generator2 = EC_GROUP_get0_generator(group2)) == NULL) 7527e8924c8Stb goto err; 7537e8924c8Stb 7547e8924c8Stb /* 7557e8924c8Stb * It does not matter whether group1 or group2 is used: both points must 7567e8924c8Stb * have a matching method for this to succeed. 7577e8924c8Stb */ 7587e8924c8Stb if ((cmp = EC_POINT_cmp(group1, generator1, generator2, ctx)) < 0) 7597e8924c8Stb goto err; 7607e8924c8Stb if (cmp == 1) 7617e8924c8Stb goto distinct; 7627e8924c8Stb cmp = 1; 7637e8924c8Stb 7647e8924c8Stb if ((order1 = EC_GROUP_get0_order(group1)) == NULL) 7657e8924c8Stb goto err; 7667e8924c8Stb if ((order2 = EC_GROUP_get0_order(group2)) == NULL) 7677e8924c8Stb goto err; 7687e8924c8Stb 7697e8924c8Stb if ((cofactor1 = EC_GROUP_get0_cofactor(group1)) == NULL) 7707e8924c8Stb goto err; 7717e8924c8Stb if ((cofactor2 = EC_GROUP_get0_cofactor(group2)) == NULL) 7727e8924c8Stb goto err; 7737e8924c8Stb 7747e8924c8Stb if (BN_cmp(order1, order2) != 0 || BN_cmp(cofactor1, cofactor2) != 0) 7757e8924c8Stb goto distinct; 7767e8924c8Stb 7777e8924c8Stb /* All parameters match: the groups are equal. */ 7787e8924c8Stb cmp = 0; 7797e8924c8Stb 7807e8924c8Stb distinct: 7817e8924c8Stb ret = cmp; 782aa389b8cSjsing 783aa389b8cSjsing err: 784aa389b8cSjsing BN_CTX_end(ctx); 7857e8924c8Stb 7867e8924c8Stb if (ctx != ctx_in) 787aa389b8cSjsing BN_CTX_free(ctx); 7887e8924c8Stb 7897e8924c8Stb return ret; 790da347917Sbeck } 791ea2baf45Sbeck LCRYPTO_ALIAS(EC_GROUP_cmp); 792da347917Sbeck 793f67ac449Stedu EC_POINT * 794f67ac449Stedu EC_POINT_new(const EC_GROUP *group) 795da347917Sbeck { 79622896994Stb EC_POINT *point = NULL; 797da347917Sbeck 798f67ac449Stedu if (group == NULL) { 7995067ae9fSbeck ECerror(ERR_R_PASSED_NULL_PARAMETER); 80022896994Stb goto err; 801da347917Sbeck } 802da347917Sbeck 80322896994Stb if ((point = calloc(1, sizeof(*point))) == NULL) { 80422896994Stb ECerror(ERR_R_MALLOC_FAILURE); 80522896994Stb goto err; 806da347917Sbeck } 80722896994Stb 8083c2cb882Stb if ((point->X = BN_new()) == NULL) 8093c2cb882Stb goto err; 8103c2cb882Stb if ((point->Y = BN_new()) == NULL) 8113c2cb882Stb goto err; 8123c2cb882Stb if ((point->Z = BN_new()) == NULL) 8133c2cb882Stb goto err; 8143c2cb882Stb 81522896994Stb point->meth = group->meth; 81622896994Stb 81722896994Stb return point; 81822896994Stb 81922896994Stb err: 82022896994Stb EC_POINT_free(point); 82122896994Stb 82222896994Stb return NULL; 823da347917Sbeck } 824ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_new); 825da347917Sbeck 826f67ac449Stedu void 827f67ac449Stedu EC_POINT_free(EC_POINT *point) 828da347917Sbeck { 829d7292987Sjsing if (point == NULL) 830f67ac449Stedu return; 831c58501deSbeck 8323c2cb882Stb BN_free(point->X); 8333c2cb882Stb BN_free(point->Y); 8343c2cb882Stb BN_free(point->Z); 835da347917Sbeck 836a7854573Sjsing freezero(point, sizeof *point); 837a7854573Sjsing } 838ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_free); 839da347917Sbeck 840f67ac449Stedu void 841f67ac449Stedu EC_POINT_clear_free(EC_POINT *point) 842da347917Sbeck { 843d7292987Sjsing EC_POINT_free(point); 844da347917Sbeck } 8458a552917Sbeck LCRYPTO_ALIAS(EC_POINT_clear_free); 846da347917Sbeck 847f67ac449Stedu int 848cb86d051Stb EC_POINT_copy(EC_POINT *dst, const EC_POINT *src) 849da347917Sbeck { 850cb86d051Stb if (dst->meth != src->meth) { 8515067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 852da347917Sbeck return 0; 853da347917Sbeck } 854cb86d051Stb if (dst == src) 855da347917Sbeck return 1; 8569da94e6dStb 857cb86d051Stb if (!bn_copy(dst->X, src->X)) 8589da94e6dStb return 0; 859cb86d051Stb if (!bn_copy(dst->Y, src->Y)) 8609da94e6dStb return 0; 861cb86d051Stb if (!bn_copy(dst->Z, src->Z)) 8629da94e6dStb return 0; 863cb86d051Stb dst->Z_is_one = src->Z_is_one; 8649da94e6dStb 8659da94e6dStb return 1; 866da347917Sbeck } 867ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_copy); 868da347917Sbeck 869f67ac449Stedu EC_POINT * 87022896994Stb EC_POINT_dup(const EC_POINT *in_point, const EC_GROUP *group) 8714fcf65c5Sdjm { 87222896994Stb EC_POINT *point = NULL; 8734fcf65c5Sdjm 87422896994Stb if (in_point == NULL) 87522896994Stb goto err; 8764fcf65c5Sdjm 87722896994Stb if ((point = EC_POINT_new(group)) == NULL) 87822896994Stb goto err; 87922896994Stb 88022896994Stb if (!EC_POINT_copy(point, in_point)) 88122896994Stb goto err; 88222896994Stb 88322896994Stb return point; 88422896994Stb 88522896994Stb err: 88622896994Stb EC_POINT_free(point); 88722896994Stb 8884fcf65c5Sdjm return NULL; 8894fcf65c5Sdjm } 890ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_dup); 8914fcf65c5Sdjm 892f67ac449Stedu int 893f67ac449Stedu EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 894da347917Sbeck { 895f67ac449Stedu if (group->meth != point->meth) { 8965067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 897da347917Sbeck return 0; 898da347917Sbeck } 8999da94e6dStb 9003c2cb882Stb BN_zero(point->Z); 9019da94e6dStb point->Z_is_one = 0; 9029da94e6dStb 9039da94e6dStb return 1; 904da347917Sbeck } 905ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_set_to_infinity); 906da347917Sbeck 9074f21b6f2Stb int 90874a506e7Stb EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, 9091f65bd71Sjsing const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx_in) 910da347917Sbeck { 9111f65bd71Sjsing BN_CTX *ctx; 9121f65bd71Sjsing int ret = 0; 9131f65bd71Sjsing 9141f65bd71Sjsing if ((ctx = ctx_in) == NULL) 9151f65bd71Sjsing ctx = BN_CTX_new(); 9161f65bd71Sjsing if (ctx == NULL) 9171f65bd71Sjsing goto err; 9181f65bd71Sjsing 91914a674d4Stb if (group->meth->point_set_affine_coordinates == NULL) { 9205067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 9211f65bd71Sjsing goto err; 922da347917Sbeck } 923f67ac449Stedu if (group->meth != point->meth) { 9245067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 9251f65bd71Sjsing goto err; 926da347917Sbeck } 927ea076652Stb if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) 9281f65bd71Sjsing goto err; 9291f65bd71Sjsing 930ea076652Stb if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 931ea076652Stb ECerror(EC_R_POINT_IS_NOT_ON_CURVE); 9321f65bd71Sjsing goto err; 933ea076652Stb } 9341f65bd71Sjsing 9351f65bd71Sjsing ret = 1; 9361f65bd71Sjsing 9371f65bd71Sjsing err: 9381f65bd71Sjsing if (ctx != ctx_in) 9391f65bd71Sjsing BN_CTX_free(ctx); 9401f65bd71Sjsing 9411f65bd71Sjsing return ret; 9424fcf65c5Sdjm } 943ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_set_affine_coordinates); 9444fcf65c5Sdjm 94574a506e7Stb int 94674a506e7Stb EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 94774a506e7Stb const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 94874a506e7Stb { 94974a506e7Stb return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); 95074a506e7Stb } 9518a552917Sbeck LCRYPTO_ALIAS(EC_POINT_set_affine_coordinates_GFp); 95274a506e7Stb 953f67ac449Stedu int 95474a506e7Stb EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, 9551f65bd71Sjsing BIGNUM *x, BIGNUM *y, BN_CTX *ctx_in) 956da347917Sbeck { 9572d40ce70Stb BN_CTX *ctx = NULL; 9581f65bd71Sjsing int ret = 0; 9591f65bd71Sjsing 9602d40ce70Stb if (EC_POINT_is_at_infinity(group, point) > 0) { 9612d40ce70Stb ECerror(EC_R_POINT_AT_INFINITY); 9622d40ce70Stb goto err; 9632d40ce70Stb } 9642d40ce70Stb 9651f65bd71Sjsing if ((ctx = ctx_in) == NULL) 9661f65bd71Sjsing ctx = BN_CTX_new(); 9671f65bd71Sjsing if (ctx == NULL) 9681f65bd71Sjsing goto err; 9691f65bd71Sjsing 97014a674d4Stb if (group->meth->point_get_affine_coordinates == NULL) { 9715067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 9727b871452Stb goto err; 973da347917Sbeck } 974f67ac449Stedu if (group->meth != point->meth) { 9755067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 9767b871452Stb goto err; 977da347917Sbeck } 9781f65bd71Sjsing ret = group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 9791f65bd71Sjsing 9801f65bd71Sjsing err: 9811f65bd71Sjsing if (ctx != ctx_in) 9821f65bd71Sjsing BN_CTX_free(ctx); 9831f65bd71Sjsing 9841f65bd71Sjsing return ret; 9854fcf65c5Sdjm } 986ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_get_affine_coordinates); 9874fcf65c5Sdjm 98874a506e7Stb int 98974a506e7Stb EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 99074a506e7Stb BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 99174a506e7Stb { 99274a506e7Stb return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); 99374a506e7Stb } 9948a552917Sbeck LCRYPTO_ALIAS(EC_POINT_get_affine_coordinates_GFp); 99574a506e7Stb 996f67ac449Stedu int 997c2bab48dStb EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, 99869100aa7Stb const BIGNUM *in_x, int y_bit, BN_CTX *ctx_in) 999c2bab48dStb { 100069100aa7Stb BIGNUM *p, *a, *b, *w, *x, *y; 1001c2bab48dStb BN_CTX *ctx; 1002c2bab48dStb int ret = 0; 1003c2bab48dStb 1004c2bab48dStb if ((ctx = ctx_in) == NULL) 1005c2bab48dStb ctx = BN_CTX_new(); 1006c2bab48dStb if (ctx == NULL) 1007c2bab48dStb goto err; 1008c2bab48dStb 100969100aa7Stb y_bit = (y_bit != 0); 101069100aa7Stb 101169100aa7Stb BN_CTX_start(ctx); 101269100aa7Stb 101369100aa7Stb if ((p = BN_CTX_get(ctx)) == NULL) 101469100aa7Stb goto err; 101569100aa7Stb if ((a = BN_CTX_get(ctx)) == NULL) 101669100aa7Stb goto err; 101769100aa7Stb if ((b = BN_CTX_get(ctx)) == NULL) 101869100aa7Stb goto err; 101969100aa7Stb if ((w = BN_CTX_get(ctx)) == NULL) 102069100aa7Stb goto err; 102169100aa7Stb if ((x = BN_CTX_get(ctx)) == NULL) 102269100aa7Stb goto err; 102369100aa7Stb if ((y = BN_CTX_get(ctx)) == NULL) 102469100aa7Stb goto err; 102569100aa7Stb 102669100aa7Stb /* 102769100aa7Stb * Weierstrass equation: y^2 = x^3 + ax + b, so y is one of the 102869100aa7Stb * square roots of x^3 + ax + b. The y-bit indicates which one. 102969100aa7Stb */ 103069100aa7Stb 103169100aa7Stb if (!EC_GROUP_get_curve(group, p, a, b, ctx)) 103269100aa7Stb goto err; 103369100aa7Stb 103469100aa7Stb /* XXX - should we not insist on 0 <= x < p instead? */ 103569100aa7Stb if (!BN_nnmod(x, in_x, p, ctx)) 103669100aa7Stb goto err; 103769100aa7Stb 103869100aa7Stb /* y = x^3 */ 103969100aa7Stb if (!BN_mod_sqr(y, x, p, ctx)) 104069100aa7Stb goto err; 104169100aa7Stb if (!BN_mod_mul(y, y, x, p, ctx)) 104269100aa7Stb goto err; 104369100aa7Stb 104469100aa7Stb /* y += ax */ 104569100aa7Stb if (group->a_is_minus3) { 104669100aa7Stb if (!BN_mod_lshift1_quick(w, x, p)) 104769100aa7Stb goto err; 104869100aa7Stb if (!BN_mod_add_quick(w, w, x, p)) 104969100aa7Stb goto err; 105069100aa7Stb if (!BN_mod_sub_quick(y, y, w, p)) 105169100aa7Stb goto err; 105269100aa7Stb } else { 105369100aa7Stb if (!BN_mod_mul(w, a, x, p, ctx)) 105469100aa7Stb goto err; 105569100aa7Stb if (!BN_mod_add_quick(y, y, w, p)) 1056c2bab48dStb goto err; 1057c2bab48dStb } 105869100aa7Stb 105969100aa7Stb /* y += b */ 106069100aa7Stb if (!BN_mod_add_quick(y, y, b, p)) 106169100aa7Stb goto err; 106269100aa7Stb 106369100aa7Stb if (!BN_mod_sqrt(y, y, p, ctx)) { 106469100aa7Stb ECerror(EC_R_INVALID_COMPRESSED_POINT); 1065c2bab48dStb goto err; 1066c2bab48dStb } 106769100aa7Stb 106869100aa7Stb if (y_bit == BN_is_odd(y)) 106969100aa7Stb goto done; 107069100aa7Stb 107169100aa7Stb if (BN_is_zero(y)) { 107269100aa7Stb ECerror(EC_R_INVALID_COMPRESSION_BIT); 107369100aa7Stb goto err; 107469100aa7Stb } 107569100aa7Stb if (!BN_usub(y, p, y)) 107669100aa7Stb goto err; 107769100aa7Stb 107869100aa7Stb if (y_bit != BN_is_odd(y)) { 107969100aa7Stb /* Can only happen if p is even and should not be reachable. */ 108069100aa7Stb ECerror(ERR_R_INTERNAL_ERROR); 108169100aa7Stb goto err; 108269100aa7Stb } 108369100aa7Stb 108469100aa7Stb done: 108569100aa7Stb if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) 108669100aa7Stb goto err; 108769100aa7Stb 108869100aa7Stb ret = 1; 1089c2bab48dStb 1090c2bab48dStb err: 109169100aa7Stb BN_CTX_end(ctx); 109269100aa7Stb 1093c2bab48dStb if (ctx != ctx_in) 1094c2bab48dStb BN_CTX_free(ctx); 1095c2bab48dStb 1096c2bab48dStb return ret; 1097c2bab48dStb } 1098c2bab48dStb LCRYPTO_ALIAS(EC_POINT_set_compressed_coordinates); 1099c2bab48dStb 1100c2bab48dStb int 1101c2bab48dStb EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 1102c2bab48dStb const BIGNUM *x, int y_bit, BN_CTX *ctx) 1103c2bab48dStb { 1104c2bab48dStb return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx); 1105c2bab48dStb } 1106c2bab48dStb LCRYPTO_ALIAS(EC_POINT_set_compressed_coordinates_GFp); 1107c2bab48dStb 1108c2bab48dStb int 1109f67ac449Stedu EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 11101f65bd71Sjsing const EC_POINT *b, BN_CTX *ctx_in) 1111da347917Sbeck { 11121f65bd71Sjsing BN_CTX *ctx; 11131f65bd71Sjsing int ret = 0; 11141f65bd71Sjsing 11151f65bd71Sjsing if ((ctx = ctx_in) == NULL) 11161f65bd71Sjsing ctx = BN_CTX_new(); 11171f65bd71Sjsing if (ctx == NULL) 11181f65bd71Sjsing goto err; 11191f65bd71Sjsing 11201f65bd71Sjsing if (group->meth->add == NULL) { 11211f65bd71Sjsing ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 11221f65bd71Sjsing goto err; 11231f65bd71Sjsing } 11241f65bd71Sjsing if (group->meth != r->meth || group->meth != a->meth || 11251f65bd71Sjsing group->meth != b->meth) { 11261f65bd71Sjsing ECerror(EC_R_INCOMPATIBLE_OBJECTS); 11271f65bd71Sjsing goto err; 11281f65bd71Sjsing } 11291f65bd71Sjsing ret = group->meth->add(group, r, a, b, ctx); 11301f65bd71Sjsing 11311f65bd71Sjsing err: 11321f65bd71Sjsing if (ctx != ctx_in) 11331f65bd71Sjsing BN_CTX_free(ctx); 11341f65bd71Sjsing 11351f65bd71Sjsing return ret; 11361f65bd71Sjsing } 1137ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_add); 11381f65bd71Sjsing 11391f65bd71Sjsing int 11401f65bd71Sjsing EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 11411f65bd71Sjsing BN_CTX *ctx_in) 11421f65bd71Sjsing { 11431f65bd71Sjsing BN_CTX *ctx; 11441f65bd71Sjsing int ret = 0; 11451f65bd71Sjsing 11461f65bd71Sjsing if ((ctx = ctx_in) == NULL) 11471f65bd71Sjsing ctx = BN_CTX_new(); 11481f65bd71Sjsing if (ctx == NULL) 11491f65bd71Sjsing goto err; 11501f65bd71Sjsing 11511f65bd71Sjsing if (group->meth->dbl == NULL) { 11525067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 11537b871452Stb goto err; 1154da347917Sbeck } 11551f65bd71Sjsing if (group->meth != r->meth || r->meth != a->meth) { 11565067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 11577b871452Stb goto err; 1158da347917Sbeck } 11591f65bd71Sjsing ret = group->meth->dbl(group, r, a, ctx); 1160da347917Sbeck 11611f65bd71Sjsing err: 11621f65bd71Sjsing if (ctx != ctx_in) 11631f65bd71Sjsing BN_CTX_free(ctx); 11641f65bd71Sjsing 11651f65bd71Sjsing return ret; 11661f65bd71Sjsing } 1167ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_dbl); 1168da347917Sbeck 1169f67ac449Stedu int 11701f65bd71Sjsing EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx_in) 1171da347917Sbeck { 11721f65bd71Sjsing BN_CTX *ctx; 11731f65bd71Sjsing int ret = 0; 1174da347917Sbeck 11751f65bd71Sjsing if ((ctx = ctx_in) == NULL) 11761f65bd71Sjsing ctx = BN_CTX_new(); 11771f65bd71Sjsing if (ctx == NULL) 11781f65bd71Sjsing goto err; 1179da347917Sbeck 11807b871452Stb if (group->meth->invert == NULL) { 11815067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 11827b871452Stb goto err; 1183da347917Sbeck } 1184f67ac449Stedu if (group->meth != a->meth) { 11855067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 11867b871452Stb goto err; 1187da347917Sbeck } 11887b871452Stb ret = group->meth->invert(group, a, ctx); 1189da347917Sbeck 11901f65bd71Sjsing err: 11911f65bd71Sjsing if (ctx != ctx_in) 11921f65bd71Sjsing BN_CTX_free(ctx); 11931f65bd71Sjsing 11941f65bd71Sjsing return ret; 11951f65bd71Sjsing } 1196ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_invert); 1197da347917Sbeck 1198f67ac449Stedu int 1199f67ac449Stedu EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 1200da347917Sbeck { 1201f67ac449Stedu if (group->meth != point->meth) { 12025067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1203da347917Sbeck return 0; 1204da347917Sbeck } 12059da94e6dStb 12063c2cb882Stb return BN_is_zero(point->Z); 1207da347917Sbeck } 1208ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_is_at_infinity); 1209da347917Sbeck 1210f67ac449Stedu int 12111f65bd71Sjsing EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 12121f65bd71Sjsing BN_CTX *ctx_in) 1213da347917Sbeck { 12141f65bd71Sjsing BN_CTX *ctx; 12151540d532Stb int ret = -1; 12161f65bd71Sjsing 12171f65bd71Sjsing if ((ctx = ctx_in) == NULL) 12181f65bd71Sjsing ctx = BN_CTX_new(); 12191f65bd71Sjsing if (ctx == NULL) 12201f65bd71Sjsing goto err; 12211f65bd71Sjsing 12224fb59ff9Stb if (group->meth->point_is_on_curve == NULL) { 12235067ae9fSbeck ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 12241f65bd71Sjsing goto err; 1225da347917Sbeck } 1226f67ac449Stedu if (group->meth != point->meth) { 12275067ae9fSbeck ECerror(EC_R_INCOMPATIBLE_OBJECTS); 12281f65bd71Sjsing goto err; 1229da347917Sbeck } 12304fb59ff9Stb ret = group->meth->point_is_on_curve(group, point, ctx); 1231da347917Sbeck 12321f65bd71Sjsing err: 12331f65bd71Sjsing if (ctx != ctx_in) 12341f65bd71Sjsing BN_CTX_free(ctx); 12351f65bd71Sjsing 12361f65bd71Sjsing return ret; 12371f65bd71Sjsing } 1238ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_is_on_curve); 1239da347917Sbeck 1240f67ac449Stedu int 1241f67ac449Stedu EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 12421f65bd71Sjsing BN_CTX *ctx_in) 1243da347917Sbeck { 12441f65bd71Sjsing BN_CTX *ctx; 12451f65bd71Sjsing int ret = -1; 1246da347917Sbeck 12471f65bd71Sjsing if ((ctx = ctx_in) == NULL) 12481f65bd71Sjsing ctx = BN_CTX_new(); 12491f65bd71Sjsing if (ctx == NULL) 12501f65bd71Sjsing goto err; 12511f65bd71Sjsing 12521f65bd71Sjsing if (group->meth->point_cmp == NULL) { 12531f65bd71Sjsing ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 12541f65bd71Sjsing goto err; 12551f65bd71Sjsing } 12561f65bd71Sjsing if (group->meth != a->meth || a->meth != b->meth) { 12571f65bd71Sjsing ECerror(EC_R_INCOMPATIBLE_OBJECTS); 12581f65bd71Sjsing goto err; 12591f65bd71Sjsing } 12601f65bd71Sjsing ret = group->meth->point_cmp(group, a, b, ctx); 12611f65bd71Sjsing 12621f65bd71Sjsing err: 12631f65bd71Sjsing if (ctx != ctx_in) 12641f65bd71Sjsing BN_CTX_free(ctx); 12651f65bd71Sjsing 12661f65bd71Sjsing return ret; 12671f65bd71Sjsing } 1268ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_cmp); 1269da347917Sbeck 1270f67ac449Stedu int 12711f65bd71Sjsing EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx_in) 1272da347917Sbeck { 12731f65bd71Sjsing BN_CTX *ctx; 127407ff836aStb BIGNUM *x, *y; 12751f65bd71Sjsing int ret = 0; 12761f65bd71Sjsing 12771f65bd71Sjsing if ((ctx = ctx_in) == NULL) 12781f65bd71Sjsing ctx = BN_CTX_new(); 12791f65bd71Sjsing if (ctx == NULL) 12801f65bd71Sjsing goto err; 12811f65bd71Sjsing 128207ff836aStb BN_CTX_start(ctx); 128307ff836aStb 128407ff836aStb if ((x = BN_CTX_get(ctx)) == NULL) 128507ff836aStb goto err; 128607ff836aStb if ((y = BN_CTX_get(ctx)) == NULL) 128707ff836aStb goto err; 128807ff836aStb 128907ff836aStb if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) 129007ff836aStb goto err; 129107ff836aStb if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) 129207ff836aStb goto err; 129307ff836aStb 129407ff836aStb ret = 1; 1295da347917Sbeck 12961f65bd71Sjsing err: 129707ff836aStb BN_CTX_end(ctx); 129807ff836aStb 12991f65bd71Sjsing if (ctx != ctx_in) 13001f65bd71Sjsing BN_CTX_free(ctx); 13011f65bd71Sjsing 13021f65bd71Sjsing return ret; 13031f65bd71Sjsing } 1304ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_make_affine); 1305da347917Sbeck 1306f67ac449Stedu int 1307f67ac449Stedu EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 13081f65bd71Sjsing const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx_in) 13094fcf65c5Sdjm { 13101f65bd71Sjsing BN_CTX *ctx; 13111f65bd71Sjsing int ret = 0; 13121f65bd71Sjsing 13131f65bd71Sjsing if ((ctx = ctx_in) == NULL) 13141f65bd71Sjsing ctx = BN_CTX_new(); 13151f65bd71Sjsing if (ctx == NULL) 13161f65bd71Sjsing goto err; 13171f65bd71Sjsing 13181447fb01Sjsing if (group->meth->mul_single_ct == NULL || 1319149fe518Stb group->meth->mul_double_nonct == NULL) { 1320149fe518Stb ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 13211f65bd71Sjsing goto err; 1322149fe518Stb } 13231f65bd71Sjsing 1324149fe518Stb if (g_scalar != NULL && point == NULL && p_scalar == NULL) { 1325149fe518Stb /* 1326149fe518Stb * In this case we want to compute g_scalar * GeneratorPoint: 1327149fe518Stb * this codepath is reached most prominently by (ephemeral) key 1328149fe518Stb * generation of EC cryptosystems (i.e. ECDSA keygen and sign 1329149fe518Stb * setup, ECDH keygen/first half), where the scalar is always 1330149fe518Stb * secret. This is why we ignore if BN_FLG_CONSTTIME is actually 1331149fe518Stb * set and we always call the constant time version. 1332149fe518Stb */ 13331447fb01Sjsing ret = group->meth->mul_single_ct(group, r, g_scalar, 13341447fb01Sjsing group->generator, ctx); 13351f65bd71Sjsing } else if (g_scalar == NULL && point != NULL && p_scalar != NULL) { 13361f65bd71Sjsing /* 13371f65bd71Sjsing * In this case we want to compute p_scalar * GenericPoint: 1338149fe518Stb * this codepath is reached most prominently by the second half 1339149fe518Stb * of ECDH, where the secret scalar is multiplied by the peer's 1340149fe518Stb * public point. To protect the secret scalar, we ignore if 1341149fe518Stb * BN_FLG_CONSTTIME is actually set and we always call the 1342149fe518Stb * constant time version. 1343149fe518Stb */ 13441f65bd71Sjsing ret = group->meth->mul_single_ct(group, r, p_scalar, point, ctx); 13451f65bd71Sjsing } else if (g_scalar != NULL && point != NULL && p_scalar != NULL) { 1346149fe518Stb /* 1347149fe518Stb * In this case we want to compute 1348149fe518Stb * g_scalar * GeneratorPoint + p_scalar * GenericPoint: 1349149fe518Stb * this codepath is reached most prominently by ECDSA signature 1350149fe518Stb * verification. So we call the non-ct version. 1351149fe518Stb */ 13521f65bd71Sjsing ret = group->meth->mul_double_nonct(group, r, g_scalar, 1353149fe518Stb p_scalar, point, ctx); 13541f65bd71Sjsing } else { 1355149fe518Stb /* Anything else is an error. */ 1356149fe518Stb ECerror(ERR_R_EC_LIB); 13571f65bd71Sjsing goto err; 13581f65bd71Sjsing } 13591f65bd71Sjsing 13601f65bd71Sjsing err: 13611f65bd71Sjsing if (ctx != ctx_in) 13621f65bd71Sjsing BN_CTX_free(ctx); 13631f65bd71Sjsing 13641f65bd71Sjsing return ret; 13654fcf65c5Sdjm } 1366ea2baf45Sbeck LCRYPTO_ALIAS(EC_POINT_mul); 13674fcf65c5Sdjm 1368c9edc1b9Stb /* 1369c9edc1b9Stb * XXX - remove everything below in the next bump 1370c9edc1b9Stb */ 1371c9edc1b9Stb 1372c9edc1b9Stb int 1373c9edc1b9Stb EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 1374c9edc1b9Stb const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) 1375c9edc1b9Stb { 1376c9edc1b9Stb ECerror(ERR_R_DISABLED); 1377c9edc1b9Stb return 0; 1378c9edc1b9Stb } 1379c9edc1b9Stb LCRYPTO_ALIAS(EC_POINT_set_Jprojective_coordinates_GFp); 1380c9edc1b9Stb 1381c9edc1b9Stb int 1382c9edc1b9Stb EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 1383c9edc1b9Stb const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) 1384c9edc1b9Stb { 1385c9edc1b9Stb ECerror(ERR_R_DISABLED); 1386c9edc1b9Stb return 0; 1387c9edc1b9Stb } 1388c9edc1b9Stb LCRYPTO_ALIAS(EC_POINT_get_Jprojective_coordinates_GFp); 1389c21af703Stb 1390c21af703Stb int 1391c21af703Stb EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], 1392c21af703Stb BN_CTX *ctx_in) 1393c21af703Stb { 1394c21af703Stb ECerror(ERR_R_DISABLED); 1395c21af703Stb return 0; 1396c21af703Stb } 1397c21af703Stb LCRYPTO_ALIAS(EC_POINTs_make_affine); 1398c21af703Stb 1399c21af703Stb int 1400c21af703Stb EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1401c21af703Stb size_t num, const EC_POINT *points[], const BIGNUM *scalars[], 1402c21af703Stb BN_CTX *ctx_in) 1403c21af703Stb { 1404c21af703Stb ECerror(ERR_R_DISABLED); 1405c21af703Stb return 0; 1406c21af703Stb } 1407c21af703Stb LCRYPTO_ALIAS(EC_POINTs_mul); 1408*a9bbc4f7Stb 1409*a9bbc4f7Stb const EC_METHOD * 1410*a9bbc4f7Stb EC_GROUP_method_of(const EC_GROUP *group) 1411*a9bbc4f7Stb { 1412*a9bbc4f7Stb ECerror(ERR_R_DISABLED); 1413*a9bbc4f7Stb return NULL; 1414*a9bbc4f7Stb } 1415*a9bbc4f7Stb LCRYPTO_ALIAS(EC_GROUP_method_of); 1416*a9bbc4f7Stb 1417*a9bbc4f7Stb int 1418*a9bbc4f7Stb EC_METHOD_get_field_type(const EC_METHOD *meth) 1419*a9bbc4f7Stb { 1420*a9bbc4f7Stb ECerror(ERR_R_DISABLED); 1421*a9bbc4f7Stb return NID_undef; 1422*a9bbc4f7Stb } 1423*a9bbc4f7Stb LCRYPTO_ALIAS(EC_METHOD_get_field_type); 1424*a9bbc4f7Stb 1425*a9bbc4f7Stb const EC_METHOD * 1426*a9bbc4f7Stb EC_POINT_method_of(const EC_POINT *point) 1427*a9bbc4f7Stb { 1428*a9bbc4f7Stb ECerror(ERR_R_DISABLED); 1429*a9bbc4f7Stb return NULL; 1430*a9bbc4f7Stb } 1431*a9bbc4f7Stb LCRYPTO_ALIAS(EC_POINT_method_of); 1432*a9bbc4f7Stb 1433*a9bbc4f7Stb int 1434*a9bbc4f7Stb EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx_in) 1435*a9bbc4f7Stb { 1436*a9bbc4f7Stb ECerror(ERR_R_DISABLED); 1437*a9bbc4f7Stb return 0; 1438*a9bbc4f7Stb } 1439*a9bbc4f7Stb LCRYPTO_ALIAS(EC_GROUP_precompute_mult); 1440*a9bbc4f7Stb 1441*a9bbc4f7Stb int 1442*a9bbc4f7Stb EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1443*a9bbc4f7Stb { 1444*a9bbc4f7Stb ECerror(ERR_R_DISABLED); 1445*a9bbc4f7Stb return 0; 1446*a9bbc4f7Stb } 1447*a9bbc4f7Stb LCRYPTO_ALIAS(EC_GROUP_have_precompute_mult); 1448