1109998Smarkm/* crypto/ec/ec_lib.c */ 2160814Ssimon/* 3160814Ssimon * Originally written by Bodo Moeller for the OpenSSL project. 4160814Ssimon */ 5109998Smarkm/* ==================================================================== 6348343Sjkim * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. 7109998Smarkm * 8109998Smarkm * Redistribution and use in source and binary forms, with or without 9109998Smarkm * modification, are permitted provided that the following conditions 10109998Smarkm * are met: 11109998Smarkm * 12109998Smarkm * 1. Redistributions of source code must retain the above copyright 13280297Sjkim * notice, this list of conditions and the following disclaimer. 14109998Smarkm * 15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 16109998Smarkm * notice, this list of conditions and the following disclaimer in 17109998Smarkm * the documentation and/or other materials provided with the 18109998Smarkm * distribution. 19109998Smarkm * 20109998Smarkm * 3. All advertising materials mentioning features or use of this 21109998Smarkm * software must display the following acknowledgment: 22109998Smarkm * "This product includes software developed by the OpenSSL Project 23109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24109998Smarkm * 25109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26109998Smarkm * endorse or promote products derived from this software without 27109998Smarkm * prior written permission. For written permission, please contact 28109998Smarkm * openssl-core@openssl.org. 29109998Smarkm * 30109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 31109998Smarkm * nor may "OpenSSL" appear in their names without prior written 32109998Smarkm * permission of the OpenSSL Project. 33109998Smarkm * 34109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 35109998Smarkm * acknowledgment: 36109998Smarkm * "This product includes software developed by the OpenSSL Project 37109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38109998Smarkm * 39109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 51109998Smarkm * ==================================================================== 52109998Smarkm * 53109998Smarkm * This product includes cryptographic software written by Eric Young 54109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 55109998Smarkm * Hudson (tjh@cryptsoft.com). 56109998Smarkm * 57109998Smarkm */ 58160814Ssimon/* ==================================================================== 59160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60280297Sjkim * Binary polynomial ECC support in OpenSSL originally developed by 61160814Ssimon * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 62160814Ssimon */ 63109998Smarkm 64109998Smarkm#include <string.h> 65109998Smarkm 66109998Smarkm#include <openssl/err.h> 67109998Smarkm#include <openssl/opensslv.h> 68109998Smarkm 69109998Smarkm#include "ec_lcl.h" 70109998Smarkm 71276861Sjkimconst char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; 72109998Smarkm 73340704Sjkim/* local function prototypes */ 74340704Sjkim 75340704Sjkimstatic int ec_precompute_mont_data(EC_GROUP *group); 76340704Sjkim 77109998Smarkm/* functions for EC_GROUP objects */ 78109998Smarkm 79109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 80280297Sjkim{ 81280297Sjkim EC_GROUP *ret; 82109998Smarkm 83280297Sjkim if (meth == NULL) { 84280297Sjkim ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); 85280297Sjkim return NULL; 86280297Sjkim } 87280297Sjkim if (meth->group_init == 0) { 88280297Sjkim ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 89280297Sjkim return NULL; 90280297Sjkim } 91109998Smarkm 92331638Sjkim ret = OPENSSL_malloc(sizeof(*ret)); 93280297Sjkim if (ret == NULL) { 94280297Sjkim ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); 95280297Sjkim return NULL; 96280297Sjkim } 97109998Smarkm 98280297Sjkim ret->meth = meth; 99109998Smarkm 100280297Sjkim ret->extra_data = NULL; 101290207Sjkim ret->mont_data = NULL; 102160814Ssimon 103280297Sjkim ret->generator = NULL; 104280297Sjkim BN_init(&ret->order); 105280297Sjkim BN_init(&ret->cofactor); 106160814Ssimon 107280297Sjkim ret->curve_name = 0; 108290207Sjkim ret->asn1_flag = ~EC_GROUP_ASN1_FLAG_MASK; 109280297Sjkim ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 110160814Ssimon 111280297Sjkim ret->seed = NULL; 112280297Sjkim ret->seed_len = 0; 113160814Ssimon 114280297Sjkim if (!meth->group_init(ret)) { 115280297Sjkim OPENSSL_free(ret); 116280297Sjkim return NULL; 117280297Sjkim } 118109998Smarkm 119280297Sjkim return ret; 120280297Sjkim} 121109998Smarkm 122109998Smarkmvoid EC_GROUP_free(EC_GROUP *group) 123280297Sjkim{ 124280297Sjkim if (!group) 125280297Sjkim return; 126109998Smarkm 127280297Sjkim if (group->meth->group_finish != 0) 128280297Sjkim group->meth->group_finish(group); 129109998Smarkm 130280297Sjkim EC_EX_DATA_free_all_data(&group->extra_data); 131109998Smarkm 132290207Sjkim if (EC_GROUP_VERSION(group) && group->mont_data) 133290207Sjkim BN_MONT_CTX_free(group->mont_data); 134290207Sjkim 135280297Sjkim if (group->generator != NULL) 136280297Sjkim EC_POINT_free(group->generator); 137280297Sjkim BN_free(&group->order); 138280297Sjkim BN_free(&group->cofactor); 139160814Ssimon 140280297Sjkim if (group->seed) 141280297Sjkim OPENSSL_free(group->seed); 142160814Ssimon 143280297Sjkim OPENSSL_free(group); 144280297Sjkim} 145109998Smarkm 146109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group) 147280297Sjkim{ 148280297Sjkim if (!group) 149280297Sjkim return; 150109998Smarkm 151280297Sjkim if (group->meth->group_clear_finish != 0) 152280297Sjkim group->meth->group_clear_finish(group); 153280297Sjkim else if (group->meth->group_finish != 0) 154280297Sjkim group->meth->group_finish(group); 155109998Smarkm 156280297Sjkim EC_EX_DATA_clear_free_all_data(&group->extra_data); 157109998Smarkm 158290207Sjkim if (EC_GROUP_VERSION(group) && group->mont_data) 159290207Sjkim BN_MONT_CTX_free(group->mont_data); 160290207Sjkim 161280297Sjkim if (group->generator != NULL) 162280297Sjkim EC_POINT_clear_free(group->generator); 163280297Sjkim BN_clear_free(&group->order); 164280297Sjkim BN_clear_free(&group->cofactor); 165160814Ssimon 166280297Sjkim if (group->seed) { 167280297Sjkim OPENSSL_cleanse(group->seed, group->seed_len); 168280297Sjkim OPENSSL_free(group->seed); 169280297Sjkim } 170160814Ssimon 171331638Sjkim OPENSSL_cleanse(group, sizeof(*group)); 172280297Sjkim OPENSSL_free(group); 173280297Sjkim} 174109998Smarkm 175109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 176280297Sjkim{ 177280297Sjkim EC_EXTRA_DATA *d; 178160814Ssimon 179280297Sjkim if (dest->meth->group_copy == 0) { 180280297Sjkim ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 181280297Sjkim return 0; 182280297Sjkim } 183280297Sjkim if (dest->meth != src->meth) { 184280297Sjkim ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); 185280297Sjkim return 0; 186280297Sjkim } 187280297Sjkim if (dest == src) 188280297Sjkim return 1; 189160814Ssimon 190280297Sjkim EC_EX_DATA_free_all_data(&dest->extra_data); 191160814Ssimon 192280297Sjkim for (d = src->extra_data; d != NULL; d = d->next) { 193280297Sjkim void *t = d->dup_func(d->data); 194109998Smarkm 195280297Sjkim if (t == NULL) 196280297Sjkim return 0; 197280297Sjkim if (!EC_EX_DATA_set_data 198280297Sjkim (&dest->extra_data, t, d->dup_func, d->free_func, 199280297Sjkim d->clear_free_func)) 200280297Sjkim return 0; 201280297Sjkim } 202160814Ssimon 203290207Sjkim if (EC_GROUP_VERSION(src) && src->mont_data != NULL) { 204290207Sjkim if (dest->mont_data == NULL) { 205290207Sjkim dest->mont_data = BN_MONT_CTX_new(); 206290207Sjkim if (dest->mont_data == NULL) 207290207Sjkim return 0; 208290207Sjkim } 209290207Sjkim if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) 210290207Sjkim return 0; 211290207Sjkim } else { 212290207Sjkim /* src->generator == NULL */ 213290207Sjkim if (EC_GROUP_VERSION(dest) && dest->mont_data != NULL) { 214290207Sjkim BN_MONT_CTX_free(dest->mont_data); 215290207Sjkim dest->mont_data = NULL; 216290207Sjkim } 217290207Sjkim } 218290207Sjkim 219280297Sjkim if (src->generator != NULL) { 220280297Sjkim if (dest->generator == NULL) { 221280297Sjkim dest->generator = EC_POINT_new(dest); 222280297Sjkim if (dest->generator == NULL) 223280297Sjkim return 0; 224280297Sjkim } 225280297Sjkim if (!EC_POINT_copy(dest->generator, src->generator)) 226280297Sjkim return 0; 227280297Sjkim } else { 228280297Sjkim /* src->generator == NULL */ 229280297Sjkim if (dest->generator != NULL) { 230280297Sjkim EC_POINT_clear_free(dest->generator); 231280297Sjkim dest->generator = NULL; 232280297Sjkim } 233280297Sjkim } 234160814Ssimon 235280297Sjkim if (!BN_copy(&dest->order, &src->order)) 236280297Sjkim return 0; 237280297Sjkim if (!BN_copy(&dest->cofactor, &src->cofactor)) 238280297Sjkim return 0; 239109998Smarkm 240280297Sjkim dest->curve_name = src->curve_name; 241280297Sjkim dest->asn1_flag = src->asn1_flag; 242280297Sjkim dest->asn1_form = src->asn1_form; 243109998Smarkm 244280297Sjkim if (src->seed) { 245280297Sjkim if (dest->seed) 246280297Sjkim OPENSSL_free(dest->seed); 247280297Sjkim dest->seed = OPENSSL_malloc(src->seed_len); 248280297Sjkim if (dest->seed == NULL) 249280297Sjkim return 0; 250280297Sjkim if (!memcpy(dest->seed, src->seed, src->seed_len)) 251280297Sjkim return 0; 252280297Sjkim dest->seed_len = src->seed_len; 253280297Sjkim } else { 254280297Sjkim if (dest->seed) 255280297Sjkim OPENSSL_free(dest->seed); 256280297Sjkim dest->seed = NULL; 257280297Sjkim dest->seed_len = 0; 258280297Sjkim } 259109998Smarkm 260280297Sjkim return dest->meth->group_copy(dest, src); 261280297Sjkim} 262280297Sjkim 263160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 264280297Sjkim{ 265280297Sjkim EC_GROUP *t = NULL; 266280297Sjkim int ok = 0; 267160814Ssimon 268280297Sjkim if (a == NULL) 269280297Sjkim return NULL; 270160814Ssimon 271280297Sjkim if ((t = EC_GROUP_new(a->meth)) == NULL) 272280297Sjkim return (NULL); 273280297Sjkim if (!EC_GROUP_copy(t, a)) 274280297Sjkim goto err; 275160814Ssimon 276280297Sjkim ok = 1; 277160814Ssimon 278280297Sjkim err: 279280297Sjkim if (!ok) { 280280297Sjkim if (t) 281280297Sjkim EC_GROUP_free(t); 282280297Sjkim return NULL; 283280297Sjkim } else 284280297Sjkim return t; 285280297Sjkim} 286160814Ssimon 287109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 288280297Sjkim{ 289280297Sjkim return group->meth; 290280297Sjkim} 291109998Smarkm 292160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth) 293280297Sjkim{ 294280297Sjkim return meth->field_type; 295280297Sjkim} 296160814Ssimon 297352193Sjkim/*- 298352193Sjkim * Try computing cofactor from the generator order (n) and field cardinality (q). 299352193Sjkim * This works for all curves of cryptographic interest. 300352193Sjkim * 301352193Sjkim * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q) 302352193Sjkim * h_min = (q + 1 - 2*sqrt(q))/n 303352193Sjkim * h_max = (q + 1 + 2*sqrt(q))/n 304352193Sjkim * h_max - h_min = 4*sqrt(q)/n 305352193Sjkim * So if n > 4*sqrt(q) holds, there is only one possible value for h: 306352193Sjkim * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil 307352193Sjkim * 308352193Sjkim * Otherwise, zero cofactor and return success. 309352193Sjkim */ 310352193Sjkimstatic int ec_guess_cofactor(EC_GROUP *group) { 311352193Sjkim int ret = 0; 312352193Sjkim BN_CTX *ctx = NULL; 313352193Sjkim BIGNUM *q = NULL; 314352193Sjkim 315352193Sjkim /*- 316352193Sjkim * If the cofactor is too large, we cannot guess it. 317352193Sjkim * The RHS of below is a strict overestimate of lg(4 * sqrt(q)) 318352193Sjkim */ 319352193Sjkim if (BN_num_bits(&group->order) <= (BN_num_bits(&group->field) + 1) / 2 + 3) { 320352193Sjkim /* default to 0 */ 321352193Sjkim BN_zero(&group->cofactor); 322352193Sjkim /* return success */ 323352193Sjkim return 1; 324352193Sjkim } 325352193Sjkim 326352193Sjkim if ((ctx = BN_CTX_new()) == NULL) 327352193Sjkim return 0; 328352193Sjkim 329352193Sjkim BN_CTX_start(ctx); 330352193Sjkim if ((q = BN_CTX_get(ctx)) == NULL) 331352193Sjkim goto err; 332352193Sjkim 333352193Sjkim /* set q = 2**m for binary fields; q = p otherwise */ 334352193Sjkim if (group->meth->field_type == NID_X9_62_characteristic_two_field) { 335352193Sjkim BN_zero(q); 336352193Sjkim if (!BN_set_bit(q, BN_num_bits(&group->field) - 1)) 337352193Sjkim goto err; 338352193Sjkim } else { 339352193Sjkim if (!BN_copy(q, &group->field)) 340352193Sjkim goto err; 341352193Sjkim } 342352193Sjkim 343352193Sjkim /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */ 344352193Sjkim if (!BN_rshift1(&group->cofactor, &group->order) /* n/2 */ 345352193Sjkim || !BN_add(&group->cofactor, &group->cofactor, q) /* q + n/2 */ 346352193Sjkim /* q + 1 + n/2 */ 347352193Sjkim || !BN_add(&group->cofactor, &group->cofactor, BN_value_one()) 348352193Sjkim /* (q + 1 + n/2)/n */ 349352193Sjkim || !BN_div(&group->cofactor, NULL, &group->cofactor, &group->order, ctx)) 350352193Sjkim goto err; 351352193Sjkim ret = 1; 352352193Sjkim err: 353352193Sjkim BN_CTX_end(ctx); 354352193Sjkim BN_CTX_free(ctx); 355352193Sjkim return ret; 356352193Sjkim} 357352193Sjkim 358280297Sjkimint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 359280297Sjkim const BIGNUM *order, const BIGNUM *cofactor) 360280297Sjkim{ 361280297Sjkim if (generator == NULL) { 362280297Sjkim ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 363280297Sjkim return 0; 364280297Sjkim } 365160814Ssimon 366352193Sjkim /* require group->field >= 1 */ 367352193Sjkim if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) { 368352193Sjkim ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD); 369352193Sjkim return 0; 370352193Sjkim } 371352193Sjkim 372352193Sjkim /*- 373352193Sjkim * - require order >= 1 374352193Sjkim * - enforce upper bound due to Hasse thm: order can be no more than one bit 375352193Sjkim * longer than field cardinality 376352193Sjkim */ 377352193Sjkim if (order == NULL || BN_is_zero(order) || BN_is_negative(order) 378352193Sjkim || BN_num_bits(order) > BN_num_bits(&group->field) + 1) { 379352193Sjkim ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER); 380352193Sjkim return 0; 381352193Sjkim } 382352193Sjkim 383352193Sjkim /*- 384352193Sjkim * Unfortunately the cofactor is an optional field in many standards. 385352193Sjkim * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor". 386352193Sjkim * So accept cofactor == NULL or cofactor >= 0. 387352193Sjkim */ 388352193Sjkim if (cofactor != NULL && BN_is_negative(cofactor)) { 389352193Sjkim ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR); 390352193Sjkim return 0; 391352193Sjkim } 392352193Sjkim 393280297Sjkim if (group->generator == NULL) { 394280297Sjkim group->generator = EC_POINT_new(group); 395280297Sjkim if (group->generator == NULL) 396280297Sjkim return 0; 397280297Sjkim } 398280297Sjkim if (!EC_POINT_copy(group->generator, generator)) 399280297Sjkim return 0; 400160814Ssimon 401352193Sjkim if (!BN_copy(&group->order, order)) 402352193Sjkim return 0; 403160814Ssimon 404352193Sjkim /* Either take the provided positive cofactor, or try to compute it */ 405352193Sjkim if (cofactor != NULL && !BN_is_zero(cofactor)) { 406280297Sjkim if (!BN_copy(&group->cofactor, cofactor)) 407280297Sjkim return 0; 408352193Sjkim } else if (!ec_guess_cofactor(group)) { 409280297Sjkim BN_zero(&group->cofactor); 410352193Sjkim return 0; 411352193Sjkim } 412160814Ssimon 413340704Sjkim /*- 414340704Sjkim * Access to the `mont_data` field of an EC_GROUP struct should always be 415340704Sjkim * guarded by an EC_GROUP_VERSION(group) check to avoid OOB accesses, as the 416340704Sjkim * group might come from the FIPS module, which does not define the 417340704Sjkim * `mont_data` field inside the EC_GROUP structure. 418290207Sjkim */ 419340704Sjkim if (EC_GROUP_VERSION(group)) { 420340704Sjkim /*- 421340704Sjkim * Some groups have an order with 422340704Sjkim * factors of two, which makes the Montgomery setup fail. 423340704Sjkim * |group->mont_data| will be NULL in this case. 424340704Sjkim */ 425340704Sjkim if (BN_is_odd(&group->order)) 426340704Sjkim return ec_precompute_mont_data(group); 427340704Sjkim 428340704Sjkim BN_MONT_CTX_free(group->mont_data); 429340704Sjkim group->mont_data = NULL; 430337982Sjkim } 431290207Sjkim 432280297Sjkim return 1; 433280297Sjkim} 434160814Ssimon 435160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 436280297Sjkim{ 437280297Sjkim return group->generator; 438280297Sjkim} 439160814Ssimon 440290207SjkimBN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) 441290207Sjkim{ 442290207Sjkim return EC_GROUP_VERSION(group) ? group->mont_data : NULL; 443290207Sjkim} 444290207Sjkim 445160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 446280297Sjkim{ 447280297Sjkim if (!BN_copy(order, &group->order)) 448280297Sjkim return 0; 449160814Ssimon 450280297Sjkim return !BN_is_zero(order); 451280297Sjkim} 452160814Ssimon 453280297Sjkimint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 454280297Sjkim BN_CTX *ctx) 455280297Sjkim{ 456280297Sjkim if (!BN_copy(cofactor, &group->cofactor)) 457280297Sjkim return 0; 458160814Ssimon 459280297Sjkim return !BN_is_zero(&group->cofactor); 460280297Sjkim} 461160814Ssimon 462160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 463280297Sjkim{ 464280297Sjkim group->curve_name = nid; 465280297Sjkim} 466160814Ssimon 467160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group) 468280297Sjkim{ 469280297Sjkim return group->curve_name; 470280297Sjkim} 471160814Ssimon 472160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 473280297Sjkim{ 474290207Sjkim group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK; 475290207Sjkim group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK; 476280297Sjkim} 477160814Ssimon 478160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 479280297Sjkim{ 480290207Sjkim return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK; 481280297Sjkim} 482160814Ssimon 483280297Sjkimvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 484160814Ssimon point_conversion_form_t form) 485280297Sjkim{ 486280297Sjkim group->asn1_form = form; 487280297Sjkim} 488160814Ssimon 489280297Sjkimpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 490280297Sjkim *group) 491280297Sjkim{ 492280297Sjkim return group->asn1_form; 493280297Sjkim} 494160814Ssimon 495160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 496280297Sjkim{ 497280297Sjkim if (group->seed) { 498280297Sjkim OPENSSL_free(group->seed); 499280297Sjkim group->seed = NULL; 500280297Sjkim group->seed_len = 0; 501280297Sjkim } 502160814Ssimon 503280297Sjkim if (!len || !p) 504280297Sjkim return 1; 505160814Ssimon 506280297Sjkim if ((group->seed = OPENSSL_malloc(len)) == NULL) 507280297Sjkim return 0; 508280297Sjkim memcpy(group->seed, p, len); 509280297Sjkim group->seed_len = len; 510160814Ssimon 511280297Sjkim return len; 512280297Sjkim} 513160814Ssimon 514160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 515280297Sjkim{ 516280297Sjkim return group->seed; 517280297Sjkim} 518160814Ssimon 519160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 520280297Sjkim{ 521280297Sjkim return group->seed_len; 522280297Sjkim} 523160814Ssimon 524280297Sjkimint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 525280297Sjkim const BIGNUM *b, BN_CTX *ctx) 526280297Sjkim{ 527280297Sjkim if (group->meth->group_set_curve == 0) { 528280297Sjkim ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 529280297Sjkim return 0; 530280297Sjkim } 531280297Sjkim return group->meth->group_set_curve(group, p, a, b, ctx); 532280297Sjkim} 533160814Ssimon 534280297Sjkimint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 535280297Sjkim BIGNUM *b, BN_CTX *ctx) 536280297Sjkim{ 537280297Sjkim if (group->meth->group_get_curve == 0) { 538280297Sjkim ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 539280297Sjkim return 0; 540280297Sjkim } 541280297Sjkim return group->meth->group_get_curve(group, p, a, b, ctx); 542280297Sjkim} 543109998Smarkm 544238405Sjkim#ifndef OPENSSL_NO_EC2M 545280297Sjkimint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 546280297Sjkim const BIGNUM *b, BN_CTX *ctx) 547280297Sjkim{ 548280297Sjkim if (group->meth->group_set_curve == 0) { 549280297Sjkim ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, 550280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 551280297Sjkim return 0; 552280297Sjkim } 553280297Sjkim return group->meth->group_set_curve(group, p, a, b, ctx); 554280297Sjkim} 555109998Smarkm 556280297Sjkimint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 557280297Sjkim BIGNUM *b, BN_CTX *ctx) 558280297Sjkim{ 559280297Sjkim if (group->meth->group_get_curve == 0) { 560280297Sjkim ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, 561280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 562280297Sjkim return 0; 563280297Sjkim } 564280297Sjkim return group->meth->group_get_curve(group, p, a, b, ctx); 565280297Sjkim} 566238405Sjkim#endif 567109998Smarkm 568160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group) 569280297Sjkim{ 570280297Sjkim if (group->meth->group_get_degree == 0) { 571280297Sjkim ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 572280297Sjkim return 0; 573280297Sjkim } 574280297Sjkim return group->meth->group_get_degree(group); 575280297Sjkim} 576109998Smarkm 577160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 578280297Sjkim{ 579280297Sjkim if (group->meth->group_check_discriminant == 0) { 580280297Sjkim ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, 581280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 582280297Sjkim return 0; 583280297Sjkim } 584280297Sjkim return group->meth->group_check_discriminant(group, ctx); 585280297Sjkim} 586109998Smarkm 587160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 588280297Sjkim{ 589280297Sjkim int r = 0; 590280297Sjkim BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 591280297Sjkim BN_CTX *ctx_new = NULL; 592160814Ssimon 593280297Sjkim /* compare the field types */ 594280297Sjkim if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 595280297Sjkim EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 596280297Sjkim return 1; 597280297Sjkim /* compare the curve name (if present in both) */ 598280297Sjkim if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 599280297Sjkim EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 600280297Sjkim return 1; 601160814Ssimon 602280297Sjkim if (!ctx) 603280297Sjkim ctx_new = ctx = BN_CTX_new(); 604280297Sjkim if (!ctx) 605280297Sjkim return -1; 606109998Smarkm 607280297Sjkim BN_CTX_start(ctx); 608280297Sjkim a1 = BN_CTX_get(ctx); 609280297Sjkim a2 = BN_CTX_get(ctx); 610280297Sjkim a3 = BN_CTX_get(ctx); 611280297Sjkim b1 = BN_CTX_get(ctx); 612280297Sjkim b2 = BN_CTX_get(ctx); 613280297Sjkim b3 = BN_CTX_get(ctx); 614280297Sjkim if (!b3) { 615280297Sjkim BN_CTX_end(ctx); 616280297Sjkim if (ctx_new) 617280297Sjkim BN_CTX_free(ctx); 618280297Sjkim return -1; 619280297Sjkim } 620160814Ssimon 621280297Sjkim /* 622280297Sjkim * XXX This approach assumes that the external representation of curves 623280297Sjkim * over the same field type is the same. 624280297Sjkim */ 625280297Sjkim if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 626280297Sjkim !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 627280297Sjkim r = 1; 628160814Ssimon 629280297Sjkim if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 630280297Sjkim r = 1; 631160814Ssimon 632280297Sjkim /* XXX EC_POINT_cmp() assumes that the methods are equal */ 633280297Sjkim if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 634280297Sjkim EC_GROUP_get0_generator(b), ctx)) 635280297Sjkim r = 1; 636160814Ssimon 637280297Sjkim if (!r) { 638280297Sjkim /* compare the order and cofactor */ 639280297Sjkim if (!EC_GROUP_get_order(a, a1, ctx) || 640280297Sjkim !EC_GROUP_get_order(b, b1, ctx) || 641280297Sjkim !EC_GROUP_get_cofactor(a, a2, ctx) || 642280297Sjkim !EC_GROUP_get_cofactor(b, b2, ctx)) { 643280297Sjkim BN_CTX_end(ctx); 644280297Sjkim if (ctx_new) 645280297Sjkim BN_CTX_free(ctx); 646280297Sjkim return -1; 647280297Sjkim } 648280297Sjkim if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 649280297Sjkim r = 1; 650280297Sjkim } 651160814Ssimon 652280297Sjkim BN_CTX_end(ctx); 653280297Sjkim if (ctx_new) 654280297Sjkim BN_CTX_free(ctx); 655109998Smarkm 656280297Sjkim return r; 657280297Sjkim} 658109998Smarkm 659109998Smarkm/* this has 'package' visibility */ 660160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 661280297Sjkim void *(*dup_func) (void *), 662280297Sjkim void (*free_func) (void *), 663280297Sjkim void (*clear_free_func) (void *)) 664280297Sjkim{ 665280297Sjkim EC_EXTRA_DATA *d; 666160814Ssimon 667280297Sjkim if (ex_data == NULL) 668280297Sjkim return 0; 669160814Ssimon 670280297Sjkim for (d = *ex_data; d != NULL; d = d->next) { 671280297Sjkim if (d->dup_func == dup_func && d->free_func == free_func 672280297Sjkim && d->clear_free_func == clear_free_func) { 673280297Sjkim ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 674280297Sjkim return 0; 675280297Sjkim } 676280297Sjkim } 677109998Smarkm 678280297Sjkim if (data == NULL) 679280297Sjkim /* no explicit entry needed */ 680280297Sjkim return 1; 681160814Ssimon 682331638Sjkim d = OPENSSL_malloc(sizeof(*d)); 683280297Sjkim if (d == NULL) 684280297Sjkim return 0; 685160814Ssimon 686280297Sjkim d->data = data; 687280297Sjkim d->dup_func = dup_func; 688280297Sjkim d->free_func = free_func; 689280297Sjkim d->clear_free_func = clear_free_func; 690160814Ssimon 691280297Sjkim d->next = *ex_data; 692280297Sjkim *ex_data = d; 693160814Ssimon 694280297Sjkim return 1; 695280297Sjkim} 696109998Smarkm 697160814Ssimon/* this has 'package' visibility */ 698160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 699280297Sjkim void *(*dup_func) (void *), 700280297Sjkim void (*free_func) (void *), 701280297Sjkim void (*clear_free_func) (void *)) 702280297Sjkim{ 703280297Sjkim const EC_EXTRA_DATA *d; 704109998Smarkm 705280297Sjkim for (d = ex_data; d != NULL; d = d->next) { 706280297Sjkim if (d->dup_func == dup_func && d->free_func == free_func 707280297Sjkim && d->clear_free_func == clear_free_func) 708280297Sjkim return d->data; 709280297Sjkim } 710160814Ssimon 711280297Sjkim return NULL; 712280297Sjkim} 713280297Sjkim 714109998Smarkm/* this has 'package' visibility */ 715160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 716280297Sjkim void *(*dup_func) (void *), 717280297Sjkim void (*free_func) (void *), 718280297Sjkim void (*clear_free_func) (void *)) 719280297Sjkim{ 720280297Sjkim EC_EXTRA_DATA **p; 721160814Ssimon 722280297Sjkim if (ex_data == NULL) 723280297Sjkim return; 724160814Ssimon 725280297Sjkim for (p = ex_data; *p != NULL; p = &((*p)->next)) { 726280297Sjkim if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 727280297Sjkim && (*p)->clear_free_func == clear_free_func) { 728280297Sjkim EC_EXTRA_DATA *next = (*p)->next; 729160814Ssimon 730280297Sjkim (*p)->free_func((*p)->data); 731280297Sjkim OPENSSL_free(*p); 732109998Smarkm 733280297Sjkim *p = next; 734280297Sjkim return; 735280297Sjkim } 736280297Sjkim } 737280297Sjkim} 738280297Sjkim 739160814Ssimon/* this has 'package' visibility */ 740160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 741280297Sjkim void *(*dup_func) (void *), 742280297Sjkim void (*free_func) (void *), 743280297Sjkim void (*clear_free_func) (void *)) 744280297Sjkim{ 745280297Sjkim EC_EXTRA_DATA **p; 746109998Smarkm 747280297Sjkim if (ex_data == NULL) 748280297Sjkim return; 749160814Ssimon 750280297Sjkim for (p = ex_data; *p != NULL; p = &((*p)->next)) { 751280297Sjkim if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 752280297Sjkim && (*p)->clear_free_func == clear_free_func) { 753280297Sjkim EC_EXTRA_DATA *next = (*p)->next; 754160814Ssimon 755280297Sjkim (*p)->clear_free_func((*p)->data); 756280297Sjkim OPENSSL_free(*p); 757160814Ssimon 758280297Sjkim *p = next; 759280297Sjkim return; 760280297Sjkim } 761280297Sjkim } 762280297Sjkim} 763280297Sjkim 764109998Smarkm/* this has 'package' visibility */ 765160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 766280297Sjkim{ 767280297Sjkim EC_EXTRA_DATA *d; 768160814Ssimon 769280297Sjkim if (ex_data == NULL) 770280297Sjkim return; 771160814Ssimon 772280297Sjkim d = *ex_data; 773280297Sjkim while (d) { 774280297Sjkim EC_EXTRA_DATA *next = d->next; 775109998Smarkm 776280297Sjkim d->free_func(d->data); 777280297Sjkim OPENSSL_free(d); 778280297Sjkim 779280297Sjkim d = next; 780280297Sjkim } 781280297Sjkim *ex_data = NULL; 782280297Sjkim} 783280297Sjkim 784160814Ssimon/* this has 'package' visibility */ 785160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 786280297Sjkim{ 787280297Sjkim EC_EXTRA_DATA *d; 788109998Smarkm 789280297Sjkim if (ex_data == NULL) 790280297Sjkim return; 791109998Smarkm 792280297Sjkim d = *ex_data; 793280297Sjkim while (d) { 794280297Sjkim EC_EXTRA_DATA *next = d->next; 795160814Ssimon 796280297Sjkim d->clear_free_func(d->data); 797280297Sjkim OPENSSL_free(d); 798160814Ssimon 799280297Sjkim d = next; 800280297Sjkim } 801280297Sjkim *ex_data = NULL; 802280297Sjkim} 803280297Sjkim 804109998Smarkm/* functions for EC_POINT objects */ 805109998Smarkm 806109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group) 807280297Sjkim{ 808280297Sjkim EC_POINT *ret; 809109998Smarkm 810280297Sjkim if (group == NULL) { 811280297Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 812280297Sjkim return NULL; 813280297Sjkim } 814280297Sjkim if (group->meth->point_init == 0) { 815280297Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 816280297Sjkim return NULL; 817280297Sjkim } 818109998Smarkm 819331638Sjkim ret = OPENSSL_malloc(sizeof(*ret)); 820280297Sjkim if (ret == NULL) { 821280297Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 822280297Sjkim return NULL; 823280297Sjkim } 824109998Smarkm 825280297Sjkim ret->meth = group->meth; 826109998Smarkm 827280297Sjkim if (!ret->meth->point_init(ret)) { 828280297Sjkim OPENSSL_free(ret); 829280297Sjkim return NULL; 830280297Sjkim } 831109998Smarkm 832280297Sjkim return ret; 833280297Sjkim} 834280297Sjkim 835109998Smarkmvoid EC_POINT_free(EC_POINT *point) 836280297Sjkim{ 837280297Sjkim if (!point) 838280297Sjkim return; 839109998Smarkm 840280297Sjkim if (point->meth->point_finish != 0) 841280297Sjkim point->meth->point_finish(point); 842280297Sjkim OPENSSL_free(point); 843280297Sjkim} 844109998Smarkm 845109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point) 846280297Sjkim{ 847280297Sjkim if (!point) 848280297Sjkim return; 849109998Smarkm 850280297Sjkim if (point->meth->point_clear_finish != 0) 851280297Sjkim point->meth->point_clear_finish(point); 852280297Sjkim else if (point->meth->point_finish != 0) 853280297Sjkim point->meth->point_finish(point); 854331638Sjkim OPENSSL_cleanse(point, sizeof(*point)); 855280297Sjkim OPENSSL_free(point); 856280297Sjkim} 857109998Smarkm 858109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 859280297Sjkim{ 860280297Sjkim if (dest->meth->point_copy == 0) { 861280297Sjkim ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 862280297Sjkim return 0; 863280297Sjkim } 864280297Sjkim if (dest->meth != src->meth) { 865280297Sjkim ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 866280297Sjkim return 0; 867280297Sjkim } 868280297Sjkim if (dest == src) 869280297Sjkim return 1; 870280297Sjkim return dest->meth->point_copy(dest, src); 871280297Sjkim} 872109998Smarkm 873160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 874280297Sjkim{ 875280297Sjkim EC_POINT *t; 876280297Sjkim int r; 877160814Ssimon 878280297Sjkim if (a == NULL) 879280297Sjkim return NULL; 880160814Ssimon 881280297Sjkim t = EC_POINT_new(group); 882280297Sjkim if (t == NULL) 883280297Sjkim return (NULL); 884280297Sjkim r = EC_POINT_copy(t, a); 885280297Sjkim if (!r) { 886280297Sjkim EC_POINT_free(t); 887280297Sjkim return NULL; 888280297Sjkim } else 889280297Sjkim return t; 890280297Sjkim} 891160814Ssimon 892109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 893280297Sjkim{ 894280297Sjkim return point->meth; 895280297Sjkim} 896109998Smarkm 897109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 898280297Sjkim{ 899280297Sjkim if (group->meth->point_set_to_infinity == 0) { 900280297Sjkim ECerr(EC_F_EC_POINT_SET_TO_INFINITY, 901280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 902280297Sjkim return 0; 903280297Sjkim } 904280297Sjkim if (group->meth != point->meth) { 905280297Sjkim ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 906280297Sjkim return 0; 907280297Sjkim } 908280297Sjkim return group->meth->point_set_to_infinity(group, point); 909280297Sjkim} 910109998Smarkm 911280297Sjkimint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 912280297Sjkim EC_POINT *point, const BIGNUM *x, 913280297Sjkim const BIGNUM *y, const BIGNUM *z, 914280297Sjkim BN_CTX *ctx) 915280297Sjkim{ 916280297Sjkim if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 917280297Sjkim ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 918280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 919280297Sjkim return 0; 920280297Sjkim } 921280297Sjkim if (group->meth != point->meth) { 922280297Sjkim ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 923280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 924280297Sjkim return 0; 925280297Sjkim } 926280297Sjkim return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, 927280297Sjkim y, z, ctx); 928280297Sjkim} 929109998Smarkm 930280297Sjkimint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 931280297Sjkim const EC_POINT *point, BIGNUM *x, 932280297Sjkim BIGNUM *y, BIGNUM *z, 933280297Sjkim BN_CTX *ctx) 934280297Sjkim{ 935280297Sjkim if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 936280297Sjkim ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 937280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 938280297Sjkim return 0; 939280297Sjkim } 940280297Sjkim if (group->meth != point->meth) { 941280297Sjkim ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 942280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 943280297Sjkim return 0; 944280297Sjkim } 945280297Sjkim return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, 946280297Sjkim y, z, ctx); 947280297Sjkim} 948109998Smarkm 949280297Sjkimint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 950280297Sjkim EC_POINT *point, const BIGNUM *x, 951280297Sjkim const BIGNUM *y, BN_CTX *ctx) 952280297Sjkim{ 953280297Sjkim if (group->meth->point_set_affine_coordinates == 0) { 954280297Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 955280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 956280297Sjkim return 0; 957280297Sjkim } 958280297Sjkim if (group->meth != point->meth) { 959280297Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 960280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 961280297Sjkim return 0; 962280297Sjkim } 963348343Sjkim if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) 964348343Sjkim return 0; 965348343Sjkim 966348343Sjkim if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 967348343Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 968348343Sjkim EC_R_POINT_IS_NOT_ON_CURVE); 969348343Sjkim return 0; 970348343Sjkim } 971348343Sjkim return 1; 972280297Sjkim} 973109998Smarkm 974238405Sjkim#ifndef OPENSSL_NO_EC2M 975280297Sjkimint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 976280297Sjkim EC_POINT *point, const BIGNUM *x, 977280297Sjkim const BIGNUM *y, BN_CTX *ctx) 978280297Sjkim{ 979280297Sjkim if (group->meth->point_set_affine_coordinates == 0) { 980280297Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 981280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 982280297Sjkim return 0; 983280297Sjkim } 984280297Sjkim if (group->meth != point->meth) { 985280297Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 986280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 987280297Sjkim return 0; 988280297Sjkim } 989348343Sjkim if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) 990348343Sjkim return 0; 991348343Sjkim 992348343Sjkim if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 993348343Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 994348343Sjkim EC_R_POINT_IS_NOT_ON_CURVE); 995348343Sjkim return 0; 996348343Sjkim } 997348343Sjkim return 1; 998280297Sjkim} 999238405Sjkim#endif 1000160814Ssimon 1001280297Sjkimint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 1002280297Sjkim const EC_POINT *point, BIGNUM *x, 1003280297Sjkim BIGNUM *y, BN_CTX *ctx) 1004280297Sjkim{ 1005280297Sjkim if (group->meth->point_get_affine_coordinates == 0) { 1006280297Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 1007280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1008280297Sjkim return 0; 1009280297Sjkim } 1010280297Sjkim if (group->meth != point->meth) { 1011280297Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 1012280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 1013280297Sjkim return 0; 1014280297Sjkim } 1015280297Sjkim return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 1016280297Sjkim} 1017109998Smarkm 1018238405Sjkim#ifndef OPENSSL_NO_EC2M 1019280297Sjkimint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 1020280297Sjkim const EC_POINT *point, BIGNUM *x, 1021280297Sjkim BIGNUM *y, BN_CTX *ctx) 1022280297Sjkim{ 1023280297Sjkim if (group->meth->point_get_affine_coordinates == 0) { 1024280297Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 1025280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1026280297Sjkim return 0; 1027280297Sjkim } 1028280297Sjkim if (group->meth != point->meth) { 1029280297Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 1030280297Sjkim EC_R_INCOMPATIBLE_OBJECTS); 1031280297Sjkim return 0; 1032280297Sjkim } 1033280297Sjkim return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 1034280297Sjkim} 1035238405Sjkim#endif 1036160814Ssimon 1037280297Sjkimint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 1038280297Sjkim const EC_POINT *b, BN_CTX *ctx) 1039280297Sjkim{ 1040280297Sjkim if (group->meth->add == 0) { 1041280297Sjkim ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1042280297Sjkim return 0; 1043280297Sjkim } 1044280297Sjkim if ((group->meth != r->meth) || (r->meth != a->meth) 1045280297Sjkim || (a->meth != b->meth)) { 1046280297Sjkim ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 1047280297Sjkim return 0; 1048280297Sjkim } 1049280297Sjkim return group->meth->add(group, r, a, b, ctx); 1050280297Sjkim} 1051109998Smarkm 1052280297Sjkimint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 1053280297Sjkim BN_CTX *ctx) 1054280297Sjkim{ 1055280297Sjkim if (group->meth->dbl == 0) { 1056280297Sjkim ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1057280297Sjkim return 0; 1058280297Sjkim } 1059280297Sjkim if ((group->meth != r->meth) || (r->meth != a->meth)) { 1060280297Sjkim ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 1061280297Sjkim return 0; 1062280297Sjkim } 1063280297Sjkim return group->meth->dbl(group, r, a, ctx); 1064280297Sjkim} 1065109998Smarkm 1066109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 1067280297Sjkim{ 1068280297Sjkim if (group->meth->invert == 0) { 1069280297Sjkim ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1070280297Sjkim return 0; 1071280297Sjkim } 1072280297Sjkim if (group->meth != a->meth) { 1073280297Sjkim ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 1074280297Sjkim return 0; 1075280297Sjkim } 1076280297Sjkim return group->meth->invert(group, a, ctx); 1077280297Sjkim} 1078109998Smarkm 1079109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 1080280297Sjkim{ 1081280297Sjkim if (group->meth->is_at_infinity == 0) { 1082280297Sjkim ECerr(EC_F_EC_POINT_IS_AT_INFINITY, 1083280297Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1084280297Sjkim return 0; 1085280297Sjkim } 1086280297Sjkim if (group->meth != point->meth) { 1087280297Sjkim ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 1088280297Sjkim return 0; 1089280297Sjkim } 1090280297Sjkim return group->meth->is_at_infinity(group, point); 1091280297Sjkim} 1092109998Smarkm 1093284283Sjkim/* 1094284283Sjkim * Check whether an EC_POINT is on the curve or not. Note that the return 1095284283Sjkim * value for this function should NOT be treated as a boolean. Return values: 1096284283Sjkim * 1: The point is on the curve 1097284283Sjkim * 0: The point is not on the curve 1098284283Sjkim * -1: An error occurred 1099284283Sjkim */ 1100280297Sjkimint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 1101280297Sjkim BN_CTX *ctx) 1102280297Sjkim{ 1103280297Sjkim if (group->meth->is_on_curve == 0) { 1104280297Sjkim ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1105280297Sjkim return 0; 1106280297Sjkim } 1107280297Sjkim if (group->meth != point->meth) { 1108280297Sjkim ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 1109280297Sjkim return 0; 1110280297Sjkim } 1111280297Sjkim return group->meth->is_on_curve(group, point, ctx); 1112280297Sjkim} 1113109998Smarkm 1114280297Sjkimint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 1115280297Sjkim BN_CTX *ctx) 1116280297Sjkim{ 1117280297Sjkim if (group->meth->point_cmp == 0) { 1118280297Sjkim ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1119280297Sjkim return -1; 1120280297Sjkim } 1121280297Sjkim if ((group->meth != a->meth) || (a->meth != b->meth)) { 1122280297Sjkim ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 1123280297Sjkim return -1; 1124280297Sjkim } 1125280297Sjkim return group->meth->point_cmp(group, a, b, ctx); 1126280297Sjkim} 1127109998Smarkm 1128109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 1129280297Sjkim{ 1130280297Sjkim if (group->meth->make_affine == 0) { 1131280297Sjkim ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1132280297Sjkim return 0; 1133280297Sjkim } 1134280297Sjkim if (group->meth != point->meth) { 1135280297Sjkim ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1136280297Sjkim return 0; 1137280297Sjkim } 1138280297Sjkim return group->meth->make_affine(group, point, ctx); 1139280297Sjkim} 1140109998Smarkm 1141280297Sjkimint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 1142280297Sjkim EC_POINT *points[], BN_CTX *ctx) 1143280297Sjkim{ 1144280297Sjkim size_t i; 1145109998Smarkm 1146280297Sjkim if (group->meth->points_make_affine == 0) { 1147280297Sjkim ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1148280297Sjkim return 0; 1149280297Sjkim } 1150280297Sjkim for (i = 0; i < num; i++) { 1151280297Sjkim if (group->meth != points[i]->meth) { 1152280297Sjkim ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1153280297Sjkim return 0; 1154280297Sjkim } 1155280297Sjkim } 1156280297Sjkim return group->meth->points_make_affine(group, num, points, ctx); 1157280297Sjkim} 1158109998Smarkm 1159280297Sjkim/* 1160280297Sjkim * Functions for point multiplication. If group->meth->mul is 0, we use the 1161280297Sjkim * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1162280297Sjkim * methods. 1163160814Ssimon */ 1164160814Ssimon 1165160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1166280297Sjkim size_t num, const EC_POINT *points[], 1167280297Sjkim const BIGNUM *scalars[], BN_CTX *ctx) 1168280297Sjkim{ 1169280297Sjkim if (group->meth->mul == 0) 1170280297Sjkim /* use default */ 1171280297Sjkim return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1172160814Ssimon 1173280297Sjkim return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1174280297Sjkim} 1175160814Ssimon 1176160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1177280297Sjkim const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1178280297Sjkim{ 1179280297Sjkim /* just a convenient interface to EC_POINTs_mul() */ 1180160814Ssimon 1181280297Sjkim const EC_POINT *points[1]; 1182280297Sjkim const BIGNUM *scalars[1]; 1183160814Ssimon 1184280297Sjkim points[0] = point; 1185280297Sjkim scalars[0] = p_scalar; 1186160814Ssimon 1187280297Sjkim return EC_POINTs_mul(group, r, g_scalar, 1188280297Sjkim (point != NULL 1189280297Sjkim && p_scalar != NULL), points, scalars, ctx); 1190280297Sjkim} 1191160814Ssimon 1192160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1193280297Sjkim{ 1194280297Sjkim if (group->meth->mul == 0) 1195280297Sjkim /* use default */ 1196280297Sjkim return ec_wNAF_precompute_mult(group, ctx); 1197160814Ssimon 1198280297Sjkim if (group->meth->precompute_mult != 0) 1199280297Sjkim return group->meth->precompute_mult(group, ctx); 1200280297Sjkim else 1201280297Sjkim return 1; /* nothing to do, so report success */ 1202280297Sjkim} 1203160814Ssimon 1204160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1205280297Sjkim{ 1206280297Sjkim if (group->meth->mul == 0) 1207280297Sjkim /* use default */ 1208280297Sjkim return ec_wNAF_have_precompute_mult(group); 1209160814Ssimon 1210280297Sjkim if (group->meth->have_precompute_mult != 0) 1211280297Sjkim return group->meth->have_precompute_mult(group); 1212280297Sjkim else 1213280297Sjkim return 0; /* cannot tell whether precomputation has 1214280297Sjkim * been performed */ 1215280297Sjkim} 1216290207Sjkim 1217340704Sjkim/*- 1218290207Sjkim * ec_precompute_mont_data sets |group->mont_data| from |group->order| and 1219290207Sjkim * returns one on success. On error it returns zero. 1220340704Sjkim * 1221340704Sjkim * Note: this function must be called only after verifying that 1222340704Sjkim * EC_GROUP_VERSION(group) returns true. 1223340704Sjkim * The reason for this is that access to the `mont_data` field of an EC_GROUP 1224340704Sjkim * struct should always be guarded by an EC_GROUP_VERSION(group) check to avoid 1225340704Sjkim * OOB accesses, as the group might come from the FIPS module, which does not 1226340704Sjkim * define the `mont_data` field inside the EC_GROUP structure. 1227290207Sjkim */ 1228340704Sjkimstatic 1229290207Sjkimint ec_precompute_mont_data(EC_GROUP *group) 1230290207Sjkim{ 1231290207Sjkim BN_CTX *ctx = BN_CTX_new(); 1232290207Sjkim int ret = 0; 1233290207Sjkim 1234290207Sjkim if (group->mont_data) { 1235290207Sjkim BN_MONT_CTX_free(group->mont_data); 1236290207Sjkim group->mont_data = NULL; 1237290207Sjkim } 1238290207Sjkim 1239290207Sjkim if (ctx == NULL) 1240290207Sjkim goto err; 1241290207Sjkim 1242290207Sjkim group->mont_data = BN_MONT_CTX_new(); 1243290207Sjkim if (!group->mont_data) 1244290207Sjkim goto err; 1245290207Sjkim 1246290207Sjkim if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) { 1247290207Sjkim BN_MONT_CTX_free(group->mont_data); 1248290207Sjkim group->mont_data = NULL; 1249290207Sjkim goto err; 1250290207Sjkim } 1251290207Sjkim 1252290207Sjkim ret = 1; 1253290207Sjkim 1254290207Sjkim err: 1255290207Sjkim 1256290207Sjkim if (ctx) 1257290207Sjkim BN_CTX_free(ctx); 1258290207Sjkim return ret; 1259290207Sjkim} 1260352193Sjkim 1261352193Sjkim/* 1262352193Sjkim * This is just a wrapper around the public functions 1263352193Sjkim * - EC_GROUP_get_curve_GF2m 1264352193Sjkim * - EC_GROUP_get_curve_GFp 1265352193Sjkim * 1266352193Sjkim * It is meant to facilitate backporting of code from newer branches, where 1267352193Sjkim * the public API includes a "field agnostic" version of it. 1268352193Sjkim */ 1269352193Sjkimint ec_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 1270352193Sjkim BIGNUM *b, BN_CTX *ctx) 1271352193Sjkim{ 1272352193Sjkim int field_nid; 1273352193Sjkim 1274352193Sjkim field_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 1275352193Sjkim 1276352193Sjkim#ifndef OPENSSL_NO_EC2M 1277352193Sjkim if (field_nid == NID_X9_62_characteristic_two_field) { 1278352193Sjkim return EC_GROUP_get_curve_GF2m(group, p, a, b, ctx); 1279352193Sjkim } else 1280352193Sjkim#endif /* !def(OPENSSL_NO_EC2M) */ 1281352193Sjkim if (field_nid == NID_X9_62_prime_field) { 1282352193Sjkim return EC_GROUP_get_curve_GFp(group, p, a, b, ctx); 1283352193Sjkim } else { 1284352193Sjkim /* this should never happen */ 1285352193Sjkim return 0; 1286352193Sjkim } 1287352193Sjkim} 1288352193Sjkim 1289352193Sjkim/* 1290352193Sjkim * This is just a wrapper around the public functions 1291352193Sjkim * - EC_POINT_get_affine_coordinates_GF2m 1292352193Sjkim * - EC_POINT_get_affine_coordinates_GFp 1293352193Sjkim * 1294352193Sjkim * It is meant to facilitate backporting of code from newer branches, where 1295352193Sjkim * the public API includes a "field agnostic" version of it. 1296352193Sjkim */ 1297352193Sjkimint ec_point_get_affine_coordinates(const EC_GROUP *group, 1298352193Sjkim const EC_POINT *point, BIGNUM *x, 1299352193Sjkim BIGNUM *y, BN_CTX *ctx) 1300352193Sjkim{ 1301352193Sjkim int field_nid; 1302352193Sjkim 1303352193Sjkim field_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); 1304352193Sjkim 1305352193Sjkim#ifndef OPENSSL_NO_EC2M 1306352193Sjkim if (field_nid == NID_X9_62_characteristic_two_field) { 1307352193Sjkim return EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx); 1308352193Sjkim } else 1309352193Sjkim#endif /* !def(OPENSSL_NO_EC2M) */ 1310352193Sjkim if (field_nid == NID_X9_62_prime_field) { 1311352193Sjkim return EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx); 1312352193Sjkim } else { 1313352193Sjkim /* this should never happen */ 1314352193Sjkim return 0; 1315352193Sjkim } 1316352193Sjkim} 1317