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 13296465Sdelphij * 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. 60296465Sdelphij * 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 71109998Smarkmstatic const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; 72109998Smarkm 73109998Smarkm/* functions for EC_GROUP objects */ 74109998Smarkm 75109998SmarkmEC_GROUP *EC_GROUP_new(const EC_METHOD *meth) 76296465Sdelphij{ 77296465Sdelphij EC_GROUP *ret; 78109998Smarkm 79296465Sdelphij if (meth == NULL) { 80296465Sdelphij ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER); 81296465Sdelphij return NULL; 82296465Sdelphij } 83296465Sdelphij if (meth->group_init == 0) { 84296465Sdelphij ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 85296465Sdelphij return NULL; 86296465Sdelphij } 87109998Smarkm 88296465Sdelphij ret = OPENSSL_malloc(sizeof *ret); 89296465Sdelphij if (ret == NULL) { 90296465Sdelphij ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); 91296465Sdelphij return NULL; 92296465Sdelphij } 93109998Smarkm 94296465Sdelphij ret->meth = meth; 95109998Smarkm 96296465Sdelphij ret->extra_data = NULL; 97160814Ssimon 98296465Sdelphij ret->generator = NULL; 99296465Sdelphij BN_init(&ret->order); 100296465Sdelphij BN_init(&ret->cofactor); 101160814Ssimon 102296465Sdelphij ret->curve_name = 0; 103296465Sdelphij ret->asn1_flag = 0; 104296465Sdelphij ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 105160814Ssimon 106296465Sdelphij ret->seed = NULL; 107296465Sdelphij ret->seed_len = 0; 108160814Ssimon 109296465Sdelphij if (!meth->group_init(ret)) { 110296465Sdelphij OPENSSL_free(ret); 111296465Sdelphij return NULL; 112296465Sdelphij } 113109998Smarkm 114296465Sdelphij return ret; 115296465Sdelphij} 116109998Smarkm 117109998Smarkmvoid EC_GROUP_free(EC_GROUP *group) 118296465Sdelphij{ 119296465Sdelphij if (!group) 120296465Sdelphij return; 121109998Smarkm 122296465Sdelphij if (group->meth->group_finish != 0) 123296465Sdelphij group->meth->group_finish(group); 124109998Smarkm 125296465Sdelphij EC_EX_DATA_free_all_data(&group->extra_data); 126109998Smarkm 127296465Sdelphij if (group->generator != NULL) 128296465Sdelphij EC_POINT_free(group->generator); 129296465Sdelphij BN_free(&group->order); 130296465Sdelphij BN_free(&group->cofactor); 131160814Ssimon 132296465Sdelphij if (group->seed) 133296465Sdelphij OPENSSL_free(group->seed); 134160814Ssimon 135296465Sdelphij OPENSSL_free(group); 136296465Sdelphij} 137109998Smarkm 138109998Smarkmvoid EC_GROUP_clear_free(EC_GROUP *group) 139296465Sdelphij{ 140296465Sdelphij if (!group) 141296465Sdelphij return; 142109998Smarkm 143296465Sdelphij if (group->meth->group_clear_finish != 0) 144296465Sdelphij group->meth->group_clear_finish(group); 145296465Sdelphij else if (group->meth->group_finish != 0) 146296465Sdelphij group->meth->group_finish(group); 147109998Smarkm 148296465Sdelphij EC_EX_DATA_clear_free_all_data(&group->extra_data); 149109998Smarkm 150296465Sdelphij if (group->generator != NULL) 151296465Sdelphij EC_POINT_clear_free(group->generator); 152296465Sdelphij BN_clear_free(&group->order); 153296465Sdelphij BN_clear_free(&group->cofactor); 154160814Ssimon 155296465Sdelphij if (group->seed) { 156296465Sdelphij OPENSSL_cleanse(group->seed, group->seed_len); 157296465Sdelphij OPENSSL_free(group->seed); 158296465Sdelphij } 159160814Ssimon 160296465Sdelphij OPENSSL_cleanse(group, sizeof *group); 161296465Sdelphij OPENSSL_free(group); 162296465Sdelphij} 163109998Smarkm 164109998Smarkmint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 165296465Sdelphij{ 166296465Sdelphij EC_EXTRA_DATA *d; 167160814Ssimon 168296465Sdelphij if (dest->meth->group_copy == 0) { 169296465Sdelphij ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 170296465Sdelphij return 0; 171296465Sdelphij } 172296465Sdelphij if (dest->meth != src->meth) { 173296465Sdelphij ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS); 174296465Sdelphij return 0; 175296465Sdelphij } 176296465Sdelphij if (dest == src) 177296465Sdelphij return 1; 178160814Ssimon 179296465Sdelphij EC_EX_DATA_free_all_data(&dest->extra_data); 180160814Ssimon 181296465Sdelphij for (d = src->extra_data; d != NULL; d = d->next) { 182296465Sdelphij void *t = d->dup_func(d->data); 183109998Smarkm 184296465Sdelphij if (t == NULL) 185296465Sdelphij return 0; 186296465Sdelphij if (!EC_EX_DATA_set_data 187296465Sdelphij (&dest->extra_data, t, d->dup_func, d->free_func, 188296465Sdelphij d->clear_free_func)) 189296465Sdelphij return 0; 190296465Sdelphij } 191160814Ssimon 192296465Sdelphij if (src->generator != NULL) { 193296465Sdelphij if (dest->generator == NULL) { 194296465Sdelphij dest->generator = EC_POINT_new(dest); 195296465Sdelphij if (dest->generator == NULL) 196296465Sdelphij return 0; 197296465Sdelphij } 198296465Sdelphij if (!EC_POINT_copy(dest->generator, src->generator)) 199296465Sdelphij return 0; 200296465Sdelphij } else { 201296465Sdelphij /* src->generator == NULL */ 202296465Sdelphij if (dest->generator != NULL) { 203296465Sdelphij EC_POINT_clear_free(dest->generator); 204296465Sdelphij dest->generator = NULL; 205296465Sdelphij } 206296465Sdelphij } 207160814Ssimon 208296465Sdelphij if (!BN_copy(&dest->order, &src->order)) 209296465Sdelphij return 0; 210296465Sdelphij if (!BN_copy(&dest->cofactor, &src->cofactor)) 211296465Sdelphij return 0; 212109998Smarkm 213296465Sdelphij dest->curve_name = src->curve_name; 214296465Sdelphij dest->asn1_flag = src->asn1_flag; 215296465Sdelphij dest->asn1_form = src->asn1_form; 216109998Smarkm 217296465Sdelphij if (src->seed) { 218296465Sdelphij if (dest->seed) 219296465Sdelphij OPENSSL_free(dest->seed); 220296465Sdelphij dest->seed = OPENSSL_malloc(src->seed_len); 221296465Sdelphij if (dest->seed == NULL) 222296465Sdelphij return 0; 223296465Sdelphij if (!memcpy(dest->seed, src->seed, src->seed_len)) 224296465Sdelphij return 0; 225296465Sdelphij dest->seed_len = src->seed_len; 226296465Sdelphij } else { 227296465Sdelphij if (dest->seed) 228296465Sdelphij OPENSSL_free(dest->seed); 229296465Sdelphij dest->seed = NULL; 230296465Sdelphij dest->seed_len = 0; 231296465Sdelphij } 232109998Smarkm 233296465Sdelphij return dest->meth->group_copy(dest, src); 234296465Sdelphij} 235296465Sdelphij 236160814SsimonEC_GROUP *EC_GROUP_dup(const EC_GROUP *a) 237296465Sdelphij{ 238296465Sdelphij EC_GROUP *t = NULL; 239296465Sdelphij int ok = 0; 240160814Ssimon 241296465Sdelphij if (a == NULL) 242296465Sdelphij return NULL; 243160814Ssimon 244296465Sdelphij if ((t = EC_GROUP_new(a->meth)) == NULL) 245296465Sdelphij return (NULL); 246296465Sdelphij if (!EC_GROUP_copy(t, a)) 247296465Sdelphij goto err; 248160814Ssimon 249296465Sdelphij ok = 1; 250160814Ssimon 251296465Sdelphij err: 252296465Sdelphij if (!ok) { 253296465Sdelphij if (t) 254296465Sdelphij EC_GROUP_free(t); 255296465Sdelphij return NULL; 256296465Sdelphij } else 257296465Sdelphij return t; 258296465Sdelphij} 259160814Ssimon 260109998Smarkmconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 261296465Sdelphij{ 262296465Sdelphij return group->meth; 263296465Sdelphij} 264109998Smarkm 265160814Ssimonint EC_METHOD_get_field_type(const EC_METHOD *meth) 266296465Sdelphij{ 267296465Sdelphij return meth->field_type; 268296465Sdelphij} 269160814Ssimon 270296465Sdelphijint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 271296465Sdelphij const BIGNUM *order, const BIGNUM *cofactor) 272296465Sdelphij{ 273296465Sdelphij if (generator == NULL) { 274296465Sdelphij ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 275296465Sdelphij return 0; 276296465Sdelphij } 277160814Ssimon 278296465Sdelphij if (group->generator == NULL) { 279296465Sdelphij group->generator = EC_POINT_new(group); 280296465Sdelphij if (group->generator == NULL) 281296465Sdelphij return 0; 282296465Sdelphij } 283296465Sdelphij if (!EC_POINT_copy(group->generator, generator)) 284296465Sdelphij return 0; 285160814Ssimon 286296465Sdelphij if (order != NULL) { 287296465Sdelphij if (!BN_copy(&group->order, order)) 288296465Sdelphij return 0; 289296465Sdelphij } else 290296465Sdelphij BN_zero(&group->order); 291160814Ssimon 292296465Sdelphij if (cofactor != NULL) { 293296465Sdelphij if (!BN_copy(&group->cofactor, cofactor)) 294296465Sdelphij return 0; 295296465Sdelphij } else 296296465Sdelphij BN_zero(&group->cofactor); 297160814Ssimon 298296465Sdelphij return 1; 299296465Sdelphij} 300160814Ssimon 301160814Ssimonconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 302296465Sdelphij{ 303296465Sdelphij return group->generator; 304296465Sdelphij} 305160814Ssimon 306160814Ssimonint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 307296465Sdelphij{ 308296465Sdelphij if (!BN_copy(order, &group->order)) 309296465Sdelphij return 0; 310160814Ssimon 311296465Sdelphij return !BN_is_zero(order); 312296465Sdelphij} 313160814Ssimon 314296465Sdelphijint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 315296465Sdelphij BN_CTX *ctx) 316296465Sdelphij{ 317296465Sdelphij if (!BN_copy(cofactor, &group->cofactor)) 318296465Sdelphij return 0; 319160814Ssimon 320296465Sdelphij return !BN_is_zero(&group->cofactor); 321296465Sdelphij} 322160814Ssimon 323160814Ssimonvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 324296465Sdelphij{ 325296465Sdelphij group->curve_name = nid; 326296465Sdelphij} 327160814Ssimon 328160814Ssimonint EC_GROUP_get_curve_name(const EC_GROUP *group) 329296465Sdelphij{ 330296465Sdelphij return group->curve_name; 331296465Sdelphij} 332160814Ssimon 333160814Ssimonvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 334296465Sdelphij{ 335296465Sdelphij group->asn1_flag = flag; 336296465Sdelphij} 337160814Ssimon 338160814Ssimonint EC_GROUP_get_asn1_flag(const EC_GROUP *group) 339296465Sdelphij{ 340296465Sdelphij return group->asn1_flag; 341296465Sdelphij} 342160814Ssimon 343296465Sdelphijvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group, 344160814Ssimon point_conversion_form_t form) 345296465Sdelphij{ 346296465Sdelphij group->asn1_form = form; 347296465Sdelphij} 348160814Ssimon 349296465Sdelphijpoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 350296465Sdelphij *group) 351296465Sdelphij{ 352296465Sdelphij return group->asn1_form; 353296465Sdelphij} 354160814Ssimon 355160814Ssimonsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 356296465Sdelphij{ 357296465Sdelphij if (group->seed) { 358296465Sdelphij OPENSSL_free(group->seed); 359296465Sdelphij group->seed = NULL; 360296465Sdelphij group->seed_len = 0; 361296465Sdelphij } 362160814Ssimon 363296465Sdelphij if (!len || !p) 364296465Sdelphij return 1; 365160814Ssimon 366296465Sdelphij if ((group->seed = OPENSSL_malloc(len)) == NULL) 367296465Sdelphij return 0; 368296465Sdelphij memcpy(group->seed, p, len); 369296465Sdelphij group->seed_len = len; 370160814Ssimon 371296465Sdelphij return len; 372296465Sdelphij} 373160814Ssimon 374160814Ssimonunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 375296465Sdelphij{ 376296465Sdelphij return group->seed; 377296465Sdelphij} 378160814Ssimon 379160814Ssimonsize_t EC_GROUP_get_seed_len(const EC_GROUP *group) 380296465Sdelphij{ 381296465Sdelphij return group->seed_len; 382296465Sdelphij} 383160814Ssimon 384296465Sdelphijint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 385296465Sdelphij const BIGNUM *b, BN_CTX *ctx) 386296465Sdelphij{ 387296465Sdelphij if (group->meth->group_set_curve == 0) { 388296465Sdelphij ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 389296465Sdelphij return 0; 390296465Sdelphij } 391296465Sdelphij return group->meth->group_set_curve(group, p, a, b, ctx); 392296465Sdelphij} 393160814Ssimon 394296465Sdelphijint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 395296465Sdelphij BIGNUM *b, BN_CTX *ctx) 396296465Sdelphij{ 397296465Sdelphij if (group->meth->group_get_curve == 0) { 398296465Sdelphij ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 399296465Sdelphij return 0; 400296465Sdelphij } 401296465Sdelphij return group->meth->group_get_curve(group, p, a, b, ctx); 402296465Sdelphij} 403109998Smarkm 404296465Sdelphijint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 405296465Sdelphij const BIGNUM *b, BN_CTX *ctx) 406296465Sdelphij{ 407296465Sdelphij if (group->meth->group_set_curve == 0) { 408296465Sdelphij ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, 409296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 410296465Sdelphij return 0; 411296465Sdelphij } 412296465Sdelphij return group->meth->group_set_curve(group, p, a, b, ctx); 413296465Sdelphij} 414109998Smarkm 415296465Sdelphijint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 416296465Sdelphij BIGNUM *b, BN_CTX *ctx) 417296465Sdelphij{ 418296465Sdelphij if (group->meth->group_get_curve == 0) { 419296465Sdelphij ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, 420296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 421296465Sdelphij return 0; 422296465Sdelphij } 423296465Sdelphij return group->meth->group_get_curve(group, p, a, b, ctx); 424296465Sdelphij} 425109998Smarkm 426160814Ssimonint EC_GROUP_get_degree(const EC_GROUP *group) 427296465Sdelphij{ 428296465Sdelphij if (group->meth->group_get_degree == 0) { 429296465Sdelphij ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 430296465Sdelphij return 0; 431296465Sdelphij } 432296465Sdelphij return group->meth->group_get_degree(group); 433296465Sdelphij} 434109998Smarkm 435160814Ssimonint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 436296465Sdelphij{ 437296465Sdelphij if (group->meth->group_check_discriminant == 0) { 438296465Sdelphij ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, 439296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 440296465Sdelphij return 0; 441296465Sdelphij } 442296465Sdelphij return group->meth->group_check_discriminant(group, ctx); 443296465Sdelphij} 444109998Smarkm 445160814Ssimonint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 446296465Sdelphij{ 447296465Sdelphij int r = 0; 448296465Sdelphij BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 449296465Sdelphij BN_CTX *ctx_new = NULL; 450160814Ssimon 451296465Sdelphij /* compare the field types */ 452296465Sdelphij if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 453296465Sdelphij EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 454296465Sdelphij return 1; 455296465Sdelphij /* compare the curve name (if present in both) */ 456296465Sdelphij if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 457296465Sdelphij EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 458296465Sdelphij return 1; 459160814Ssimon 460296465Sdelphij if (!ctx) 461296465Sdelphij ctx_new = ctx = BN_CTX_new(); 462296465Sdelphij if (!ctx) 463296465Sdelphij return -1; 464109998Smarkm 465296465Sdelphij BN_CTX_start(ctx); 466296465Sdelphij a1 = BN_CTX_get(ctx); 467296465Sdelphij a2 = BN_CTX_get(ctx); 468296465Sdelphij a3 = BN_CTX_get(ctx); 469296465Sdelphij b1 = BN_CTX_get(ctx); 470296465Sdelphij b2 = BN_CTX_get(ctx); 471296465Sdelphij b3 = BN_CTX_get(ctx); 472296465Sdelphij if (!b3) { 473296465Sdelphij BN_CTX_end(ctx); 474296465Sdelphij if (ctx_new) 475296465Sdelphij BN_CTX_free(ctx); 476296465Sdelphij return -1; 477296465Sdelphij } 478160814Ssimon 479296465Sdelphij /* 480296465Sdelphij * XXX This approach assumes that the external representation of curves 481296465Sdelphij * over the same field type is the same. 482296465Sdelphij */ 483296465Sdelphij if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 484296465Sdelphij !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 485296465Sdelphij r = 1; 486160814Ssimon 487296465Sdelphij if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 488296465Sdelphij r = 1; 489160814Ssimon 490296465Sdelphij /* XXX EC_POINT_cmp() assumes that the methods are equal */ 491296465Sdelphij if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 492296465Sdelphij EC_GROUP_get0_generator(b), ctx)) 493296465Sdelphij r = 1; 494160814Ssimon 495296465Sdelphij if (!r) { 496296465Sdelphij /* compare the order and cofactor */ 497296465Sdelphij if (!EC_GROUP_get_order(a, a1, ctx) || 498296465Sdelphij !EC_GROUP_get_order(b, b1, ctx) || 499296465Sdelphij !EC_GROUP_get_cofactor(a, a2, ctx) || 500296465Sdelphij !EC_GROUP_get_cofactor(b, b2, ctx)) { 501296465Sdelphij BN_CTX_end(ctx); 502296465Sdelphij if (ctx_new) 503296465Sdelphij BN_CTX_free(ctx); 504296465Sdelphij return -1; 505296465Sdelphij } 506296465Sdelphij if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 507296465Sdelphij r = 1; 508296465Sdelphij } 509160814Ssimon 510296465Sdelphij BN_CTX_end(ctx); 511296465Sdelphij if (ctx_new) 512296465Sdelphij BN_CTX_free(ctx); 513109998Smarkm 514296465Sdelphij return r; 515296465Sdelphij} 516109998Smarkm 517109998Smarkm/* this has 'package' visibility */ 518160814Ssimonint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 519296465Sdelphij void *(*dup_func) (void *), 520296465Sdelphij void (*free_func) (void *), 521296465Sdelphij void (*clear_free_func) (void *)) 522296465Sdelphij{ 523296465Sdelphij EC_EXTRA_DATA *d; 524160814Ssimon 525296465Sdelphij if (ex_data == NULL) 526296465Sdelphij return 0; 527160814Ssimon 528296465Sdelphij for (d = *ex_data; d != NULL; d = d->next) { 529296465Sdelphij if (d->dup_func == dup_func && d->free_func == free_func 530296465Sdelphij && d->clear_free_func == clear_free_func) { 531296465Sdelphij ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 532296465Sdelphij return 0; 533296465Sdelphij } 534296465Sdelphij } 535109998Smarkm 536296465Sdelphij if (data == NULL) 537296465Sdelphij /* no explicit entry needed */ 538296465Sdelphij return 1; 539160814Ssimon 540296465Sdelphij d = OPENSSL_malloc(sizeof *d); 541296465Sdelphij if (d == NULL) 542296465Sdelphij return 0; 543160814Ssimon 544296465Sdelphij d->data = data; 545296465Sdelphij d->dup_func = dup_func; 546296465Sdelphij d->free_func = free_func; 547296465Sdelphij d->clear_free_func = clear_free_func; 548160814Ssimon 549296465Sdelphij d->next = *ex_data; 550296465Sdelphij *ex_data = d; 551160814Ssimon 552296465Sdelphij return 1; 553296465Sdelphij} 554109998Smarkm 555160814Ssimon/* this has 'package' visibility */ 556160814Ssimonvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 557296465Sdelphij void *(*dup_func) (void *), 558296465Sdelphij void (*free_func) (void *), 559296465Sdelphij void (*clear_free_func) (void *)) 560296465Sdelphij{ 561296465Sdelphij const EC_EXTRA_DATA *d; 562109998Smarkm 563296465Sdelphij for (d = ex_data; d != NULL; d = d->next) { 564296465Sdelphij if (d->dup_func == dup_func && d->free_func == free_func 565296465Sdelphij && d->clear_free_func == clear_free_func) 566296465Sdelphij return d->data; 567296465Sdelphij } 568160814Ssimon 569296465Sdelphij return NULL; 570296465Sdelphij} 571296465Sdelphij 572109998Smarkm/* this has 'package' visibility */ 573160814Ssimonvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 574296465Sdelphij void *(*dup_func) (void *), 575296465Sdelphij void (*free_func) (void *), 576296465Sdelphij void (*clear_free_func) (void *)) 577296465Sdelphij{ 578296465Sdelphij EC_EXTRA_DATA **p; 579160814Ssimon 580296465Sdelphij if (ex_data == NULL) 581296465Sdelphij return; 582160814Ssimon 583296465Sdelphij for (p = ex_data; *p != NULL; p = &((*p)->next)) { 584296465Sdelphij if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 585296465Sdelphij && (*p)->clear_free_func == clear_free_func) { 586296465Sdelphij EC_EXTRA_DATA *next = (*p)->next; 587160814Ssimon 588296465Sdelphij (*p)->free_func((*p)->data); 589296465Sdelphij OPENSSL_free(*p); 590109998Smarkm 591296465Sdelphij *p = next; 592296465Sdelphij return; 593296465Sdelphij } 594296465Sdelphij } 595296465Sdelphij} 596296465Sdelphij 597160814Ssimon/* this has 'package' visibility */ 598160814Ssimonvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 599296465Sdelphij void *(*dup_func) (void *), 600296465Sdelphij void (*free_func) (void *), 601296465Sdelphij void (*clear_free_func) (void *)) 602296465Sdelphij{ 603296465Sdelphij EC_EXTRA_DATA **p; 604109998Smarkm 605296465Sdelphij if (ex_data == NULL) 606296465Sdelphij return; 607160814Ssimon 608296465Sdelphij for (p = ex_data; *p != NULL; p = &((*p)->next)) { 609296465Sdelphij if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 610296465Sdelphij && (*p)->clear_free_func == clear_free_func) { 611296465Sdelphij EC_EXTRA_DATA *next = (*p)->next; 612160814Ssimon 613296465Sdelphij (*p)->clear_free_func((*p)->data); 614296465Sdelphij OPENSSL_free(*p); 615160814Ssimon 616296465Sdelphij *p = next; 617296465Sdelphij return; 618296465Sdelphij } 619296465Sdelphij } 620296465Sdelphij} 621296465Sdelphij 622109998Smarkm/* this has 'package' visibility */ 623160814Ssimonvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 624296465Sdelphij{ 625296465Sdelphij EC_EXTRA_DATA *d; 626160814Ssimon 627296465Sdelphij if (ex_data == NULL) 628296465Sdelphij return; 629160814Ssimon 630296465Sdelphij d = *ex_data; 631296465Sdelphij while (d) { 632296465Sdelphij EC_EXTRA_DATA *next = d->next; 633109998Smarkm 634296465Sdelphij d->free_func(d->data); 635296465Sdelphij OPENSSL_free(d); 636296465Sdelphij 637296465Sdelphij d = next; 638296465Sdelphij } 639296465Sdelphij *ex_data = NULL; 640296465Sdelphij} 641296465Sdelphij 642160814Ssimon/* this has 'package' visibility */ 643160814Ssimonvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 644296465Sdelphij{ 645296465Sdelphij EC_EXTRA_DATA *d; 646109998Smarkm 647296465Sdelphij if (ex_data == NULL) 648296465Sdelphij return; 649109998Smarkm 650296465Sdelphij d = *ex_data; 651296465Sdelphij while (d) { 652296465Sdelphij EC_EXTRA_DATA *next = d->next; 653160814Ssimon 654296465Sdelphij d->clear_free_func(d->data); 655296465Sdelphij OPENSSL_free(d); 656160814Ssimon 657296465Sdelphij d = next; 658296465Sdelphij } 659296465Sdelphij *ex_data = NULL; 660296465Sdelphij} 661296465Sdelphij 662109998Smarkm/* functions for EC_POINT objects */ 663109998Smarkm 664109998SmarkmEC_POINT *EC_POINT_new(const EC_GROUP *group) 665296465Sdelphij{ 666296465Sdelphij EC_POINT *ret; 667109998Smarkm 668296465Sdelphij if (group == NULL) { 669296465Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 670296465Sdelphij return NULL; 671296465Sdelphij } 672296465Sdelphij if (group->meth->point_init == 0) { 673296465Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 674296465Sdelphij return NULL; 675296465Sdelphij } 676109998Smarkm 677296465Sdelphij ret = OPENSSL_malloc(sizeof *ret); 678296465Sdelphij if (ret == NULL) { 679296465Sdelphij ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 680296465Sdelphij return NULL; 681296465Sdelphij } 682109998Smarkm 683296465Sdelphij ret->meth = group->meth; 684109998Smarkm 685296465Sdelphij if (!ret->meth->point_init(ret)) { 686296465Sdelphij OPENSSL_free(ret); 687296465Sdelphij return NULL; 688296465Sdelphij } 689109998Smarkm 690296465Sdelphij return ret; 691296465Sdelphij} 692296465Sdelphij 693109998Smarkmvoid EC_POINT_free(EC_POINT *point) 694296465Sdelphij{ 695296465Sdelphij if (!point) 696296465Sdelphij return; 697109998Smarkm 698296465Sdelphij if (point->meth->point_finish != 0) 699296465Sdelphij point->meth->point_finish(point); 700296465Sdelphij OPENSSL_free(point); 701296465Sdelphij} 702109998Smarkm 703109998Smarkmvoid EC_POINT_clear_free(EC_POINT *point) 704296465Sdelphij{ 705296465Sdelphij if (!point) 706296465Sdelphij return; 707109998Smarkm 708296465Sdelphij if (point->meth->point_clear_finish != 0) 709296465Sdelphij point->meth->point_clear_finish(point); 710296465Sdelphij else if (point->meth != NULL && point->meth->point_finish != 0) 711296465Sdelphij point->meth->point_finish(point); 712296465Sdelphij OPENSSL_cleanse(point, sizeof *point); 713296465Sdelphij OPENSSL_free(point); 714296465Sdelphij} 715109998Smarkm 716109998Smarkmint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 717296465Sdelphij{ 718296465Sdelphij if (dest->meth->point_copy == 0) { 719296465Sdelphij ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 720296465Sdelphij return 0; 721296465Sdelphij } 722296465Sdelphij if (dest->meth != src->meth) { 723296465Sdelphij ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 724296465Sdelphij return 0; 725296465Sdelphij } 726296465Sdelphij if (dest == src) 727296465Sdelphij return 1; 728296465Sdelphij return dest->meth->point_copy(dest, src); 729296465Sdelphij} 730109998Smarkm 731160814SsimonEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 732296465Sdelphij{ 733296465Sdelphij EC_POINT *t; 734296465Sdelphij int r; 735160814Ssimon 736296465Sdelphij if (a == NULL) 737296465Sdelphij return NULL; 738160814Ssimon 739296465Sdelphij t = EC_POINT_new(group); 740296465Sdelphij if (t == NULL) 741296465Sdelphij return (NULL); 742296465Sdelphij r = EC_POINT_copy(t, a); 743296465Sdelphij if (!r) { 744296465Sdelphij EC_POINT_free(t); 745296465Sdelphij return NULL; 746296465Sdelphij } else 747296465Sdelphij return t; 748296465Sdelphij} 749160814Ssimon 750109998Smarkmconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 751296465Sdelphij{ 752296465Sdelphij return point->meth; 753296465Sdelphij} 754109998Smarkm 755109998Smarkmint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 756296465Sdelphij{ 757296465Sdelphij if (group->meth->point_set_to_infinity == 0) { 758296465Sdelphij ECerr(EC_F_EC_POINT_SET_TO_INFINITY, 759296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 760296465Sdelphij return 0; 761296465Sdelphij } 762296465Sdelphij if (group->meth != point->meth) { 763296465Sdelphij ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 764296465Sdelphij return 0; 765296465Sdelphij } 766296465Sdelphij return group->meth->point_set_to_infinity(group, point); 767296465Sdelphij} 768109998Smarkm 769296465Sdelphijint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 770296465Sdelphij EC_POINT *point, const BIGNUM *x, 771296465Sdelphij const BIGNUM *y, const BIGNUM *z, 772296465Sdelphij BN_CTX *ctx) 773296465Sdelphij{ 774296465Sdelphij if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 775296465Sdelphij ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 776296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 777296465Sdelphij return 0; 778296465Sdelphij } 779296465Sdelphij if (group->meth != point->meth) { 780296465Sdelphij ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 781296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 782296465Sdelphij return 0; 783296465Sdelphij } 784296465Sdelphij return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, 785296465Sdelphij y, z, ctx); 786296465Sdelphij} 787109998Smarkm 788296465Sdelphijint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 789296465Sdelphij const EC_POINT *point, BIGNUM *x, 790296465Sdelphij BIGNUM *y, BIGNUM *z, 791296465Sdelphij BN_CTX *ctx) 792296465Sdelphij{ 793296465Sdelphij if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 794296465Sdelphij ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 795296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 796296465Sdelphij return 0; 797296465Sdelphij } 798296465Sdelphij if (group->meth != point->meth) { 799296465Sdelphij ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 800296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 801296465Sdelphij return 0; 802296465Sdelphij } 803296465Sdelphij return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, 804296465Sdelphij y, z, ctx); 805296465Sdelphij} 806109998Smarkm 807296465Sdelphijint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 808296465Sdelphij EC_POINT *point, const BIGNUM *x, 809296465Sdelphij const BIGNUM *y, BN_CTX *ctx) 810296465Sdelphij{ 811296465Sdelphij if (group->meth->point_set_affine_coordinates == 0) { 812296465Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 813296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 814296465Sdelphij return 0; 815296465Sdelphij } 816296465Sdelphij if (group->meth != point->meth) { 817296465Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 818296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 819296465Sdelphij return 0; 820296465Sdelphij } 821296465Sdelphij return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 822296465Sdelphij} 823109998Smarkm 824296465Sdelphijint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 825296465Sdelphij EC_POINT *point, const BIGNUM *x, 826296465Sdelphij const BIGNUM *y, BN_CTX *ctx) 827296465Sdelphij{ 828296465Sdelphij if (group->meth->point_set_affine_coordinates == 0) { 829296465Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 830296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 831296465Sdelphij return 0; 832296465Sdelphij } 833296465Sdelphij if (group->meth != point->meth) { 834296465Sdelphij ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 835296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 836296465Sdelphij return 0; 837296465Sdelphij } 838296465Sdelphij return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 839296465Sdelphij} 840109998Smarkm 841296465Sdelphijint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 842296465Sdelphij const EC_POINT *point, BIGNUM *x, 843296465Sdelphij BIGNUM *y, BN_CTX *ctx) 844296465Sdelphij{ 845296465Sdelphij if (group->meth->point_get_affine_coordinates == 0) { 846296465Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 847296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 848296465Sdelphij return 0; 849296465Sdelphij } 850296465Sdelphij if (group->meth != point->meth) { 851296465Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 852296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 853296465Sdelphij return 0; 854296465Sdelphij } 855296465Sdelphij return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 856296465Sdelphij} 857109998Smarkm 858296465Sdelphijint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 859296465Sdelphij const EC_POINT *point, BIGNUM *x, 860296465Sdelphij BIGNUM *y, BN_CTX *ctx) 861296465Sdelphij{ 862296465Sdelphij if (group->meth->point_get_affine_coordinates == 0) { 863296465Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 864296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 865296465Sdelphij return 0; 866296465Sdelphij } 867296465Sdelphij if (group->meth != point->meth) { 868296465Sdelphij ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 869296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 870296465Sdelphij return 0; 871296465Sdelphij } 872296465Sdelphij return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 873296465Sdelphij} 874109998Smarkm 875296465Sdelphijint EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, 876296465Sdelphij EC_POINT *point, const BIGNUM *x, 877296465Sdelphij int y_bit, BN_CTX *ctx) 878296465Sdelphij{ 879296465Sdelphij if (group->meth->point_set_compressed_coordinates == 0) { 880296465Sdelphij ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 881296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 882296465Sdelphij return 0; 883296465Sdelphij } 884296465Sdelphij if (group->meth != point->meth) { 885296465Sdelphij ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, 886296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 887296465Sdelphij return 0; 888296465Sdelphij } 889296465Sdelphij return group->meth->point_set_compressed_coordinates(group, point, x, 890296465Sdelphij y_bit, ctx); 891296465Sdelphij} 892109998Smarkm 893296465Sdelphijint EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, 894296465Sdelphij EC_POINT *point, const BIGNUM *x, 895296465Sdelphij int y_bit, BN_CTX *ctx) 896296465Sdelphij{ 897296465Sdelphij if (group->meth->point_set_compressed_coordinates == 0) { 898296465Sdelphij ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 899296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 900296465Sdelphij return 0; 901296465Sdelphij } 902296465Sdelphij if (group->meth != point->meth) { 903296465Sdelphij ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, 904296465Sdelphij EC_R_INCOMPATIBLE_OBJECTS); 905296465Sdelphij return 0; 906296465Sdelphij } 907296465Sdelphij return group->meth->point_set_compressed_coordinates(group, point, x, 908296465Sdelphij y_bit, ctx); 909296465Sdelphij} 910160814Ssimon 911296465Sdelphijsize_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, 912296465Sdelphij point_conversion_form_t form, unsigned char *buf, 913296465Sdelphij size_t len, BN_CTX *ctx) 914296465Sdelphij{ 915296465Sdelphij if (group->meth->point2oct == 0) { 916296465Sdelphij ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 917296465Sdelphij return 0; 918296465Sdelphij } 919296465Sdelphij if (group->meth != point->meth) { 920296465Sdelphij ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS); 921296465Sdelphij return 0; 922296465Sdelphij } 923296465Sdelphij return group->meth->point2oct(group, point, form, buf, len, ctx); 924296465Sdelphij} 925160814Ssimon 926109998Smarkmint EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, 927296465Sdelphij const unsigned char *buf, size_t len, BN_CTX *ctx) 928296465Sdelphij{ 929296465Sdelphij if (group->meth->oct2point == 0) { 930296465Sdelphij ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 931296465Sdelphij return 0; 932296465Sdelphij } 933296465Sdelphij if (group->meth != point->meth) { 934296465Sdelphij ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS); 935296465Sdelphij return 0; 936296465Sdelphij } 937296465Sdelphij return group->meth->oct2point(group, point, buf, len, ctx); 938296465Sdelphij} 939109998Smarkm 940296465Sdelphijint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 941296465Sdelphij const EC_POINT *b, BN_CTX *ctx) 942296465Sdelphij{ 943296465Sdelphij if (group->meth->add == 0) { 944296465Sdelphij ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 945296465Sdelphij return 0; 946296465Sdelphij } 947296465Sdelphij if ((group->meth != r->meth) || (r->meth != a->meth) 948296465Sdelphij || (a->meth != b->meth)) { 949296465Sdelphij ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 950296465Sdelphij return 0; 951296465Sdelphij } 952296465Sdelphij return group->meth->add(group, r, a, b, ctx); 953296465Sdelphij} 954109998Smarkm 955296465Sdelphijint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 956296465Sdelphij BN_CTX *ctx) 957296465Sdelphij{ 958296465Sdelphij if (group->meth->dbl == 0) { 959296465Sdelphij ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 960296465Sdelphij return 0; 961296465Sdelphij } 962296465Sdelphij if ((group->meth != r->meth) || (r->meth != a->meth)) { 963296465Sdelphij ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 964296465Sdelphij return 0; 965296465Sdelphij } 966296465Sdelphij return group->meth->dbl(group, r, a, ctx); 967296465Sdelphij} 968109998Smarkm 969109998Smarkmint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 970296465Sdelphij{ 971296465Sdelphij if (group->meth->invert == 0) { 972296465Sdelphij ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 973296465Sdelphij return 0; 974296465Sdelphij } 975296465Sdelphij if (group->meth != a->meth) { 976296465Sdelphij ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 977296465Sdelphij return 0; 978296465Sdelphij } 979296465Sdelphij return group->meth->invert(group, a, ctx); 980296465Sdelphij} 981109998Smarkm 982109998Smarkmint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 983296465Sdelphij{ 984296465Sdelphij if (group->meth->is_at_infinity == 0) { 985296465Sdelphij ECerr(EC_F_EC_POINT_IS_AT_INFINITY, 986296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 987296465Sdelphij return 0; 988296465Sdelphij } 989296465Sdelphij if (group->meth != point->meth) { 990296465Sdelphij ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 991296465Sdelphij return 0; 992296465Sdelphij } 993296465Sdelphij return group->meth->is_at_infinity(group, point); 994296465Sdelphij} 995109998Smarkm 996284295Sdelphij/* 997284295Sdelphij * Check whether an EC_POINT is on the curve or not. Note that the return 998284295Sdelphij * value for this function should NOT be treated as a boolean. Return values: 999284295Sdelphij * 1: The point is on the curve 1000284295Sdelphij * 0: The point is not on the curve 1001284295Sdelphij * -1: An error occurred 1002284295Sdelphij */ 1003284295Sdelphijint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 1004284295Sdelphij BN_CTX *ctx) 1005296465Sdelphij{ 1006296465Sdelphij if (group->meth->is_on_curve == 0) { 1007296465Sdelphij ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1008296465Sdelphij return 0; 1009296465Sdelphij } 1010296465Sdelphij if (group->meth != point->meth) { 1011296465Sdelphij ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 1012296465Sdelphij return 0; 1013296465Sdelphij } 1014296465Sdelphij return group->meth->is_on_curve(group, point, ctx); 1015296465Sdelphij} 1016109998Smarkm 1017296465Sdelphijint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 1018296465Sdelphij BN_CTX *ctx) 1019296465Sdelphij{ 1020296465Sdelphij if (group->meth->point_cmp == 0) { 1021296465Sdelphij ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1022296465Sdelphij return -1; 1023296465Sdelphij } 1024296465Sdelphij if ((group->meth != a->meth) || (a->meth != b->meth)) { 1025296465Sdelphij ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 1026296465Sdelphij return -1; 1027296465Sdelphij } 1028296465Sdelphij return group->meth->point_cmp(group, a, b, ctx); 1029296465Sdelphij} 1030109998Smarkm 1031109998Smarkmint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 1032296465Sdelphij{ 1033296465Sdelphij if (group->meth->make_affine == 0) { 1034296465Sdelphij ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1035296465Sdelphij return 0; 1036296465Sdelphij } 1037296465Sdelphij if (group->meth != point->meth) { 1038296465Sdelphij ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1039296465Sdelphij return 0; 1040296465Sdelphij } 1041296465Sdelphij return group->meth->make_affine(group, point, ctx); 1042296465Sdelphij} 1043109998Smarkm 1044296465Sdelphijint EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 1045296465Sdelphij EC_POINT *points[], BN_CTX *ctx) 1046296465Sdelphij{ 1047296465Sdelphij size_t i; 1048109998Smarkm 1049296465Sdelphij if (group->meth->points_make_affine == 0) { 1050296465Sdelphij ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1051296465Sdelphij return 0; 1052296465Sdelphij } 1053296465Sdelphij for (i = 0; i < num; i++) { 1054296465Sdelphij if (group->meth != points[i]->meth) { 1055296465Sdelphij ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1056296465Sdelphij return 0; 1057296465Sdelphij } 1058296465Sdelphij } 1059296465Sdelphij return group->meth->points_make_affine(group, num, points, ctx); 1060296465Sdelphij} 1061109998Smarkm 1062296465Sdelphij/* 1063296465Sdelphij * Functions for point multiplication. If group->meth->mul is 0, we use the 1064296465Sdelphij * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1065296465Sdelphij * methods. 1066160814Ssimon */ 1067160814Ssimon 1068160814Ssimonint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1069296465Sdelphij size_t num, const EC_POINT *points[], 1070296465Sdelphij const BIGNUM *scalars[], BN_CTX *ctx) 1071296465Sdelphij{ 1072296465Sdelphij if (group->meth->mul == 0) 1073296465Sdelphij /* use default */ 1074296465Sdelphij return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1075160814Ssimon 1076296465Sdelphij return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1077296465Sdelphij} 1078160814Ssimon 1079160814Ssimonint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1080296465Sdelphij const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1081296465Sdelphij{ 1082296465Sdelphij /* just a convenient interface to EC_POINTs_mul() */ 1083160814Ssimon 1084296465Sdelphij const EC_POINT *points[1]; 1085296465Sdelphij const BIGNUM *scalars[1]; 1086160814Ssimon 1087296465Sdelphij points[0] = point; 1088296465Sdelphij scalars[0] = p_scalar; 1089160814Ssimon 1090296465Sdelphij return EC_POINTs_mul(group, r, g_scalar, 1091296465Sdelphij (point != NULL 1092296465Sdelphij && p_scalar != NULL), points, scalars, ctx); 1093296465Sdelphij} 1094160814Ssimon 1095160814Ssimonint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1096296465Sdelphij{ 1097296465Sdelphij if (group->meth->mul == 0) 1098296465Sdelphij /* use default */ 1099296465Sdelphij return ec_wNAF_precompute_mult(group, ctx); 1100160814Ssimon 1101296465Sdelphij if (group->meth->precompute_mult != 0) 1102296465Sdelphij return group->meth->precompute_mult(group, ctx); 1103296465Sdelphij else 1104296465Sdelphij return 1; /* nothing to do, so report success */ 1105296465Sdelphij} 1106160814Ssimon 1107160814Ssimonint EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1108296465Sdelphij{ 1109296465Sdelphij if (group->meth->mul == 0) 1110296465Sdelphij /* use default */ 1111296465Sdelphij return ec_wNAF_have_precompute_mult(group); 1112160814Ssimon 1113296465Sdelphij if (group->meth->have_precompute_mult != 0) 1114296465Sdelphij return group->meth->have_precompute_mult(group); 1115296465Sdelphij else 1116296465Sdelphij return 0; /* cannot tell whether precomputation has 1117296465Sdelphij * been performed */ 1118296465Sdelphij} 1119