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