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 13109998Smarkm * 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. 60160814Ssimon * 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 71279264Sdelphijconst char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; 72109998Smarkm 73109998Smarkm 74109998Smarkm/* functions for EC_GROUP objects */ 75109998Smarkm 76109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 77109998Smarkm { 78109998Smarkm EC_GROUP *ret; 79109998Smarkm 80109998Smarkm if (meth == NULL) 81109998Smarkm { 82238405Sjkim ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); 83109998Smarkm return NULL; 84109998Smarkm } 85109998Smarkm if (meth->group_init == 0) 86109998Smarkm { 87109998Smarkm ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 88109998Smarkm return NULL; 89109998Smarkm } 90109998Smarkm 91109998Smarkm ret = OPENSSL_malloc(sizeof *ret); 92109998Smarkm if (ret == NULL) 93109998Smarkm { 94109998Smarkm ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); 95109998Smarkm return NULL; 96109998Smarkm } 97109998Smarkm 98109998Smarkm ret->meth = meth; 99109998Smarkm 100109998Smarkm ret->extra_data = NULL; 101160814Ssimon 102160814Ssimon ret->generator = NULL; 103160814Ssimon BN_init(&ret->order); 104160814Ssimon BN_init(&ret->cofactor); 105160814Ssimon 106160814Ssimon ret->curve_name = 0; 107160814Ssimon ret->asn1_flag = 0; 108160814Ssimon ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 109160814Ssimon 110160814Ssimon ret->seed = NULL; 111160814Ssimon ret->seed_len = 0; 112160814Ssimon 113109998Smarkm if (!meth->group_init(ret)) 114109998Smarkm { 115109998Smarkm OPENSSL_free(ret); 116109998Smarkm return NULL; 117109998Smarkm } 118109998Smarkm 119109998Smarkm return ret; 120109998Smarkm } 121109998Smarkm 122109998Smarkm 123109998Smarkmvoid EC_GROUP_free(EC_GROUP *group) 124109998Smarkm { 125109998Smarkm if (!group) return; 126109998Smarkm 127109998Smarkm if (group->meth->group_finish != 0) 128109998Smarkm group->meth->group_finish(group); 129109998Smarkm 130160814Ssimon EC_EX_DATA_free_all_data(&group->extra_data); 131109998Smarkm 132160814Ssimon if (group->generator != NULL) 133160814Ssimon EC_POINT_free(group->generator); 134160814Ssimon BN_free(&group->order); 135160814Ssimon BN_free(&group->cofactor); 136160814Ssimon 137160814Ssimon if (group->seed) 138160814Ssimon OPENSSL_free(group->seed); 139160814Ssimon 140109998Smarkm OPENSSL_free(group); 141109998Smarkm } 142109998Smarkm 143109998Smarkm 144109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group) 145109998Smarkm { 146109998Smarkm if (!group) return; 147109998Smarkm 148109998Smarkm if (group->meth->group_clear_finish != 0) 149109998Smarkm group->meth->group_clear_finish(group); 150160814Ssimon else if (group->meth->group_finish != 0) 151109998Smarkm group->meth->group_finish(group); 152109998Smarkm 153160814Ssimon EC_EX_DATA_clear_free_all_data(&group->extra_data); 154109998Smarkm 155160814Ssimon if (group->generator != NULL) 156160814Ssimon EC_POINT_clear_free(group->generator); 157160814Ssimon BN_clear_free(&group->order); 158160814Ssimon BN_clear_free(&group->cofactor); 159160814Ssimon 160160814Ssimon if (group->seed) 161160814Ssimon { 162160814Ssimon OPENSSL_cleanse(group->seed, group->seed_len); 163160814Ssimon OPENSSL_free(group->seed); 164160814Ssimon } 165160814Ssimon 166109998Smarkm OPENSSL_cleanse(group, sizeof *group); 167109998Smarkm OPENSSL_free(group); 168109998Smarkm } 169109998Smarkm 170109998Smarkm 171109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 172109998Smarkm { 173160814Ssimon EC_EXTRA_DATA *d; 174160814Ssimon 175109998Smarkm if (dest->meth->group_copy == 0) 176109998Smarkm { 177109998Smarkm ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 178109998Smarkm return 0; 179109998Smarkm } 180109998Smarkm if (dest->meth != src->meth) 181109998Smarkm { 182109998Smarkm ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); 183109998Smarkm return 0; 184109998Smarkm } 185109998Smarkm if (dest == src) 186109998Smarkm return 1; 187109998Smarkm 188160814Ssimon EC_EX_DATA_free_all_data(&dest->extra_data); 189160814Ssimon 190160814Ssimon for (d = src->extra_data; d != NULL; d = d->next) 191109998Smarkm { 192160814Ssimon void *t = d->dup_func(d->data); 193160814Ssimon 194160814Ssimon if (t == NULL) 195160814Ssimon return 0; 196160814Ssimon if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func)) 197160814Ssimon return 0; 198160814Ssimon } 199160814Ssimon 200160814Ssimon if (src->generator != NULL) 201160814Ssimon { 202160814Ssimon if (dest->generator == NULL) 203109998Smarkm { 204160814Ssimon dest->generator = EC_POINT_new(dest); 205160814Ssimon if (dest->generator == NULL) return 0; 206109998Smarkm } 207160814Ssimon if (!EC_POINT_copy(dest->generator, src->generator)) return 0; 208160814Ssimon } 209160814Ssimon else 210160814Ssimon { 211160814Ssimon /* src->generator == NULL */ 212160814Ssimon if (dest->generator != NULL) 213160814Ssimon { 214160814Ssimon EC_POINT_clear_free(dest->generator); 215160814Ssimon dest->generator = NULL; 216160814Ssimon } 217160814Ssimon } 218109998Smarkm 219160814Ssimon if (!BN_copy(&dest->order, &src->order)) return 0; 220160814Ssimon if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0; 221160814Ssimon 222160814Ssimon dest->curve_name = src->curve_name; 223160814Ssimon dest->asn1_flag = src->asn1_flag; 224160814Ssimon dest->asn1_form = src->asn1_form; 225160814Ssimon 226160814Ssimon if (src->seed) 227160814Ssimon { 228160814Ssimon if (dest->seed) 229160814Ssimon OPENSSL_free(dest->seed); 230160814Ssimon dest->seed = OPENSSL_malloc(src->seed_len); 231160814Ssimon if (dest->seed == NULL) 232160814Ssimon return 0; 233160814Ssimon if (!memcpy(dest->seed, src->seed, src->seed_len)) 234160814Ssimon return 0; 235160814Ssimon dest->seed_len = src->seed_len; 236109998Smarkm } 237160814Ssimon else 238160814Ssimon { 239160814Ssimon if (dest->seed) 240160814Ssimon OPENSSL_free(dest->seed); 241160814Ssimon dest->seed = NULL; 242160814Ssimon dest->seed_len = 0; 243160814Ssimon } 244160814Ssimon 245109998Smarkm 246109998Smarkm return dest->meth->group_copy(dest, src); 247109998Smarkm } 248109998Smarkm 249109998Smarkm 250160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 251160814Ssimon { 252160814Ssimon EC_GROUP *t = NULL; 253160814Ssimon int ok = 0; 254160814Ssimon 255160814Ssimon if (a == NULL) return NULL; 256160814Ssimon 257160814Ssimon if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL); 258160814Ssimon if (!EC_GROUP_copy(t, a)) goto err; 259160814Ssimon 260160814Ssimon ok = 1; 261160814Ssimon 262160814Ssimon err: 263160814Ssimon if (!ok) 264160814Ssimon { 265160814Ssimon if (t) EC_GROUP_free(t); 266160814Ssimon return NULL; 267160814Ssimon } 268160814Ssimon else return t; 269160814Ssimon } 270160814Ssimon 271160814Ssimon 272109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 273109998Smarkm { 274109998Smarkm return group->meth; 275109998Smarkm } 276109998Smarkm 277109998Smarkm 278160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth) 279160814Ssimon { 280160814Ssimon return meth->field_type; 281160814Ssimon } 282160814Ssimon 283160814Ssimon 284160814Ssimonint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) 285160814Ssimon { 286160814Ssimon if (generator == NULL) 287160814Ssimon { 288160814Ssimon ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 289160814Ssimon return 0 ; 290160814Ssimon } 291160814Ssimon 292160814Ssimon if (group->generator == NULL) 293160814Ssimon { 294160814Ssimon group->generator = EC_POINT_new(group); 295160814Ssimon if (group->generator == NULL) return 0; 296160814Ssimon } 297160814Ssimon if (!EC_POINT_copy(group->generator, generator)) return 0; 298160814Ssimon 299160814Ssimon if (order != NULL) 300160814Ssimon { if (!BN_copy(&group->order, order)) return 0; } 301160814Ssimon else 302160814Ssimon BN_zero(&group->order); 303160814Ssimon 304160814Ssimon if (cofactor != NULL) 305160814Ssimon { if (!BN_copy(&group->cofactor, cofactor)) return 0; } 306160814Ssimon else 307160814Ssimon BN_zero(&group->cofactor); 308160814Ssimon 309160814Ssimon return 1; 310160814Ssimon } 311160814Ssimon 312160814Ssimon 313160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 314160814Ssimon { 315160814Ssimon return group->generator; 316160814Ssimon } 317160814Ssimon 318160814Ssimon 319160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 320160814Ssimon { 321160814Ssimon if (!BN_copy(order, &group->order)) 322160814Ssimon return 0; 323160814Ssimon 324160814Ssimon return !BN_is_zero(order); 325160814Ssimon } 326160814Ssimon 327160814Ssimon 328160814Ssimonint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 329160814Ssimon { 330160814Ssimon if (!BN_copy(cofactor, &group->cofactor)) 331160814Ssimon return 0; 332160814Ssimon 333160814Ssimon return !BN_is_zero(&group->cofactor); 334160814Ssimon } 335160814Ssimon 336160814Ssimon 337160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 338160814Ssimon { 339160814Ssimon group->curve_name = nid; 340160814Ssimon } 341160814Ssimon 342160814Ssimon 343160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group) 344160814Ssimon { 345160814Ssimon return group->curve_name; 346160814Ssimon } 347160814Ssimon 348160814Ssimon 349160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 350160814Ssimon { 351160814Ssimon group->asn1_flag = flag; 352160814Ssimon } 353160814Ssimon 354160814Ssimon 355160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 356160814Ssimon { 357160814Ssimon return group->asn1_flag; 358160814Ssimon } 359160814Ssimon 360160814Ssimon 361160814Ssimonvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 362160814Ssimon point_conversion_form_t form) 363160814Ssimon { 364160814Ssimon group->asn1_form = form; 365160814Ssimon } 366160814Ssimon 367160814Ssimon 368160814Ssimonpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group) 369160814Ssimon { 370160814Ssimon return group->asn1_form; 371160814Ssimon } 372160814Ssimon 373160814Ssimon 374160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 375160814Ssimon { 376160814Ssimon if (group->seed) 377160814Ssimon { 378160814Ssimon OPENSSL_free(group->seed); 379160814Ssimon group->seed = NULL; 380160814Ssimon group->seed_len = 0; 381160814Ssimon } 382160814Ssimon 383160814Ssimon if (!len || !p) 384160814Ssimon return 1; 385160814Ssimon 386160814Ssimon if ((group->seed = OPENSSL_malloc(len)) == NULL) 387160814Ssimon return 0; 388160814Ssimon memcpy(group->seed, p, len); 389160814Ssimon group->seed_len = len; 390160814Ssimon 391160814Ssimon return len; 392160814Ssimon } 393160814Ssimon 394160814Ssimon 395160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 396160814Ssimon { 397160814Ssimon return group->seed; 398160814Ssimon } 399160814Ssimon 400160814Ssimon 401160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 402160814Ssimon { 403160814Ssimon return group->seed_len; 404160814Ssimon } 405160814Ssimon 406160814Ssimon 407109998Smarkmint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 408109998Smarkm { 409160814Ssimon if (group->meth->group_set_curve == 0) 410109998Smarkm { 411109998Smarkm ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 412109998Smarkm return 0; 413109998Smarkm } 414160814Ssimon return group->meth->group_set_curve(group, p, a, b, ctx); 415109998Smarkm } 416109998Smarkm 417109998Smarkm 418109998Smarkmint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 419109998Smarkm { 420160814Ssimon if (group->meth->group_get_curve == 0) 421109998Smarkm { 422109998Smarkm ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 423109998Smarkm return 0; 424109998Smarkm } 425160814Ssimon return group->meth->group_get_curve(group, p, a, b, ctx); 426109998Smarkm } 427109998Smarkm 428238405Sjkim#ifndef OPENSSL_NO_EC2M 429160814Ssimonint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 430109998Smarkm { 431160814Ssimon if (group->meth->group_set_curve == 0) 432109998Smarkm { 433160814Ssimon ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 434109998Smarkm return 0; 435109998Smarkm } 436160814Ssimon return group->meth->group_set_curve(group, p, a, b, ctx); 437109998Smarkm } 438109998Smarkm 439109998Smarkm 440160814Ssimonint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 441109998Smarkm { 442160814Ssimon if (group->meth->group_get_curve == 0) 443109998Smarkm { 444160814Ssimon ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 445109998Smarkm return 0; 446109998Smarkm } 447160814Ssimon return group->meth->group_get_curve(group, p, a, b, ctx); 448109998Smarkm } 449238405Sjkim#endif 450109998Smarkm 451160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group) 452109998Smarkm { 453160814Ssimon if (group->meth->group_get_degree == 0) 454109998Smarkm { 455160814Ssimon ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 456109998Smarkm return 0; 457109998Smarkm } 458160814Ssimon return group->meth->group_get_degree(group); 459109998Smarkm } 460109998Smarkm 461109998Smarkm 462160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 463109998Smarkm { 464160814Ssimon if (group->meth->group_check_discriminant == 0) 465109998Smarkm { 466160814Ssimon ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 467109998Smarkm return 0; 468109998Smarkm } 469160814Ssimon return group->meth->group_check_discriminant(group, ctx); 470109998Smarkm } 471109998Smarkm 472109998Smarkm 473160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 474109998Smarkm { 475160814Ssimon int r = 0; 476160814Ssimon BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 477160814Ssimon BN_CTX *ctx_new = NULL; 478160814Ssimon 479160814Ssimon /* compare the field types*/ 480160814Ssimon if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 481160814Ssimon EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 482160814Ssimon return 1; 483279264Sdelphij /* compare the curve name (if present in both) */ 484160814Ssimon if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 485279264Sdelphij EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 486279264Sdelphij return 1; 487160814Ssimon 488160814Ssimon if (!ctx) 489160814Ssimon ctx_new = ctx = BN_CTX_new(); 490160814Ssimon if (!ctx) 491160814Ssimon return -1; 492160814Ssimon 493160814Ssimon BN_CTX_start(ctx); 494160814Ssimon a1 = BN_CTX_get(ctx); 495160814Ssimon a2 = BN_CTX_get(ctx); 496160814Ssimon a3 = BN_CTX_get(ctx); 497160814Ssimon b1 = BN_CTX_get(ctx); 498160814Ssimon b2 = BN_CTX_get(ctx); 499160814Ssimon b3 = BN_CTX_get(ctx); 500160814Ssimon if (!b3) 501109998Smarkm { 502160814Ssimon BN_CTX_end(ctx); 503160814Ssimon if (ctx_new) 504160814Ssimon BN_CTX_free(ctx); 505160814Ssimon return -1; 506109998Smarkm } 507109998Smarkm 508160814Ssimon /* XXX This approach assumes that the external representation 509160814Ssimon * of curves over the same field type is the same. 510160814Ssimon */ 511160814Ssimon if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 512160814Ssimon !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 513160814Ssimon r = 1; 514160814Ssimon 515160814Ssimon if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 516160814Ssimon r = 1; 517160814Ssimon 518160814Ssimon /* XXX EC_POINT_cmp() assumes that the methods are equal */ 519160814Ssimon if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 520160814Ssimon EC_GROUP_get0_generator(b), ctx)) 521160814Ssimon r = 1; 522160814Ssimon 523160814Ssimon if (!r) 524160814Ssimon { 525160814Ssimon /* compare the order and cofactor */ 526160814Ssimon if (!EC_GROUP_get_order(a, a1, ctx) || 527160814Ssimon !EC_GROUP_get_order(b, b1, ctx) || 528160814Ssimon !EC_GROUP_get_cofactor(a, a2, ctx) || 529160814Ssimon !EC_GROUP_get_cofactor(b, b2, ctx)) 530160814Ssimon { 531160814Ssimon BN_CTX_end(ctx); 532160814Ssimon if (ctx_new) 533160814Ssimon BN_CTX_free(ctx); 534160814Ssimon return -1; 535160814Ssimon } 536160814Ssimon if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 537160814Ssimon r = 1; 538160814Ssimon } 539160814Ssimon 540160814Ssimon BN_CTX_end(ctx); 541160814Ssimon if (ctx_new) 542160814Ssimon BN_CTX_free(ctx); 543160814Ssimon 544160814Ssimon return r; 545109998Smarkm } 546109998Smarkm 547109998Smarkm 548109998Smarkm/* this has 'package' visibility */ 549160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 550160814Ssimon void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) 551109998Smarkm { 552160814Ssimon EC_EXTRA_DATA *d; 553160814Ssimon 554160814Ssimon if (ex_data == NULL) 555160814Ssimon return 0; 556160814Ssimon 557160814Ssimon for (d = *ex_data; d != NULL; d = d->next) 558109998Smarkm { 559160814Ssimon if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) 560160814Ssimon { 561160814Ssimon ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 562160814Ssimon return 0; 563160814Ssimon } 564109998Smarkm } 565109998Smarkm 566160814Ssimon if (data == NULL) 567160814Ssimon /* no explicit entry needed */ 568160814Ssimon return 1; 569160814Ssimon 570160814Ssimon d = OPENSSL_malloc(sizeof *d); 571160814Ssimon if (d == NULL) 572160814Ssimon return 0; 573160814Ssimon 574160814Ssimon d->data = data; 575160814Ssimon d->dup_func = dup_func; 576160814Ssimon d->free_func = free_func; 577160814Ssimon d->clear_free_func = clear_free_func; 578160814Ssimon 579160814Ssimon d->next = *ex_data; 580160814Ssimon *ex_data = d; 581160814Ssimon 582160814Ssimon return 1; 583109998Smarkm } 584109998Smarkm 585160814Ssimon/* this has 'package' visibility */ 586160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 587160814Ssimon void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) 588160814Ssimon { 589160814Ssimon const EC_EXTRA_DATA *d; 590109998Smarkm 591160814Ssimon for (d = ex_data; d != NULL; d = d->next) 592160814Ssimon { 593160814Ssimon if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) 594160814Ssimon return d->data; 595160814Ssimon } 596160814Ssimon 597160814Ssimon return NULL; 598160814Ssimon } 599160814Ssimon 600109998Smarkm/* this has 'package' visibility */ 601160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 602160814Ssimon void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) 603109998Smarkm { 604160814Ssimon EC_EXTRA_DATA **p; 605160814Ssimon 606160814Ssimon if (ex_data == NULL) 607160814Ssimon return; 608160814Ssimon 609160814Ssimon for (p = ex_data; *p != NULL; p = &((*p)->next)) 610160814Ssimon { 611160814Ssimon if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) 612160814Ssimon { 613160814Ssimon EC_EXTRA_DATA *next = (*p)->next; 614160814Ssimon 615160814Ssimon (*p)->free_func((*p)->data); 616160814Ssimon OPENSSL_free(*p); 617160814Ssimon 618160814Ssimon *p = next; 619160814Ssimon return; 620160814Ssimon } 621160814Ssimon } 622109998Smarkm } 623109998Smarkm 624160814Ssimon/* this has 'package' visibility */ 625160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 626160814Ssimon void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) 627160814Ssimon { 628160814Ssimon EC_EXTRA_DATA **p; 629109998Smarkm 630160814Ssimon if (ex_data == NULL) 631160814Ssimon return; 632160814Ssimon 633160814Ssimon for (p = ex_data; *p != NULL; p = &((*p)->next)) 634160814Ssimon { 635160814Ssimon if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) 636160814Ssimon { 637160814Ssimon EC_EXTRA_DATA *next = (*p)->next; 638160814Ssimon 639160814Ssimon (*p)->clear_free_func((*p)->data); 640160814Ssimon OPENSSL_free(*p); 641160814Ssimon 642160814Ssimon *p = next; 643160814Ssimon return; 644160814Ssimon } 645160814Ssimon } 646160814Ssimon } 647160814Ssimon 648109998Smarkm/* this has 'package' visibility */ 649160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 650109998Smarkm { 651160814Ssimon EC_EXTRA_DATA *d; 652160814Ssimon 653160814Ssimon if (ex_data == NULL) 654160814Ssimon return; 655160814Ssimon 656160814Ssimon d = *ex_data; 657160814Ssimon while (d) 658160814Ssimon { 659160814Ssimon EC_EXTRA_DATA *next = d->next; 660160814Ssimon 661160814Ssimon d->free_func(d->data); 662160814Ssimon OPENSSL_free(d); 663160814Ssimon 664160814Ssimon d = next; 665160814Ssimon } 666160814Ssimon *ex_data = NULL; 667109998Smarkm } 668109998Smarkm 669160814Ssimon/* this has 'package' visibility */ 670160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 671160814Ssimon { 672160814Ssimon EC_EXTRA_DATA *d; 673109998Smarkm 674160814Ssimon if (ex_data == NULL) 675160814Ssimon return; 676109998Smarkm 677160814Ssimon d = *ex_data; 678160814Ssimon while (d) 679160814Ssimon { 680160814Ssimon EC_EXTRA_DATA *next = d->next; 681160814Ssimon 682160814Ssimon d->clear_free_func(d->data); 683160814Ssimon OPENSSL_free(d); 684160814Ssimon 685160814Ssimon d = next; 686160814Ssimon } 687160814Ssimon *ex_data = NULL; 688160814Ssimon } 689160814Ssimon 690160814Ssimon 691109998Smarkm/* functions for EC_POINT objects */ 692109998Smarkm 693109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group) 694109998Smarkm { 695109998Smarkm EC_POINT *ret; 696109998Smarkm 697109998Smarkm if (group == NULL) 698109998Smarkm { 699109998Smarkm ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 700109998Smarkm return NULL; 701109998Smarkm } 702109998Smarkm if (group->meth->point_init == 0) 703109998Smarkm { 704109998Smarkm ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 705109998Smarkm return NULL; 706109998Smarkm } 707109998Smarkm 708109998Smarkm ret = OPENSSL_malloc(sizeof *ret); 709109998Smarkm if (ret == NULL) 710109998Smarkm { 711109998Smarkm ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 712109998Smarkm return NULL; 713109998Smarkm } 714109998Smarkm 715109998Smarkm ret->meth = group->meth; 716109998Smarkm 717109998Smarkm if (!ret->meth->point_init(ret)) 718109998Smarkm { 719109998Smarkm OPENSSL_free(ret); 720109998Smarkm return NULL; 721109998Smarkm } 722109998Smarkm 723109998Smarkm return ret; 724109998Smarkm } 725109998Smarkm 726109998Smarkm 727109998Smarkmvoid EC_POINT_free(EC_POINT *point) 728109998Smarkm { 729109998Smarkm if (!point) return; 730109998Smarkm 731109998Smarkm if (point->meth->point_finish != 0) 732109998Smarkm point->meth->point_finish(point); 733109998Smarkm OPENSSL_free(point); 734109998Smarkm } 735109998Smarkm 736109998Smarkm 737109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point) 738109998Smarkm { 739109998Smarkm if (!point) return; 740109998Smarkm 741109998Smarkm if (point->meth->point_clear_finish != 0) 742109998Smarkm point->meth->point_clear_finish(point); 743238405Sjkim else if (point->meth->point_finish != 0) 744109998Smarkm point->meth->point_finish(point); 745109998Smarkm OPENSSL_cleanse(point, sizeof *point); 746109998Smarkm OPENSSL_free(point); 747109998Smarkm } 748109998Smarkm 749109998Smarkm 750109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 751109998Smarkm { 752109998Smarkm if (dest->meth->point_copy == 0) 753109998Smarkm { 754109998Smarkm ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 755109998Smarkm return 0; 756109998Smarkm } 757109998Smarkm if (dest->meth != src->meth) 758109998Smarkm { 759109998Smarkm ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 760109998Smarkm return 0; 761109998Smarkm } 762109998Smarkm if (dest == src) 763109998Smarkm return 1; 764109998Smarkm return dest->meth->point_copy(dest, src); 765109998Smarkm } 766109998Smarkm 767109998Smarkm 768160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 769160814Ssimon { 770160814Ssimon EC_POINT *t; 771160814Ssimon int r; 772160814Ssimon 773160814Ssimon if (a == NULL) return NULL; 774160814Ssimon 775160814Ssimon t = EC_POINT_new(group); 776160814Ssimon if (t == NULL) return(NULL); 777160814Ssimon r = EC_POINT_copy(t, a); 778160814Ssimon if (!r) 779160814Ssimon { 780160814Ssimon EC_POINT_free(t); 781160814Ssimon return NULL; 782160814Ssimon } 783160814Ssimon else return t; 784160814Ssimon } 785160814Ssimon 786160814Ssimon 787109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 788109998Smarkm { 789109998Smarkm return point->meth; 790109998Smarkm } 791109998Smarkm 792109998Smarkm 793109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 794109998Smarkm { 795109998Smarkm if (group->meth->point_set_to_infinity == 0) 796109998Smarkm { 797109998Smarkm ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 798109998Smarkm return 0; 799109998Smarkm } 800109998Smarkm if (group->meth != point->meth) 801109998Smarkm { 802109998Smarkm ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 803109998Smarkm return 0; 804109998Smarkm } 805109998Smarkm return group->meth->point_set_to_infinity(group, point); 806109998Smarkm } 807109998Smarkm 808109998Smarkm 809109998Smarkmint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 810109998Smarkm const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) 811109998Smarkm { 812109998Smarkm if (group->meth->point_set_Jprojective_coordinates_GFp == 0) 813109998Smarkm { 814109998Smarkm ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 815109998Smarkm return 0; 816109998Smarkm } 817109998Smarkm if (group->meth != point->meth) 818109998Smarkm { 819109998Smarkm ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 820109998Smarkm return 0; 821109998Smarkm } 822109998Smarkm return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); 823109998Smarkm } 824109998Smarkm 825109998Smarkm 826109998Smarkmint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 827109998Smarkm BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) 828109998Smarkm { 829109998Smarkm if (group->meth->point_get_Jprojective_coordinates_GFp == 0) 830109998Smarkm { 831109998Smarkm ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 832109998Smarkm return 0; 833109998Smarkm } 834109998Smarkm if (group->meth != point->meth) 835109998Smarkm { 836109998Smarkm ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 837109998Smarkm return 0; 838109998Smarkm } 839109998Smarkm return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); 840109998Smarkm } 841109998Smarkm 842109998Smarkm 843109998Smarkmint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 844109998Smarkm const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 845109998Smarkm { 846160814Ssimon if (group->meth->point_set_affine_coordinates == 0) 847109998Smarkm { 848109998Smarkm ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 849109998Smarkm return 0; 850109998Smarkm } 851109998Smarkm if (group->meth != point->meth) 852109998Smarkm { 853109998Smarkm ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 854109998Smarkm return 0; 855109998Smarkm } 856160814Ssimon return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 857109998Smarkm } 858109998Smarkm 859238405Sjkim#ifndef OPENSSL_NO_EC2M 860160814Ssimonint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, 861160814Ssimon const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 862160814Ssimon { 863160814Ssimon if (group->meth->point_set_affine_coordinates == 0) 864160814Ssimon { 865160814Ssimon ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 866160814Ssimon return 0; 867160814Ssimon } 868160814Ssimon if (group->meth != point->meth) 869160814Ssimon { 870160814Ssimon ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); 871160814Ssimon return 0; 872160814Ssimon } 873160814Ssimon return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 874160814Ssimon } 875238405Sjkim#endif 876160814Ssimon 877109998Smarkmint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 878109998Smarkm BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 879109998Smarkm { 880160814Ssimon if (group->meth->point_get_affine_coordinates == 0) 881109998Smarkm { 882109998Smarkm ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 883109998Smarkm return 0; 884109998Smarkm } 885109998Smarkm if (group->meth != point->meth) 886109998Smarkm { 887109998Smarkm ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 888109998Smarkm return 0; 889109998Smarkm } 890160814Ssimon return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 891109998Smarkm } 892109998Smarkm 893238405Sjkim#ifndef OPENSSL_NO_EC2M 894160814Ssimonint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, 895160814Ssimon BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 896160814Ssimon { 897160814Ssimon if (group->meth->point_get_affine_coordinates == 0) 898160814Ssimon { 899160814Ssimon ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 900160814Ssimon return 0; 901160814Ssimon } 902160814Ssimon if (group->meth != point->meth) 903160814Ssimon { 904160814Ssimon ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); 905160814Ssimon return 0; 906160814Ssimon } 907160814Ssimon return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 908160814Ssimon } 909238405Sjkim#endif 910160814Ssimon 911109998Smarkmint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 912109998Smarkm { 913109998Smarkm if (group->meth->add == 0) 914109998Smarkm { 915109998Smarkm ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 916109998Smarkm return 0; 917109998Smarkm } 918109998Smarkm if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth)) 919109998Smarkm { 920109998Smarkm ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 921109998Smarkm return 0; 922109998Smarkm } 923109998Smarkm return group->meth->add(group, r, a, b, ctx); 924109998Smarkm } 925109998Smarkm 926109998Smarkm 927109998Smarkmint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) 928109998Smarkm { 929109998Smarkm if (group->meth->dbl == 0) 930109998Smarkm { 931109998Smarkm ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 932109998Smarkm return 0; 933109998Smarkm } 934109998Smarkm if ((group->meth != r->meth) || (r->meth != a->meth)) 935109998Smarkm { 936109998Smarkm ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 937109998Smarkm return 0; 938109998Smarkm } 939109998Smarkm return group->meth->dbl(group, r, a, ctx); 940109998Smarkm } 941109998Smarkm 942109998Smarkm 943109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 944109998Smarkm { 945279264Sdelphij if (group->meth->invert == 0) 946109998Smarkm { 947160814Ssimon ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 948109998Smarkm return 0; 949109998Smarkm } 950109998Smarkm if (group->meth != a->meth) 951109998Smarkm { 952160814Ssimon ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 953109998Smarkm return 0; 954109998Smarkm } 955109998Smarkm return group->meth->invert(group, a, ctx); 956109998Smarkm } 957109998Smarkm 958109998Smarkm 959109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 960109998Smarkm { 961109998Smarkm if (group->meth->is_at_infinity == 0) 962109998Smarkm { 963109998Smarkm ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 964109998Smarkm return 0; 965109998Smarkm } 966109998Smarkm if (group->meth != point->meth) 967109998Smarkm { 968109998Smarkm ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 969109998Smarkm return 0; 970109998Smarkm } 971109998Smarkm return group->meth->is_at_infinity(group, point); 972109998Smarkm } 973109998Smarkm 974109998Smarkm 975109998Smarkmint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) 976109998Smarkm { 977109998Smarkm if (group->meth->is_on_curve == 0) 978109998Smarkm { 979109998Smarkm ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 980109998Smarkm return 0; 981109998Smarkm } 982109998Smarkm if (group->meth != point->meth) 983109998Smarkm { 984109998Smarkm ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 985109998Smarkm return 0; 986109998Smarkm } 987109998Smarkm return group->meth->is_on_curve(group, point, ctx); 988109998Smarkm } 989109998Smarkm 990109998Smarkm 991109998Smarkmint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 992109998Smarkm { 993109998Smarkm if (group->meth->point_cmp == 0) 994109998Smarkm { 995109998Smarkm ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 996279264Sdelphij return -1; 997109998Smarkm } 998109998Smarkm if ((group->meth != a->meth) || (a->meth != b->meth)) 999109998Smarkm { 1000109998Smarkm ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 1001279264Sdelphij return -1; 1002109998Smarkm } 1003109998Smarkm return group->meth->point_cmp(group, a, b, ctx); 1004109998Smarkm } 1005109998Smarkm 1006109998Smarkm 1007109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 1008109998Smarkm { 1009109998Smarkm if (group->meth->make_affine == 0) 1010109998Smarkm { 1011109998Smarkm ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1012109998Smarkm return 0; 1013109998Smarkm } 1014109998Smarkm if (group->meth != point->meth) 1015109998Smarkm { 1016109998Smarkm ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1017109998Smarkm return 0; 1018109998Smarkm } 1019109998Smarkm return group->meth->make_affine(group, point, ctx); 1020109998Smarkm } 1021109998Smarkm 1022109998Smarkm 1023109998Smarkmint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) 1024109998Smarkm { 1025109998Smarkm size_t i; 1026109998Smarkm 1027109998Smarkm if (group->meth->points_make_affine == 0) 1028109998Smarkm { 1029109998Smarkm ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1030109998Smarkm return 0; 1031109998Smarkm } 1032109998Smarkm for (i = 0; i < num; i++) 1033109998Smarkm { 1034109998Smarkm if (group->meth != points[i]->meth) 1035109998Smarkm { 1036109998Smarkm ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1037109998Smarkm return 0; 1038109998Smarkm } 1039109998Smarkm } 1040109998Smarkm return group->meth->points_make_affine(group, num, points, ctx); 1041109998Smarkm } 1042160814Ssimon 1043160814Ssimon 1044160814Ssimon/* Functions for point multiplication. 1045160814Ssimon * 1046160814Ssimon * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c; 1047160814Ssimon * otherwise we dispatch through methods. 1048160814Ssimon */ 1049160814Ssimon 1050160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1051160814Ssimon size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) 1052160814Ssimon { 1053160814Ssimon if (group->meth->mul == 0) 1054160814Ssimon /* use default */ 1055160814Ssimon return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1056160814Ssimon 1057160814Ssimon return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1058160814Ssimon } 1059160814Ssimon 1060160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1061160814Ssimon const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1062160814Ssimon { 1063160814Ssimon /* just a convenient interface to EC_POINTs_mul() */ 1064160814Ssimon 1065160814Ssimon const EC_POINT *points[1]; 1066160814Ssimon const BIGNUM *scalars[1]; 1067160814Ssimon 1068160814Ssimon points[0] = point; 1069160814Ssimon scalars[0] = p_scalar; 1070160814Ssimon 1071160814Ssimon return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx); 1072160814Ssimon } 1073160814Ssimon 1074160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1075160814Ssimon { 1076160814Ssimon if (group->meth->mul == 0) 1077160814Ssimon /* use default */ 1078160814Ssimon return ec_wNAF_precompute_mult(group, ctx); 1079160814Ssimon 1080160814Ssimon if (group->meth->precompute_mult != 0) 1081160814Ssimon return group->meth->precompute_mult(group, ctx); 1082160814Ssimon else 1083160814Ssimon return 1; /* nothing to do, so report success */ 1084160814Ssimon } 1085160814Ssimon 1086160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1087160814Ssimon { 1088160814Ssimon if (group->meth->mul == 0) 1089160814Ssimon /* use default */ 1090160814Ssimon return ec_wNAF_have_precompute_mult(group); 1091160814Ssimon 1092160814Ssimon if (group->meth->have_precompute_mult != 0) 1093160814Ssimon return group->meth->have_precompute_mult(group); 1094160814Ssimon else 1095160814Ssimon return 0; /* cannot tell whether precomputation has been performed */ 1096160814Ssimon } 1097