1 /* $OpenBSD: ec_lib.c,v 1.61 2023/06/25 18:52:27 tb Exp $ */ 2 /* 3 * Originally written by Bodo Moeller for the OpenSSL project. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * openssl-core@openssl.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 /* ==================================================================== 59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60 * Binary polynomial ECC support in OpenSSL originally developed by 61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 62 */ 63 64 #include <string.h> 65 66 #include <openssl/opensslconf.h> 67 68 #include <openssl/err.h> 69 #include <openssl/opensslv.h> 70 71 #include "bn_local.h" 72 #include "ec_local.h" 73 74 /* functions for EC_GROUP objects */ 75 76 EC_GROUP * 77 EC_GROUP_new(const EC_METHOD *meth) 78 { 79 EC_GROUP *ret; 80 81 if (meth == NULL) { 82 ECerror(EC_R_SLOT_FULL); 83 return NULL; 84 } 85 if (meth->group_init == NULL) { 86 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 87 return NULL; 88 } 89 ret = malloc(sizeof *ret); 90 if (ret == NULL) { 91 ECerror(ERR_R_MALLOC_FAILURE); 92 return NULL; 93 } 94 ret->meth = meth; 95 96 ret->generator = NULL; 97 BN_init(&ret->order); 98 BN_init(&ret->cofactor); 99 100 ret->curve_name = 0; 101 ret->asn1_flag = OPENSSL_EC_NAMED_CURVE; 102 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 103 104 ret->seed = NULL; 105 ret->seed_len = 0; 106 107 if (!meth->group_init(ret)) { 108 free(ret); 109 return NULL; 110 } 111 return ret; 112 } 113 114 115 void 116 EC_GROUP_free(EC_GROUP *group) 117 { 118 if (group == NULL) 119 return; 120 121 if (group->meth->group_finish != NULL) 122 group->meth->group_finish(group); 123 124 EC_POINT_free(group->generator); 125 BN_free(&group->order); 126 BN_free(&group->cofactor); 127 128 freezero(group->seed, group->seed_len); 129 freezero(group, sizeof *group); 130 } 131 132 void 133 EC_GROUP_clear_free(EC_GROUP *group) 134 { 135 EC_GROUP_free(group); 136 } 137 138 int 139 EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 140 { 141 if (dest->meth->group_copy == NULL) { 142 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 143 return 0; 144 } 145 if (dest->meth != src->meth) { 146 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 147 return 0; 148 } 149 if (dest == src) 150 return 1; 151 152 if (src->generator != NULL) { 153 if (dest->generator == NULL) { 154 dest->generator = EC_POINT_new(dest); 155 if (dest->generator == NULL) 156 return 0; 157 } 158 if (!EC_POINT_copy(dest->generator, src->generator)) 159 return 0; 160 } else { 161 /* src->generator == NULL */ 162 EC_POINT_free(dest->generator); 163 dest->generator = NULL; 164 } 165 166 if (!bn_copy(&dest->order, &src->order)) 167 return 0; 168 if (!bn_copy(&dest->cofactor, &src->cofactor)) 169 return 0; 170 171 dest->curve_name = src->curve_name; 172 dest->asn1_flag = src->asn1_flag; 173 dest->asn1_form = src->asn1_form; 174 175 if (src->seed) { 176 free(dest->seed); 177 dest->seed = malloc(src->seed_len); 178 if (dest->seed == NULL) 179 return 0; 180 memcpy(dest->seed, src->seed, src->seed_len); 181 dest->seed_len = src->seed_len; 182 } else { 183 free(dest->seed); 184 dest->seed = NULL; 185 dest->seed_len = 0; 186 } 187 188 189 return dest->meth->group_copy(dest, src); 190 } 191 192 193 EC_GROUP * 194 EC_GROUP_dup(const EC_GROUP *a) 195 { 196 EC_GROUP *t = NULL; 197 198 if ((a != NULL) && ((t = EC_GROUP_new(a->meth)) != NULL) && 199 (!EC_GROUP_copy(t, a))) { 200 EC_GROUP_free(t); 201 t = NULL; 202 } 203 return t; 204 } 205 206 207 const EC_METHOD * 208 EC_GROUP_method_of(const EC_GROUP *group) 209 { 210 return group->meth; 211 } 212 213 214 int 215 EC_METHOD_get_field_type(const EC_METHOD *meth) 216 { 217 return meth->field_type; 218 } 219 220 /* 221 * If there is a user-provided cofactor, sanity check and use it. Otherwise 222 * try computing the cofactor from generator order n and field cardinality q. 223 * This works for all curves of cryptographic interest. 224 * 225 * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q) 226 * 227 * So: h_min = (q + 1 - 2*sqrt(q)) / n and h_max = (q + 1 + 2*sqrt(q)) / n and 228 * therefore h_max - h_min = 4*sqrt(q) / n. So if n > 4*sqrt(q) holds, there is 229 * only one possible value for h: 230 * 231 * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil 232 * 233 * Otherwise, zero cofactor and return success. 234 */ 235 static int 236 ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) 237 { 238 BN_CTX *ctx = NULL; 239 BIGNUM *cofactor; 240 int ret = 0; 241 242 BN_zero(&group->cofactor); 243 244 if ((ctx = BN_CTX_new()) == NULL) 245 goto err; 246 247 BN_CTX_start(ctx); 248 if ((cofactor = BN_CTX_get(ctx)) == NULL) 249 goto err; 250 251 /* 252 * Unfortunately, the cofactor is an optional field in many standards. 253 * Internally, the library uses a 0 cofactor as a marker for "unknown 254 * cofactor". So accept in_cofactor == NULL or in_cofactor >= 0. 255 */ 256 if (in_cofactor != NULL && !BN_is_zero(in_cofactor)) { 257 if (BN_is_negative(in_cofactor)) { 258 ECerror(EC_R_UNKNOWN_COFACTOR); 259 goto err; 260 } 261 if (!bn_copy(cofactor, in_cofactor)) 262 goto err; 263 goto done; 264 } 265 266 /* 267 * If the cofactor is too large, we cannot guess it and default to zero. 268 * The RHS of below is a strict overestimate of log(4 * sqrt(q)). 269 */ 270 if (BN_num_bits(&group->order) <= 271 (BN_num_bits(&group->field) + 1) / 2 + 3) 272 goto done; 273 274 /* 275 * Compute 276 * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor. 277 */ 278 279 /* h = n/2 */ 280 if (!BN_rshift1(cofactor, &group->order)) 281 goto err; 282 /* h = 1 + n/2 */ 283 if (!BN_add_word(cofactor, 1)) 284 goto err; 285 /* h = q + 1 + n/2 */ 286 if (!BN_add(cofactor, cofactor, &group->field)) 287 goto err; 288 /* h = (q + 1 + n/2) / n */ 289 if (!BN_div_ct(cofactor, NULL, cofactor, &group->order, ctx)) 290 goto err; 291 292 done: 293 /* Use Hasse's theorem to bound the cofactor. */ 294 if (BN_num_bits(cofactor) > BN_num_bits(&group->field) + 1) { 295 ECerror(EC_R_INVALID_GROUP_ORDER); 296 goto err; 297 } 298 299 if (!bn_copy(&group->cofactor, cofactor)) 300 goto err; 301 302 ret = 1; 303 304 err: 305 BN_CTX_end(ctx); 306 BN_CTX_free(ctx); 307 308 return ret; 309 } 310 311 int 312 EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 313 const BIGNUM *order, const BIGNUM *cofactor) 314 { 315 if (generator == NULL) { 316 ECerror(ERR_R_PASSED_NULL_PARAMETER); 317 return 0; 318 } 319 320 /* Require group->field >= 1. */ 321 if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) { 322 ECerror(EC_R_INVALID_FIELD); 323 return 0; 324 } 325 326 /* 327 * Require order > 1 and enforce an upper bound of at most one bit more 328 * than the field cardinality due to Hasse's theorem. 329 */ 330 if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 || 331 BN_num_bits(order) > BN_num_bits(&group->field) + 1) { 332 ECerror(EC_R_INVALID_GROUP_ORDER); 333 return 0; 334 } 335 336 if (group->generator == NULL) { 337 group->generator = EC_POINT_new(group); 338 if (group->generator == NULL) 339 return 0; 340 } 341 if (!EC_POINT_copy(group->generator, generator)) 342 return 0; 343 344 if (!bn_copy(&group->order, order)) 345 return 0; 346 347 if (!ec_set_cofactor(group, cofactor)) 348 return 0; 349 350 return 1; 351 } 352 353 354 const EC_POINT * 355 EC_GROUP_get0_generator(const EC_GROUP *group) 356 { 357 return group->generator; 358 } 359 360 361 int 362 EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 363 { 364 if (!bn_copy(order, &group->order)) 365 return 0; 366 367 return !BN_is_zero(order); 368 } 369 370 int 371 EC_GROUP_order_bits(const EC_GROUP *group) 372 { 373 return group->meth->group_order_bits(group); 374 } 375 376 int 377 EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 378 { 379 if (!bn_copy(cofactor, &group->cofactor)) 380 return 0; 381 382 return !BN_is_zero(&group->cofactor); 383 } 384 385 386 void 387 EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 388 { 389 group->curve_name = nid; 390 } 391 392 393 int 394 EC_GROUP_get_curve_name(const EC_GROUP *group) 395 { 396 return group->curve_name; 397 } 398 399 400 void 401 EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 402 { 403 group->asn1_flag = flag; 404 } 405 406 407 int 408 EC_GROUP_get_asn1_flag(const EC_GROUP *group) 409 { 410 return group->asn1_flag; 411 } 412 413 414 void 415 EC_GROUP_set_point_conversion_form(EC_GROUP *group, 416 point_conversion_form_t form) 417 { 418 group->asn1_form = form; 419 } 420 421 422 point_conversion_form_t 423 EC_GROUP_get_point_conversion_form(const EC_GROUP *group) 424 { 425 return group->asn1_form; 426 } 427 428 429 size_t 430 EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 431 { 432 if (group->seed) { 433 free(group->seed); 434 group->seed = NULL; 435 group->seed_len = 0; 436 } 437 if (!len || !p) 438 return 1; 439 440 if ((group->seed = malloc(len)) == NULL) 441 return 0; 442 memcpy(group->seed, p, len); 443 group->seed_len = len; 444 445 return len; 446 } 447 448 449 unsigned char * 450 EC_GROUP_get0_seed(const EC_GROUP *group) 451 { 452 return group->seed; 453 } 454 455 456 size_t 457 EC_GROUP_get_seed_len(const EC_GROUP *group) 458 { 459 return group->seed_len; 460 } 461 462 int 463 EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 464 const BIGNUM *b, BN_CTX *ctx_in) 465 { 466 BN_CTX *ctx; 467 int ret = 0; 468 469 if ((ctx = ctx_in) == NULL) 470 ctx = BN_CTX_new(); 471 if (ctx == NULL) 472 goto err; 473 474 if (group->meth->group_set_curve == NULL) { 475 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 476 goto err; 477 } 478 ret = group->meth->group_set_curve(group, p, a, b, ctx); 479 480 err: 481 if (ctx != ctx_in) 482 BN_CTX_free(ctx); 483 484 return ret; 485 } 486 487 int 488 EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, 489 BN_CTX *ctx_in) 490 { 491 BN_CTX *ctx; 492 int ret = 0; 493 494 if ((ctx = ctx_in) == NULL) 495 ctx = BN_CTX_new(); 496 if (ctx == NULL) 497 goto err; 498 499 if (group->meth->group_get_curve == NULL) { 500 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 501 goto err; 502 } 503 ret = group->meth->group_get_curve(group, p, a, b, ctx); 504 505 err: 506 if (ctx != ctx_in) 507 BN_CTX_free(ctx); 508 509 return ret; 510 } 511 512 int 513 EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 514 const BIGNUM *b, BN_CTX *ctx) 515 { 516 return EC_GROUP_set_curve(group, p, a, b, ctx); 517 } 518 519 int 520 EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, 521 BN_CTX *ctx) 522 { 523 return EC_GROUP_get_curve(group, p, a, b, ctx); 524 } 525 526 int 527 EC_GROUP_get_degree(const EC_GROUP *group) 528 { 529 if (group->meth->group_get_degree == NULL) { 530 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 531 return 0; 532 } 533 return group->meth->group_get_degree(group); 534 } 535 536 537 int 538 EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx_in) 539 { 540 BN_CTX *ctx; 541 int ret = 0; 542 543 if ((ctx = ctx_in) == NULL) 544 ctx = BN_CTX_new(); 545 if (ctx == NULL) 546 goto err; 547 548 if (group->meth->group_check_discriminant == NULL) { 549 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 550 goto err; 551 } 552 ret = group->meth->group_check_discriminant(group, ctx); 553 554 err: 555 if (ctx != ctx_in) 556 BN_CTX_free(ctx); 557 558 return ret; 559 } 560 561 562 int 563 EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 564 { 565 int r = 0; 566 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 567 BN_CTX *ctx_new = NULL; 568 569 /* compare the field types */ 570 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 571 EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 572 return 1; 573 /* compare the curve name (if present in both) */ 574 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 575 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 576 return 1; 577 578 if (!ctx) 579 ctx_new = ctx = BN_CTX_new(); 580 if (!ctx) 581 return -1; 582 583 BN_CTX_start(ctx); 584 if ((a1 = BN_CTX_get(ctx)) == NULL) 585 goto err; 586 if ((a2 = BN_CTX_get(ctx)) == NULL) 587 goto err; 588 if ((a3 = BN_CTX_get(ctx)) == NULL) 589 goto err; 590 if ((b1 = BN_CTX_get(ctx)) == NULL) 591 goto err; 592 if ((b2 = BN_CTX_get(ctx)) == NULL) 593 goto err; 594 if ((b3 = BN_CTX_get(ctx)) == NULL) 595 goto err; 596 597 /* 598 * XXX This approach assumes that the external representation of 599 * curves over the same field type is the same. 600 */ 601 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 602 !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 603 r = 1; 604 605 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 606 r = 1; 607 608 /* XXX EC_POINT_cmp() assumes that the methods are equal */ 609 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 610 EC_GROUP_get0_generator(b), ctx)) 611 r = 1; 612 613 if (!r) { 614 /* compare the order and cofactor */ 615 if (!EC_GROUP_get_order(a, a1, ctx) || 616 !EC_GROUP_get_order(b, b1, ctx) || 617 !EC_GROUP_get_cofactor(a, a2, ctx) || 618 !EC_GROUP_get_cofactor(b, b2, ctx)) 619 goto err; 620 if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 621 r = 1; 622 } 623 BN_CTX_end(ctx); 624 if (ctx_new) 625 BN_CTX_free(ctx); 626 627 return r; 628 629 err: 630 BN_CTX_end(ctx); 631 if (ctx_new) 632 BN_CTX_free(ctx); 633 return -1; 634 } 635 636 /* 637 * Coordinate blinding for EC_POINT. 638 * 639 * The underlying EC_METHOD can optionally implement this function: 640 * underlying implementations should return 0 on errors, or 1 on success. 641 * 642 * This wrapper returns 1 in case the underlying EC_METHOD does not support 643 * coordinate blinding. 644 */ 645 int 646 ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) 647 { 648 if (group->meth->blind_coordinates == NULL) 649 return 1; 650 651 return group->meth->blind_coordinates(group, p, ctx); 652 } 653 654 EC_POINT * 655 EC_POINT_new(const EC_GROUP *group) 656 { 657 EC_POINT *ret; 658 659 if (group == NULL) { 660 ECerror(ERR_R_PASSED_NULL_PARAMETER); 661 return NULL; 662 } 663 if (group->meth->point_init == NULL) { 664 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 665 return NULL; 666 } 667 ret = malloc(sizeof *ret); 668 if (ret == NULL) { 669 ECerror(ERR_R_MALLOC_FAILURE); 670 return NULL; 671 } 672 ret->meth = group->meth; 673 674 if (!ret->meth->point_init(ret)) { 675 free(ret); 676 return NULL; 677 } 678 return ret; 679 } 680 681 void 682 EC_POINT_free(EC_POINT *point) 683 { 684 if (point == NULL) 685 return; 686 687 if (point->meth->point_finish != NULL) 688 point->meth->point_finish(point); 689 690 freezero(point, sizeof *point); 691 } 692 693 void 694 EC_POINT_clear_free(EC_POINT *point) 695 { 696 EC_POINT_free(point); 697 } 698 699 int 700 EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 701 { 702 if (dest->meth->point_copy == NULL) { 703 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 704 return 0; 705 } 706 if (dest->meth != src->meth) { 707 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 708 return 0; 709 } 710 if (dest == src) 711 return 1; 712 return dest->meth->point_copy(dest, src); 713 } 714 715 EC_POINT * 716 EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 717 { 718 EC_POINT *t; 719 int r; 720 721 if (a == NULL) 722 return NULL; 723 724 t = EC_POINT_new(group); 725 if (t == NULL) 726 return (NULL); 727 r = EC_POINT_copy(t, a); 728 if (!r) { 729 EC_POINT_free(t); 730 return NULL; 731 } else 732 return t; 733 } 734 735 const EC_METHOD * 736 EC_POINT_method_of(const EC_POINT *point) 737 { 738 return point->meth; 739 } 740 741 int 742 EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 743 { 744 if (group->meth->point_set_to_infinity == NULL) { 745 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 746 return 0; 747 } 748 if (group->meth != point->meth) { 749 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 750 return 0; 751 } 752 return group->meth->point_set_to_infinity(group, point); 753 } 754 755 int 756 EC_POINT_set_Jprojective_coordinates(const EC_GROUP *group, EC_POINT *point, 757 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx_in) 758 { 759 BN_CTX *ctx; 760 int ret = 0; 761 762 if ((ctx = ctx_in) == NULL) 763 ctx = BN_CTX_new(); 764 if (ctx == NULL) 765 goto err; 766 767 if (group->meth->point_set_Jprojective_coordinates == NULL) { 768 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 769 goto err; 770 } 771 if (group->meth != point->meth) { 772 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 773 goto err; 774 } 775 if (!group->meth->point_set_Jprojective_coordinates(group, point, 776 x, y, z, ctx)) 777 goto err; 778 779 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 780 ECerror(EC_R_POINT_IS_NOT_ON_CURVE); 781 goto err; 782 } 783 784 ret = 1; 785 786 err: 787 if (ctx != ctx_in) 788 BN_CTX_free(ctx); 789 790 return ret; 791 } 792 793 int 794 EC_POINT_get_Jprojective_coordinates(const EC_GROUP *group, 795 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx_in) 796 { 797 BN_CTX *ctx; 798 int ret = 0; 799 800 if ((ctx = ctx_in) == NULL) 801 ctx = BN_CTX_new(); 802 if (ctx == NULL) 803 goto err; 804 805 if (group->meth->point_get_Jprojective_coordinates == NULL) { 806 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 807 goto err; 808 } 809 if (group->meth != point->meth) { 810 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 811 goto err; 812 } 813 ret = group->meth->point_get_Jprojective_coordinates(group, point, 814 x, y, z, ctx); 815 816 err: 817 if (ctx != ctx_in) 818 BN_CTX_free(ctx); 819 820 return ret; 821 } 822 823 int 824 EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 825 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) 826 { 827 return EC_POINT_set_Jprojective_coordinates(group, point, x, y, z, ctx); 828 } 829 830 int 831 EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 832 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) 833 { 834 return EC_POINT_get_Jprojective_coordinates(group, point, x, y, z, ctx); 835 } 836 837 int 838 EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, 839 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx_in) 840 { 841 BN_CTX *ctx; 842 int ret = 0; 843 844 if ((ctx = ctx_in) == NULL) 845 ctx = BN_CTX_new(); 846 if (ctx == NULL) 847 goto err; 848 849 if (group->meth->point_set_affine_coordinates == NULL) { 850 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 851 goto err; 852 } 853 if (group->meth != point->meth) { 854 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 855 goto err; 856 } 857 if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx)) 858 goto err; 859 860 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { 861 ECerror(EC_R_POINT_IS_NOT_ON_CURVE); 862 goto err; 863 } 864 865 ret = 1; 866 867 err: 868 if (ctx != ctx_in) 869 BN_CTX_free(ctx); 870 871 return ret; 872 } 873 874 int 875 EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 876 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 877 { 878 return EC_POINT_set_affine_coordinates(group, point, x, y, ctx); 879 } 880 881 int 882 EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, 883 BIGNUM *x, BIGNUM *y, BN_CTX *ctx_in) 884 { 885 BN_CTX *ctx; 886 int ret = 0; 887 888 if ((ctx = ctx_in) == NULL) 889 ctx = BN_CTX_new(); 890 if (ctx == NULL) 891 goto err; 892 893 if (group->meth->point_get_affine_coordinates == NULL) { 894 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 895 goto err; 896 } 897 if (group->meth != point->meth) { 898 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 899 goto err; 900 } 901 ret = group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 902 903 err: 904 if (ctx != ctx_in) 905 BN_CTX_free(ctx); 906 907 return ret; 908 } 909 910 int 911 EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 912 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 913 { 914 return EC_POINT_get_affine_coordinates(group, point, x, y, ctx); 915 } 916 917 int 918 EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 919 const EC_POINT *b, BN_CTX *ctx_in) 920 { 921 BN_CTX *ctx; 922 int ret = 0; 923 924 if ((ctx = ctx_in) == NULL) 925 ctx = BN_CTX_new(); 926 if (ctx == NULL) 927 goto err; 928 929 if (group->meth->add == NULL) { 930 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 931 goto err; 932 } 933 if (group->meth != r->meth || group->meth != a->meth || 934 group->meth != b->meth) { 935 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 936 goto err; 937 } 938 ret = group->meth->add(group, r, a, b, ctx); 939 940 err: 941 if (ctx != ctx_in) 942 BN_CTX_free(ctx); 943 944 return ret; 945 } 946 947 int 948 EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 949 BN_CTX *ctx_in) 950 { 951 BN_CTX *ctx; 952 int ret = 0; 953 954 if ((ctx = ctx_in) == NULL) 955 ctx = BN_CTX_new(); 956 if (ctx == NULL) 957 goto err; 958 959 if (group->meth->dbl == NULL) { 960 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 961 goto err; 962 } 963 if (group->meth != r->meth || r->meth != a->meth) { 964 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 965 goto err; 966 } 967 ret = group->meth->dbl(group, r, a, ctx); 968 969 err: 970 if (ctx != ctx_in) 971 BN_CTX_free(ctx); 972 973 return ret; 974 } 975 976 int 977 EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx_in) 978 { 979 BN_CTX *ctx; 980 int ret = 0; 981 982 if ((ctx = ctx_in) == NULL) 983 ctx = BN_CTX_new(); 984 if (ctx == NULL) 985 goto err; 986 987 if (group->meth->invert == NULL) { 988 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 989 goto err; 990 } 991 if (group->meth != a->meth) { 992 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 993 goto err; 994 } 995 ret = group->meth->invert(group, a, ctx); 996 997 err: 998 if (ctx != ctx_in) 999 BN_CTX_free(ctx); 1000 1001 return ret; 1002 } 1003 1004 int 1005 EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 1006 { 1007 if (group->meth->is_at_infinity == NULL) { 1008 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1009 return 0; 1010 } 1011 if (group->meth != point->meth) { 1012 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1013 return 0; 1014 } 1015 return group->meth->is_at_infinity(group, point); 1016 } 1017 1018 int 1019 EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 1020 BN_CTX *ctx_in) 1021 { 1022 BN_CTX *ctx; 1023 int ret = 0; 1024 1025 if ((ctx = ctx_in) == NULL) 1026 ctx = BN_CTX_new(); 1027 if (ctx == NULL) 1028 goto err; 1029 1030 if (group->meth->is_on_curve == NULL) { 1031 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1032 goto err; 1033 } 1034 if (group->meth != point->meth) { 1035 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1036 goto err; 1037 } 1038 ret = group->meth->is_on_curve(group, point, ctx); 1039 1040 err: 1041 if (ctx != ctx_in) 1042 BN_CTX_free(ctx); 1043 1044 return ret; 1045 } 1046 1047 int 1048 EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 1049 BN_CTX *ctx_in) 1050 { 1051 BN_CTX *ctx; 1052 int ret = -1; 1053 1054 if ((ctx = ctx_in) == NULL) 1055 ctx = BN_CTX_new(); 1056 if (ctx == NULL) 1057 goto err; 1058 1059 if (group->meth->point_cmp == NULL) { 1060 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1061 goto err; 1062 } 1063 if (group->meth != a->meth || a->meth != b->meth) { 1064 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1065 goto err; 1066 } 1067 ret = group->meth->point_cmp(group, a, b, ctx); 1068 1069 err: 1070 if (ctx != ctx_in) 1071 BN_CTX_free(ctx); 1072 1073 return ret; 1074 } 1075 1076 int 1077 EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx_in) 1078 { 1079 BN_CTX *ctx; 1080 int ret = 0; 1081 1082 if ((ctx = ctx_in) == NULL) 1083 ctx = BN_CTX_new(); 1084 if (ctx == NULL) 1085 goto err; 1086 1087 if (group->meth->make_affine == NULL) { 1088 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1089 goto err; 1090 } 1091 if (group->meth != point->meth) { 1092 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1093 goto err; 1094 } 1095 ret = group->meth->make_affine(group, point, ctx); 1096 1097 err: 1098 if (ctx != ctx_in) 1099 BN_CTX_free(ctx); 1100 1101 return ret; 1102 } 1103 1104 int 1105 EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], 1106 BN_CTX *ctx_in) 1107 { 1108 BN_CTX *ctx; 1109 size_t i; 1110 int ret = 0; 1111 1112 if ((ctx = ctx_in) == NULL) 1113 ctx = BN_CTX_new(); 1114 if (ctx == NULL) 1115 goto err; 1116 1117 if (group->meth->points_make_affine == NULL) { 1118 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1119 goto err; 1120 } 1121 for (i = 0; i < num; i++) { 1122 if (group->meth != points[i]->meth) { 1123 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1124 goto err; 1125 } 1126 } 1127 ret = group->meth->points_make_affine(group, num, points, ctx); 1128 1129 err: 1130 if (ctx != ctx_in) 1131 BN_CTX_free(ctx); 1132 1133 return ret; 1134 } 1135 1136 int 1137 EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1138 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], 1139 BN_CTX *ctx_in) 1140 { 1141 BN_CTX *ctx; 1142 int ret = 0; 1143 1144 if ((ctx = ctx_in) == NULL) 1145 ctx = BN_CTX_new(); 1146 if (ctx == NULL) 1147 goto err; 1148 1149 /* Only num == 0 and num == 1 is supported. */ 1150 if (group->meth->mul_generator_ct == NULL || 1151 group->meth->mul_single_ct == NULL || 1152 group->meth->mul_double_nonct == NULL || 1153 num > 1) { 1154 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1155 goto err; 1156 } 1157 1158 if (num == 1 && points != NULL && scalars != NULL) { 1159 /* Either bP or aG + bP, this is sane. */ 1160 ret = EC_POINT_mul(group, r, scalar, points[0], scalars[0], ctx); 1161 } else if (scalar != NULL && points == NULL && scalars == NULL) { 1162 /* aG, this is sane */ 1163 ret = EC_POINT_mul(group, r, scalar, NULL, NULL, ctx); 1164 } else { 1165 /* anything else is an error */ 1166 ECerror(ERR_R_EC_LIB); 1167 goto err; 1168 } 1169 1170 err: 1171 if (ctx != ctx_in) 1172 BN_CTX_free(ctx); 1173 1174 return ret; 1175 } 1176 1177 int 1178 EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1179 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx_in) 1180 { 1181 BN_CTX *ctx; 1182 int ret = 0; 1183 1184 if ((ctx = ctx_in) == NULL) 1185 ctx = BN_CTX_new(); 1186 if (ctx == NULL) 1187 goto err; 1188 1189 if (group->meth->mul_generator_ct == NULL || 1190 group->meth->mul_single_ct == NULL || 1191 group->meth->mul_double_nonct == NULL) { 1192 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1193 goto err; 1194 } 1195 1196 if (g_scalar != NULL && point == NULL && p_scalar == NULL) { 1197 /* 1198 * In this case we want to compute g_scalar * GeneratorPoint: 1199 * this codepath is reached most prominently by (ephemeral) key 1200 * generation of EC cryptosystems (i.e. ECDSA keygen and sign 1201 * setup, ECDH keygen/first half), where the scalar is always 1202 * secret. This is why we ignore if BN_FLG_CONSTTIME is actually 1203 * set and we always call the constant time version. 1204 */ 1205 ret = group->meth->mul_generator_ct(group, r, g_scalar, ctx); 1206 } else if (g_scalar == NULL && point != NULL && p_scalar != NULL) { 1207 /* 1208 * In this case we want to compute p_scalar * GenericPoint: 1209 * this codepath is reached most prominently by the second half 1210 * of ECDH, where the secret scalar is multiplied by the peer's 1211 * public point. To protect the secret scalar, we ignore if 1212 * BN_FLG_CONSTTIME is actually set and we always call the 1213 * constant time version. 1214 */ 1215 ret = group->meth->mul_single_ct(group, r, p_scalar, point, ctx); 1216 } else if (g_scalar != NULL && point != NULL && p_scalar != NULL) { 1217 /* 1218 * In this case we want to compute 1219 * g_scalar * GeneratorPoint + p_scalar * GenericPoint: 1220 * this codepath is reached most prominently by ECDSA signature 1221 * verification. So we call the non-ct version. 1222 */ 1223 ret = group->meth->mul_double_nonct(group, r, g_scalar, 1224 p_scalar, point, ctx); 1225 } else { 1226 /* Anything else is an error. */ 1227 ECerror(ERR_R_EC_LIB); 1228 goto err; 1229 } 1230 1231 err: 1232 if (ctx != ctx_in) 1233 BN_CTX_free(ctx); 1234 1235 return ret; 1236 } 1237 1238 int 1239 EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx_in) 1240 { 1241 return 1; 1242 } 1243 1244 int 1245 EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1246 { 1247 return 0; 1248 } 1249 1250 int 1251 ec_group_simple_order_bits(const EC_GROUP *group) 1252 { 1253 /* XXX change group->order to a pointer? */ 1254 #if 0 1255 if (group->order == NULL) 1256 return 0; 1257 #endif 1258 return BN_num_bits(&group->order); 1259 } 1260 1261 EC_KEY * 1262 ECParameters_dup(EC_KEY *key) 1263 { 1264 const unsigned char *p; 1265 unsigned char *der = NULL; 1266 EC_KEY *dup = NULL; 1267 int len; 1268 1269 if (key == NULL) 1270 return NULL; 1271 1272 if ((len = i2d_ECParameters(key, &der)) <= 0) 1273 return NULL; 1274 1275 p = der; 1276 dup = d2i_ECParameters(NULL, &p, len); 1277 freezero(der, len); 1278 1279 return dup; 1280 } 1281