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 13296341Sdelphij * 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. 60296341Sdelphij * 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/* functions for EC_GROUP objects */ 74109998Smarkm 75109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 76296341Sdelphij{ 77296341Sdelphij EC_GROUP *ret; 78109998Smarkm 79296341Sdelphij if (meth == NULL) { 80296341Sdelphij ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); 81296341Sdelphij return NULL; 82296341Sdelphij } 83296341Sdelphij if (meth->group_init == 0) { 84296341Sdelphij ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 85296341Sdelphij return NULL; 86296341Sdelphij } 87109998Smarkm 88296341Sdelphij ret = OPENSSL_malloc(sizeof *ret); 89296341Sdelphij if (ret == NULL) { 90296341Sdelphij ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); 91296341Sdelphij return NULL; 92296341Sdelphij } 93109998Smarkm 94296341Sdelphij ret->meth = meth; 95109998Smarkm 96296341Sdelphij ret->extra_data = NULL; 97160814Ssimon 98296341Sdelphij ret->generator = NULL; 99296341Sdelphij BN_init(&ret->order); 100296341Sdelphij BN_init(&ret->cofactor); 101160814Ssimon 102296341Sdelphij ret->curve_name = 0; 103296341Sdelphij ret->asn1_flag = 0; 104296341Sdelphij ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 105160814Ssimon 106296341Sdelphij ret->seed = NULL; 107296341Sdelphij ret->seed_len = 0; 108160814Ssimon 109296341Sdelphij if (!meth->group_init(ret)) { 110296341Sdelphij OPENSSL_free(ret); 111296341Sdelphij return NULL; 112296341Sdelphij } 113109998Smarkm 114296341Sdelphij return ret; 115296341Sdelphij} 116109998Smarkm 117109998Smarkmvoid EC_GROUP_free(EC_GROUP *group) 118296341Sdelphij{ 119296341Sdelphij if (!group) 120296341Sdelphij return; 121109998Smarkm 122296341Sdelphij if (group->meth->group_finish != 0) 123296341Sdelphij group->meth->group_finish(group); 124109998Smarkm 125296341Sdelphij EC_EX_DATA_free_all_data(&group->extra_data); 126109998Smarkm 127296341Sdelphij if (group->generator != NULL) 128296341Sdelphij EC_POINT_free(group->generator); 129296341Sdelphij BN_free(&group->order); 130296341Sdelphij BN_free(&group->cofactor); 131160814Ssimon 132296341Sdelphij if (group->seed) 133296341Sdelphij OPENSSL_free(group->seed); 134160814Ssimon 135296341Sdelphij OPENSSL_free(group); 136296341Sdelphij} 137109998Smarkm 138109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group) 139296341Sdelphij{ 140296341Sdelphij if (!group) 141296341Sdelphij return; 142109998Smarkm 143296341Sdelphij if (group->meth->group_clear_finish != 0) 144296341Sdelphij group->meth->group_clear_finish(group); 145296341Sdelphij else if (group->meth->group_finish != 0) 146296341Sdelphij group->meth->group_finish(group); 147109998Smarkm 148296341Sdelphij EC_EX_DATA_clear_free_all_data(&group->extra_data); 149109998Smarkm 150296341Sdelphij if (group->generator != NULL) 151296341Sdelphij EC_POINT_clear_free(group->generator); 152296341Sdelphij BN_clear_free(&group->order); 153296341Sdelphij BN_clear_free(&group->cofactor); 154160814Ssimon 155296341Sdelphij if (group->seed) { 156296341Sdelphij OPENSSL_cleanse(group->seed, group->seed_len); 157296341Sdelphij OPENSSL_free(group->seed); 158296341Sdelphij } 159160814Ssimon 160296341Sdelphij OPENSSL_cleanse(group, sizeof *group); 161296341Sdelphij OPENSSL_free(group); 162296341Sdelphij} 163109998Smarkm 164109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 165296341Sdelphij{ 166296341Sdelphij EC_EXTRA_DATA *d; 167160814Ssimon 168296341Sdelphij if (dest->meth->group_copy == 0) { 169296341Sdelphij ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 170296341Sdelphij return 0; 171296341Sdelphij } 172296341Sdelphij if (dest->meth != src->meth) { 173296341Sdelphij ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); 174296341Sdelphij return 0; 175296341Sdelphij } 176296341Sdelphij if (dest == src) 177296341Sdelphij return 1; 178160814Ssimon 179296341Sdelphij EC_EX_DATA_free_all_data(&dest->extra_data); 180160814Ssimon 181296341Sdelphij for (d = src->extra_data; d != NULL; d = d->next) { 182296341Sdelphij void *t = d->dup_func(d->data); 183109998Smarkm 184296341Sdelphij if (t == NULL) 185296341Sdelphij return 0; 186296341Sdelphij if (!EC_EX_DATA_set_data 187296341Sdelphij (&dest->extra_data, t, d->dup_func, d->free_func, 188296341Sdelphij d->clear_free_func)) 189296341Sdelphij return 0; 190296341Sdelphij } 191160814Ssimon 192296341Sdelphij if (src->generator != NULL) { 193296341Sdelphij if (dest->generator == NULL) { 194296341Sdelphij dest->generator = EC_POINT_new(dest); 195296341Sdelphij if (dest->generator == NULL) 196296341Sdelphij return 0; 197296341Sdelphij } 198296341Sdelphij if (!EC_POINT_copy(dest->generator, src->generator)) 199296341Sdelphij return 0; 200296341Sdelphij } else { 201296341Sdelphij /* src->generator == NULL */ 202296341Sdelphij if (dest->generator != NULL) { 203296341Sdelphij EC_POINT_clear_free(dest->generator); 204296341Sdelphij dest->generator = NULL; 205296341Sdelphij } 206296341Sdelphij } 207160814Ssimon 208296341Sdelphij if (!BN_copy(&dest->order, &src->order)) 209296341Sdelphij return 0; 210296341Sdelphij if (!BN_copy(&dest->cofactor, &src->cofactor)) 211296341Sdelphij return 0; 212109998Smarkm 213296341Sdelphij dest->curve_name = src->curve_name; 214296341Sdelphij dest->asn1_flag = src->asn1_flag; 215296341Sdelphij dest->asn1_form = src->asn1_form; 216109998Smarkm 217296341Sdelphij if (src->seed) { 218296341Sdelphij if (dest->seed) 219296341Sdelphij OPENSSL_free(dest->seed); 220296341Sdelphij dest->seed = OPENSSL_malloc(src->seed_len); 221296341Sdelphij if (dest->seed == NULL) 222296341Sdelphij return 0; 223296341Sdelphij if (!memcpy(dest->seed, src->seed, src->seed_len)) 224296341Sdelphij return 0; 225296341Sdelphij dest->seed_len = src->seed_len; 226296341Sdelphij } else { 227296341Sdelphij if (dest->seed) 228296341Sdelphij OPENSSL_free(dest->seed); 229296341Sdelphij dest->seed = NULL; 230296341Sdelphij dest->seed_len = 0; 231296341Sdelphij } 232109998Smarkm 233296341Sdelphij return dest->meth->group_copy(dest, src); 234296341Sdelphij} 235296341Sdelphij 236160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 237296341Sdelphij{ 238296341Sdelphij EC_GROUP *t = NULL; 239296341Sdelphij int ok = 0; 240160814Ssimon 241296341Sdelphij if (a == NULL) 242296341Sdelphij return NULL; 243160814Ssimon 244296341Sdelphij if ((t = EC_GROUP_new(a->meth)) == NULL) 245296341Sdelphij return (NULL); 246296341Sdelphij if (!EC_GROUP_copy(t, a)) 247296341Sdelphij goto err; 248160814Ssimon 249296341Sdelphij ok = 1; 250160814Ssimon 251296341Sdelphij err: 252296341Sdelphij if (!ok) { 253296341Sdelphij if (t) 254296341Sdelphij EC_GROUP_free(t); 255296341Sdelphij return NULL; 256296341Sdelphij } else 257296341Sdelphij return t; 258296341Sdelphij} 259160814Ssimon 260109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 261296341Sdelphij{ 262296341Sdelphij return group->meth; 263296341Sdelphij} 264109998Smarkm 265160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth) 266296341Sdelphij{ 267296341Sdelphij return meth->field_type; 268296341Sdelphij} 269160814Ssimon 270296341Sdelphijint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 271296341Sdelphij const BIGNUM *order, const BIGNUM *cofactor) 272296341Sdelphij{ 273296341Sdelphij if (generator == NULL) { 274296341Sdelphij ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 275296341Sdelphij return 0; 276296341Sdelphij } 277160814Ssimon 278296341Sdelphij if (group->generator == NULL) { 279296341Sdelphij group->generator = EC_POINT_new(group); 280296341Sdelphij if (group->generator == NULL) 281296341Sdelphij return 0; 282296341Sdelphij } 283296341Sdelphij if (!EC_POINT_copy(group->generator, generator)) 284296341Sdelphij return 0; 285160814Ssimon 286296341Sdelphij if (order != NULL) { 287296341Sdelphij if (!BN_copy(&group->order, order)) 288296341Sdelphij return 0; 289296341Sdelphij } else 290296341Sdelphij BN_zero(&group->order); 291160814Ssimon 292296341Sdelphij if (cofactor != NULL) { 293296341Sdelphij if (!BN_copy(&group->cofactor, cofactor)) 294296341Sdelphij return 0; 295296341Sdelphij } else 296296341Sdelphij BN_zero(&group->cofactor); 297160814Ssimon 298296341Sdelphij return 1; 299296341Sdelphij} 300160814Ssimon 301160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 302296341Sdelphij{ 303296341Sdelphij return group->generator; 304296341Sdelphij} 305160814Ssimon 306160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 307296341Sdelphij{ 308296341Sdelphij if (!BN_copy(order, &group->order)) 309296341Sdelphij return 0; 310160814Ssimon 311296341Sdelphij return !BN_is_zero(order); 312296341Sdelphij} 313160814Ssimon 314296341Sdelphijint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 315296341Sdelphij BN_CTX *ctx) 316296341Sdelphij{ 317296341Sdelphij if (!BN_copy(cofactor, &group->cofactor)) 318296341Sdelphij return 0; 319160814Ssimon 320296341Sdelphij return !BN_is_zero(&group->cofactor); 321296341Sdelphij} 322160814Ssimon 323160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 324296341Sdelphij{ 325296341Sdelphij group->curve_name = nid; 326296341Sdelphij} 327160814Ssimon 328160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group) 329296341Sdelphij{ 330296341Sdelphij return group->curve_name; 331296341Sdelphij} 332160814Ssimon 333160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 334296341Sdelphij{ 335296341Sdelphij group->asn1_flag = flag; 336296341Sdelphij} 337160814Ssimon 338160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 339296341Sdelphij{ 340296341Sdelphij return group->asn1_flag; 341296341Sdelphij} 342160814Ssimon 343296341Sdelphijvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 344160814Ssimon point_conversion_form_t form) 345296341Sdelphij{ 346296341Sdelphij group->asn1_form = form; 347296341Sdelphij} 348160814Ssimon 349296341Sdelphijpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 350296341Sdelphij *group) 351296341Sdelphij{ 352296341Sdelphij return group->asn1_form; 353296341Sdelphij} 354160814Ssimon 355160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 356296341Sdelphij{ 357296341Sdelphij if (group->seed) { 358296341Sdelphij OPENSSL_free(group->seed); 359296341Sdelphij group->seed = NULL; 360296341Sdelphij group->seed_len = 0; 361296341Sdelphij } 362160814Ssimon 363296341Sdelphij if (!len || !p) 364296341Sdelphij return 1; 365160814Ssimon 366296341Sdelphij if ((group->seed = OPENSSL_malloc(len)) == NULL) 367296341Sdelphij return 0; 368296341Sdelphij memcpy(group->seed, p, len); 369296341Sdelphij group->seed_len = len; 370160814Ssimon 371296341Sdelphij return len; 372296341Sdelphij} 373160814Ssimon 374160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 375296341Sdelphij{ 376296341Sdelphij return group->seed; 377296341Sdelphij} 378160814Ssimon 379160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 380296341Sdelphij{ 381296341Sdelphij return group->seed_len; 382296341Sdelphij} 383160814Ssimon 384296341Sdelphijint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 385296341Sdelphij const BIGNUM *b, BN_CTX *ctx) 386296341Sdelphij{ 387296341Sdelphij if (group->meth->group_set_curve == 0) { 388296341Sdelphij ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 389296341Sdelphij return 0; 390296341Sdelphij } 391296341Sdelphij return group->meth->group_set_curve(group, p, a, b, ctx); 392296341Sdelphij} 393160814Ssimon 394296341Sdelphijint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 395296341Sdelphij BIGNUM *b, BN_CTX *ctx) 396296341Sdelphij{ 397296341Sdelphij if (group->meth->group_get_curve == 0) { 398296341Sdelphij ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 399296341Sdelphij return 0; 400296341Sdelphij } 401296341Sdelphij return group->meth->group_get_curve(group, p, a, b, ctx); 402296341Sdelphij} 403109998Smarkm 404238405Sjkim#ifndef OPENSSL_NO_EC2M 405296341Sdelphijint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 406296341Sdelphij const BIGNUM *b, BN_CTX *ctx) 407296341Sdelphij{ 408296341Sdelphij if (group->meth->group_set_curve == 0) { 409296341Sdelphij ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, 410296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 411296341Sdelphij return 0; 412296341Sdelphij } 413296341Sdelphij return group->meth->group_set_curve(group, p, a, b, ctx); 414296341Sdelphij} 415109998Smarkm 416296341Sdelphijint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 417296341Sdelphij BIGNUM *b, BN_CTX *ctx) 418296341Sdelphij{ 419296341Sdelphij if (group->meth->group_get_curve == 0) { 420296341Sdelphij ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, 421296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 422296341Sdelphij return 0; 423296341Sdelphij } 424296341Sdelphij return group->meth->group_get_curve(group, p, a, b, ctx); 425296341Sdelphij} 426238405Sjkim#endif 427109998Smarkm 428160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group) 429296341Sdelphij{ 430296341Sdelphij if (group->meth->group_get_degree == 0) { 431296341Sdelphij ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 432296341Sdelphij return 0; 433296341Sdelphij } 434296341Sdelphij return group->meth->group_get_degree(group); 435296341Sdelphij} 436109998Smarkm 437160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 438296341Sdelphij{ 439296341Sdelphij if (group->meth->group_check_discriminant == 0) { 440296341Sdelphij ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, 441296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 442296341Sdelphij return 0; 443296341Sdelphij } 444296341Sdelphij return group->meth->group_check_discriminant(group, ctx); 445296341Sdelphij} 446109998Smarkm 447160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 448296341Sdelphij{ 449296341Sdelphij int r = 0; 450296341Sdelphij BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 451296341Sdelphij BN_CTX *ctx_new = NULL; 452160814Ssimon 453296341Sdelphij /* compare the field types */ 454296341Sdelphij if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 455296341Sdelphij EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 456296341Sdelphij return 1; 457296341Sdelphij /* compare the curve name (if present in both) */ 458296341Sdelphij if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 459296341Sdelphij EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 460296341Sdelphij return 1; 461160814Ssimon 462296341Sdelphij if (!ctx) 463296341Sdelphij ctx_new = ctx = BN_CTX_new(); 464296341Sdelphij if (!ctx) 465296341Sdelphij return -1; 466109998Smarkm 467296341Sdelphij BN_CTX_start(ctx); 468296341Sdelphij a1 = BN_CTX_get(ctx); 469296341Sdelphij a2 = BN_CTX_get(ctx); 470296341Sdelphij a3 = BN_CTX_get(ctx); 471296341Sdelphij b1 = BN_CTX_get(ctx); 472296341Sdelphij b2 = BN_CTX_get(ctx); 473296341Sdelphij b3 = BN_CTX_get(ctx); 474296341Sdelphij if (!b3) { 475296341Sdelphij BN_CTX_end(ctx); 476296341Sdelphij if (ctx_new) 477296341Sdelphij BN_CTX_free(ctx); 478296341Sdelphij return -1; 479296341Sdelphij } 480160814Ssimon 481296341Sdelphij /* 482296341Sdelphij * XXX This approach assumes that the external representation of curves 483296341Sdelphij * over the same field type is the same. 484296341Sdelphij */ 485296341Sdelphij if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 486296341Sdelphij !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 487296341Sdelphij r = 1; 488160814Ssimon 489296341Sdelphij if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 490296341Sdelphij r = 1; 491160814Ssimon 492296341Sdelphij /* XXX EC_POINT_cmp() assumes that the methods are equal */ 493296341Sdelphij if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 494296341Sdelphij EC_GROUP_get0_generator(b), ctx)) 495296341Sdelphij r = 1; 496160814Ssimon 497296341Sdelphij if (!r) { 498296341Sdelphij /* compare the order and cofactor */ 499296341Sdelphij if (!EC_GROUP_get_order(a, a1, ctx) || 500296341Sdelphij !EC_GROUP_get_order(b, b1, ctx) || 501296341Sdelphij !EC_GROUP_get_cofactor(a, a2, ctx) || 502296341Sdelphij !EC_GROUP_get_cofactor(b, b2, ctx)) { 503296341Sdelphij BN_CTX_end(ctx); 504296341Sdelphij if (ctx_new) 505296341Sdelphij BN_CTX_free(ctx); 506296341Sdelphij return -1; 507296341Sdelphij } 508296341Sdelphij if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 509296341Sdelphij r = 1; 510296341Sdelphij } 511160814Ssimon 512296341Sdelphij BN_CTX_end(ctx); 513296341Sdelphij if (ctx_new) 514296341Sdelphij BN_CTX_free(ctx); 515109998Smarkm 516296341Sdelphij return r; 517296341Sdelphij} 518109998Smarkm 519109998Smarkm/* this has 'package' visibility */ 520160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 521296341Sdelphij void *(*dup_func) (void *), 522296341Sdelphij void (*free_func) (void *), 523296341Sdelphij void (*clear_free_func) (void *)) 524296341Sdelphij{ 525296341Sdelphij EC_EXTRA_DATA *d; 526160814Ssimon 527296341Sdelphij if (ex_data == NULL) 528296341Sdelphij return 0; 529160814Ssimon 530296341Sdelphij for (d = *ex_data; d != NULL; d = d->next) { 531296341Sdelphij if (d->dup_func == dup_func && d->free_func == free_func 532296341Sdelphij && d->clear_free_func == clear_free_func) { 533296341Sdelphij ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 534296341Sdelphij return 0; 535296341Sdelphij } 536296341Sdelphij } 537109998Smarkm 538296341Sdelphij if (data == NULL) 539296341Sdelphij /* no explicit entry needed */ 540296341Sdelphij return 1; 541160814Ssimon 542296341Sdelphij d = OPENSSL_malloc(sizeof *d); 543296341Sdelphij if (d == NULL) 544296341Sdelphij return 0; 545160814Ssimon 546296341Sdelphij d->data = data; 547296341Sdelphij d->dup_func = dup_func; 548296341Sdelphij d->free_func = free_func; 549296341Sdelphij d->clear_free_func = clear_free_func; 550160814Ssimon 551296341Sdelphij d->next = *ex_data; 552296341Sdelphij *ex_data = d; 553160814Ssimon 554296341Sdelphij return 1; 555296341Sdelphij} 556109998Smarkm 557160814Ssimon/* this has 'package' visibility */ 558160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 559296341Sdelphij void *(*dup_func) (void *), 560296341Sdelphij void (*free_func) (void *), 561296341Sdelphij void (*clear_free_func) (void *)) 562296341Sdelphij{ 563296341Sdelphij const EC_EXTRA_DATA *d; 564109998Smarkm 565296341Sdelphij for (d = ex_data; d != NULL; d = d->next) { 566296341Sdelphij if (d->dup_func == dup_func && d->free_func == free_func 567296341Sdelphij && d->clear_free_func == clear_free_func) 568296341Sdelphij return d->data; 569296341Sdelphij } 570160814Ssimon 571296341Sdelphij return NULL; 572296341Sdelphij} 573296341Sdelphij 574109998Smarkm/* this has 'package' visibility */ 575160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 576296341Sdelphij void *(*dup_func) (void *), 577296341Sdelphij void (*free_func) (void *), 578296341Sdelphij void (*clear_free_func) (void *)) 579296341Sdelphij{ 580296341Sdelphij EC_EXTRA_DATA **p; 581160814Ssimon 582296341Sdelphij if (ex_data == NULL) 583296341Sdelphij return; 584160814Ssimon 585296341Sdelphij for (p = ex_data; *p != NULL; p = &((*p)->next)) { 586296341Sdelphij if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 587296341Sdelphij && (*p)->clear_free_func == clear_free_func) { 588296341Sdelphij EC_EXTRA_DATA *next = (*p)->next; 589160814Ssimon 590296341Sdelphij (*p)->free_func((*p)->data); 591296341Sdelphij OPENSSL_free(*p); 592109998Smarkm 593296341Sdelphij *p = next; 594296341Sdelphij return; 595296341Sdelphij } 596296341Sdelphij } 597296341Sdelphij} 598296341Sdelphij 599160814Ssimon/* this has 'package' visibility */ 600160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 601296341Sdelphij void *(*dup_func) (void *), 602296341Sdelphij void (*free_func) (void *), 603296341Sdelphij void (*clear_free_func) (void *)) 604296341Sdelphij{ 605296341Sdelphij EC_EXTRA_DATA **p; 606109998Smarkm 607296341Sdelphij if (ex_data == NULL) 608296341Sdelphij return; 609160814Ssimon 610296341Sdelphij for (p = ex_data; *p != NULL; p = &((*p)->next)) { 611296341Sdelphij if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 612296341Sdelphij && (*p)->clear_free_func == clear_free_func) { 613296341Sdelphij EC_EXTRA_DATA *next = (*p)->next; 614160814Ssimon 615296341Sdelphij (*p)->clear_free_func((*p)->data); 616296341Sdelphij OPENSSL_free(*p); 617160814Ssimon 618296341Sdelphij *p = next; 619296341Sdelphij return; 620296341Sdelphij } 621296341Sdelphij } 622296341Sdelphij} 623296341Sdelphij 624109998Smarkm/* this has 'package' visibility */ 625160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 626296341Sdelphij{ 627296341Sdelphij EC_EXTRA_DATA *d; 628160814Ssimon 629296341Sdelphij if (ex_data == NULL) 630296341Sdelphij return; 631160814Ssimon 632296341Sdelphij d = *ex_data; 633296341Sdelphij while (d) { 634296341Sdelphij EC_EXTRA_DATA *next = d->next; 635109998Smarkm 636296341Sdelphij d->free_func(d->data); 637296341Sdelphij OPENSSL_free(d); 638296341Sdelphij 639296341Sdelphij d = next; 640296341Sdelphij } 641296341Sdelphij *ex_data = NULL; 642296341Sdelphij} 643296341Sdelphij 644160814Ssimon/* this has 'package' visibility */ 645160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 646296341Sdelphij{ 647296341Sdelphij EC_EXTRA_DATA *d; 648109998Smarkm 649296341Sdelphij if (ex_data == NULL) 650296341Sdelphij return; 651109998Smarkm 652296341Sdelphij d = *ex_data; 653296341Sdelphij while (d) { 654296341Sdelphij EC_EXTRA_DATA *next = d->next; 655160814Ssimon 656296341Sdelphij d->clear_free_func(d->data); 657296341Sdelphij OPENSSL_free(d); 658160814Ssimon 659296341Sdelphij d = next; 660296341Sdelphij } 661296341Sdelphij *ex_data = NULL; 662296341Sdelphij} 663296341Sdelphij 664109998Smarkm/* functions for EC_POINT objects */ 665109998Smarkm 666109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group) 667296341Sdelphij{ 668296341Sdelphij EC_POINT *ret; 669109998Smarkm 670296341Sdelphij if (group == NULL) { 671296341Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 672296341Sdelphij return NULL; 673296341Sdelphij } 674296341Sdelphij if (group->meth->point_init == 0) { 675296341Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 676296341Sdelphij return NULL; 677296341Sdelphij } 678109998Smarkm 679296341Sdelphij ret = OPENSSL_malloc(sizeof *ret); 680296341Sdelphij if (ret == NULL) { 681296341Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 682296341Sdelphij return NULL; 683296341Sdelphij } 684109998Smarkm 685296341Sdelphij ret->meth = group->meth; 686109998Smarkm 687296341Sdelphij if (!ret->meth->point_init(ret)) { 688296341Sdelphij OPENSSL_free(ret); 689296341Sdelphij return NULL; 690296341Sdelphij } 691109998Smarkm 692296341Sdelphij return ret; 693296341Sdelphij} 694296341Sdelphij 695109998Smarkmvoid EC_POINT_free(EC_POINT *point) 696296341Sdelphij{ 697296341Sdelphij if (!point) 698296341Sdelphij return; 699109998Smarkm 700296341Sdelphij if (point->meth->point_finish != 0) 701296341Sdelphij point->meth->point_finish(point); 702296341Sdelphij OPENSSL_free(point); 703296341Sdelphij} 704109998Smarkm 705109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point) 706296341Sdelphij{ 707296341Sdelphij if (!point) 708296341Sdelphij return; 709109998Smarkm 710296341Sdelphij if (point->meth->point_clear_finish != 0) 711296341Sdelphij point->meth->point_clear_finish(point); 712296341Sdelphij else if (point->meth->point_finish != 0) 713296341Sdelphij point->meth->point_finish(point); 714296341Sdelphij OPENSSL_cleanse(point, sizeof *point); 715296341Sdelphij OPENSSL_free(point); 716296341Sdelphij} 717109998Smarkm 718109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 719296341Sdelphij{ 720296341Sdelphij if (dest->meth->point_copy == 0) { 721296341Sdelphij ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 722296341Sdelphij return 0; 723296341Sdelphij } 724296341Sdelphij if (dest->meth != src->meth) { 725296341Sdelphij ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 726296341Sdelphij return 0; 727296341Sdelphij } 728296341Sdelphij if (dest == src) 729296341Sdelphij return 1; 730296341Sdelphij return dest->meth->point_copy(dest, src); 731296341Sdelphij} 732109998Smarkm 733160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 734296341Sdelphij{ 735296341Sdelphij EC_POINT *t; 736296341Sdelphij int r; 737160814Ssimon 738296341Sdelphij if (a == NULL) 739296341Sdelphij return NULL; 740160814Ssimon 741296341Sdelphij t = EC_POINT_new(group); 742296341Sdelphij if (t == NULL) 743296341Sdelphij return (NULL); 744296341Sdelphij r = EC_POINT_copy(t, a); 745296341Sdelphij if (!r) { 746296341Sdelphij EC_POINT_free(t); 747296341Sdelphij return NULL; 748296341Sdelphij } else 749296341Sdelphij return t; 750296341Sdelphij} 751160814Ssimon 752109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 753296341Sdelphij{ 754296341Sdelphij return point->meth; 755296341Sdelphij} 756109998Smarkm 757109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 758296341Sdelphij{ 759296341Sdelphij if (group->meth->point_set_to_infinity == 0) { 760296341Sdelphij ECerr(EC_F_EC_POINT_SET_TO_INFINITY, 761296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 762296341Sdelphij return 0; 763296341Sdelphij } 764296341Sdelphij if (group->meth != point->meth) { 765296341Sdelphij ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 766296341Sdelphij return 0; 767296341Sdelphij } 768296341Sdelphij return group->meth->point_set_to_infinity(group, point); 769296341Sdelphij} 770109998Smarkm 771296341Sdelphijint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 772296341Sdelphij EC_POINT *point, const BIGNUM *x, 773296341Sdelphij const BIGNUM *y, const BIGNUM *z, 774296341Sdelphij BN_CTX *ctx) 775296341Sdelphij{ 776296341Sdelphij if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 777296341Sdelphij ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 778296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 779296341Sdelphij return 0; 780296341Sdelphij } 781296341Sdelphij if (group->meth != point->meth) { 782296341Sdelphij ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 783296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 784296341Sdelphij return 0; 785296341Sdelphij } 786296341Sdelphij return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, 787296341Sdelphij y, z, ctx); 788296341Sdelphij} 789109998Smarkm 790296341Sdelphijint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 791296341Sdelphij const EC_POINT *point, BIGNUM *x, 792296341Sdelphij BIGNUM *y, BIGNUM *z, 793296341Sdelphij BN_CTX *ctx) 794296341Sdelphij{ 795296341Sdelphij if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 796296341Sdelphij ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 797296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 798296341Sdelphij return 0; 799296341Sdelphij } 800296341Sdelphij if (group->meth != point->meth) { 801296341Sdelphij ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 802296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 803296341Sdelphij return 0; 804296341Sdelphij } 805296341Sdelphij return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, 806296341Sdelphij y, z, ctx); 807296341Sdelphij} 808109998Smarkm 809296341Sdelphijint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 810296341Sdelphij EC_POINT *point, const BIGNUM *x, 811296341Sdelphij const BIGNUM *y, BN_CTX *ctx) 812296341Sdelphij{ 813296341Sdelphij if (group->meth->point_set_affine_coordinates == 0) { 814296341Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 815296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 816296341Sdelphij return 0; 817296341Sdelphij } 818296341Sdelphij if (group->meth != point->meth) { 819296341Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 820296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 821296341Sdelphij return 0; 822296341Sdelphij } 823296341Sdelphij return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 824296341Sdelphij} 825109998Smarkm 826238405Sjkim#ifndef OPENSSL_NO_EC2M 827296341Sdelphijint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 828296341Sdelphij EC_POINT *point, const BIGNUM *x, 829296341Sdelphij const BIGNUM *y, BN_CTX *ctx) 830296341Sdelphij{ 831296341Sdelphij if (group->meth->point_set_affine_coordinates == 0) { 832296341Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 833296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 834296341Sdelphij return 0; 835296341Sdelphij } 836296341Sdelphij if (group->meth != point->meth) { 837296341Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 838296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 839296341Sdelphij return 0; 840296341Sdelphij } 841296341Sdelphij return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 842296341Sdelphij} 843238405Sjkim#endif 844160814Ssimon 845296341Sdelphijint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 846296341Sdelphij const EC_POINT *point, BIGNUM *x, 847296341Sdelphij BIGNUM *y, BN_CTX *ctx) 848296341Sdelphij{ 849296341Sdelphij if (group->meth->point_get_affine_coordinates == 0) { 850296341Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 851296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 852296341Sdelphij return 0; 853296341Sdelphij } 854296341Sdelphij if (group->meth != point->meth) { 855296341Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 856296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 857296341Sdelphij return 0; 858296341Sdelphij } 859296341Sdelphij return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 860296341Sdelphij} 861109998Smarkm 862238405Sjkim#ifndef OPENSSL_NO_EC2M 863296341Sdelphijint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 864296341Sdelphij const EC_POINT *point, BIGNUM *x, 865296341Sdelphij BIGNUM *y, BN_CTX *ctx) 866296341Sdelphij{ 867296341Sdelphij if (group->meth->point_get_affine_coordinates == 0) { 868296341Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 869296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 870296341Sdelphij return 0; 871296341Sdelphij } 872296341Sdelphij if (group->meth != point->meth) { 873296341Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 874296341Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 875296341Sdelphij return 0; 876296341Sdelphij } 877296341Sdelphij return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 878296341Sdelphij} 879238405Sjkim#endif 880160814Ssimon 881296341Sdelphijint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 882296341Sdelphij const EC_POINT *b, BN_CTX *ctx) 883296341Sdelphij{ 884296341Sdelphij if (group->meth->add == 0) { 885296341Sdelphij ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 886296341Sdelphij return 0; 887296341Sdelphij } 888296341Sdelphij if ((group->meth != r->meth) || (r->meth != a->meth) 889296341Sdelphij || (a->meth != b->meth)) { 890296341Sdelphij ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 891296341Sdelphij return 0; 892296341Sdelphij } 893296341Sdelphij return group->meth->add(group, r, a, b, ctx); 894296341Sdelphij} 895109998Smarkm 896296341Sdelphijint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 897296341Sdelphij BN_CTX *ctx) 898296341Sdelphij{ 899296341Sdelphij if (group->meth->dbl == 0) { 900296341Sdelphij ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 901296341Sdelphij return 0; 902296341Sdelphij } 903296341Sdelphij if ((group->meth != r->meth) || (r->meth != a->meth)) { 904296341Sdelphij ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 905296341Sdelphij return 0; 906296341Sdelphij } 907296341Sdelphij return group->meth->dbl(group, r, a, ctx); 908296341Sdelphij} 909109998Smarkm 910109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 911296341Sdelphij{ 912296341Sdelphij if (group->meth->invert == 0) { 913296341Sdelphij ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 914296341Sdelphij return 0; 915296341Sdelphij } 916296341Sdelphij if (group->meth != a->meth) { 917296341Sdelphij ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 918296341Sdelphij return 0; 919296341Sdelphij } 920296341Sdelphij return group->meth->invert(group, a, ctx); 921296341Sdelphij} 922109998Smarkm 923109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 924296341Sdelphij{ 925296341Sdelphij if (group->meth->is_at_infinity == 0) { 926296341Sdelphij ECerr(EC_F_EC_POINT_IS_AT_INFINITY, 927296341Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 928296341Sdelphij return 0; 929296341Sdelphij } 930296341Sdelphij if (group->meth != point->meth) { 931296341Sdelphij ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 932296341Sdelphij return 0; 933296341Sdelphij } 934296341Sdelphij return group->meth->is_at_infinity(group, point); 935296341Sdelphij} 936109998Smarkm 937284295Sdelphij/* 938284295Sdelphij * Check whether an EC_POINT is on the curve or not. Note that the return 939284295Sdelphij * value for this function should NOT be treated as a boolean. Return values: 940284295Sdelphij * 1: The point is on the curve 941284295Sdelphij * 0: The point is not on the curve 942284295Sdelphij * -1: An error occurred 943284295Sdelphij */ 944284295Sdelphijint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 945284295Sdelphij BN_CTX *ctx) 946296341Sdelphij{ 947296341Sdelphij if (group->meth->is_on_curve == 0) { 948296341Sdelphij ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 949296341Sdelphij return 0; 950296341Sdelphij } 951296341Sdelphij if (group->meth != point->meth) { 952296341Sdelphij ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 953296341Sdelphij return 0; 954296341Sdelphij } 955296341Sdelphij return group->meth->is_on_curve(group, point, ctx); 956296341Sdelphij} 957109998Smarkm 958296341Sdelphijint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 959296341Sdelphij BN_CTX *ctx) 960296341Sdelphij{ 961296341Sdelphij if (group->meth->point_cmp == 0) { 962296341Sdelphij ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 963296341Sdelphij return -1; 964296341Sdelphij } 965296341Sdelphij if ((group->meth != a->meth) || (a->meth != b->meth)) { 966296341Sdelphij ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 967296341Sdelphij return -1; 968296341Sdelphij } 969296341Sdelphij return group->meth->point_cmp(group, a, b, ctx); 970296341Sdelphij} 971109998Smarkm 972109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 973296341Sdelphij{ 974296341Sdelphij if (group->meth->make_affine == 0) { 975296341Sdelphij ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 976296341Sdelphij return 0; 977296341Sdelphij } 978296341Sdelphij if (group->meth != point->meth) { 979296341Sdelphij ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 980296341Sdelphij return 0; 981296341Sdelphij } 982296341Sdelphij return group->meth->make_affine(group, point, ctx); 983296341Sdelphij} 984109998Smarkm 985296341Sdelphijint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 986296341Sdelphij EC_POINT *points[], BN_CTX *ctx) 987296341Sdelphij{ 988296341Sdelphij size_t i; 989109998Smarkm 990296341Sdelphij if (group->meth->points_make_affine == 0) { 991296341Sdelphij ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 992296341Sdelphij return 0; 993296341Sdelphij } 994296341Sdelphij for (i = 0; i < num; i++) { 995296341Sdelphij if (group->meth != points[i]->meth) { 996296341Sdelphij ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 997296341Sdelphij return 0; 998296341Sdelphij } 999296341Sdelphij } 1000296341Sdelphij return group->meth->points_make_affine(group, num, points, ctx); 1001296341Sdelphij} 1002109998Smarkm 1003296341Sdelphij/* 1004296341Sdelphij * Functions for point multiplication. If group->meth->mul is 0, we use the 1005296341Sdelphij * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1006296341Sdelphij * methods. 1007160814Ssimon */ 1008160814Ssimon 1009160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1010296341Sdelphij size_t num, const EC_POINT *points[], 1011296341Sdelphij const BIGNUM *scalars[], BN_CTX *ctx) 1012296341Sdelphij{ 1013296341Sdelphij if (group->meth->mul == 0) 1014296341Sdelphij /* use default */ 1015296341Sdelphij return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1016160814Ssimon 1017296341Sdelphij return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1018296341Sdelphij} 1019160814Ssimon 1020160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1021296341Sdelphij const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1022296341Sdelphij{ 1023296341Sdelphij /* just a convenient interface to EC_POINTs_mul() */ 1024160814Ssimon 1025296341Sdelphij const EC_POINT *points[1]; 1026296341Sdelphij const BIGNUM *scalars[1]; 1027160814Ssimon 1028296341Sdelphij points[0] = point; 1029296341Sdelphij scalars[0] = p_scalar; 1030160814Ssimon 1031296341Sdelphij return EC_POINTs_mul(group, r, g_scalar, 1032296341Sdelphij (point != NULL 1033296341Sdelphij && p_scalar != NULL), points, scalars, ctx); 1034296341Sdelphij} 1035160814Ssimon 1036160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1037296341Sdelphij{ 1038296341Sdelphij if (group->meth->mul == 0) 1039296341Sdelphij /* use default */ 1040296341Sdelphij return ec_wNAF_precompute_mult(group, ctx); 1041160814Ssimon 1042296341Sdelphij if (group->meth->precompute_mult != 0) 1043296341Sdelphij return group->meth->precompute_mult(group, ctx); 1044296341Sdelphij else 1045296341Sdelphij return 1; /* nothing to do, so report success */ 1046296341Sdelphij} 1047160814Ssimon 1048160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1049296341Sdelphij{ 1050296341Sdelphij if (group->meth->mul == 0) 1051296341Sdelphij /* use default */ 1052296341Sdelphij return ec_wNAF_have_precompute_mult(group); 1053160814Ssimon 1054296341Sdelphij if (group->meth->have_precompute_mult != 0) 1055296341Sdelphij return group->meth->have_precompute_mult(group); 1056296341Sdelphij else 1057296341Sdelphij return 0; /* cannot tell whether precomputation has 1058296341Sdelphij * been performed */ 1059296341Sdelphij} 1060