1160814Ssimon/* crypto/ec/ec2_smpl.c */ 2160814Ssimon/* ==================================================================== 3160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 4160814Ssimon * 5160814Ssimon * The Elliptic Curve Public-Key Crypto Library (ECC Code) included 6160814Ssimon * herein is developed by SUN MICROSYSTEMS, INC., and is contributed 7160814Ssimon * to the OpenSSL project. 8160814Ssimon * 9160814Ssimon * The ECC Code is licensed pursuant to the OpenSSL open source 10160814Ssimon * license provided below. 11160814Ssimon * 12160814Ssimon * The software is originally written by Sheueling Chang Shantz and 13160814Ssimon * Douglas Stebila of Sun Microsystems Laboratories. 14160814Ssimon * 15160814Ssimon */ 16160814Ssimon/* ==================================================================== 17160814Ssimon * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 18160814Ssimon * 19160814Ssimon * Redistribution and use in source and binary forms, with or without 20160814Ssimon * modification, are permitted provided that the following conditions 21160814Ssimon * are met: 22160814Ssimon * 23160814Ssimon * 1. Redistributions of source code must retain the above copyright 24296465Sdelphij * notice, this list of conditions and the following disclaimer. 25160814Ssimon * 26160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 27160814Ssimon * notice, this list of conditions and the following disclaimer in 28160814Ssimon * the documentation and/or other materials provided with the 29160814Ssimon * distribution. 30160814Ssimon * 31160814Ssimon * 3. All advertising materials mentioning features or use of this 32160814Ssimon * software must display the following acknowledgment: 33160814Ssimon * "This product includes software developed by the OpenSSL Project 34160814Ssimon * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 35160814Ssimon * 36160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 37160814Ssimon * endorse or promote products derived from this software without 38160814Ssimon * prior written permission. For written permission, please contact 39160814Ssimon * openssl-core@openssl.org. 40160814Ssimon * 41160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 42160814Ssimon * nor may "OpenSSL" appear in their names without prior written 43160814Ssimon * permission of the OpenSSL Project. 44160814Ssimon * 45160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 46160814Ssimon * acknowledgment: 47160814Ssimon * "This product includes software developed by the OpenSSL Project 48160814Ssimon * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 49160814Ssimon * 50160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 51160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 54160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 61160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 62160814Ssimon * ==================================================================== 63160814Ssimon * 64160814Ssimon * This product includes cryptographic software written by Eric Young 65160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 66160814Ssimon * Hudson (tjh@cryptsoft.com). 67160814Ssimon * 68160814Ssimon */ 69160814Ssimon 70160814Ssimon#include <openssl/err.h> 71160814Ssimon 72160814Ssimon#include "ec_lcl.h" 73160814Ssimon 74160814Ssimonconst EC_METHOD *EC_GF2m_simple_method(void) 75296465Sdelphij{ 76296465Sdelphij static const EC_METHOD ret = { 77296465Sdelphij NID_X9_62_characteristic_two_field, 78296465Sdelphij ec_GF2m_simple_group_init, 79296465Sdelphij ec_GF2m_simple_group_finish, 80296465Sdelphij ec_GF2m_simple_group_clear_finish, 81296465Sdelphij ec_GF2m_simple_group_copy, 82296465Sdelphij ec_GF2m_simple_group_set_curve, 83296465Sdelphij ec_GF2m_simple_group_get_curve, 84296465Sdelphij ec_GF2m_simple_group_get_degree, 85296465Sdelphij ec_GF2m_simple_group_check_discriminant, 86296465Sdelphij ec_GF2m_simple_point_init, 87296465Sdelphij ec_GF2m_simple_point_finish, 88296465Sdelphij ec_GF2m_simple_point_clear_finish, 89296465Sdelphij ec_GF2m_simple_point_copy, 90296465Sdelphij ec_GF2m_simple_point_set_to_infinity, 91296465Sdelphij 0 /* set_Jprojective_coordinates_GFp */ , 92296465Sdelphij 0 /* get_Jprojective_coordinates_GFp */ , 93296465Sdelphij ec_GF2m_simple_point_set_affine_coordinates, 94296465Sdelphij ec_GF2m_simple_point_get_affine_coordinates, 95296465Sdelphij ec_GF2m_simple_set_compressed_coordinates, 96296465Sdelphij ec_GF2m_simple_point2oct, 97296465Sdelphij ec_GF2m_simple_oct2point, 98296465Sdelphij ec_GF2m_simple_add, 99296465Sdelphij ec_GF2m_simple_dbl, 100296465Sdelphij ec_GF2m_simple_invert, 101296465Sdelphij ec_GF2m_simple_is_at_infinity, 102296465Sdelphij ec_GF2m_simple_is_on_curve, 103296465Sdelphij ec_GF2m_simple_cmp, 104296465Sdelphij ec_GF2m_simple_make_affine, 105296465Sdelphij ec_GF2m_simple_points_make_affine, 106160814Ssimon 107296465Sdelphij /* 108296465Sdelphij * the following three method functions are defined in ec2_mult.c 109296465Sdelphij */ 110296465Sdelphij ec_GF2m_simple_mul, 111296465Sdelphij ec_GF2m_precompute_mult, 112296465Sdelphij ec_GF2m_have_precompute_mult, 113160814Ssimon 114296465Sdelphij ec_GF2m_simple_field_mul, 115296465Sdelphij ec_GF2m_simple_field_sqr, 116296465Sdelphij ec_GF2m_simple_field_div, 117296465Sdelphij 0 /* field_encode */ , 118296465Sdelphij 0 /* field_decode */ , 119296465Sdelphij 0 /* field_set_to_one */ 120296465Sdelphij }; 121160814Ssimon 122296465Sdelphij return &ret; 123296465Sdelphij} 124160814Ssimon 125296465Sdelphij/* 126296465Sdelphij * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members 127296465Sdelphij * are handled by EC_GROUP_new. 128160814Ssimon */ 129160814Ssimonint ec_GF2m_simple_group_init(EC_GROUP *group) 130296465Sdelphij{ 131296465Sdelphij BN_init(&group->field); 132296465Sdelphij BN_init(&group->a); 133296465Sdelphij BN_init(&group->b); 134296465Sdelphij return 1; 135296465Sdelphij} 136160814Ssimon 137296465Sdelphij/* 138296465Sdelphij * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are 139296465Sdelphij * handled by EC_GROUP_free. 140160814Ssimon */ 141160814Ssimonvoid ec_GF2m_simple_group_finish(EC_GROUP *group) 142296465Sdelphij{ 143296465Sdelphij BN_free(&group->field); 144296465Sdelphij BN_free(&group->a); 145296465Sdelphij BN_free(&group->b); 146296465Sdelphij} 147160814Ssimon 148296465Sdelphij/* 149296465Sdelphij * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other 150296465Sdelphij * members are handled by EC_GROUP_clear_free. 151160814Ssimon */ 152160814Ssimonvoid ec_GF2m_simple_group_clear_finish(EC_GROUP *group) 153296465Sdelphij{ 154296465Sdelphij BN_clear_free(&group->field); 155296465Sdelphij BN_clear_free(&group->a); 156296465Sdelphij BN_clear_free(&group->b); 157296465Sdelphij group->poly[0] = 0; 158296465Sdelphij group->poly[1] = 0; 159296465Sdelphij group->poly[2] = 0; 160296465Sdelphij group->poly[3] = 0; 161296465Sdelphij group->poly[4] = 0; 162296465Sdelphij} 163160814Ssimon 164296465Sdelphij/* 165296465Sdelphij * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are 166296465Sdelphij * handled by EC_GROUP_copy. 167160814Ssimon */ 168160814Ssimonint ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) 169296465Sdelphij{ 170296465Sdelphij int i; 171296465Sdelphij if (!BN_copy(&dest->field, &src->field)) 172296465Sdelphij return 0; 173296465Sdelphij if (!BN_copy(&dest->a, &src->a)) 174296465Sdelphij return 0; 175296465Sdelphij if (!BN_copy(&dest->b, &src->b)) 176296465Sdelphij return 0; 177296465Sdelphij dest->poly[0] = src->poly[0]; 178296465Sdelphij dest->poly[1] = src->poly[1]; 179296465Sdelphij dest->poly[2] = src->poly[2]; 180296465Sdelphij dest->poly[3] = src->poly[3]; 181296465Sdelphij dest->poly[4] = src->poly[4]; 182296465Sdelphij if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) 183296465Sdelphij == NULL) 184296465Sdelphij return 0; 185296465Sdelphij if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) 186296465Sdelphij == NULL) 187296465Sdelphij return 0; 188296465Sdelphij for (i = dest->a.top; i < dest->a.dmax; i++) 189296465Sdelphij dest->a.d[i] = 0; 190296465Sdelphij for (i = dest->b.top; i < dest->b.dmax; i++) 191296465Sdelphij dest->b.d[i] = 0; 192296465Sdelphij return 1; 193296465Sdelphij} 194160814Ssimon 195160814Ssimon/* Set the curve parameters of an EC_GROUP structure. */ 196160814Ssimonint ec_GF2m_simple_group_set_curve(EC_GROUP *group, 197296465Sdelphij const BIGNUM *p, const BIGNUM *a, 198296465Sdelphij const BIGNUM *b, BN_CTX *ctx) 199296465Sdelphij{ 200296465Sdelphij int ret = 0, i; 201160814Ssimon 202296465Sdelphij /* group->field */ 203296465Sdelphij if (!BN_copy(&group->field, p)) 204296465Sdelphij goto err; 205296465Sdelphij i = BN_GF2m_poly2arr(&group->field, group->poly, 5); 206296465Sdelphij if ((i != 5) && (i != 3)) { 207296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); 208296465Sdelphij goto err; 209296465Sdelphij } 210160814Ssimon 211296465Sdelphij /* group->a */ 212296465Sdelphij if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) 213296465Sdelphij goto err; 214296465Sdelphij if (bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) 215296465Sdelphij == NULL) 216296465Sdelphij goto err; 217296465Sdelphij for (i = group->a.top; i < group->a.dmax; i++) 218296465Sdelphij group->a.d[i] = 0; 219160814Ssimon 220296465Sdelphij /* group->b */ 221296465Sdelphij if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) 222296465Sdelphij goto err; 223296465Sdelphij if (bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) 224296465Sdelphij == NULL) 225296465Sdelphij goto err; 226296465Sdelphij for (i = group->b.top; i < group->b.dmax; i++) 227296465Sdelphij group->b.d[i] = 0; 228160814Ssimon 229296465Sdelphij ret = 1; 230296465Sdelphij err: 231296465Sdelphij return ret; 232296465Sdelphij} 233296465Sdelphij 234296465Sdelphij/* 235296465Sdelphij * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL 236296465Sdelphij * then there values will not be set but the method will return with success. 237160814Ssimon */ 238296465Sdelphijint ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, 239296465Sdelphij BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 240296465Sdelphij{ 241296465Sdelphij int ret = 0; 242160814Ssimon 243296465Sdelphij if (p != NULL) { 244296465Sdelphij if (!BN_copy(p, &group->field)) 245296465Sdelphij return 0; 246296465Sdelphij } 247160814Ssimon 248296465Sdelphij if (a != NULL) { 249296465Sdelphij if (!BN_copy(a, &group->a)) 250296465Sdelphij goto err; 251296465Sdelphij } 252160814Ssimon 253296465Sdelphij if (b != NULL) { 254296465Sdelphij if (!BN_copy(b, &group->b)) 255296465Sdelphij goto err; 256296465Sdelphij } 257160814Ssimon 258296465Sdelphij ret = 1; 259160814Ssimon 260296465Sdelphij err: 261296465Sdelphij return ret; 262296465Sdelphij} 263160814Ssimon 264296465Sdelphij/* 265296465Sdelphij * Gets the degree of the field. For a curve over GF(2^m) this is the value 266296465Sdelphij * m. 267160814Ssimon */ 268296465Sdelphijint ec_GF2m_simple_group_get_degree(const EC_GROUP *group) 269296465Sdelphij{ 270296465Sdelphij return BN_num_bits(&group->field) - 1; 271296465Sdelphij} 272160814Ssimon 273296465Sdelphij/* 274296465Sdelphij * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an 275296465Sdelphij * elliptic curve <=> b != 0 (mod p) 276296465Sdelphij */ 277296465Sdelphijint ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, 278296465Sdelphij BN_CTX *ctx) 279296465Sdelphij{ 280296465Sdelphij int ret = 0; 281296465Sdelphij BIGNUM *b; 282296465Sdelphij BN_CTX *new_ctx = NULL; 283160814Ssimon 284296465Sdelphij if (ctx == NULL) { 285296465Sdelphij ctx = new_ctx = BN_CTX_new(); 286296465Sdelphij if (ctx == NULL) { 287296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 288296465Sdelphij ERR_R_MALLOC_FAILURE); 289296465Sdelphij goto err; 290296465Sdelphij } 291296465Sdelphij } 292296465Sdelphij BN_CTX_start(ctx); 293296465Sdelphij b = BN_CTX_get(ctx); 294296465Sdelphij if (b == NULL) 295296465Sdelphij goto err; 296160814Ssimon 297296465Sdelphij if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) 298296465Sdelphij goto err; 299160814Ssimon 300296465Sdelphij /* 301296465Sdelphij * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic 302296465Sdelphij * curve <=> b != 0 (mod p) 303296465Sdelphij */ 304296465Sdelphij if (BN_is_zero(b)) 305296465Sdelphij goto err; 306160814Ssimon 307296465Sdelphij ret = 1; 308160814Ssimon 309296465Sdelphij err: 310296465Sdelphij if (ctx != NULL) 311296465Sdelphij BN_CTX_end(ctx); 312296465Sdelphij if (new_ctx != NULL) 313296465Sdelphij BN_CTX_free(new_ctx); 314296465Sdelphij return ret; 315296465Sdelphij} 316296465Sdelphij 317160814Ssimon/* Initializes an EC_POINT. */ 318160814Ssimonint ec_GF2m_simple_point_init(EC_POINT *point) 319296465Sdelphij{ 320296465Sdelphij BN_init(&point->X); 321296465Sdelphij BN_init(&point->Y); 322296465Sdelphij BN_init(&point->Z); 323296465Sdelphij return 1; 324296465Sdelphij} 325160814Ssimon 326160814Ssimon/* Frees an EC_POINT. */ 327160814Ssimonvoid ec_GF2m_simple_point_finish(EC_POINT *point) 328296465Sdelphij{ 329296465Sdelphij BN_free(&point->X); 330296465Sdelphij BN_free(&point->Y); 331296465Sdelphij BN_free(&point->Z); 332296465Sdelphij} 333160814Ssimon 334160814Ssimon/* Clears and frees an EC_POINT. */ 335160814Ssimonvoid ec_GF2m_simple_point_clear_finish(EC_POINT *point) 336296465Sdelphij{ 337296465Sdelphij BN_clear_free(&point->X); 338296465Sdelphij BN_clear_free(&point->Y); 339296465Sdelphij BN_clear_free(&point->Z); 340296465Sdelphij point->Z_is_one = 0; 341296465Sdelphij} 342160814Ssimon 343296465Sdelphij/* 344296465Sdelphij * Copy the contents of one EC_POINT into another. Assumes dest is 345296465Sdelphij * initialized. 346296465Sdelphij */ 347160814Ssimonint ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) 348296465Sdelphij{ 349296465Sdelphij if (!BN_copy(&dest->X, &src->X)) 350296465Sdelphij return 0; 351296465Sdelphij if (!BN_copy(&dest->Y, &src->Y)) 352296465Sdelphij return 0; 353296465Sdelphij if (!BN_copy(&dest->Z, &src->Z)) 354296465Sdelphij return 0; 355296465Sdelphij dest->Z_is_one = src->Z_is_one; 356160814Ssimon 357296465Sdelphij return 1; 358296465Sdelphij} 359160814Ssimon 360296465Sdelphij/* 361296465Sdelphij * Set an EC_POINT to the point at infinity. A point at infinity is 362296465Sdelphij * represented by having Z=0. 363160814Ssimon */ 364296465Sdelphijint ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, 365296465Sdelphij EC_POINT *point) 366296465Sdelphij{ 367296465Sdelphij point->Z_is_one = 0; 368296465Sdelphij BN_zero(&point->Z); 369296465Sdelphij return 1; 370296465Sdelphij} 371160814Ssimon 372296465Sdelphij/* 373296465Sdelphij * Set the coordinates of an EC_POINT using affine coordinates. Note that 374296465Sdelphij * the simple implementation only uses affine coordinates. 375160814Ssimon */ 376296465Sdelphijint ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, 377296465Sdelphij EC_POINT *point, 378296465Sdelphij const BIGNUM *x, 379296465Sdelphij const BIGNUM *y, BN_CTX *ctx) 380296465Sdelphij{ 381296465Sdelphij int ret = 0; 382296465Sdelphij if (x == NULL || y == NULL) { 383296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 384296465Sdelphij ERR_R_PASSED_NULL_PARAMETER); 385296465Sdelphij return 0; 386296465Sdelphij } 387160814Ssimon 388296465Sdelphij if (!BN_copy(&point->X, x)) 389296465Sdelphij goto err; 390296465Sdelphij BN_set_negative(&point->X, 0); 391296465Sdelphij if (!BN_copy(&point->Y, y)) 392296465Sdelphij goto err; 393296465Sdelphij BN_set_negative(&point->Y, 0); 394296465Sdelphij if (!BN_copy(&point->Z, BN_value_one())) 395296465Sdelphij goto err; 396296465Sdelphij BN_set_negative(&point->Z, 0); 397296465Sdelphij point->Z_is_one = 1; 398296465Sdelphij ret = 1; 399160814Ssimon 400296465Sdelphij err: 401296465Sdelphij return ret; 402296465Sdelphij} 403160814Ssimon 404296465Sdelphij/* 405296465Sdelphij * Gets the affine coordinates of an EC_POINT. Note that the simple 406296465Sdelphij * implementation only uses affine coordinates. 407160814Ssimon */ 408296465Sdelphijint ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, 409296465Sdelphij const EC_POINT *point, 410296465Sdelphij BIGNUM *x, BIGNUM *y, 411296465Sdelphij BN_CTX *ctx) 412296465Sdelphij{ 413296465Sdelphij int ret = 0; 414160814Ssimon 415296465Sdelphij if (EC_POINT_is_at_infinity(group, point)) { 416296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 417296465Sdelphij EC_R_POINT_AT_INFINITY); 418296465Sdelphij return 0; 419296465Sdelphij } 420160814Ssimon 421296465Sdelphij if (BN_cmp(&point->Z, BN_value_one())) { 422296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 423296465Sdelphij ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 424296465Sdelphij return 0; 425296465Sdelphij } 426296465Sdelphij if (x != NULL) { 427296465Sdelphij if (!BN_copy(x, &point->X)) 428296465Sdelphij goto err; 429296465Sdelphij BN_set_negative(x, 0); 430296465Sdelphij } 431296465Sdelphij if (y != NULL) { 432296465Sdelphij if (!BN_copy(y, &point->Y)) 433296465Sdelphij goto err; 434296465Sdelphij BN_set_negative(y, 0); 435296465Sdelphij } 436296465Sdelphij ret = 1; 437296465Sdelphij 438160814Ssimon err: 439296465Sdelphij return ret; 440296465Sdelphij} 441160814Ssimon 442160814Ssimon/* Include patented algorithms. */ 443160814Ssimon#include "ec2_smpt.c" 444160814Ssimon 445296465Sdelphij/* 446296465Sdelphij * Converts an EC_POINT to an octet string. If buf is NULL, the encoded 447296465Sdelphij * length will be returned. If the length len of buf is smaller than required 448296465Sdelphij * an error will be returned. The point compression section of this function 449296465Sdelphij * is patented by Certicom Corp. under US Patent 6,141,420. Point 450296465Sdelphij * compression is disabled by default and can be enabled by defining the 451296465Sdelphij * preprocessor macro OPENSSL_EC_BIN_PT_COMP at Configure-time. 452160814Ssimon */ 453296465Sdelphijsize_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, 454296465Sdelphij point_conversion_form_t form, 455296465Sdelphij unsigned char *buf, size_t len, BN_CTX *ctx) 456296465Sdelphij{ 457296465Sdelphij size_t ret; 458296465Sdelphij BN_CTX *new_ctx = NULL; 459296465Sdelphij int used_ctx = 0; 460296465Sdelphij BIGNUM *x, *y, *yxi; 461296465Sdelphij size_t field_len, i, skip; 462160814Ssimon 463160814Ssimon#ifndef OPENSSL_EC_BIN_PT_COMP 464296465Sdelphij if ((form == POINT_CONVERSION_COMPRESSED) 465296465Sdelphij || (form == POINT_CONVERSION_HYBRID)) { 466296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_DISABLED); 467296465Sdelphij goto err; 468296465Sdelphij } 469160814Ssimon#endif 470160814Ssimon 471296465Sdelphij if ((form != POINT_CONVERSION_COMPRESSED) 472296465Sdelphij && (form != POINT_CONVERSION_UNCOMPRESSED) 473296465Sdelphij && (form != POINT_CONVERSION_HYBRID)) { 474296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); 475296465Sdelphij goto err; 476296465Sdelphij } 477160814Ssimon 478296465Sdelphij if (EC_POINT_is_at_infinity(group, point)) { 479296465Sdelphij /* encodes to a single 0 octet */ 480296465Sdelphij if (buf != NULL) { 481296465Sdelphij if (len < 1) { 482296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); 483296465Sdelphij return 0; 484296465Sdelphij } 485296465Sdelphij buf[0] = 0; 486296465Sdelphij } 487296465Sdelphij return 1; 488296465Sdelphij } 489160814Ssimon 490296465Sdelphij /* ret := required output buffer length */ 491296465Sdelphij field_len = (EC_GROUP_get_degree(group) + 7) / 8; 492296465Sdelphij ret = 493296465Sdelphij (form == 494296465Sdelphij POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 495160814Ssimon 496296465Sdelphij /* if 'buf' is NULL, just return required length */ 497296465Sdelphij if (buf != NULL) { 498296465Sdelphij if (len < ret) { 499296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); 500296465Sdelphij goto err; 501296465Sdelphij } 502160814Ssimon 503296465Sdelphij if (ctx == NULL) { 504296465Sdelphij ctx = new_ctx = BN_CTX_new(); 505296465Sdelphij if (ctx == NULL) 506296465Sdelphij return 0; 507296465Sdelphij } 508160814Ssimon 509296465Sdelphij BN_CTX_start(ctx); 510296465Sdelphij used_ctx = 1; 511296465Sdelphij x = BN_CTX_get(ctx); 512296465Sdelphij y = BN_CTX_get(ctx); 513296465Sdelphij yxi = BN_CTX_get(ctx); 514296465Sdelphij if (yxi == NULL) 515296465Sdelphij goto err; 516160814Ssimon 517296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) 518296465Sdelphij goto err; 519160814Ssimon 520296465Sdelphij buf[0] = form; 521160814Ssimon#ifdef OPENSSL_EC_BIN_PT_COMP 522296465Sdelphij if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) { 523296465Sdelphij if (!group->meth->field_div(group, yxi, y, x, ctx)) 524296465Sdelphij goto err; 525296465Sdelphij if (BN_is_odd(yxi)) 526296465Sdelphij buf[0]++; 527296465Sdelphij } 528160814Ssimon#endif 529160814Ssimon 530296465Sdelphij i = 1; 531160814Ssimon 532296465Sdelphij skip = field_len - BN_num_bytes(x); 533296465Sdelphij if (skip > field_len) { 534296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); 535296465Sdelphij goto err; 536296465Sdelphij } 537296465Sdelphij while (skip > 0) { 538296465Sdelphij buf[i++] = 0; 539296465Sdelphij skip--; 540296465Sdelphij } 541296465Sdelphij skip = BN_bn2bin(x, buf + i); 542296465Sdelphij i += skip; 543296465Sdelphij if (i != 1 + field_len) { 544296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); 545296465Sdelphij goto err; 546296465Sdelphij } 547160814Ssimon 548296465Sdelphij if (form == POINT_CONVERSION_UNCOMPRESSED 549296465Sdelphij || form == POINT_CONVERSION_HYBRID) { 550296465Sdelphij skip = field_len - BN_num_bytes(y); 551296465Sdelphij if (skip > field_len) { 552296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); 553296465Sdelphij goto err; 554296465Sdelphij } 555296465Sdelphij while (skip > 0) { 556296465Sdelphij buf[i++] = 0; 557296465Sdelphij skip--; 558296465Sdelphij } 559296465Sdelphij skip = BN_bn2bin(y, buf + i); 560296465Sdelphij i += skip; 561296465Sdelphij } 562160814Ssimon 563296465Sdelphij if (i != ret) { 564296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); 565296465Sdelphij goto err; 566296465Sdelphij } 567296465Sdelphij } 568296465Sdelphij 569296465Sdelphij if (used_ctx) 570296465Sdelphij BN_CTX_end(ctx); 571296465Sdelphij if (new_ctx != NULL) 572296465Sdelphij BN_CTX_free(new_ctx); 573296465Sdelphij return ret; 574296465Sdelphij 575160814Ssimon err: 576296465Sdelphij if (used_ctx) 577296465Sdelphij BN_CTX_end(ctx); 578296465Sdelphij if (new_ctx != NULL) 579296465Sdelphij BN_CTX_free(new_ctx); 580296465Sdelphij return 0; 581296465Sdelphij} 582160814Ssimon 583296465Sdelphij/* 584296465Sdelphij * Converts an octet string representation to an EC_POINT. Note that the 585296465Sdelphij * simple implementation only uses affine coordinates. 586160814Ssimon */ 587160814Ssimonint ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, 588296465Sdelphij const unsigned char *buf, size_t len, 589296465Sdelphij BN_CTX *ctx) 590296465Sdelphij{ 591296465Sdelphij point_conversion_form_t form; 592296465Sdelphij int y_bit; 593296465Sdelphij BN_CTX *new_ctx = NULL; 594296465Sdelphij BIGNUM *x, *y, *yxi; 595296465Sdelphij size_t field_len, enc_len; 596296465Sdelphij int ret = 0; 597160814Ssimon 598296465Sdelphij if (len == 0) { 599296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); 600296465Sdelphij return 0; 601296465Sdelphij } 602296465Sdelphij form = buf[0]; 603296465Sdelphij y_bit = form & 1; 604296465Sdelphij form = form & ~1U; 605296465Sdelphij if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) 606296465Sdelphij && (form != POINT_CONVERSION_UNCOMPRESSED) 607296465Sdelphij && (form != POINT_CONVERSION_HYBRID)) { 608296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 609296465Sdelphij return 0; 610296465Sdelphij } 611296465Sdelphij if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { 612296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 613296465Sdelphij return 0; 614296465Sdelphij } 615160814Ssimon 616296465Sdelphij if (form == 0) { 617296465Sdelphij if (len != 1) { 618296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 619296465Sdelphij return 0; 620296465Sdelphij } 621160814Ssimon 622296465Sdelphij return EC_POINT_set_to_infinity(group, point); 623296465Sdelphij } 624160814Ssimon 625296465Sdelphij field_len = (EC_GROUP_get_degree(group) + 7) / 8; 626296465Sdelphij enc_len = 627296465Sdelphij (form == 628296465Sdelphij POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 629160814Ssimon 630296465Sdelphij if (len != enc_len) { 631296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 632296465Sdelphij return 0; 633296465Sdelphij } 634160814Ssimon 635296465Sdelphij if (ctx == NULL) { 636296465Sdelphij ctx = new_ctx = BN_CTX_new(); 637296465Sdelphij if (ctx == NULL) 638296465Sdelphij return 0; 639296465Sdelphij } 640160814Ssimon 641296465Sdelphij BN_CTX_start(ctx); 642296465Sdelphij x = BN_CTX_get(ctx); 643296465Sdelphij y = BN_CTX_get(ctx); 644296465Sdelphij yxi = BN_CTX_get(ctx); 645296465Sdelphij if (yxi == NULL) 646296465Sdelphij goto err; 647160814Ssimon 648296465Sdelphij if (!BN_bin2bn(buf + 1, field_len, x)) 649296465Sdelphij goto err; 650296465Sdelphij if (BN_ucmp(x, &group->field) >= 0) { 651296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 652296465Sdelphij goto err; 653296465Sdelphij } 654160814Ssimon 655296465Sdelphij if (form == POINT_CONVERSION_COMPRESSED) { 656296465Sdelphij if (!EC_POINT_set_compressed_coordinates_GF2m 657296465Sdelphij (group, point, x, y_bit, ctx)) 658296465Sdelphij goto err; 659296465Sdelphij } else { 660296465Sdelphij if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) 661296465Sdelphij goto err; 662296465Sdelphij if (BN_ucmp(y, &group->field) >= 0) { 663296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 664296465Sdelphij goto err; 665296465Sdelphij } 666296465Sdelphij if (form == POINT_CONVERSION_HYBRID) { 667296465Sdelphij if (!group->meth->field_div(group, yxi, y, x, ctx)) 668296465Sdelphij goto err; 669296465Sdelphij if (y_bit != BN_is_odd(yxi)) { 670296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); 671296465Sdelphij goto err; 672296465Sdelphij } 673296465Sdelphij } 674160814Ssimon 675296465Sdelphij if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) 676296465Sdelphij goto err; 677296465Sdelphij } 678296465Sdelphij 679296465Sdelphij /* test required by X9.62 */ 680296465Sdelphij if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 681296465Sdelphij ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); 682296465Sdelphij goto err; 683296465Sdelphij } 684296465Sdelphij 685296465Sdelphij ret = 1; 686296465Sdelphij 687160814Ssimon err: 688296465Sdelphij BN_CTX_end(ctx); 689296465Sdelphij if (new_ctx != NULL) 690296465Sdelphij BN_CTX_free(new_ctx); 691296465Sdelphij return ret; 692296465Sdelphij} 693160814Ssimon 694296465Sdelphij/* 695296465Sdelphij * Computes a + b and stores the result in r. r could be a or b, a could be 696296465Sdelphij * b. Uses algorithm A.10.2 of IEEE P1363. 697160814Ssimon */ 698296465Sdelphijint ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 699296465Sdelphij const EC_POINT *b, BN_CTX *ctx) 700296465Sdelphij{ 701296465Sdelphij BN_CTX *new_ctx = NULL; 702296465Sdelphij BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; 703296465Sdelphij int ret = 0; 704160814Ssimon 705296465Sdelphij if (EC_POINT_is_at_infinity(group, a)) { 706296465Sdelphij if (!EC_POINT_copy(r, b)) 707296465Sdelphij return 0; 708296465Sdelphij return 1; 709296465Sdelphij } 710160814Ssimon 711296465Sdelphij if (EC_POINT_is_at_infinity(group, b)) { 712296465Sdelphij if (!EC_POINT_copy(r, a)) 713296465Sdelphij return 0; 714296465Sdelphij return 1; 715296465Sdelphij } 716160814Ssimon 717296465Sdelphij if (ctx == NULL) { 718296465Sdelphij ctx = new_ctx = BN_CTX_new(); 719296465Sdelphij if (ctx == NULL) 720296465Sdelphij return 0; 721296465Sdelphij } 722160814Ssimon 723296465Sdelphij BN_CTX_start(ctx); 724296465Sdelphij x0 = BN_CTX_get(ctx); 725296465Sdelphij y0 = BN_CTX_get(ctx); 726296465Sdelphij x1 = BN_CTX_get(ctx); 727296465Sdelphij y1 = BN_CTX_get(ctx); 728296465Sdelphij x2 = BN_CTX_get(ctx); 729296465Sdelphij y2 = BN_CTX_get(ctx); 730296465Sdelphij s = BN_CTX_get(ctx); 731296465Sdelphij t = BN_CTX_get(ctx); 732296465Sdelphij if (t == NULL) 733296465Sdelphij goto err; 734160814Ssimon 735296465Sdelphij if (a->Z_is_one) { 736296465Sdelphij if (!BN_copy(x0, &a->X)) 737296465Sdelphij goto err; 738296465Sdelphij if (!BN_copy(y0, &a->Y)) 739296465Sdelphij goto err; 740296465Sdelphij } else { 741296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) 742296465Sdelphij goto err; 743296465Sdelphij } 744296465Sdelphij if (b->Z_is_one) { 745296465Sdelphij if (!BN_copy(x1, &b->X)) 746296465Sdelphij goto err; 747296465Sdelphij if (!BN_copy(y1, &b->Y)) 748296465Sdelphij goto err; 749296465Sdelphij } else { 750296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) 751296465Sdelphij goto err; 752296465Sdelphij } 753160814Ssimon 754296465Sdelphij if (BN_GF2m_cmp(x0, x1)) { 755296465Sdelphij if (!BN_GF2m_add(t, x0, x1)) 756296465Sdelphij goto err; 757296465Sdelphij if (!BN_GF2m_add(s, y0, y1)) 758296465Sdelphij goto err; 759296465Sdelphij if (!group->meth->field_div(group, s, s, t, ctx)) 760296465Sdelphij goto err; 761296465Sdelphij if (!group->meth->field_sqr(group, x2, s, ctx)) 762296465Sdelphij goto err; 763296465Sdelphij if (!BN_GF2m_add(x2, x2, &group->a)) 764296465Sdelphij goto err; 765296465Sdelphij if (!BN_GF2m_add(x2, x2, s)) 766296465Sdelphij goto err; 767296465Sdelphij if (!BN_GF2m_add(x2, x2, t)) 768296465Sdelphij goto err; 769296465Sdelphij } else { 770296465Sdelphij if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { 771296465Sdelphij if (!EC_POINT_set_to_infinity(group, r)) 772296465Sdelphij goto err; 773296465Sdelphij ret = 1; 774296465Sdelphij goto err; 775296465Sdelphij } 776296465Sdelphij if (!group->meth->field_div(group, s, y1, x1, ctx)) 777296465Sdelphij goto err; 778296465Sdelphij if (!BN_GF2m_add(s, s, x1)) 779296465Sdelphij goto err; 780160814Ssimon 781296465Sdelphij if (!group->meth->field_sqr(group, x2, s, ctx)) 782296465Sdelphij goto err; 783296465Sdelphij if (!BN_GF2m_add(x2, x2, s)) 784296465Sdelphij goto err; 785296465Sdelphij if (!BN_GF2m_add(x2, x2, &group->a)) 786296465Sdelphij goto err; 787296465Sdelphij } 788160814Ssimon 789296465Sdelphij if (!BN_GF2m_add(y2, x1, x2)) 790296465Sdelphij goto err; 791296465Sdelphij if (!group->meth->field_mul(group, y2, y2, s, ctx)) 792296465Sdelphij goto err; 793296465Sdelphij if (!BN_GF2m_add(y2, y2, x2)) 794296465Sdelphij goto err; 795296465Sdelphij if (!BN_GF2m_add(y2, y2, y1)) 796296465Sdelphij goto err; 797160814Ssimon 798296465Sdelphij if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) 799296465Sdelphij goto err; 800160814Ssimon 801296465Sdelphij ret = 1; 802296465Sdelphij 803160814Ssimon err: 804296465Sdelphij BN_CTX_end(ctx); 805296465Sdelphij if (new_ctx != NULL) 806296465Sdelphij BN_CTX_free(new_ctx); 807296465Sdelphij return ret; 808296465Sdelphij} 809160814Ssimon 810296465Sdelphij/* 811296465Sdelphij * Computes 2 * a and stores the result in r. r could be a. Uses algorithm 812296465Sdelphij * A.10.2 of IEEE P1363. 813160814Ssimon */ 814296465Sdelphijint ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 815296465Sdelphij BN_CTX *ctx) 816296465Sdelphij{ 817296465Sdelphij return ec_GF2m_simple_add(group, r, a, a, ctx); 818296465Sdelphij} 819160814Ssimon 820160814Ssimonint ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 821296465Sdelphij{ 822296465Sdelphij if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) 823296465Sdelphij /* point is its own inverse */ 824296465Sdelphij return 1; 825160814Ssimon 826296465Sdelphij if (!EC_POINT_make_affine(group, point, ctx)) 827296465Sdelphij return 0; 828296465Sdelphij return BN_GF2m_add(&point->Y, &point->X, &point->Y); 829296465Sdelphij} 830160814Ssimon 831160814Ssimon/* Indicates whether the given point is the point at infinity. */ 832296465Sdelphijint ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, 833296465Sdelphij const EC_POINT *point) 834296465Sdelphij{ 835296465Sdelphij return BN_is_zero(&point->Z); 836296465Sdelphij} 837160814Ssimon 838296465Sdelphij/*- 839296465Sdelphij * Determines whether the given EC_POINT is an actual point on the curve defined 840160814Ssimon * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: 841160814Ssimon * y^2 + x*y = x^3 + a*x^2 + b. 842160814Ssimon */ 843296465Sdelphijint ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 844296465Sdelphij BN_CTX *ctx) 845296465Sdelphij{ 846296465Sdelphij int ret = -1; 847296465Sdelphij BN_CTX *new_ctx = NULL; 848296465Sdelphij BIGNUM *lh, *y2; 849296465Sdelphij int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, 850296465Sdelphij const BIGNUM *, BN_CTX *); 851296465Sdelphij int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 852160814Ssimon 853296465Sdelphij if (EC_POINT_is_at_infinity(group, point)) 854296465Sdelphij return 1; 855160814Ssimon 856296465Sdelphij field_mul = group->meth->field_mul; 857296465Sdelphij field_sqr = group->meth->field_sqr; 858160814Ssimon 859296465Sdelphij /* only support affine coordinates */ 860296465Sdelphij if (!point->Z_is_one) 861296465Sdelphij return -1; 862160814Ssimon 863296465Sdelphij if (ctx == NULL) { 864296465Sdelphij ctx = new_ctx = BN_CTX_new(); 865296465Sdelphij if (ctx == NULL) 866296465Sdelphij return -1; 867296465Sdelphij } 868160814Ssimon 869296465Sdelphij BN_CTX_start(ctx); 870296465Sdelphij y2 = BN_CTX_get(ctx); 871296465Sdelphij lh = BN_CTX_get(ctx); 872296465Sdelphij if (lh == NULL) 873296465Sdelphij goto err; 874160814Ssimon 875296465Sdelphij /*- 876296465Sdelphij * We have a curve defined by a Weierstrass equation 877296465Sdelphij * y^2 + x*y = x^3 + a*x^2 + b. 878296465Sdelphij * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 879296465Sdelphij * <=> ((x + a) * x + y ) * x + b + y^2 = 0 880296465Sdelphij */ 881296465Sdelphij if (!BN_GF2m_add(lh, &point->X, &group->a)) 882296465Sdelphij goto err; 883296465Sdelphij if (!field_mul(group, lh, lh, &point->X, ctx)) 884296465Sdelphij goto err; 885296465Sdelphij if (!BN_GF2m_add(lh, lh, &point->Y)) 886296465Sdelphij goto err; 887296465Sdelphij if (!field_mul(group, lh, lh, &point->X, ctx)) 888296465Sdelphij goto err; 889296465Sdelphij if (!BN_GF2m_add(lh, lh, &group->b)) 890296465Sdelphij goto err; 891296465Sdelphij if (!field_sqr(group, y2, &point->Y, ctx)) 892296465Sdelphij goto err; 893296465Sdelphij if (!BN_GF2m_add(lh, lh, y2)) 894296465Sdelphij goto err; 895296465Sdelphij ret = BN_is_zero(lh); 896160814Ssimon err: 897296465Sdelphij if (ctx) 898296465Sdelphij BN_CTX_end(ctx); 899296465Sdelphij if (new_ctx) 900296465Sdelphij BN_CTX_free(new_ctx); 901296465Sdelphij return ret; 902296465Sdelphij} 903160814Ssimon 904296465Sdelphij/*- 905296465Sdelphij * Indicates whether two points are equal. 906160814Ssimon * Return values: 907160814Ssimon * -1 error 908160814Ssimon * 0 equal (in affine coordinates) 909160814Ssimon * 1 not equal 910160814Ssimon */ 911296465Sdelphijint ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, 912296465Sdelphij const EC_POINT *b, BN_CTX *ctx) 913296465Sdelphij{ 914296465Sdelphij BIGNUM *aX, *aY, *bX, *bY; 915296465Sdelphij BN_CTX *new_ctx = NULL; 916296465Sdelphij int ret = -1; 917160814Ssimon 918296465Sdelphij if (EC_POINT_is_at_infinity(group, a)) { 919296465Sdelphij return EC_POINT_is_at_infinity(group, b) ? 0 : 1; 920296465Sdelphij } 921237998Sjkim 922296465Sdelphij if (EC_POINT_is_at_infinity(group, b)) 923296465Sdelphij return 1; 924160814Ssimon 925296465Sdelphij if (a->Z_is_one && b->Z_is_one) { 926296465Sdelphij return ((BN_cmp(&a->X, &b->X) == 0) 927296465Sdelphij && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; 928296465Sdelphij } 929160814Ssimon 930296465Sdelphij if (ctx == NULL) { 931296465Sdelphij ctx = new_ctx = BN_CTX_new(); 932296465Sdelphij if (ctx == NULL) 933296465Sdelphij return -1; 934296465Sdelphij } 935160814Ssimon 936296465Sdelphij BN_CTX_start(ctx); 937296465Sdelphij aX = BN_CTX_get(ctx); 938296465Sdelphij aY = BN_CTX_get(ctx); 939296465Sdelphij bX = BN_CTX_get(ctx); 940296465Sdelphij bY = BN_CTX_get(ctx); 941296465Sdelphij if (bY == NULL) 942296465Sdelphij goto err; 943160814Ssimon 944296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) 945296465Sdelphij goto err; 946296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) 947296465Sdelphij goto err; 948296465Sdelphij ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; 949160814Ssimon 950296465Sdelphij err: 951296465Sdelphij if (ctx) 952296465Sdelphij BN_CTX_end(ctx); 953296465Sdelphij if (new_ctx) 954296465Sdelphij BN_CTX_free(new_ctx); 955296465Sdelphij return ret; 956296465Sdelphij} 957160814Ssimon 958160814Ssimon/* Forces the given EC_POINT to internally use affine coordinates. */ 959296465Sdelphijint ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, 960296465Sdelphij BN_CTX *ctx) 961296465Sdelphij{ 962296465Sdelphij BN_CTX *new_ctx = NULL; 963296465Sdelphij BIGNUM *x, *y; 964296465Sdelphij int ret = 0; 965160814Ssimon 966296465Sdelphij if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) 967296465Sdelphij return 1; 968160814Ssimon 969296465Sdelphij if (ctx == NULL) { 970296465Sdelphij ctx = new_ctx = BN_CTX_new(); 971296465Sdelphij if (ctx == NULL) 972296465Sdelphij return 0; 973296465Sdelphij } 974160814Ssimon 975296465Sdelphij BN_CTX_start(ctx); 976296465Sdelphij x = BN_CTX_get(ctx); 977296465Sdelphij y = BN_CTX_get(ctx); 978296465Sdelphij if (y == NULL) 979296465Sdelphij goto err; 980160814Ssimon 981296465Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) 982296465Sdelphij goto err; 983296465Sdelphij if (!BN_copy(&point->X, x)) 984296465Sdelphij goto err; 985296465Sdelphij if (!BN_copy(&point->Y, y)) 986296465Sdelphij goto err; 987296465Sdelphij if (!BN_one(&point->Z)) 988296465Sdelphij goto err; 989160814Ssimon 990296465Sdelphij ret = 1; 991160814Ssimon 992296465Sdelphij err: 993296465Sdelphij if (ctx) 994296465Sdelphij BN_CTX_end(ctx); 995296465Sdelphij if (new_ctx) 996296465Sdelphij BN_CTX_free(new_ctx); 997296465Sdelphij return ret; 998296465Sdelphij} 999160814Ssimon 1000296465Sdelphij/* 1001296465Sdelphij * Forces each of the EC_POINTs in the given array to use affine coordinates. 1002296465Sdelphij */ 1003296465Sdelphijint ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, 1004296465Sdelphij EC_POINT *points[], BN_CTX *ctx) 1005296465Sdelphij{ 1006296465Sdelphij size_t i; 1007160814Ssimon 1008296465Sdelphij for (i = 0; i < num; i++) { 1009296465Sdelphij if (!group->meth->make_affine(group, points[i], ctx)) 1010296465Sdelphij return 0; 1011296465Sdelphij } 1012160814Ssimon 1013296465Sdelphij return 1; 1014296465Sdelphij} 1015296465Sdelphij 1016160814Ssimon/* Wrapper to simple binary polynomial field multiplication implementation. */ 1017296465Sdelphijint ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, 1018296465Sdelphij const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 1019296465Sdelphij{ 1020296465Sdelphij return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); 1021296465Sdelphij} 1022160814Ssimon 1023160814Ssimon/* Wrapper to simple binary polynomial field squaring implementation. */ 1024296465Sdelphijint ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, 1025296465Sdelphij const BIGNUM *a, BN_CTX *ctx) 1026296465Sdelphij{ 1027296465Sdelphij return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); 1028296465Sdelphij} 1029160814Ssimon 1030160814Ssimon/* Wrapper to simple binary polynomial field division implementation. */ 1031296465Sdelphijint ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, 1032296465Sdelphij const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 1033296465Sdelphij{ 1034296465Sdelphij return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 1035296465Sdelphij} 1036