1 /* Originally written by Bodo Moeller for the OpenSSL project. 2 * ==================================================================== 3 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core (at) openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay (at) cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh (at) cryptsoft.com). 53 * 54 */ 55 /* ==================================================================== 56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 57 * 58 * Portions of the attached software ("Contribution") are developed by 59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 60 * 61 * The Contribution is licensed pursuant to the OpenSSL open source 62 * license provided above. 63 * 64 * The elliptic curve binary polynomial software is originally written by 65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 66 * Laboratories. */ 67 68 #include <openssl/ec.h> 69 70 #include <openssl/bn.h> 71 #include <openssl/err.h> 72 #include <openssl/mem.h> 73 74 #include "internal.h" 75 76 77 const EC_METHOD *EC_GFp_simple_method(void) { 78 static const EC_METHOD ret = {EC_FLAGS_DEFAULT_OCT, 79 ec_GFp_simple_group_init, 80 ec_GFp_simple_group_finish, 81 ec_GFp_simple_group_clear_finish, 82 ec_GFp_simple_group_copy, 83 ec_GFp_simple_group_set_curve, 84 ec_GFp_simple_group_get_curve, 85 ec_GFp_simple_group_get_degree, 86 ec_GFp_simple_group_check_discriminant, 87 ec_GFp_simple_point_init, 88 ec_GFp_simple_point_finish, 89 ec_GFp_simple_point_clear_finish, 90 ec_GFp_simple_point_copy, 91 ec_GFp_simple_point_set_to_infinity, 92 ec_GFp_simple_set_Jprojective_coordinates_GFp, 93 ec_GFp_simple_get_Jprojective_coordinates_GFp, 94 ec_GFp_simple_point_set_affine_coordinates, 95 ec_GFp_simple_point_get_affine_coordinates, 96 0, 97 0, 98 0, 99 ec_GFp_simple_add, 100 ec_GFp_simple_dbl, 101 ec_GFp_simple_invert, 102 ec_GFp_simple_is_at_infinity, 103 ec_GFp_simple_is_on_curve, 104 ec_GFp_simple_cmp, 105 ec_GFp_simple_make_affine, 106 ec_GFp_simple_points_make_affine, 107 0 /* mul */, 108 0 /* precompute_mult */, 109 0 /* have_precompute_mult */, 110 ec_GFp_simple_field_mul, 111 ec_GFp_simple_field_sqr, 112 0 /* field_div */, 113 0 /* field_encode */, 114 0 /* field_decode */, 115 0 /* field_set_to_one */}; 116 117 return &ret; 118 } 119 120 121 /* Most method functions in this file are designed to work with non-trivial 122 * representations of field elements if necessary (see ecp_mont.c): while 123 * standard modular addition and subtraction are used, the field_mul and 124 * field_sqr methods will be used for multiplication, and field_encode and 125 * field_decode (if defined) will be used for converting between 126 * representations. 127 128 * Functions ec_GFp_simple_points_make_affine() and 129 * ec_GFp_simple_point_get_affine_coordinates() specifically assume that if a 130 * non-trivial representation is used, it is a Montgomery representation (i.e. 131 * 'encoding' means multiplying by some factor R). */ 132 133 int ec_GFp_simple_group_init(EC_GROUP *group) { 134 BN_init(&group->field); 135 BN_init(&group->a); 136 BN_init(&group->b); 137 group->a_is_minus3 = 0; 138 return 1; 139 } 140 141 void ec_GFp_simple_group_finish(EC_GROUP *group) { 142 BN_free(&group->field); 143 BN_free(&group->a); 144 BN_free(&group->b); 145 } 146 147 void ec_GFp_simple_group_clear_finish(EC_GROUP *group) { 148 BN_clear_free(&group->field); 149 BN_clear_free(&group->a); 150 BN_clear_free(&group->b); 151 } 152 153 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) { 154 if (!BN_copy(&dest->field, &src->field) || 155 !BN_copy(&dest->a, &src->a) || 156 !BN_copy(&dest->b, &src->b)) { 157 return 0; 158 } 159 160 dest->a_is_minus3 = src->a_is_minus3; 161 return 1; 162 } 163 164 int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, 165 const BIGNUM *a, const BIGNUM *b, 166 BN_CTX *ctx) { 167 int ret = 0; 168 BN_CTX *new_ctx = NULL; 169 BIGNUM *tmp_a; 170 171 /* p must be a prime > 3 */ 172 if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { 173 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_group_set_curve, EC_R_INVALID_FIELD); 174 return 0; 175 } 176 177 if (ctx == NULL) { 178 ctx = new_ctx = BN_CTX_new(); 179 if (ctx == NULL) 180 return 0; 181 } 182 183 BN_CTX_start(ctx); 184 tmp_a = BN_CTX_get(ctx); 185 if (tmp_a == NULL) 186 goto err; 187 188 /* group->field */ 189 if (!BN_copy(&group->field, p)) 190 goto err; 191 BN_set_negative(&group->field, 0); 192 193 /* group->a */ 194 if (!BN_nnmod(tmp_a, a, p, ctx)) 195 goto err; 196 if (group->meth->field_encode) { 197 if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) 198 goto err; 199 } else if (!BN_copy(&group->a, tmp_a)) 200 goto err; 201 202 /* group->b */ 203 if (!BN_nnmod(&group->b, b, p, ctx)) 204 goto err; 205 if (group->meth->field_encode) 206 if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) 207 goto err; 208 209 /* group->a_is_minus3 */ 210 if (!BN_add_word(tmp_a, 3)) 211 goto err; 212 group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); 213 214 ret = 1; 215 216 err: 217 BN_CTX_end(ctx); 218 if (new_ctx != NULL) 219 BN_CTX_free(new_ctx); 220 return ret; 221 } 222 223 int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 224 BIGNUM *b, BN_CTX *ctx) { 225 int ret = 0; 226 BN_CTX *new_ctx = NULL; 227 228 if (p != NULL) { 229 if (!BN_copy(p, &group->field)) 230 return 0; 231 } 232 233 if (a != NULL || b != NULL) { 234 if (group->meth->field_decode) { 235 if (ctx == NULL) { 236 ctx = new_ctx = BN_CTX_new(); 237 if (ctx == NULL) 238 return 0; 239 } 240 if (a != NULL) { 241 if (!group->meth->field_decode(group, a, &group->a, ctx)) 242 goto err; 243 } 244 if (b != NULL) { 245 if (!group->meth->field_decode(group, b, &group->b, ctx)) 246 goto err; 247 } 248 } else { 249 if (a != NULL) { 250 if (!BN_copy(a, &group->a)) 251 goto err; 252 } 253 if (b != NULL) { 254 if (!BN_copy(b, &group->b)) 255 goto err; 256 } 257 } 258 } 259 260 ret = 1; 261 262 err: 263 if (new_ctx) 264 BN_CTX_free(new_ctx); 265 return ret; 266 } 267 268 int ec_GFp_simple_group_get_degree(const EC_GROUP *group) { 269 return BN_num_bits(&group->field); 270 } 271 272 int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) { 273 int ret = 0; 274 BIGNUM *a, *b, *order, *tmp_1, *tmp_2; 275 const BIGNUM *p = &group->field; 276 BN_CTX *new_ctx = NULL; 277 278 if (ctx == NULL) { 279 ctx = new_ctx = BN_CTX_new(); 280 if (ctx == NULL) { 281 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_group_check_discriminant, 282 ERR_R_MALLOC_FAILURE); 283 goto err; 284 } 285 } 286 BN_CTX_start(ctx); 287 a = BN_CTX_get(ctx); 288 b = BN_CTX_get(ctx); 289 tmp_1 = BN_CTX_get(ctx); 290 tmp_2 = BN_CTX_get(ctx); 291 order = BN_CTX_get(ctx); 292 if (order == NULL) 293 goto err; 294 295 if (group->meth->field_decode) { 296 if (!group->meth->field_decode(group, a, &group->a, ctx)) 297 goto err; 298 if (!group->meth->field_decode(group, b, &group->b, ctx)) 299 goto err; 300 } else { 301 if (!BN_copy(a, &group->a)) 302 goto err; 303 if (!BN_copy(b, &group->b)) 304 goto err; 305 } 306 307 /* check the discriminant: 308 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) 309 * 0 =< a, b < p */ 310 if (BN_is_zero(a)) { 311 if (BN_is_zero(b)) 312 goto err; 313 } else if (!BN_is_zero(b)) { 314 if (!BN_mod_sqr(tmp_1, a, p, ctx)) 315 goto err; 316 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) 317 goto err; 318 if (!BN_lshift(tmp_1, tmp_2, 2)) 319 goto err; 320 /* tmp_1 = 4*a^3 */ 321 322 if (!BN_mod_sqr(tmp_2, b, p, ctx)) 323 goto err; 324 if (!BN_mul_word(tmp_2, 27)) 325 goto err; 326 /* tmp_2 = 27*b^2 */ 327 328 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) 329 goto err; 330 if (BN_is_zero(a)) 331 goto err; 332 } 333 ret = 1; 334 335 err: 336 if (ctx != NULL) 337 BN_CTX_end(ctx); 338 if (new_ctx != NULL) 339 BN_CTX_free(new_ctx); 340 return ret; 341 } 342 343 int ec_GFp_simple_point_init(EC_POINT *point) { 344 BN_init(&point->X); 345 BN_init(&point->Y); 346 BN_init(&point->Z); 347 point->Z_is_one = 0; 348 349 return 1; 350 } 351 352 void ec_GFp_simple_point_finish(EC_POINT *point) { 353 BN_free(&point->X); 354 BN_free(&point->Y); 355 BN_free(&point->Z); 356 } 357 358 void ec_GFp_simple_point_clear_finish(EC_POINT *point) { 359 BN_clear_free(&point->X); 360 BN_clear_free(&point->Y); 361 BN_clear_free(&point->Z); 362 point->Z_is_one = 0; 363 } 364 365 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) { 366 if (!BN_copy(&dest->X, &src->X)) 367 return 0; 368 if (!BN_copy(&dest->Y, &src->Y)) 369 return 0; 370 if (!BN_copy(&dest->Z, &src->Z)) 371 return 0; 372 dest->Z_is_one = src->Z_is_one; 373 374 return 1; 375 } 376 377 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, 378 EC_POINT *point) { 379 point->Z_is_one = 0; 380 BN_zero(&point->Z); 381 return 1; 382 } 383 384 int ec_GFp_simple_set_Jprojective_coordinates_GFp( 385 const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, 386 const BIGNUM *z, BN_CTX *ctx) { 387 BN_CTX *new_ctx = NULL; 388 int ret = 0; 389 390 if (ctx == NULL) { 391 ctx = new_ctx = BN_CTX_new(); 392 if (ctx == NULL) 393 return 0; 394 } 395 396 if (x != NULL) { 397 if (!BN_nnmod(&point->X, x, &group->field, ctx)) 398 goto err; 399 if (group->meth->field_encode) { 400 if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) 401 goto err; 402 } 403 } 404 405 if (y != NULL) { 406 if (!BN_nnmod(&point->Y, y, &group->field, ctx)) 407 goto err; 408 if (group->meth->field_encode) { 409 if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) 410 goto err; 411 } 412 } 413 414 if (z != NULL) { 415 int Z_is_one; 416 417 if (!BN_nnmod(&point->Z, z, &group->field, ctx)) 418 goto err; 419 Z_is_one = BN_is_one(&point->Z); 420 if (group->meth->field_encode) { 421 if (Z_is_one && (group->meth->field_set_to_one != 0)) { 422 if (!group->meth->field_set_to_one(group, &point->Z, ctx)) 423 goto err; 424 } else { 425 if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) 426 goto err; 427 } 428 } 429 point->Z_is_one = Z_is_one; 430 } 431 432 ret = 1; 433 434 err: 435 if (new_ctx != NULL) 436 BN_CTX_free(new_ctx); 437 return ret; 438 } 439 440 int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 441 const EC_POINT *point, 442 BIGNUM *x, BIGNUM *y, 443 BIGNUM *z, BN_CTX *ctx) { 444 BN_CTX *new_ctx = NULL; 445 int ret = 0; 446 447 if (group->meth->field_decode != 0) { 448 if (ctx == NULL) { 449 ctx = new_ctx = BN_CTX_new(); 450 if (ctx == NULL) 451 return 0; 452 } 453 454 if (x != NULL) { 455 if (!group->meth->field_decode(group, x, &point->X, ctx)) 456 goto err; 457 } 458 if (y != NULL) { 459 if (!group->meth->field_decode(group, y, &point->Y, ctx)) 460 goto err; 461 } 462 if (z != NULL) { 463 if (!group->meth->field_decode(group, z, &point->Z, ctx)) 464 goto err; 465 } 466 } else { 467 if (x != NULL) { 468 if (!BN_copy(x, &point->X)) 469 goto err; 470 } 471 if (y != NULL) { 472 if (!BN_copy(y, &point->Y)) 473 goto err; 474 } 475 if (z != NULL) { 476 if (!BN_copy(z, &point->Z)) 477 goto err; 478 } 479 } 480 481 ret = 1; 482 483 err: 484 if (new_ctx != NULL) 485 BN_CTX_free(new_ctx); 486 return ret; 487 } 488 489 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, 490 EC_POINT *point, const BIGNUM *x, 491 const BIGNUM *y, BN_CTX *ctx) { 492 if (x == NULL || y == NULL) { 493 /* unlike for projective coordinates, we do not tolerate this */ 494 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_set_affine_coordinates, 495 ERR_R_PASSED_NULL_PARAMETER); 496 return 0; 497 } 498 499 return ec_point_set_Jprojective_coordinates_GFp(group, point, x, y, 500 BN_value_one(), ctx); 501 } 502 503 int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, 504 const EC_POINT *point, BIGNUM *x, 505 BIGNUM *y, BN_CTX *ctx) { 506 BN_CTX *new_ctx = NULL; 507 BIGNUM *Z, *Z_1, *Z_2, *Z_3; 508 const BIGNUM *Z_; 509 int ret = 0; 510 511 if (EC_POINT_is_at_infinity(group, point)) { 512 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_get_affine_coordinates, 513 EC_R_POINT_AT_INFINITY); 514 return 0; 515 } 516 517 if (ctx == NULL) { 518 ctx = new_ctx = BN_CTX_new(); 519 if (ctx == NULL) 520 return 0; 521 } 522 523 BN_CTX_start(ctx); 524 Z = BN_CTX_get(ctx); 525 Z_1 = BN_CTX_get(ctx); 526 Z_2 = BN_CTX_get(ctx); 527 Z_3 = BN_CTX_get(ctx); 528 if (Z_3 == NULL) 529 goto err; 530 531 /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ 532 533 if (group->meth->field_decode) { 534 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) 535 goto err; 536 Z_ = Z; 537 } else { 538 Z_ = &point->Z; 539 } 540 541 if (BN_is_one(Z_)) { 542 if (group->meth->field_decode) { 543 if (x != NULL) { 544 if (!group->meth->field_decode(group, x, &point->X, ctx)) 545 goto err; 546 } 547 if (y != NULL) { 548 if (!group->meth->field_decode(group, y, &point->Y, ctx)) 549 goto err; 550 } 551 } else { 552 if (x != NULL) { 553 if (!BN_copy(x, &point->X)) 554 goto err; 555 } 556 if (y != NULL) { 557 if (!BN_copy(y, &point->Y)) 558 goto err; 559 } 560 } 561 } else { 562 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) { 563 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_point_get_affine_coordinates, 564 ERR_R_BN_LIB); 565 goto err; 566 } 567 568 if (group->meth->field_encode == 0) { 569 /* field_sqr works on standard representation */ 570 if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) 571 goto err; 572 } else { 573 if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) 574 goto err; 575 } 576 577 if (x != NULL) { 578 /* in the Montgomery case, field_mul will cancel out Montgomery factor in 579 * X: */ 580 if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) 581 goto err; 582 } 583 584 if (y != NULL) { 585 if (group->meth->field_encode == 0) { 586 /* field_mul works on standard representation */ 587 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) 588 goto err; 589 } else { 590 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) 591 goto err; 592 } 593 594 /* in the Montgomery case, field_mul will cancel out Montgomery factor in 595 * Y: */ 596 if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) 597 goto err; 598 } 599 } 600 601 ret = 1; 602 603 err: 604 BN_CTX_end(ctx); 605 if (new_ctx != NULL) 606 BN_CTX_free(new_ctx); 607 return ret; 608 } 609 610 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 611 const EC_POINT *b, BN_CTX *ctx) { 612 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, 613 BN_CTX *); 614 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 615 const BIGNUM *p; 616 BN_CTX *new_ctx = NULL; 617 BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; 618 int ret = 0; 619 620 if (a == b) 621 return EC_POINT_dbl(group, r, a, ctx); 622 if (EC_POINT_is_at_infinity(group, a)) 623 return EC_POINT_copy(r, b); 624 if (EC_POINT_is_at_infinity(group, b)) 625 return EC_POINT_copy(r, a); 626 627 field_mul = group->meth->field_mul; 628 field_sqr = group->meth->field_sqr; 629 p = &group->field; 630 631 if (ctx == NULL) { 632 ctx = new_ctx = BN_CTX_new(); 633 if (ctx == NULL) 634 return 0; 635 } 636 637 BN_CTX_start(ctx); 638 n0 = BN_CTX_get(ctx); 639 n1 = BN_CTX_get(ctx); 640 n2 = BN_CTX_get(ctx); 641 n3 = BN_CTX_get(ctx); 642 n4 = BN_CTX_get(ctx); 643 n5 = BN_CTX_get(ctx); 644 n6 = BN_CTX_get(ctx); 645 if (n6 == NULL) 646 goto end; 647 648 /* Note that in this function we must not read components of 'a' or 'b' 649 * once we have written the corresponding components of 'r'. 650 * ('r' might be one of 'a' or 'b'.) 651 */ 652 653 /* n1, n2 */ 654 if (b->Z_is_one) { 655 if (!BN_copy(n1, &a->X)) 656 goto end; 657 if (!BN_copy(n2, &a->Y)) 658 goto end; 659 /* n1 = X_a */ 660 /* n2 = Y_a */ 661 } else { 662 if (!field_sqr(group, n0, &b->Z, ctx)) 663 goto end; 664 if (!field_mul(group, n1, &a->X, n0, ctx)) 665 goto end; 666 /* n1 = X_a * Z_b^2 */ 667 668 if (!field_mul(group, n0, n0, &b->Z, ctx)) 669 goto end; 670 if (!field_mul(group, n2, &a->Y, n0, ctx)) 671 goto end; 672 /* n2 = Y_a * Z_b^3 */ 673 } 674 675 /* n3, n4 */ 676 if (a->Z_is_one) { 677 if (!BN_copy(n3, &b->X)) 678 goto end; 679 if (!BN_copy(n4, &b->Y)) 680 goto end; 681 /* n3 = X_b */ 682 /* n4 = Y_b */ 683 } else { 684 if (!field_sqr(group, n0, &a->Z, ctx)) 685 goto end; 686 if (!field_mul(group, n3, &b->X, n0, ctx)) 687 goto end; 688 /* n3 = X_b * Z_a^2 */ 689 690 if (!field_mul(group, n0, n0, &a->Z, ctx)) 691 goto end; 692 if (!field_mul(group, n4, &b->Y, n0, ctx)) 693 goto end; 694 /* n4 = Y_b * Z_a^3 */ 695 } 696 697 /* n5, n6 */ 698 if (!BN_mod_sub_quick(n5, n1, n3, p)) 699 goto end; 700 if (!BN_mod_sub_quick(n6, n2, n4, p)) 701 goto end; 702 /* n5 = n1 - n3 */ 703 /* n6 = n2 - n4 */ 704 705 if (BN_is_zero(n5)) { 706 if (BN_is_zero(n6)) { 707 /* a is the same point as b */ 708 BN_CTX_end(ctx); 709 ret = EC_POINT_dbl(group, r, a, ctx); 710 ctx = NULL; 711 goto end; 712 } else { 713 /* a is the inverse of b */ 714 BN_zero(&r->Z); 715 r->Z_is_one = 0; 716 ret = 1; 717 goto end; 718 } 719 } 720 721 /* 'n7', 'n8' */ 722 if (!BN_mod_add_quick(n1, n1, n3, p)) 723 goto end; 724 if (!BN_mod_add_quick(n2, n2, n4, p)) 725 goto end; 726 /* 'n7' = n1 + n3 */ 727 /* 'n8' = n2 + n4 */ 728 729 /* Z_r */ 730 if (a->Z_is_one && b->Z_is_one) { 731 if (!BN_copy(&r->Z, n5)) 732 goto end; 733 } else { 734 if (a->Z_is_one) { 735 if (!BN_copy(n0, &b->Z)) 736 goto end; 737 } else if (b->Z_is_one) { 738 if (!BN_copy(n0, &a->Z)) 739 goto end; 740 } else { 741 if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) 742 goto end; 743 } 744 if (!field_mul(group, &r->Z, n0, n5, ctx)) 745 goto end; 746 } 747 r->Z_is_one = 0; 748 /* Z_r = Z_a * Z_b * n5 */ 749 750 /* X_r */ 751 if (!field_sqr(group, n0, n6, ctx)) 752 goto end; 753 if (!field_sqr(group, n4, n5, ctx)) 754 goto end; 755 if (!field_mul(group, n3, n1, n4, ctx)) 756 goto end; 757 if (!BN_mod_sub_quick(&r->X, n0, n3, p)) 758 goto end; 759 /* X_r = n6^2 - n5^2 * 'n7' */ 760 761 /* 'n9' */ 762 if (!BN_mod_lshift1_quick(n0, &r->X, p)) 763 goto end; 764 if (!BN_mod_sub_quick(n0, n3, n0, p)) 765 goto end; 766 /* n9 = n5^2 * 'n7' - 2 * X_r */ 767 768 /* Y_r */ 769 if (!field_mul(group, n0, n0, n6, ctx)) 770 goto end; 771 if (!field_mul(group, n5, n4, n5, ctx)) 772 goto end; /* now n5 is n5^3 */ 773 if (!field_mul(group, n1, n2, n5, ctx)) 774 goto end; 775 if (!BN_mod_sub_quick(n0, n0, n1, p)) 776 goto end; 777 if (BN_is_odd(n0)) 778 if (!BN_add(n0, n0, p)) 779 goto end; 780 /* now 0 <= n0 < 2*p, and n0 is even */ 781 if (!BN_rshift1(&r->Y, n0)) 782 goto end; 783 /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ 784 785 ret = 1; 786 787 end: 788 if (ctx) /* otherwise we already called BN_CTX_end */ 789 BN_CTX_end(ctx); 790 if (new_ctx != NULL) 791 BN_CTX_free(new_ctx); 792 return ret; 793 } 794 795 int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 796 BN_CTX *ctx) { 797 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, 798 BN_CTX *); 799 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 800 const BIGNUM *p; 801 BN_CTX *new_ctx = NULL; 802 BIGNUM *n0, *n1, *n2, *n3; 803 int ret = 0; 804 805 if (EC_POINT_is_at_infinity(group, a)) { 806 BN_zero(&r->Z); 807 r->Z_is_one = 0; 808 return 1; 809 } 810 811 field_mul = group->meth->field_mul; 812 field_sqr = group->meth->field_sqr; 813 p = &group->field; 814 815 if (ctx == NULL) { 816 ctx = new_ctx = BN_CTX_new(); 817 if (ctx == NULL) 818 return 0; 819 } 820 821 BN_CTX_start(ctx); 822 n0 = BN_CTX_get(ctx); 823 n1 = BN_CTX_get(ctx); 824 n2 = BN_CTX_get(ctx); 825 n3 = BN_CTX_get(ctx); 826 if (n3 == NULL) 827 goto err; 828 829 /* Note that in this function we must not read components of 'a' 830 * once we have written the corresponding components of 'r'. 831 * ('r' might the same as 'a'.) 832 */ 833 834 /* n1 */ 835 if (a->Z_is_one) { 836 if (!field_sqr(group, n0, &a->X, ctx)) 837 goto err; 838 if (!BN_mod_lshift1_quick(n1, n0, p)) 839 goto err; 840 if (!BN_mod_add_quick(n0, n0, n1, p)) 841 goto err; 842 if (!BN_mod_add_quick(n1, n0, &group->a, p)) 843 goto err; 844 /* n1 = 3 * X_a^2 + a_curve */ 845 } else if (group->a_is_minus3) { 846 if (!field_sqr(group, n1, &a->Z, ctx)) 847 goto err; 848 if (!BN_mod_add_quick(n0, &a->X, n1, p)) 849 goto err; 850 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) 851 goto err; 852 if (!field_mul(group, n1, n0, n2, ctx)) 853 goto err; 854 if (!BN_mod_lshift1_quick(n0, n1, p)) 855 goto err; 856 if (!BN_mod_add_quick(n1, n0, n1, p)) 857 goto err; 858 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) 859 * = 3 * X_a^2 - 3 * Z_a^4 */ 860 } else { 861 if (!field_sqr(group, n0, &a->X, ctx)) 862 goto err; 863 if (!BN_mod_lshift1_quick(n1, n0, p)) 864 goto err; 865 if (!BN_mod_add_quick(n0, n0, n1, p)) 866 goto err; 867 if (!field_sqr(group, n1, &a->Z, ctx)) 868 goto err; 869 if (!field_sqr(group, n1, n1, ctx)) 870 goto err; 871 if (!field_mul(group, n1, n1, &group->a, ctx)) 872 goto err; 873 if (!BN_mod_add_quick(n1, n1, n0, p)) 874 goto err; 875 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ 876 } 877 878 /* Z_r */ 879 if (a->Z_is_one) { 880 if (!BN_copy(n0, &a->Y)) 881 goto err; 882 } else { 883 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) 884 goto err; 885 } 886 if (!BN_mod_lshift1_quick(&r->Z, n0, p)) 887 goto err; 888 r->Z_is_one = 0; 889 /* Z_r = 2 * Y_a * Z_a */ 890 891 /* n2 */ 892 if (!field_sqr(group, n3, &a->Y, ctx)) 893 goto err; 894 if (!field_mul(group, n2, &a->X, n3, ctx)) 895 goto err; 896 if (!BN_mod_lshift_quick(n2, n2, 2, p)) 897 goto err; 898 /* n2 = 4 * X_a * Y_a^2 */ 899 900 /* X_r */ 901 if (!BN_mod_lshift1_quick(n0, n2, p)) 902 goto err; 903 if (!field_sqr(group, &r->X, n1, ctx)) 904 goto err; 905 if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) 906 goto err; 907 /* X_r = n1^2 - 2 * n2 */ 908 909 /* n3 */ 910 if (!field_sqr(group, n0, n3, ctx)) 911 goto err; 912 if (!BN_mod_lshift_quick(n3, n0, 3, p)) 913 goto err; 914 /* n3 = 8 * Y_a^4 */ 915 916 /* Y_r */ 917 if (!BN_mod_sub_quick(n0, n2, &r->X, p)) 918 goto err; 919 if (!field_mul(group, n0, n1, n0, ctx)) 920 goto err; 921 if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) 922 goto err; 923 /* Y_r = n1 * (n2 - X_r) - n3 */ 924 925 ret = 1; 926 927 err: 928 BN_CTX_end(ctx); 929 if (new_ctx != NULL) 930 BN_CTX_free(new_ctx); 931 return ret; 932 } 933 934 int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { 935 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) 936 /* point is its own inverse */ 937 return 1; 938 939 return BN_usub(&point->Y, &group->field, &point->Y); 940 } 941 942 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { 943 return !point->Z_is_one && BN_is_zero(&point->Z); 944 } 945 946 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 947 BN_CTX *ctx) { 948 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, 949 BN_CTX *); 950 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 951 const BIGNUM *p; 952 BN_CTX *new_ctx = NULL; 953 BIGNUM *rh, *tmp, *Z4, *Z6; 954 int ret = -1; 955 956 if (EC_POINT_is_at_infinity(group, point)) 957 return 1; 958 959 field_mul = group->meth->field_mul; 960 field_sqr = group->meth->field_sqr; 961 p = &group->field; 962 963 if (ctx == NULL) { 964 ctx = new_ctx = BN_CTX_new(); 965 if (ctx == NULL) 966 return -1; 967 } 968 969 BN_CTX_start(ctx); 970 rh = BN_CTX_get(ctx); 971 tmp = BN_CTX_get(ctx); 972 Z4 = BN_CTX_get(ctx); 973 Z6 = BN_CTX_get(ctx); 974 if (Z6 == NULL) 975 goto err; 976 977 /* We have a curve defined by a Weierstrass equation 978 * y^2 = x^3 + a*x + b. 979 * The point to consider is given in Jacobian projective coordinates 980 * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). 981 * Substituting this and multiplying by Z^6 transforms the above equation 982 * into 983 * Y^2 = X^3 + a*X*Z^4 + b*Z^6. 984 * To test this, we add up the right-hand side in 'rh'. 985 */ 986 987 /* rh := X^2 */ 988 if (!field_sqr(group, rh, &point->X, ctx)) 989 goto err; 990 991 if (!point->Z_is_one) { 992 if (!field_sqr(group, tmp, &point->Z, ctx)) 993 goto err; 994 if (!field_sqr(group, Z4, tmp, ctx)) 995 goto err; 996 if (!field_mul(group, Z6, Z4, tmp, ctx)) 997 goto err; 998 999 /* rh := (rh + a*Z^4)*X */ 1000 if (group->a_is_minus3) { 1001 if (!BN_mod_lshift1_quick(tmp, Z4, p)) 1002 goto err; 1003 if (!BN_mod_add_quick(tmp, tmp, Z4, p)) 1004 goto err; 1005 if (!BN_mod_sub_quick(rh, rh, tmp, p)) 1006 goto err; 1007 if (!field_mul(group, rh, rh, &point->X, ctx)) 1008 goto err; 1009 } else { 1010 if (!field_mul(group, tmp, Z4, &group->a, ctx)) 1011 goto err; 1012 if (!BN_mod_add_quick(rh, rh, tmp, p)) 1013 goto err; 1014 if (!field_mul(group, rh, rh, &point->X, ctx)) 1015 goto err; 1016 } 1017 1018 /* rh := rh + b*Z^6 */ 1019 if (!field_mul(group, tmp, &group->b, Z6, ctx)) 1020 goto err; 1021 if (!BN_mod_add_quick(rh, rh, tmp, p)) 1022 goto err; 1023 } else { 1024 /* point->Z_is_one */ 1025 1026 /* rh := (rh + a)*X */ 1027 if (!BN_mod_add_quick(rh, rh, &group->a, p)) 1028 goto err; 1029 if (!field_mul(group, rh, rh, &point->X, ctx)) 1030 goto err; 1031 /* rh := rh + b */ 1032 if (!BN_mod_add_quick(rh, rh, &group->b, p)) 1033 goto err; 1034 } 1035 1036 /* 'lh' := Y^2 */ 1037 if (!field_sqr(group, tmp, &point->Y, ctx)) 1038 goto err; 1039 1040 ret = (0 == BN_ucmp(tmp, rh)); 1041 1042 err: 1043 BN_CTX_end(ctx); 1044 if (new_ctx != NULL) 1045 BN_CTX_free(new_ctx); 1046 return ret; 1047 } 1048 1049 int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, 1050 const EC_POINT *b, BN_CTX *ctx) { 1051 /* return values: 1052 * -1 error 1053 * 0 equal (in affine coordinates) 1054 * 1 not equal 1055 */ 1056 1057 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, 1058 BN_CTX *); 1059 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 1060 BN_CTX *new_ctx = NULL; 1061 BIGNUM *tmp1, *tmp2, *Za23, *Zb23; 1062 const BIGNUM *tmp1_, *tmp2_; 1063 int ret = -1; 1064 1065 if (EC_POINT_is_at_infinity(group, a)) { 1066 return EC_POINT_is_at_infinity(group, b) ? 0 : 1; 1067 } 1068 1069 if (EC_POINT_is_at_infinity(group, b)) 1070 return 1; 1071 1072 if (a->Z_is_one && b->Z_is_one) { 1073 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; 1074 } 1075 1076 field_mul = group->meth->field_mul; 1077 field_sqr = group->meth->field_sqr; 1078 1079 if (ctx == NULL) { 1080 ctx = new_ctx = BN_CTX_new(); 1081 if (ctx == NULL) 1082 return -1; 1083 } 1084 1085 BN_CTX_start(ctx); 1086 tmp1 = BN_CTX_get(ctx); 1087 tmp2 = BN_CTX_get(ctx); 1088 Za23 = BN_CTX_get(ctx); 1089 Zb23 = BN_CTX_get(ctx); 1090 if (Zb23 == NULL) 1091 goto end; 1092 1093 /* We have to decide whether 1094 * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), 1095 * or equivalently, whether 1096 * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). 1097 */ 1098 1099 if (!b->Z_is_one) { 1100 if (!field_sqr(group, Zb23, &b->Z, ctx)) 1101 goto end; 1102 if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) 1103 goto end; 1104 tmp1_ = tmp1; 1105 } else 1106 tmp1_ = &a->X; 1107 if (!a->Z_is_one) { 1108 if (!field_sqr(group, Za23, &a->Z, ctx)) 1109 goto end; 1110 if (!field_mul(group, tmp2, &b->X, Za23, ctx)) 1111 goto end; 1112 tmp2_ = tmp2; 1113 } else 1114 tmp2_ = &b->X; 1115 1116 /* compare X_a*Z_b^2 with X_b*Z_a^2 */ 1117 if (BN_cmp(tmp1_, tmp2_) != 0) { 1118 ret = 1; /* points differ */ 1119 goto end; 1120 } 1121 1122 1123 if (!b->Z_is_one) { 1124 if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) 1125 goto end; 1126 if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) 1127 goto end; 1128 /* tmp1_ = tmp1 */ 1129 } else 1130 tmp1_ = &a->Y; 1131 if (!a->Z_is_one) { 1132 if (!field_mul(group, Za23, Za23, &a->Z, ctx)) 1133 goto end; 1134 if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) 1135 goto end; 1136 /* tmp2_ = tmp2 */ 1137 } else 1138 tmp2_ = &b->Y; 1139 1140 /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ 1141 if (BN_cmp(tmp1_, tmp2_) != 0) { 1142 ret = 1; /* points differ */ 1143 goto end; 1144 } 1145 1146 /* points are equal */ 1147 ret = 0; 1148 1149 end: 1150 BN_CTX_end(ctx); 1151 if (new_ctx != NULL) 1152 BN_CTX_free(new_ctx); 1153 return ret; 1154 } 1155 1156 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, 1157 BN_CTX *ctx) { 1158 BN_CTX *new_ctx = NULL; 1159 BIGNUM *x, *y; 1160 int ret = 0; 1161 1162 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) 1163 return 1; 1164 1165 if (ctx == NULL) { 1166 ctx = new_ctx = BN_CTX_new(); 1167 if (ctx == NULL) 1168 return 0; 1169 } 1170 1171 BN_CTX_start(ctx); 1172 x = BN_CTX_get(ctx); 1173 y = BN_CTX_get(ctx); 1174 if (y == NULL) 1175 goto err; 1176 1177 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) 1178 goto err; 1179 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) 1180 goto err; 1181 if (!point->Z_is_one) { 1182 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_make_affine, ERR_R_INTERNAL_ERROR); 1183 goto err; 1184 } 1185 1186 ret = 1; 1187 1188 err: 1189 BN_CTX_end(ctx); 1190 if (new_ctx != NULL) 1191 BN_CTX_free(new_ctx); 1192 return ret; 1193 } 1194 1195 int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, 1196 EC_POINT *points[], BN_CTX *ctx) { 1197 BN_CTX *new_ctx = NULL; 1198 BIGNUM *tmp, *tmp_Z; 1199 BIGNUM **prod_Z = NULL; 1200 size_t i; 1201 int ret = 0; 1202 1203 if (num == 0) { 1204 return 1; 1205 } 1206 1207 if (ctx == NULL) { 1208 ctx = new_ctx = BN_CTX_new(); 1209 if (ctx == NULL) { 1210 return 0; 1211 } 1212 } 1213 1214 BN_CTX_start(ctx); 1215 tmp = BN_CTX_get(ctx); 1216 tmp_Z = BN_CTX_get(ctx); 1217 if (tmp == NULL || tmp_Z == NULL) { 1218 goto err; 1219 } 1220 1221 prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0])); 1222 if (prod_Z == NULL) { 1223 goto err; 1224 } 1225 memset(prod_Z, 0, num * sizeof(prod_Z[0])); 1226 for (i = 0; i < num; i++) { 1227 prod_Z[i] = BN_new(); 1228 if (prod_Z[i] == NULL) { 1229 goto err; 1230 } 1231 } 1232 1233 /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, 1234 * skipping any zero-valued inputs (pretend that they're 1). */ 1235 1236 if (!BN_is_zero(&points[0]->Z)) { 1237 if (!BN_copy(prod_Z[0], &points[0]->Z)) { 1238 goto err; 1239 } 1240 } else { 1241 if (group->meth->field_set_to_one != 0) { 1242 if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) { 1243 goto err; 1244 } 1245 } else { 1246 if (!BN_one(prod_Z[0])) { 1247 goto err; 1248 } 1249 } 1250 } 1251 1252 for (i = 1; i < num; i++) { 1253 if (!BN_is_zero(&points[i]->Z)) { 1254 if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], 1255 &points[i]->Z, ctx)) { 1256 goto err; 1257 } 1258 } else { 1259 if (!BN_copy(prod_Z[i], prod_Z[i - 1])) { 1260 goto err; 1261 } 1262 } 1263 } 1264 1265 /* Now use a single explicit inversion to replace every 1266 * non-zero points[i]->Z by its inverse. */ 1267 1268 if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { 1269 OPENSSL_PUT_ERROR(EC, ec_GFp_simple_points_make_affine, ERR_R_BN_LIB); 1270 goto err; 1271 } 1272 1273 if (group->meth->field_encode != NULL) { 1274 /* In the Montgomery case, we just turned R*H (representing H) 1275 * into 1/(R*H), but we need R*(1/H) (representing 1/H); 1276 * i.e. we need to multiply by the Montgomery factor twice. */ 1277 if (!group->meth->field_encode(group, tmp, tmp, ctx) || 1278 !group->meth->field_encode(group, tmp, tmp, ctx)) { 1279 goto err; 1280 } 1281 } 1282 1283 for (i = num - 1; i > 0; --i) { 1284 /* Loop invariant: tmp is the product of the inverses of 1285 * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */ 1286 if (BN_is_zero(&points[i]->Z)) { 1287 continue; 1288 } 1289 1290 /* Set tmp_Z to the inverse of points[i]->Z (as product 1291 * of Z inverses 0 .. i, Z values 0 .. i - 1). */ 1292 if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx) || 1293 /* Update tmp to satisfy the loop invariant for i - 1. */ 1294 !group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx) || 1295 /* Replace points[i]->Z by its inverse. */ 1296 !BN_copy(&points[i]->Z, tmp_Z)) { 1297 goto err; 1298 } 1299 } 1300 1301 /* Replace points[0]->Z by its inverse. */ 1302 if (!BN_is_zero(&points[0]->Z) && !BN_copy(&points[0]->Z, tmp)) { 1303 goto err; 1304 } 1305 1306 /* Finally, fix up the X and Y coordinates for all points. */ 1307 for (i = 0; i < num; i++) { 1308 EC_POINT *p = points[i]; 1309 1310 if (!BN_is_zero(&p->Z)) { 1311 /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1). */ 1312 if (!group->meth->field_sqr(group, tmp, &p->Z, ctx) || 1313 !group->meth->field_mul(group, &p->X, &p->X, tmp, ctx) || 1314 !group->meth->field_mul(group, tmp, tmp, &p->Z, ctx) || 1315 !group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) { 1316 goto err; 1317 } 1318 1319 if (group->meth->field_set_to_one != NULL) { 1320 if (!group->meth->field_set_to_one(group, &p->Z, ctx)) { 1321 goto err; 1322 } 1323 } else { 1324 if (!BN_one(&p->Z)) { 1325 goto err; 1326 } 1327 } 1328 p->Z_is_one = 1; 1329 } 1330 } 1331 1332 ret = 1; 1333 1334 err: 1335 BN_CTX_end(ctx); 1336 if (new_ctx != NULL) { 1337 BN_CTX_free(new_ctx); 1338 } 1339 if (prod_Z != NULL) { 1340 for (i = 0; i < num; i++) { 1341 if (prod_Z[i] != NULL) { 1342 BN_clear_free(prod_Z[i]); 1343 } 1344 } 1345 OPENSSL_free(prod_Z); 1346 } 1347 1348 return ret; 1349 } 1350 1351 int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 1352 const BIGNUM *b, BN_CTX *ctx) { 1353 return BN_mod_mul(r, a, b, &group->field, ctx); 1354 } 1355 1356 int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 1357 BN_CTX *ctx) { 1358 return BN_mod_sqr(r, a, &group->field, ctx); 1359 } 1360