1109998Smarkm/* crypto/ec/ec_lib.c */ 2160814Ssimon/* 3160814Ssimon * Originally written by Bodo Moeller for the OpenSSL project. 4160814Ssimon */ 5109998Smarkm/* ==================================================================== 6160814Ssimon * Copyright (c) 1998-2003 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 13280304Sjkim * 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. 60280304Sjkim * 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 71276864Sjkimconst char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; 72109998Smarkm 73109998Smarkm/* functions for EC_GROUP objects */ 74109998Smarkm 75109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 76280304Sjkim{ 77280304Sjkim EC_GROUP *ret; 78109998Smarkm 79280304Sjkim if (meth == NULL) { 80280304Sjkim ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); 81280304Sjkim return NULL; 82280304Sjkim } 83280304Sjkim if (meth->group_init == 0) { 84280304Sjkim ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 85280304Sjkim return NULL; 86280304Sjkim } 87109998Smarkm 88280304Sjkim ret = OPENSSL_malloc(sizeof *ret); 89280304Sjkim if (ret == NULL) { 90280304Sjkim ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); 91280304Sjkim return NULL; 92280304Sjkim } 93109998Smarkm 94280304Sjkim ret->meth = meth; 95109998Smarkm 96280304Sjkim ret->extra_data = NULL; 97160814Ssimon 98280304Sjkim ret->generator = NULL; 99280304Sjkim BN_init(&ret->order); 100280304Sjkim BN_init(&ret->cofactor); 101160814Ssimon 102280304Sjkim ret->curve_name = 0; 103280304Sjkim ret->asn1_flag = 0; 104280304Sjkim ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 105160814Ssimon 106280304Sjkim ret->seed = NULL; 107280304Sjkim ret->seed_len = 0; 108160814Ssimon 109280304Sjkim if (!meth->group_init(ret)) { 110280304Sjkim OPENSSL_free(ret); 111280304Sjkim return NULL; 112280304Sjkim } 113109998Smarkm 114280304Sjkim return ret; 115280304Sjkim} 116109998Smarkm 117109998Smarkmvoid EC_GROUP_free(EC_GROUP *group) 118280304Sjkim{ 119280304Sjkim if (!group) 120280304Sjkim return; 121109998Smarkm 122280304Sjkim if (group->meth->group_finish != 0) 123280304Sjkim group->meth->group_finish(group); 124109998Smarkm 125280304Sjkim EC_EX_DATA_free_all_data(&group->extra_data); 126109998Smarkm 127280304Sjkim if (group->generator != NULL) 128280304Sjkim EC_POINT_free(group->generator); 129280304Sjkim BN_free(&group->order); 130280304Sjkim BN_free(&group->cofactor); 131160814Ssimon 132280304Sjkim if (group->seed) 133280304Sjkim OPENSSL_free(group->seed); 134160814Ssimon 135280304Sjkim OPENSSL_free(group); 136280304Sjkim} 137109998Smarkm 138109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group) 139280304Sjkim{ 140280304Sjkim if (!group) 141280304Sjkim return; 142109998Smarkm 143280304Sjkim if (group->meth->group_clear_finish != 0) 144280304Sjkim group->meth->group_clear_finish(group); 145280304Sjkim else if (group->meth->group_finish != 0) 146280304Sjkim group->meth->group_finish(group); 147109998Smarkm 148280304Sjkim EC_EX_DATA_clear_free_all_data(&group->extra_data); 149109998Smarkm 150280304Sjkim if (group->generator != NULL) 151280304Sjkim EC_POINT_clear_free(group->generator); 152280304Sjkim BN_clear_free(&group->order); 153280304Sjkim BN_clear_free(&group->cofactor); 154160814Ssimon 155280304Sjkim if (group->seed) { 156280304Sjkim OPENSSL_cleanse(group->seed, group->seed_len); 157280304Sjkim OPENSSL_free(group->seed); 158280304Sjkim } 159160814Ssimon 160280304Sjkim OPENSSL_cleanse(group, sizeof *group); 161280304Sjkim OPENSSL_free(group); 162280304Sjkim} 163109998Smarkm 164109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 165280304Sjkim{ 166280304Sjkim EC_EXTRA_DATA *d; 167160814Ssimon 168280304Sjkim if (dest->meth->group_copy == 0) { 169280304Sjkim ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 170280304Sjkim return 0; 171280304Sjkim } 172280304Sjkim if (dest->meth != src->meth) { 173280304Sjkim ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); 174280304Sjkim return 0; 175280304Sjkim } 176280304Sjkim if (dest == src) 177280304Sjkim return 1; 178160814Ssimon 179280304Sjkim EC_EX_DATA_free_all_data(&dest->extra_data); 180160814Ssimon 181280304Sjkim for (d = src->extra_data; d != NULL; d = d->next) { 182280304Sjkim void *t = d->dup_func(d->data); 183109998Smarkm 184280304Sjkim if (t == NULL) 185280304Sjkim return 0; 186280304Sjkim if (!EC_EX_DATA_set_data 187280304Sjkim (&dest->extra_data, t, d->dup_func, d->free_func, 188280304Sjkim d->clear_free_func)) 189280304Sjkim return 0; 190280304Sjkim } 191160814Ssimon 192280304Sjkim if (src->generator != NULL) { 193280304Sjkim if (dest->generator == NULL) { 194280304Sjkim dest->generator = EC_POINT_new(dest); 195280304Sjkim if (dest->generator == NULL) 196280304Sjkim return 0; 197280304Sjkim } 198280304Sjkim if (!EC_POINT_copy(dest->generator, src->generator)) 199280304Sjkim return 0; 200280304Sjkim } else { 201280304Sjkim /* src->generator == NULL */ 202280304Sjkim if (dest->generator != NULL) { 203280304Sjkim EC_POINT_clear_free(dest->generator); 204280304Sjkim dest->generator = NULL; 205280304Sjkim } 206280304Sjkim } 207160814Ssimon 208280304Sjkim if (!BN_copy(&dest->order, &src->order)) 209280304Sjkim return 0; 210280304Sjkim if (!BN_copy(&dest->cofactor, &src->cofactor)) 211280304Sjkim return 0; 212109998Smarkm 213280304Sjkim dest->curve_name = src->curve_name; 214280304Sjkim dest->asn1_flag = src->asn1_flag; 215280304Sjkim dest->asn1_form = src->asn1_form; 216109998Smarkm 217280304Sjkim if (src->seed) { 218280304Sjkim if (dest->seed) 219280304Sjkim OPENSSL_free(dest->seed); 220280304Sjkim dest->seed = OPENSSL_malloc(src->seed_len); 221280304Sjkim if (dest->seed == NULL) 222280304Sjkim return 0; 223280304Sjkim if (!memcpy(dest->seed, src->seed, src->seed_len)) 224280304Sjkim return 0; 225280304Sjkim dest->seed_len = src->seed_len; 226280304Sjkim } else { 227280304Sjkim if (dest->seed) 228280304Sjkim OPENSSL_free(dest->seed); 229280304Sjkim dest->seed = NULL; 230280304Sjkim dest->seed_len = 0; 231280304Sjkim } 232109998Smarkm 233280304Sjkim return dest->meth->group_copy(dest, src); 234280304Sjkim} 235280304Sjkim 236160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 237280304Sjkim{ 238280304Sjkim EC_GROUP *t = NULL; 239280304Sjkim int ok = 0; 240160814Ssimon 241280304Sjkim if (a == NULL) 242280304Sjkim return NULL; 243160814Ssimon 244280304Sjkim if ((t = EC_GROUP_new(a->meth)) == NULL) 245280304Sjkim return (NULL); 246280304Sjkim if (!EC_GROUP_copy(t, a)) 247280304Sjkim goto err; 248160814Ssimon 249280304Sjkim ok = 1; 250160814Ssimon 251280304Sjkim err: 252280304Sjkim if (!ok) { 253280304Sjkim if (t) 254280304Sjkim EC_GROUP_free(t); 255280304Sjkim return NULL; 256280304Sjkim } else 257280304Sjkim return t; 258280304Sjkim} 259160814Ssimon 260109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 261280304Sjkim{ 262280304Sjkim return group->meth; 263280304Sjkim} 264109998Smarkm 265160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth) 266280304Sjkim{ 267280304Sjkim return meth->field_type; 268280304Sjkim} 269160814Ssimon 270280304Sjkimint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 271280304Sjkim const BIGNUM *order, const BIGNUM *cofactor) 272280304Sjkim{ 273280304Sjkim if (generator == NULL) { 274280304Sjkim ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 275280304Sjkim return 0; 276280304Sjkim } 277160814Ssimon 278280304Sjkim if (group->generator == NULL) { 279280304Sjkim group->generator = EC_POINT_new(group); 280280304Sjkim if (group->generator == NULL) 281280304Sjkim return 0; 282280304Sjkim } 283280304Sjkim if (!EC_POINT_copy(group->generator, generator)) 284280304Sjkim return 0; 285160814Ssimon 286280304Sjkim if (order != NULL) { 287280304Sjkim if (!BN_copy(&group->order, order)) 288280304Sjkim return 0; 289280304Sjkim } else 290280304Sjkim BN_zero(&group->order); 291160814Ssimon 292280304Sjkim if (cofactor != NULL) { 293280304Sjkim if (!BN_copy(&group->cofactor, cofactor)) 294280304Sjkim return 0; 295280304Sjkim } else 296280304Sjkim BN_zero(&group->cofactor); 297160814Ssimon 298280304Sjkim return 1; 299280304Sjkim} 300160814Ssimon 301160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 302280304Sjkim{ 303280304Sjkim return group->generator; 304280304Sjkim} 305160814Ssimon 306160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 307280304Sjkim{ 308280304Sjkim if (!BN_copy(order, &group->order)) 309280304Sjkim return 0; 310160814Ssimon 311280304Sjkim return !BN_is_zero(order); 312280304Sjkim} 313160814Ssimon 314280304Sjkimint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 315280304Sjkim BN_CTX *ctx) 316280304Sjkim{ 317280304Sjkim if (!BN_copy(cofactor, &group->cofactor)) 318280304Sjkim return 0; 319160814Ssimon 320280304Sjkim return !BN_is_zero(&group->cofactor); 321280304Sjkim} 322160814Ssimon 323160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 324280304Sjkim{ 325280304Sjkim group->curve_name = nid; 326280304Sjkim} 327160814Ssimon 328160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group) 329280304Sjkim{ 330280304Sjkim return group->curve_name; 331280304Sjkim} 332160814Ssimon 333160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 334280304Sjkim{ 335280304Sjkim group->asn1_flag = flag; 336280304Sjkim} 337160814Ssimon 338160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 339280304Sjkim{ 340280304Sjkim return group->asn1_flag; 341280304Sjkim} 342160814Ssimon 343280304Sjkimvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 344160814Ssimon point_conversion_form_t form) 345280304Sjkim{ 346280304Sjkim group->asn1_form = form; 347280304Sjkim} 348160814Ssimon 349280304Sjkimpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 350280304Sjkim *group) 351280304Sjkim{ 352280304Sjkim return group->asn1_form; 353280304Sjkim} 354160814Ssimon 355160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 356280304Sjkim{ 357280304Sjkim if (group->seed) { 358280304Sjkim OPENSSL_free(group->seed); 359280304Sjkim group->seed = NULL; 360280304Sjkim group->seed_len = 0; 361280304Sjkim } 362160814Ssimon 363280304Sjkim if (!len || !p) 364280304Sjkim return 1; 365160814Ssimon 366280304Sjkim if ((group->seed = OPENSSL_malloc(len)) == NULL) 367280304Sjkim return 0; 368280304Sjkim memcpy(group->seed, p, len); 369280304Sjkim group->seed_len = len; 370160814Ssimon 371280304Sjkim return len; 372280304Sjkim} 373160814Ssimon 374160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 375280304Sjkim{ 376280304Sjkim return group->seed; 377280304Sjkim} 378160814Ssimon 379160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 380280304Sjkim{ 381280304Sjkim return group->seed_len; 382280304Sjkim} 383160814Ssimon 384280304Sjkimint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 385280304Sjkim const BIGNUM *b, BN_CTX *ctx) 386280304Sjkim{ 387280304Sjkim if (group->meth->group_set_curve == 0) { 388280304Sjkim ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 389280304Sjkim return 0; 390280304Sjkim } 391280304Sjkim return group->meth->group_set_curve(group, p, a, b, ctx); 392280304Sjkim} 393160814Ssimon 394280304Sjkimint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 395280304Sjkim BIGNUM *b, BN_CTX *ctx) 396280304Sjkim{ 397280304Sjkim if (group->meth->group_get_curve == 0) { 398280304Sjkim ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 399280304Sjkim return 0; 400280304Sjkim } 401280304Sjkim return group->meth->group_get_curve(group, p, a, b, ctx); 402280304Sjkim} 403109998Smarkm 404238405Sjkim#ifndef OPENSSL_NO_EC2M 405280304Sjkimint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 406280304Sjkim const BIGNUM *b, BN_CTX *ctx) 407280304Sjkim{ 408280304Sjkim if (group->meth->group_set_curve == 0) { 409280304Sjkim ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, 410280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 411280304Sjkim return 0; 412280304Sjkim } 413280304Sjkim return group->meth->group_set_curve(group, p, a, b, ctx); 414280304Sjkim} 415109998Smarkm 416280304Sjkimint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 417280304Sjkim BIGNUM *b, BN_CTX *ctx) 418280304Sjkim{ 419280304Sjkim if (group->meth->group_get_curve == 0) { 420280304Sjkim ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, 421280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 422280304Sjkim return 0; 423280304Sjkim } 424280304Sjkim return group->meth->group_get_curve(group, p, a, b, ctx); 425280304Sjkim} 426238405Sjkim#endif 427109998Smarkm 428160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group) 429280304Sjkim{ 430280304Sjkim if (group->meth->group_get_degree == 0) { 431280304Sjkim ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 432280304Sjkim return 0; 433280304Sjkim } 434280304Sjkim return group->meth->group_get_degree(group); 435280304Sjkim} 436109998Smarkm 437160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 438280304Sjkim{ 439280304Sjkim if (group->meth->group_check_discriminant == 0) { 440280304Sjkim ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, 441280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 442280304Sjkim return 0; 443280304Sjkim } 444280304Sjkim return group->meth->group_check_discriminant(group, ctx); 445280304Sjkim} 446109998Smarkm 447160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 448280304Sjkim{ 449280304Sjkim int r = 0; 450280304Sjkim BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 451280304Sjkim BN_CTX *ctx_new = NULL; 452160814Ssimon 453280304Sjkim /* compare the field types */ 454280304Sjkim if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 455280304Sjkim EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 456280304Sjkim return 1; 457280304Sjkim /* compare the curve name (if present in both) */ 458280304Sjkim if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 459280304Sjkim EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 460280304Sjkim return 1; 461160814Ssimon 462280304Sjkim if (!ctx) 463280304Sjkim ctx_new = ctx = BN_CTX_new(); 464280304Sjkim if (!ctx) 465280304Sjkim return -1; 466109998Smarkm 467280304Sjkim BN_CTX_start(ctx); 468280304Sjkim a1 = BN_CTX_get(ctx); 469280304Sjkim a2 = BN_CTX_get(ctx); 470280304Sjkim a3 = BN_CTX_get(ctx); 471280304Sjkim b1 = BN_CTX_get(ctx); 472280304Sjkim b2 = BN_CTX_get(ctx); 473280304Sjkim b3 = BN_CTX_get(ctx); 474280304Sjkim if (!b3) { 475280304Sjkim BN_CTX_end(ctx); 476280304Sjkim if (ctx_new) 477280304Sjkim BN_CTX_free(ctx); 478280304Sjkim return -1; 479280304Sjkim } 480160814Ssimon 481280304Sjkim /* 482280304Sjkim * XXX This approach assumes that the external representation of curves 483280304Sjkim * over the same field type is the same. 484280304Sjkim */ 485280304Sjkim if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 486280304Sjkim !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 487280304Sjkim r = 1; 488160814Ssimon 489280304Sjkim if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 490280304Sjkim r = 1; 491160814Ssimon 492280304Sjkim /* XXX EC_POINT_cmp() assumes that the methods are equal */ 493280304Sjkim if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 494280304Sjkim EC_GROUP_get0_generator(b), ctx)) 495280304Sjkim r = 1; 496160814Ssimon 497280304Sjkim if (!r) { 498280304Sjkim /* compare the order and cofactor */ 499280304Sjkim if (!EC_GROUP_get_order(a, a1, ctx) || 500280304Sjkim !EC_GROUP_get_order(b, b1, ctx) || 501280304Sjkim !EC_GROUP_get_cofactor(a, a2, ctx) || 502280304Sjkim !EC_GROUP_get_cofactor(b, b2, ctx)) { 503280304Sjkim BN_CTX_end(ctx); 504280304Sjkim if (ctx_new) 505280304Sjkim BN_CTX_free(ctx); 506280304Sjkim return -1; 507280304Sjkim } 508280304Sjkim if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 509280304Sjkim r = 1; 510280304Sjkim } 511160814Ssimon 512280304Sjkim BN_CTX_end(ctx); 513280304Sjkim if (ctx_new) 514280304Sjkim BN_CTX_free(ctx); 515109998Smarkm 516280304Sjkim return r; 517280304Sjkim} 518109998Smarkm 519109998Smarkm/* this has 'package' visibility */ 520160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 521280304Sjkim void *(*dup_func) (void *), 522280304Sjkim void (*free_func) (void *), 523280304Sjkim void (*clear_free_func) (void *)) 524280304Sjkim{ 525280304Sjkim EC_EXTRA_DATA *d; 526160814Ssimon 527280304Sjkim if (ex_data == NULL) 528280304Sjkim return 0; 529160814Ssimon 530280304Sjkim for (d = *ex_data; d != NULL; d = d->next) { 531280304Sjkim if (d->dup_func == dup_func && d->free_func == free_func 532280304Sjkim && d->clear_free_func == clear_free_func) { 533280304Sjkim ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 534280304Sjkim return 0; 535280304Sjkim } 536280304Sjkim } 537109998Smarkm 538280304Sjkim if (data == NULL) 539280304Sjkim /* no explicit entry needed */ 540280304Sjkim return 1; 541160814Ssimon 542280304Sjkim d = OPENSSL_malloc(sizeof *d); 543280304Sjkim if (d == NULL) 544280304Sjkim return 0; 545160814Ssimon 546280304Sjkim d->data = data; 547280304Sjkim d->dup_func = dup_func; 548280304Sjkim d->free_func = free_func; 549280304Sjkim d->clear_free_func = clear_free_func; 550160814Ssimon 551280304Sjkim d->next = *ex_data; 552280304Sjkim *ex_data = d; 553160814Ssimon 554280304Sjkim return 1; 555280304Sjkim} 556109998Smarkm 557160814Ssimon/* this has 'package' visibility */ 558160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 559280304Sjkim void *(*dup_func) (void *), 560280304Sjkim void (*free_func) (void *), 561280304Sjkim void (*clear_free_func) (void *)) 562280304Sjkim{ 563280304Sjkim const EC_EXTRA_DATA *d; 564109998Smarkm 565280304Sjkim for (d = ex_data; d != NULL; d = d->next) { 566280304Sjkim if (d->dup_func == dup_func && d->free_func == free_func 567280304Sjkim && d->clear_free_func == clear_free_func) 568280304Sjkim return d->data; 569280304Sjkim } 570160814Ssimon 571280304Sjkim return NULL; 572280304Sjkim} 573280304Sjkim 574109998Smarkm/* this has 'package' visibility */ 575160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 576280304Sjkim void *(*dup_func) (void *), 577280304Sjkim void (*free_func) (void *), 578280304Sjkim void (*clear_free_func) (void *)) 579280304Sjkim{ 580280304Sjkim EC_EXTRA_DATA **p; 581160814Ssimon 582280304Sjkim if (ex_data == NULL) 583280304Sjkim return; 584160814Ssimon 585280304Sjkim for (p = ex_data; *p != NULL; p = &((*p)->next)) { 586280304Sjkim if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 587280304Sjkim && (*p)->clear_free_func == clear_free_func) { 588280304Sjkim EC_EXTRA_DATA *next = (*p)->next; 589160814Ssimon 590280304Sjkim (*p)->free_func((*p)->data); 591280304Sjkim OPENSSL_free(*p); 592109998Smarkm 593280304Sjkim *p = next; 594280304Sjkim return; 595280304Sjkim } 596280304Sjkim } 597280304Sjkim} 598280304Sjkim 599160814Ssimon/* this has 'package' visibility */ 600160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 601280304Sjkim void *(*dup_func) (void *), 602280304Sjkim void (*free_func) (void *), 603280304Sjkim void (*clear_free_func) (void *)) 604280304Sjkim{ 605280304Sjkim EC_EXTRA_DATA **p; 606109998Smarkm 607280304Sjkim if (ex_data == NULL) 608280304Sjkim return; 609160814Ssimon 610280304Sjkim for (p = ex_data; *p != NULL; p = &((*p)->next)) { 611280304Sjkim if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 612280304Sjkim && (*p)->clear_free_func == clear_free_func) { 613280304Sjkim EC_EXTRA_DATA *next = (*p)->next; 614160814Ssimon 615280304Sjkim (*p)->clear_free_func((*p)->data); 616280304Sjkim OPENSSL_free(*p); 617160814Ssimon 618280304Sjkim *p = next; 619280304Sjkim return; 620280304Sjkim } 621280304Sjkim } 622280304Sjkim} 623280304Sjkim 624109998Smarkm/* this has 'package' visibility */ 625160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 626280304Sjkim{ 627280304Sjkim EC_EXTRA_DATA *d; 628160814Ssimon 629280304Sjkim if (ex_data == NULL) 630280304Sjkim return; 631160814Ssimon 632280304Sjkim d = *ex_data; 633280304Sjkim while (d) { 634280304Sjkim EC_EXTRA_DATA *next = d->next; 635109998Smarkm 636280304Sjkim d->free_func(d->data); 637280304Sjkim OPENSSL_free(d); 638280304Sjkim 639280304Sjkim d = next; 640280304Sjkim } 641280304Sjkim *ex_data = NULL; 642280304Sjkim} 643280304Sjkim 644160814Ssimon/* this has 'package' visibility */ 645160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 646280304Sjkim{ 647280304Sjkim EC_EXTRA_DATA *d; 648109998Smarkm 649280304Sjkim if (ex_data == NULL) 650280304Sjkim return; 651109998Smarkm 652280304Sjkim d = *ex_data; 653280304Sjkim while (d) { 654280304Sjkim EC_EXTRA_DATA *next = d->next; 655160814Ssimon 656280304Sjkim d->clear_free_func(d->data); 657280304Sjkim OPENSSL_free(d); 658160814Ssimon 659280304Sjkim d = next; 660280304Sjkim } 661280304Sjkim *ex_data = NULL; 662280304Sjkim} 663280304Sjkim 664109998Smarkm/* functions for EC_POINT objects */ 665109998Smarkm 666109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group) 667280304Sjkim{ 668280304Sjkim EC_POINT *ret; 669109998Smarkm 670280304Sjkim if (group == NULL) { 671280304Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 672280304Sjkim return NULL; 673280304Sjkim } 674280304Sjkim if (group->meth->point_init == 0) { 675280304Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 676280304Sjkim return NULL; 677280304Sjkim } 678109998Smarkm 679280304Sjkim ret = OPENSSL_malloc(sizeof *ret); 680280304Sjkim if (ret == NULL) { 681280304Sjkim ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 682280304Sjkim return NULL; 683280304Sjkim } 684109998Smarkm 685280304Sjkim ret->meth = group->meth; 686109998Smarkm 687280304Sjkim if (!ret->meth->point_init(ret)) { 688280304Sjkim OPENSSL_free(ret); 689280304Sjkim return NULL; 690280304Sjkim } 691109998Smarkm 692280304Sjkim return ret; 693280304Sjkim} 694280304Sjkim 695109998Smarkmvoid EC_POINT_free(EC_POINT *point) 696280304Sjkim{ 697280304Sjkim if (!point) 698280304Sjkim return; 699109998Smarkm 700280304Sjkim if (point->meth->point_finish != 0) 701280304Sjkim point->meth->point_finish(point); 702280304Sjkim OPENSSL_free(point); 703280304Sjkim} 704109998Smarkm 705109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point) 706280304Sjkim{ 707280304Sjkim if (!point) 708280304Sjkim return; 709109998Smarkm 710280304Sjkim if (point->meth->point_clear_finish != 0) 711280304Sjkim point->meth->point_clear_finish(point); 712280304Sjkim else if (point->meth->point_finish != 0) 713280304Sjkim point->meth->point_finish(point); 714280304Sjkim OPENSSL_cleanse(point, sizeof *point); 715280304Sjkim OPENSSL_free(point); 716280304Sjkim} 717109998Smarkm 718109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 719280304Sjkim{ 720280304Sjkim if (dest->meth->point_copy == 0) { 721280304Sjkim ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 722280304Sjkim return 0; 723280304Sjkim } 724280304Sjkim if (dest->meth != src->meth) { 725280304Sjkim ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 726280304Sjkim return 0; 727280304Sjkim } 728280304Sjkim if (dest == src) 729280304Sjkim return 1; 730280304Sjkim return dest->meth->point_copy(dest, src); 731280304Sjkim} 732109998Smarkm 733160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 734280304Sjkim{ 735280304Sjkim EC_POINT *t; 736280304Sjkim int r; 737160814Ssimon 738280304Sjkim if (a == NULL) 739280304Sjkim return NULL; 740160814Ssimon 741280304Sjkim t = EC_POINT_new(group); 742280304Sjkim if (t == NULL) 743280304Sjkim return (NULL); 744280304Sjkim r = EC_POINT_copy(t, a); 745280304Sjkim if (!r) { 746280304Sjkim EC_POINT_free(t); 747280304Sjkim return NULL; 748280304Sjkim } else 749280304Sjkim return t; 750280304Sjkim} 751160814Ssimon 752109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 753280304Sjkim{ 754280304Sjkim return point->meth; 755280304Sjkim} 756109998Smarkm 757109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 758280304Sjkim{ 759280304Sjkim if (group->meth->point_set_to_infinity == 0) { 760280304Sjkim ECerr(EC_F_EC_POINT_SET_TO_INFINITY, 761280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 762280304Sjkim return 0; 763280304Sjkim } 764280304Sjkim if (group->meth != point->meth) { 765280304Sjkim ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 766280304Sjkim return 0; 767280304Sjkim } 768280304Sjkim return group->meth->point_set_to_infinity(group, point); 769280304Sjkim} 770109998Smarkm 771280304Sjkimint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 772280304Sjkim EC_POINT *point, const BIGNUM *x, 773280304Sjkim const BIGNUM *y, const BIGNUM *z, 774280304Sjkim BN_CTX *ctx) 775280304Sjkim{ 776280304Sjkim if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 777280304Sjkim ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 778280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 779280304Sjkim return 0; 780280304Sjkim } 781280304Sjkim if (group->meth != point->meth) { 782280304Sjkim ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 783280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 784280304Sjkim return 0; 785280304Sjkim } 786280304Sjkim return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, 787280304Sjkim y, z, ctx); 788280304Sjkim} 789109998Smarkm 790280304Sjkimint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 791280304Sjkim const EC_POINT *point, BIGNUM *x, 792280304Sjkim BIGNUM *y, BIGNUM *z, 793280304Sjkim BN_CTX *ctx) 794280304Sjkim{ 795280304Sjkim if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 796280304Sjkim ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 797280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 798280304Sjkim return 0; 799280304Sjkim } 800280304Sjkim if (group->meth != point->meth) { 801280304Sjkim ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 802280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 803280304Sjkim return 0; 804280304Sjkim } 805280304Sjkim return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, 806280304Sjkim y, z, ctx); 807280304Sjkim} 808109998Smarkm 809280304Sjkimint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 810280304Sjkim EC_POINT *point, const BIGNUM *x, 811280304Sjkim const BIGNUM *y, BN_CTX *ctx) 812280304Sjkim{ 813280304Sjkim if (group->meth->point_set_affine_coordinates == 0) { 814280304Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 815280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 816280304Sjkim return 0; 817280304Sjkim } 818280304Sjkim if (group->meth != point->meth) { 819280304Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 820280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 821280304Sjkim return 0; 822280304Sjkim } 823280304Sjkim return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 824280304Sjkim} 825109998Smarkm 826238405Sjkim#ifndef OPENSSL_NO_EC2M 827280304Sjkimint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 828280304Sjkim EC_POINT *point, const BIGNUM *x, 829280304Sjkim const BIGNUM *y, BN_CTX *ctx) 830280304Sjkim{ 831280304Sjkim if (group->meth->point_set_affine_coordinates == 0) { 832280304Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 833280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 834280304Sjkim return 0; 835280304Sjkim } 836280304Sjkim if (group->meth != point->meth) { 837280304Sjkim ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 838280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 839280304Sjkim return 0; 840280304Sjkim } 841280304Sjkim return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 842280304Sjkim} 843238405Sjkim#endif 844160814Ssimon 845280304Sjkimint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 846280304Sjkim const EC_POINT *point, BIGNUM *x, 847280304Sjkim BIGNUM *y, BN_CTX *ctx) 848280304Sjkim{ 849280304Sjkim if (group->meth->point_get_affine_coordinates == 0) { 850280304Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 851280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 852280304Sjkim return 0; 853280304Sjkim } 854280304Sjkim if (group->meth != point->meth) { 855280304Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 856280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 857280304Sjkim return 0; 858280304Sjkim } 859280304Sjkim return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 860280304Sjkim} 861109998Smarkm 862238405Sjkim#ifndef OPENSSL_NO_EC2M 863280304Sjkimint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 864280304Sjkim const EC_POINT *point, BIGNUM *x, 865280304Sjkim BIGNUM *y, BN_CTX *ctx) 866280304Sjkim{ 867280304Sjkim if (group->meth->point_get_affine_coordinates == 0) { 868280304Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 869280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 870280304Sjkim return 0; 871280304Sjkim } 872280304Sjkim if (group->meth != point->meth) { 873280304Sjkim ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 874280304Sjkim EC_R_INCOMPATIBLE_OBJECTS); 875280304Sjkim return 0; 876280304Sjkim } 877280304Sjkim return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 878280304Sjkim} 879238405Sjkim#endif 880160814Ssimon 881280304Sjkimint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 882280304Sjkim const EC_POINT *b, BN_CTX *ctx) 883280304Sjkim{ 884280304Sjkim if (group->meth->add == 0) { 885280304Sjkim ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 886280304Sjkim return 0; 887280304Sjkim } 888280304Sjkim if ((group->meth != r->meth) || (r->meth != a->meth) 889280304Sjkim || (a->meth != b->meth)) { 890280304Sjkim ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 891280304Sjkim return 0; 892280304Sjkim } 893280304Sjkim return group->meth->add(group, r, a, b, ctx); 894280304Sjkim} 895109998Smarkm 896280304Sjkimint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 897280304Sjkim BN_CTX *ctx) 898280304Sjkim{ 899280304Sjkim if (group->meth->dbl == 0) { 900280304Sjkim ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 901280304Sjkim return 0; 902280304Sjkim } 903280304Sjkim if ((group->meth != r->meth) || (r->meth != a->meth)) { 904280304Sjkim ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 905280304Sjkim return 0; 906280304Sjkim } 907280304Sjkim return group->meth->dbl(group, r, a, ctx); 908280304Sjkim} 909109998Smarkm 910109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 911280304Sjkim{ 912280304Sjkim if (group->meth->invert == 0) { 913280304Sjkim ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 914280304Sjkim return 0; 915280304Sjkim } 916280304Sjkim if (group->meth != a->meth) { 917280304Sjkim ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 918280304Sjkim return 0; 919280304Sjkim } 920280304Sjkim return group->meth->invert(group, a, ctx); 921280304Sjkim} 922109998Smarkm 923109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 924280304Sjkim{ 925280304Sjkim if (group->meth->is_at_infinity == 0) { 926280304Sjkim ECerr(EC_F_EC_POINT_IS_AT_INFINITY, 927280304Sjkim ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 928280304Sjkim return 0; 929280304Sjkim } 930280304Sjkim if (group->meth != point->meth) { 931280304Sjkim ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 932280304Sjkim return 0; 933280304Sjkim } 934280304Sjkim return group->meth->is_at_infinity(group, point); 935280304Sjkim} 936109998Smarkm 937284285Sjkim/* 938284285Sjkim * Check whether an EC_POINT is on the curve or not. Note that the return 939284285Sjkim * value for this function should NOT be treated as a boolean. Return values: 940284285Sjkim * 1: The point is on the curve 941284285Sjkim * 0: The point is not on the curve 942284285Sjkim * -1: An error occurred 943284285Sjkim */ 944280304Sjkimint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 945280304Sjkim BN_CTX *ctx) 946280304Sjkim{ 947280304Sjkim if (group->meth->is_on_curve == 0) { 948280304Sjkim ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 949280304Sjkim return 0; 950280304Sjkim } 951280304Sjkim if (group->meth != point->meth) { 952280304Sjkim ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 953280304Sjkim return 0; 954280304Sjkim } 955280304Sjkim return group->meth->is_on_curve(group, point, ctx); 956280304Sjkim} 957109998Smarkm 958280304Sjkimint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 959280304Sjkim BN_CTX *ctx) 960280304Sjkim{ 961280304Sjkim if (group->meth->point_cmp == 0) { 962280304Sjkim ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 963280304Sjkim return -1; 964280304Sjkim } 965280304Sjkim if ((group->meth != a->meth) || (a->meth != b->meth)) { 966280304Sjkim ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 967280304Sjkim return -1; 968280304Sjkim } 969280304Sjkim return group->meth->point_cmp(group, a, b, ctx); 970280304Sjkim} 971109998Smarkm 972109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 973280304Sjkim{ 974280304Sjkim if (group->meth->make_affine == 0) { 975280304Sjkim ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 976280304Sjkim return 0; 977280304Sjkim } 978280304Sjkim if (group->meth != point->meth) { 979280304Sjkim ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 980280304Sjkim return 0; 981280304Sjkim } 982280304Sjkim return group->meth->make_affine(group, point, ctx); 983280304Sjkim} 984109998Smarkm 985280304Sjkimint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 986280304Sjkim EC_POINT *points[], BN_CTX *ctx) 987280304Sjkim{ 988280304Sjkim size_t i; 989109998Smarkm 990280304Sjkim if (group->meth->points_make_affine == 0) { 991280304Sjkim ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 992280304Sjkim return 0; 993280304Sjkim } 994280304Sjkim for (i = 0; i < num; i++) { 995280304Sjkim if (group->meth != points[i]->meth) { 996280304Sjkim ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 997280304Sjkim return 0; 998280304Sjkim } 999280304Sjkim } 1000280304Sjkim return group->meth->points_make_affine(group, num, points, ctx); 1001280304Sjkim} 1002109998Smarkm 1003280304Sjkim/* 1004280304Sjkim * Functions for point multiplication. If group->meth->mul is 0, we use the 1005280304Sjkim * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1006280304Sjkim * methods. 1007160814Ssimon */ 1008160814Ssimon 1009160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1010280304Sjkim size_t num, const EC_POINT *points[], 1011280304Sjkim const BIGNUM *scalars[], BN_CTX *ctx) 1012280304Sjkim{ 1013280304Sjkim if (group->meth->mul == 0) 1014280304Sjkim /* use default */ 1015280304Sjkim return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1016160814Ssimon 1017280304Sjkim return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1018280304Sjkim} 1019160814Ssimon 1020160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1021280304Sjkim const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1022280304Sjkim{ 1023280304Sjkim /* just a convenient interface to EC_POINTs_mul() */ 1024160814Ssimon 1025280304Sjkim const EC_POINT *points[1]; 1026280304Sjkim const BIGNUM *scalars[1]; 1027160814Ssimon 1028280304Sjkim points[0] = point; 1029280304Sjkim scalars[0] = p_scalar; 1030160814Ssimon 1031280304Sjkim return EC_POINTs_mul(group, r, g_scalar, 1032280304Sjkim (point != NULL 1033280304Sjkim && p_scalar != NULL), points, scalars, ctx); 1034280304Sjkim} 1035160814Ssimon 1036160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1037280304Sjkim{ 1038280304Sjkim if (group->meth->mul == 0) 1039280304Sjkim /* use default */ 1040280304Sjkim return ec_wNAF_precompute_mult(group, ctx); 1041160814Ssimon 1042280304Sjkim if (group->meth->precompute_mult != 0) 1043280304Sjkim return group->meth->precompute_mult(group, ctx); 1044280304Sjkim else 1045280304Sjkim return 1; /* nothing to do, so report success */ 1046280304Sjkim} 1047160814Ssimon 1048160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1049280304Sjkim{ 1050280304Sjkim if (group->meth->mul == 0) 1051280304Sjkim /* use default */ 1052280304Sjkim return ec_wNAF_have_precompute_mult(group); 1053160814Ssimon 1054280304Sjkim if (group->meth->have_precompute_mult != 0) 1055280304Sjkim return group->meth->have_precompute_mult(group); 1056280304Sjkim else 1057280304Sjkim return 0; /* cannot tell whether precomputation has 1058280304Sjkim * been performed */ 1059280304Sjkim} 1060