1 /* crypto/ec/ec2_smpl.c */ 2 /* ==================================================================== 3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 4 * 5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included 6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed 7 * to the OpenSSL project. 8 * 9 * The ECC Code is licensed pursuant to the OpenSSL open source 10 * license provided below. 11 * 12 * The software is originally written by Sheueling Chang Shantz and 13 * Douglas Stebila of Sun Microsystems Laboratories. 14 * 15 */ 16 /* ==================================================================== 17 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in 28 * the documentation and/or other materials provided with the 29 * distribution. 30 * 31 * 3. All advertising materials mentioning features or use of this 32 * software must display the following acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 35 * 36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 37 * endorse or promote products derived from this software without 38 * prior written permission. For written permission, please contact 39 * openssl-core@openssl.org. 40 * 41 * 5. Products derived from this software may not be called "OpenSSL" 42 * nor may "OpenSSL" appear in their names without prior written 43 * permission of the OpenSSL Project. 44 * 45 * 6. Redistributions of any form whatsoever must retain the following 46 * acknowledgment: 47 * "This product includes software developed by the OpenSSL Project 48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 61 * OF THE POSSIBILITY OF SUCH DAMAGE. 62 * ==================================================================== 63 * 64 * This product includes cryptographic software written by Eric Young 65 * (eay@cryptsoft.com). This product includes software written by Tim 66 * Hudson (tjh@cryptsoft.com). 67 * 68 */ 69 70 #include <openssl/err.h> 71 72 #include "ec_lcl.h" 73 74 #ifndef OPENSSL_NO_EC2M 75 76 # ifdef OPENSSL_FIPS 77 # include <openssl/fips.h> 78 # endif 79 80 const EC_METHOD *EC_GF2m_simple_method(void) 81 { 82 static const EC_METHOD ret = { 83 EC_FLAGS_DEFAULT_OCT, 84 NID_X9_62_characteristic_two_field, 85 ec_GF2m_simple_group_init, 86 ec_GF2m_simple_group_finish, 87 ec_GF2m_simple_group_clear_finish, 88 ec_GF2m_simple_group_copy, 89 ec_GF2m_simple_group_set_curve, 90 ec_GF2m_simple_group_get_curve, 91 ec_GF2m_simple_group_get_degree, 92 ec_GF2m_simple_group_check_discriminant, 93 ec_GF2m_simple_point_init, 94 ec_GF2m_simple_point_finish, 95 ec_GF2m_simple_point_clear_finish, 96 ec_GF2m_simple_point_copy, 97 ec_GF2m_simple_point_set_to_infinity, 98 0 /* set_Jprojective_coordinates_GFp */ , 99 0 /* get_Jprojective_coordinates_GFp */ , 100 ec_GF2m_simple_point_set_affine_coordinates, 101 ec_GF2m_simple_point_get_affine_coordinates, 102 0, 0, 0, 103 ec_GF2m_simple_add, 104 ec_GF2m_simple_dbl, 105 ec_GF2m_simple_invert, 106 ec_GF2m_simple_is_at_infinity, 107 ec_GF2m_simple_is_on_curve, 108 ec_GF2m_simple_cmp, 109 ec_GF2m_simple_make_affine, 110 ec_GF2m_simple_points_make_affine, 111 112 /* 113 * the following three method functions are defined in ec2_mult.c 114 */ 115 ec_GF2m_simple_mul, 116 ec_GF2m_precompute_mult, 117 ec_GF2m_have_precompute_mult, 118 119 ec_GF2m_simple_field_mul, 120 ec_GF2m_simple_field_sqr, 121 ec_GF2m_simple_field_div, 122 0 /* field_encode */ , 123 0 /* field_decode */ , 124 0 /* field_set_to_one */ 125 }; 126 127 # ifdef OPENSSL_FIPS 128 if (FIPS_mode()) 129 return fips_ec_gf2m_simple_method(); 130 # endif 131 132 return &ret; 133 } 134 135 /* 136 * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members 137 * are handled by EC_GROUP_new. 138 */ 139 int ec_GF2m_simple_group_init(EC_GROUP *group) 140 { 141 BN_init(&group->field); 142 BN_init(&group->a); 143 BN_init(&group->b); 144 return 1; 145 } 146 147 /* 148 * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are 149 * handled by EC_GROUP_free. 150 */ 151 void ec_GF2m_simple_group_finish(EC_GROUP *group) 152 { 153 BN_free(&group->field); 154 BN_free(&group->a); 155 BN_free(&group->b); 156 } 157 158 /* 159 * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other 160 * members are handled by EC_GROUP_clear_free. 161 */ 162 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) 163 { 164 BN_clear_free(&group->field); 165 BN_clear_free(&group->a); 166 BN_clear_free(&group->b); 167 group->poly[0] = 0; 168 group->poly[1] = 0; 169 group->poly[2] = 0; 170 group->poly[3] = 0; 171 group->poly[4] = 0; 172 group->poly[5] = -1; 173 } 174 175 /* 176 * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are 177 * handled by EC_GROUP_copy. 178 */ 179 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) 180 { 181 int i; 182 if (!BN_copy(&dest->field, &src->field)) 183 return 0; 184 if (!BN_copy(&dest->a, &src->a)) 185 return 0; 186 if (!BN_copy(&dest->b, &src->b)) 187 return 0; 188 dest->poly[0] = src->poly[0]; 189 dest->poly[1] = src->poly[1]; 190 dest->poly[2] = src->poly[2]; 191 dest->poly[3] = src->poly[3]; 192 dest->poly[4] = src->poly[4]; 193 dest->poly[5] = src->poly[5]; 194 if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) 195 == NULL) 196 return 0; 197 if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) 198 == NULL) 199 return 0; 200 for (i = dest->a.top; i < dest->a.dmax; i++) 201 dest->a.d[i] = 0; 202 for (i = dest->b.top; i < dest->b.dmax; i++) 203 dest->b.d[i] = 0; 204 return 1; 205 } 206 207 /* Set the curve parameters of an EC_GROUP structure. */ 208 int ec_GF2m_simple_group_set_curve(EC_GROUP *group, 209 const BIGNUM *p, const BIGNUM *a, 210 const BIGNUM *b, BN_CTX *ctx) 211 { 212 int ret = 0, i; 213 214 /* group->field */ 215 if (!BN_copy(&group->field, p)) 216 goto err; 217 i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; 218 if ((i != 5) && (i != 3)) { 219 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); 220 goto err; 221 } 222 223 /* group->a */ 224 if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) 225 goto err; 226 if (bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) 227 == NULL) 228 goto err; 229 for (i = group->a.top; i < group->a.dmax; i++) 230 group->a.d[i] = 0; 231 232 /* group->b */ 233 if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) 234 goto err; 235 if (bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) 236 == NULL) 237 goto err; 238 for (i = group->b.top; i < group->b.dmax; i++) 239 group->b.d[i] = 0; 240 241 ret = 1; 242 err: 243 return ret; 244 } 245 246 /* 247 * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL 248 * then there values will not be set but the method will return with success. 249 */ 250 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, 251 BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 252 { 253 int ret = 0; 254 255 if (p != NULL) { 256 if (!BN_copy(p, &group->field)) 257 return 0; 258 } 259 260 if (a != NULL) { 261 if (!BN_copy(a, &group->a)) 262 goto err; 263 } 264 265 if (b != NULL) { 266 if (!BN_copy(b, &group->b)) 267 goto err; 268 } 269 270 ret = 1; 271 272 err: 273 return ret; 274 } 275 276 /* 277 * Gets the degree of the field. For a curve over GF(2^m) this is the value 278 * m. 279 */ 280 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) 281 { 282 return BN_num_bits(&group->field) - 1; 283 } 284 285 /* 286 * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an 287 * elliptic curve <=> b != 0 (mod p) 288 */ 289 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, 290 BN_CTX *ctx) 291 { 292 int ret = 0; 293 BIGNUM *b; 294 BN_CTX *new_ctx = NULL; 295 296 if (ctx == NULL) { 297 ctx = new_ctx = BN_CTX_new(); 298 if (ctx == NULL) { 299 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, 300 ERR_R_MALLOC_FAILURE); 301 goto err; 302 } 303 } 304 BN_CTX_start(ctx); 305 b = BN_CTX_get(ctx); 306 if (b == NULL) 307 goto err; 308 309 if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) 310 goto err; 311 312 /* 313 * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic 314 * curve <=> b != 0 (mod p) 315 */ 316 if (BN_is_zero(b)) 317 goto err; 318 319 ret = 1; 320 321 err: 322 if (ctx != NULL) 323 BN_CTX_end(ctx); 324 if (new_ctx != NULL) 325 BN_CTX_free(new_ctx); 326 return ret; 327 } 328 329 /* Initializes an EC_POINT. */ 330 int ec_GF2m_simple_point_init(EC_POINT *point) 331 { 332 BN_init(&point->X); 333 BN_init(&point->Y); 334 BN_init(&point->Z); 335 return 1; 336 } 337 338 /* Frees an EC_POINT. */ 339 void ec_GF2m_simple_point_finish(EC_POINT *point) 340 { 341 BN_free(&point->X); 342 BN_free(&point->Y); 343 BN_free(&point->Z); 344 } 345 346 /* Clears and frees an EC_POINT. */ 347 void ec_GF2m_simple_point_clear_finish(EC_POINT *point) 348 { 349 BN_clear_free(&point->X); 350 BN_clear_free(&point->Y); 351 BN_clear_free(&point->Z); 352 point->Z_is_one = 0; 353 } 354 355 /* 356 * Copy the contents of one EC_POINT into another. Assumes dest is 357 * initialized. 358 */ 359 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) 360 { 361 if (!BN_copy(&dest->X, &src->X)) 362 return 0; 363 if (!BN_copy(&dest->Y, &src->Y)) 364 return 0; 365 if (!BN_copy(&dest->Z, &src->Z)) 366 return 0; 367 dest->Z_is_one = src->Z_is_one; 368 369 return 1; 370 } 371 372 /* 373 * Set an EC_POINT to the point at infinity. A point at infinity is 374 * represented by having Z=0. 375 */ 376 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, 377 EC_POINT *point) 378 { 379 point->Z_is_one = 0; 380 BN_zero(&point->Z); 381 return 1; 382 } 383 384 /* 385 * Set the coordinates of an EC_POINT using affine coordinates. Note that 386 * the simple implementation only uses affine coordinates. 387 */ 388 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, 389 EC_POINT *point, 390 const BIGNUM *x, 391 const BIGNUM *y, BN_CTX *ctx) 392 { 393 int ret = 0; 394 if (x == NULL || y == NULL) { 395 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, 396 ERR_R_PASSED_NULL_PARAMETER); 397 return 0; 398 } 399 400 if (!BN_copy(&point->X, x)) 401 goto err; 402 BN_set_negative(&point->X, 0); 403 if (!BN_copy(&point->Y, y)) 404 goto err; 405 BN_set_negative(&point->Y, 0); 406 if (!BN_copy(&point->Z, BN_value_one())) 407 goto err; 408 BN_set_negative(&point->Z, 0); 409 point->Z_is_one = 1; 410 ret = 1; 411 412 err: 413 return ret; 414 } 415 416 /* 417 * Gets the affine coordinates of an EC_POINT. Note that the simple 418 * implementation only uses affine coordinates. 419 */ 420 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, 421 const EC_POINT *point, 422 BIGNUM *x, BIGNUM *y, 423 BN_CTX *ctx) 424 { 425 int ret = 0; 426 427 if (EC_POINT_is_at_infinity(group, point)) { 428 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 429 EC_R_POINT_AT_INFINITY); 430 return 0; 431 } 432 433 if (BN_cmp(&point->Z, BN_value_one())) { 434 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, 435 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 436 return 0; 437 } 438 if (x != NULL) { 439 if (!BN_copy(x, &point->X)) 440 goto err; 441 BN_set_negative(x, 0); 442 } 443 if (y != NULL) { 444 if (!BN_copy(y, &point->Y)) 445 goto err; 446 BN_set_negative(y, 0); 447 } 448 ret = 1; 449 450 err: 451 return ret; 452 } 453 454 /* 455 * Computes a + b and stores the result in r. r could be a or b, a could be 456 * b. Uses algorithm A.10.2 of IEEE P1363. 457 */ 458 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 459 const EC_POINT *b, BN_CTX *ctx) 460 { 461 BN_CTX *new_ctx = NULL; 462 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; 463 int ret = 0; 464 465 if (EC_POINT_is_at_infinity(group, a)) { 466 if (!EC_POINT_copy(r, b)) 467 return 0; 468 return 1; 469 } 470 471 if (EC_POINT_is_at_infinity(group, b)) { 472 if (!EC_POINT_copy(r, a)) 473 return 0; 474 return 1; 475 } 476 477 if (ctx == NULL) { 478 ctx = new_ctx = BN_CTX_new(); 479 if (ctx == NULL) 480 return 0; 481 } 482 483 BN_CTX_start(ctx); 484 x0 = BN_CTX_get(ctx); 485 y0 = BN_CTX_get(ctx); 486 x1 = BN_CTX_get(ctx); 487 y1 = BN_CTX_get(ctx); 488 x2 = BN_CTX_get(ctx); 489 y2 = BN_CTX_get(ctx); 490 s = BN_CTX_get(ctx); 491 t = BN_CTX_get(ctx); 492 if (t == NULL) 493 goto err; 494 495 if (a->Z_is_one) { 496 if (!BN_copy(x0, &a->X)) 497 goto err; 498 if (!BN_copy(y0, &a->Y)) 499 goto err; 500 } else { 501 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) 502 goto err; 503 } 504 if (b->Z_is_one) { 505 if (!BN_copy(x1, &b->X)) 506 goto err; 507 if (!BN_copy(y1, &b->Y)) 508 goto err; 509 } else { 510 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) 511 goto err; 512 } 513 514 if (BN_GF2m_cmp(x0, x1)) { 515 if (!BN_GF2m_add(t, x0, x1)) 516 goto err; 517 if (!BN_GF2m_add(s, y0, y1)) 518 goto err; 519 if (!group->meth->field_div(group, s, s, t, ctx)) 520 goto err; 521 if (!group->meth->field_sqr(group, x2, s, ctx)) 522 goto err; 523 if (!BN_GF2m_add(x2, x2, &group->a)) 524 goto err; 525 if (!BN_GF2m_add(x2, x2, s)) 526 goto err; 527 if (!BN_GF2m_add(x2, x2, t)) 528 goto err; 529 } else { 530 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { 531 if (!EC_POINT_set_to_infinity(group, r)) 532 goto err; 533 ret = 1; 534 goto err; 535 } 536 if (!group->meth->field_div(group, s, y1, x1, ctx)) 537 goto err; 538 if (!BN_GF2m_add(s, s, x1)) 539 goto err; 540 541 if (!group->meth->field_sqr(group, x2, s, ctx)) 542 goto err; 543 if (!BN_GF2m_add(x2, x2, s)) 544 goto err; 545 if (!BN_GF2m_add(x2, x2, &group->a)) 546 goto err; 547 } 548 549 if (!BN_GF2m_add(y2, x1, x2)) 550 goto err; 551 if (!group->meth->field_mul(group, y2, y2, s, ctx)) 552 goto err; 553 if (!BN_GF2m_add(y2, y2, x2)) 554 goto err; 555 if (!BN_GF2m_add(y2, y2, y1)) 556 goto err; 557 558 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) 559 goto err; 560 561 ret = 1; 562 563 err: 564 BN_CTX_end(ctx); 565 if (new_ctx != NULL) 566 BN_CTX_free(new_ctx); 567 return ret; 568 } 569 570 /* 571 * Computes 2 * a and stores the result in r. r could be a. Uses algorithm 572 * A.10.2 of IEEE P1363. 573 */ 574 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 575 BN_CTX *ctx) 576 { 577 return ec_GF2m_simple_add(group, r, a, a, ctx); 578 } 579 580 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 581 { 582 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) 583 /* point is its own inverse */ 584 return 1; 585 586 if (!EC_POINT_make_affine(group, point, ctx)) 587 return 0; 588 return BN_GF2m_add(&point->Y, &point->X, &point->Y); 589 } 590 591 /* Indicates whether the given point is the point at infinity. */ 592 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, 593 const EC_POINT *point) 594 { 595 return BN_is_zero(&point->Z); 596 } 597 598 /*- 599 * Determines whether the given EC_POINT is an actual point on the curve defined 600 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: 601 * y^2 + x*y = x^3 + a*x^2 + b. 602 */ 603 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 604 BN_CTX *ctx) 605 { 606 int ret = -1; 607 BN_CTX *new_ctx = NULL; 608 BIGNUM *lh, *y2; 609 int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, 610 const BIGNUM *, BN_CTX *); 611 int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 612 613 if (EC_POINT_is_at_infinity(group, point)) 614 return 1; 615 616 field_mul = group->meth->field_mul; 617 field_sqr = group->meth->field_sqr; 618 619 /* only support affine coordinates */ 620 if (!point->Z_is_one) 621 return -1; 622 623 if (ctx == NULL) { 624 ctx = new_ctx = BN_CTX_new(); 625 if (ctx == NULL) 626 return -1; 627 } 628 629 BN_CTX_start(ctx); 630 y2 = BN_CTX_get(ctx); 631 lh = BN_CTX_get(ctx); 632 if (lh == NULL) 633 goto err; 634 635 /*- 636 * We have a curve defined by a Weierstrass equation 637 * y^2 + x*y = x^3 + a*x^2 + b. 638 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 639 * <=> ((x + a) * x + y ) * x + b + y^2 = 0 640 */ 641 if (!BN_GF2m_add(lh, &point->X, &group->a)) 642 goto err; 643 if (!field_mul(group, lh, lh, &point->X, ctx)) 644 goto err; 645 if (!BN_GF2m_add(lh, lh, &point->Y)) 646 goto err; 647 if (!field_mul(group, lh, lh, &point->X, ctx)) 648 goto err; 649 if (!BN_GF2m_add(lh, lh, &group->b)) 650 goto err; 651 if (!field_sqr(group, y2, &point->Y, ctx)) 652 goto err; 653 if (!BN_GF2m_add(lh, lh, y2)) 654 goto err; 655 ret = BN_is_zero(lh); 656 err: 657 if (ctx) 658 BN_CTX_end(ctx); 659 if (new_ctx) 660 BN_CTX_free(new_ctx); 661 return ret; 662 } 663 664 /*- 665 * Indicates whether two points are equal. 666 * Return values: 667 * -1 error 668 * 0 equal (in affine coordinates) 669 * 1 not equal 670 */ 671 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, 672 const EC_POINT *b, BN_CTX *ctx) 673 { 674 BIGNUM *aX, *aY, *bX, *bY; 675 BN_CTX *new_ctx = NULL; 676 int ret = -1; 677 678 if (EC_POINT_is_at_infinity(group, a)) { 679 return EC_POINT_is_at_infinity(group, b) ? 0 : 1; 680 } 681 682 if (EC_POINT_is_at_infinity(group, b)) 683 return 1; 684 685 if (a->Z_is_one && b->Z_is_one) { 686 return ((BN_cmp(&a->X, &b->X) == 0) 687 && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; 688 } 689 690 if (ctx == NULL) { 691 ctx = new_ctx = BN_CTX_new(); 692 if (ctx == NULL) 693 return -1; 694 } 695 696 BN_CTX_start(ctx); 697 aX = BN_CTX_get(ctx); 698 aY = BN_CTX_get(ctx); 699 bX = BN_CTX_get(ctx); 700 bY = BN_CTX_get(ctx); 701 if (bY == NULL) 702 goto err; 703 704 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) 705 goto err; 706 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) 707 goto err; 708 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; 709 710 err: 711 if (ctx) 712 BN_CTX_end(ctx); 713 if (new_ctx) 714 BN_CTX_free(new_ctx); 715 return ret; 716 } 717 718 /* Forces the given EC_POINT to internally use affine coordinates. */ 719 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, 720 BN_CTX *ctx) 721 { 722 BN_CTX *new_ctx = NULL; 723 BIGNUM *x, *y; 724 int ret = 0; 725 726 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) 727 return 1; 728 729 if (ctx == NULL) { 730 ctx = new_ctx = BN_CTX_new(); 731 if (ctx == NULL) 732 return 0; 733 } 734 735 BN_CTX_start(ctx); 736 x = BN_CTX_get(ctx); 737 y = BN_CTX_get(ctx); 738 if (y == NULL) 739 goto err; 740 741 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) 742 goto err; 743 if (!BN_copy(&point->X, x)) 744 goto err; 745 if (!BN_copy(&point->Y, y)) 746 goto err; 747 if (!BN_one(&point->Z)) 748 goto err; 749 point->Z_is_one = 1; 750 751 ret = 1; 752 753 err: 754 if (ctx) 755 BN_CTX_end(ctx); 756 if (new_ctx) 757 BN_CTX_free(new_ctx); 758 return ret; 759 } 760 761 /* 762 * Forces each of the EC_POINTs in the given array to use affine coordinates. 763 */ 764 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, 765 EC_POINT *points[], BN_CTX *ctx) 766 { 767 size_t i; 768 769 for (i = 0; i < num; i++) { 770 if (!group->meth->make_affine(group, points[i], ctx)) 771 return 0; 772 } 773 774 return 1; 775 } 776 777 /* Wrapper to simple binary polynomial field multiplication implementation. */ 778 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, 779 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 780 { 781 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); 782 } 783 784 /* Wrapper to simple binary polynomial field squaring implementation. */ 785 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, 786 const BIGNUM *a, BN_CTX *ctx) 787 { 788 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); 789 } 790 791 /* Wrapper to simple binary polynomial field division implementation. */ 792 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, 793 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 794 { 795 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 796 } 797 798 #endif 799