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