1 /* $OpenBSD: ec_lib.c,v 1.24 2017/05/02 03:59:44 deraadt 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 "ec_lcl.h" 72 73 /* functions for EC_GROUP objects */ 74 75 EC_GROUP * 76 EC_GROUP_new(const EC_METHOD * meth) 77 { 78 EC_GROUP *ret; 79 80 if (meth == NULL) { 81 ECerror(EC_R_SLOT_FULL); 82 return NULL; 83 } 84 if (meth->group_init == 0) { 85 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 86 return NULL; 87 } 88 ret = malloc(sizeof *ret); 89 if (ret == NULL) { 90 ECerror(ERR_R_MALLOC_FAILURE); 91 return NULL; 92 } 93 ret->meth = meth; 94 95 ret->extra_data = NULL; 96 97 ret->generator = NULL; 98 BN_init(&ret->order); 99 BN_init(&ret->cofactor); 100 101 ret->curve_name = 0; 102 ret->asn1_flag = 0; 103 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; 104 105 ret->seed = NULL; 106 ret->seed_len = 0; 107 108 if (!meth->group_init(ret)) { 109 free(ret); 110 return NULL; 111 } 112 return ret; 113 } 114 115 116 void 117 EC_GROUP_free(EC_GROUP * group) 118 { 119 if (!group) 120 return; 121 122 if (group->meth->group_finish != 0) 123 group->meth->group_finish(group); 124 125 EC_EX_DATA_free_all_data(&group->extra_data); 126 127 EC_POINT_free(group->generator); 128 BN_free(&group->order); 129 BN_free(&group->cofactor); 130 131 free(group->seed); 132 133 free(group); 134 } 135 136 137 void 138 EC_GROUP_clear_free(EC_GROUP * group) 139 { 140 if (!group) 141 return; 142 143 if (group->meth->group_clear_finish != 0) 144 group->meth->group_clear_finish(group); 145 else if (group->meth->group_finish != 0) 146 group->meth->group_finish(group); 147 148 EC_EX_DATA_clear_free_all_data(&group->extra_data); 149 150 EC_POINT_clear_free(group->generator); 151 BN_clear_free(&group->order); 152 BN_clear_free(&group->cofactor); 153 154 freezero(group->seed, group->seed_len); 155 freezero(group, sizeof *group); 156 } 157 158 159 int 160 EC_GROUP_copy(EC_GROUP * dest, const EC_GROUP * src) 161 { 162 EC_EXTRA_DATA *d; 163 164 if (dest->meth->group_copy == 0) { 165 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 166 return 0; 167 } 168 if (dest->meth != src->meth) { 169 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 170 return 0; 171 } 172 if (dest == src) 173 return 1; 174 175 EC_EX_DATA_free_all_data(&dest->extra_data); 176 177 for (d = src->extra_data; d != NULL; d = d->next) { 178 void *t = d->dup_func(d->data); 179 180 if (t == NULL) 181 return 0; 182 if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, 183 d->free_func, d->clear_free_func)) 184 return 0; 185 } 186 187 if (src->generator != NULL) { 188 if (dest->generator == NULL) { 189 dest->generator = EC_POINT_new(dest); 190 if (dest->generator == NULL) 191 return 0; 192 } 193 if (!EC_POINT_copy(dest->generator, src->generator)) 194 return 0; 195 } else { 196 /* src->generator == NULL */ 197 EC_POINT_clear_free(dest->generator); 198 dest->generator = NULL; 199 } 200 201 if (!BN_copy(&dest->order, &src->order)) 202 return 0; 203 if (!BN_copy(&dest->cofactor, &src->cofactor)) 204 return 0; 205 206 dest->curve_name = src->curve_name; 207 dest->asn1_flag = src->asn1_flag; 208 dest->asn1_form = src->asn1_form; 209 210 if (src->seed) { 211 free(dest->seed); 212 dest->seed = malloc(src->seed_len); 213 if (dest->seed == NULL) 214 return 0; 215 memcpy(dest->seed, src->seed, src->seed_len); 216 dest->seed_len = src->seed_len; 217 } else { 218 free(dest->seed); 219 dest->seed = NULL; 220 dest->seed_len = 0; 221 } 222 223 224 return dest->meth->group_copy(dest, src); 225 } 226 227 228 EC_GROUP * 229 EC_GROUP_dup(const EC_GROUP * a) 230 { 231 EC_GROUP *t = NULL; 232 233 if ((a != NULL) && ((t = EC_GROUP_new(a->meth)) != NULL) && 234 (!EC_GROUP_copy(t, a))) { 235 EC_GROUP_free(t); 236 t = NULL; 237 } 238 return t; 239 } 240 241 242 const EC_METHOD * 243 EC_GROUP_method_of(const EC_GROUP *group) 244 { 245 return group->meth; 246 } 247 248 249 int 250 EC_METHOD_get_field_type(const EC_METHOD *meth) 251 { 252 return meth->field_type; 253 } 254 255 256 int 257 EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 258 const BIGNUM *order, const BIGNUM *cofactor) 259 { 260 if (generator == NULL) { 261 ECerror(ERR_R_PASSED_NULL_PARAMETER); 262 return 0; 263 } 264 if (group->generator == NULL) { 265 group->generator = EC_POINT_new(group); 266 if (group->generator == NULL) 267 return 0; 268 } 269 if (!EC_POINT_copy(group->generator, generator)) 270 return 0; 271 272 if (order != NULL) { 273 if (!BN_copy(&group->order, order)) 274 return 0; 275 } else 276 BN_zero(&group->order); 277 278 if (cofactor != NULL) { 279 if (!BN_copy(&group->cofactor, cofactor)) 280 return 0; 281 } else 282 BN_zero(&group->cofactor); 283 284 return 1; 285 } 286 287 288 const EC_POINT * 289 EC_GROUP_get0_generator(const EC_GROUP *group) 290 { 291 return group->generator; 292 } 293 294 295 int 296 EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 297 { 298 if (!BN_copy(order, &group->order)) 299 return 0; 300 301 return !BN_is_zero(order); 302 } 303 304 305 int 306 EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 307 { 308 if (!BN_copy(cofactor, &group->cofactor)) 309 return 0; 310 311 return !BN_is_zero(&group->cofactor); 312 } 313 314 315 void 316 EC_GROUP_set_curve_name(EC_GROUP * group, int nid) 317 { 318 group->curve_name = nid; 319 } 320 321 322 int 323 EC_GROUP_get_curve_name(const EC_GROUP * group) 324 { 325 return group->curve_name; 326 } 327 328 329 void 330 EC_GROUP_set_asn1_flag(EC_GROUP * group, int flag) 331 { 332 group->asn1_flag = flag; 333 } 334 335 336 int 337 EC_GROUP_get_asn1_flag(const EC_GROUP * group) 338 { 339 return group->asn1_flag; 340 } 341 342 343 void 344 EC_GROUP_set_point_conversion_form(EC_GROUP * group, 345 point_conversion_form_t form) 346 { 347 group->asn1_form = form; 348 } 349 350 351 point_conversion_form_t 352 EC_GROUP_get_point_conversion_form(const EC_GROUP * group) 353 { 354 return group->asn1_form; 355 } 356 357 358 size_t 359 EC_GROUP_set_seed(EC_GROUP * group, const unsigned char *p, size_t len) 360 { 361 if (group->seed) { 362 free(group->seed); 363 group->seed = NULL; 364 group->seed_len = 0; 365 } 366 if (!len || !p) 367 return 1; 368 369 if ((group->seed = malloc(len)) == NULL) 370 return 0; 371 memcpy(group->seed, p, len); 372 group->seed_len = len; 373 374 return len; 375 } 376 377 378 unsigned char * 379 EC_GROUP_get0_seed(const EC_GROUP * group) 380 { 381 return group->seed; 382 } 383 384 385 size_t 386 EC_GROUP_get_seed_len(const EC_GROUP * group) 387 { 388 return group->seed_len; 389 } 390 391 392 int 393 EC_GROUP_set_curve_GFp(EC_GROUP * group, const BIGNUM * p, const BIGNUM * a, 394 const BIGNUM * b, BN_CTX * ctx) 395 { 396 if (group->meth->group_set_curve == 0) { 397 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 398 return 0; 399 } 400 return group->meth->group_set_curve(group, p, a, b, ctx); 401 } 402 403 404 int 405 EC_GROUP_get_curve_GFp(const EC_GROUP * group, BIGNUM * p, BIGNUM * a, 406 BIGNUM * b, BN_CTX * ctx) 407 { 408 if (group->meth->group_get_curve == 0) { 409 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 410 return 0; 411 } 412 return group->meth->group_get_curve(group, p, a, b, ctx); 413 } 414 415 #ifndef OPENSSL_NO_EC2M 416 int 417 EC_GROUP_set_curve_GF2m(EC_GROUP * group, const BIGNUM * p, const BIGNUM * a, 418 const BIGNUM * b, BN_CTX * ctx) 419 { 420 if (group->meth->group_set_curve == 0) { 421 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 422 return 0; 423 } 424 return group->meth->group_set_curve(group, p, a, b, ctx); 425 } 426 427 428 int 429 EC_GROUP_get_curve_GF2m(const EC_GROUP * group, BIGNUM * p, BIGNUM * a, 430 BIGNUM * b, BN_CTX * ctx) 431 { 432 if (group->meth->group_get_curve == 0) { 433 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 434 return 0; 435 } 436 return group->meth->group_get_curve(group, p, a, b, ctx); 437 } 438 #endif 439 440 int 441 EC_GROUP_get_degree(const EC_GROUP * group) 442 { 443 if (group->meth->group_get_degree == 0) { 444 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 445 return 0; 446 } 447 return group->meth->group_get_degree(group); 448 } 449 450 451 int 452 EC_GROUP_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) 453 { 454 if (group->meth->group_check_discriminant == 0) { 455 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 456 return 0; 457 } 458 return group->meth->group_check_discriminant(group, ctx); 459 } 460 461 462 int 463 EC_GROUP_cmp(const EC_GROUP * a, const EC_GROUP * b, BN_CTX * ctx) 464 { 465 int r = 0; 466 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 467 BN_CTX *ctx_new = NULL; 468 469 /* compare the field types */ 470 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 471 EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 472 return 1; 473 /* compare the curve name (if present in both) */ 474 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 475 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 476 return 1; 477 478 if (!ctx) 479 ctx_new = ctx = BN_CTX_new(); 480 if (!ctx) 481 return -1; 482 483 BN_CTX_start(ctx); 484 if ((a1 = BN_CTX_get(ctx)) == NULL) 485 goto err; 486 if ((a2 = BN_CTX_get(ctx)) == NULL) 487 goto err; 488 if ((a3 = BN_CTX_get(ctx)) == NULL) 489 goto err; 490 if ((b1 = BN_CTX_get(ctx)) == NULL) 491 goto err; 492 if ((b2 = BN_CTX_get(ctx)) == NULL) 493 goto err; 494 if ((b3 = BN_CTX_get(ctx)) == NULL) 495 goto err; 496 497 /* 498 * XXX This approach assumes that the external representation of 499 * curves over the same field type is the same. 500 */ 501 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 502 !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 503 r = 1; 504 505 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 506 r = 1; 507 508 /* XXX EC_POINT_cmp() assumes that the methods are equal */ 509 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 510 EC_GROUP_get0_generator(b), ctx)) 511 r = 1; 512 513 if (!r) { 514 /* compare the order and cofactor */ 515 if (!EC_GROUP_get_order(a, a1, ctx) || 516 !EC_GROUP_get_order(b, b1, ctx) || 517 !EC_GROUP_get_cofactor(a, a2, ctx) || 518 !EC_GROUP_get_cofactor(b, b2, ctx)) 519 goto err; 520 if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 521 r = 1; 522 } 523 BN_CTX_end(ctx); 524 if (ctx_new) 525 BN_CTX_free(ctx); 526 527 return r; 528 529 err: 530 BN_CTX_end(ctx); 531 if (ctx_new) 532 BN_CTX_free(ctx); 533 return -1; 534 } 535 536 537 /* this has 'package' visibility */ 538 int 539 EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data, void *data, 540 void *(*dup_func) (void *), 541 void (*free_func) (void *), 542 void (*clear_free_func) (void *)) 543 { 544 EC_EXTRA_DATA *d; 545 546 if (ex_data == NULL) 547 return 0; 548 549 for (d = *ex_data; d != NULL; d = d->next) { 550 if (d->dup_func == dup_func && d->free_func == free_func && 551 d->clear_free_func == clear_free_func) { 552 ECerror(EC_R_SLOT_FULL); 553 return 0; 554 } 555 } 556 557 if (data == NULL) 558 /* no explicit entry needed */ 559 return 1; 560 561 d = malloc(sizeof *d); 562 if (d == NULL) 563 return 0; 564 565 d->data = data; 566 d->dup_func = dup_func; 567 d->free_func = free_func; 568 d->clear_free_func = clear_free_func; 569 570 d->next = *ex_data; 571 *ex_data = d; 572 573 return 1; 574 } 575 576 /* this has 'package' visibility */ 577 void * 578 EC_EX_DATA_get_data(const EC_EXTRA_DATA * ex_data, 579 void *(*dup_func) (void *), 580 void (*free_func) (void *), 581 void (*clear_free_func) (void *)) 582 { 583 const EC_EXTRA_DATA *d; 584 585 for (d = ex_data; d != NULL; d = d->next) { 586 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) 587 return d->data; 588 } 589 590 return NULL; 591 } 592 593 /* this has 'package' visibility */ 594 void 595 EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data, 596 void *(*dup_func) (void *), 597 void (*free_func) (void *), 598 void (*clear_free_func) (void *)) 599 { 600 EC_EXTRA_DATA **p; 601 602 if (ex_data == NULL) 603 return; 604 605 for (p = ex_data; *p != NULL; p = &((*p)->next)) { 606 if ((*p)->dup_func == dup_func && 607 (*p)->free_func == free_func && 608 (*p)->clear_free_func == clear_free_func) { 609 EC_EXTRA_DATA *next = (*p)->next; 610 611 (*p)->free_func((*p)->data); 612 free(*p); 613 614 *p = next; 615 return; 616 } 617 } 618 } 619 620 /* this has 'package' visibility */ 621 void 622 EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data, 623 void *(*dup_func) (void *), 624 void (*free_func) (void *), 625 void (*clear_free_func) (void *)) 626 { 627 EC_EXTRA_DATA **p; 628 629 if (ex_data == NULL) 630 return; 631 632 for (p = ex_data; *p != NULL; p = &((*p)->next)) { 633 if ((*p)->dup_func == dup_func && 634 (*p)->free_func == free_func && 635 (*p)->clear_free_func == clear_free_func) { 636 EC_EXTRA_DATA *next = (*p)->next; 637 638 (*p)->clear_free_func((*p)->data); 639 free(*p); 640 641 *p = next; 642 return; 643 } 644 } 645 } 646 647 /* this has 'package' visibility */ 648 void 649 EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data) 650 { 651 EC_EXTRA_DATA *d; 652 653 if (ex_data == NULL) 654 return; 655 656 d = *ex_data; 657 while (d) { 658 EC_EXTRA_DATA *next = d->next; 659 660 d->free_func(d->data); 661 free(d); 662 663 d = next; 664 } 665 *ex_data = NULL; 666 } 667 668 /* this has 'package' visibility */ 669 void 670 EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data) 671 { 672 EC_EXTRA_DATA *d; 673 674 if (ex_data == NULL) 675 return; 676 677 d = *ex_data; 678 while (d) { 679 EC_EXTRA_DATA *next = d->next; 680 681 d->clear_free_func(d->data); 682 free(d); 683 684 d = next; 685 } 686 *ex_data = NULL; 687 } 688 689 690 /* functions for EC_POINT objects */ 691 692 EC_POINT * 693 EC_POINT_new(const EC_GROUP * group) 694 { 695 EC_POINT *ret; 696 697 if (group == NULL) { 698 ECerror(ERR_R_PASSED_NULL_PARAMETER); 699 return NULL; 700 } 701 if (group->meth->point_init == 0) { 702 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 703 return NULL; 704 } 705 ret = malloc(sizeof *ret); 706 if (ret == NULL) { 707 ECerror(ERR_R_MALLOC_FAILURE); 708 return NULL; 709 } 710 ret->meth = group->meth; 711 712 if (!ret->meth->point_init(ret)) { 713 free(ret); 714 return NULL; 715 } 716 return ret; 717 } 718 719 720 void 721 EC_POINT_free(EC_POINT * point) 722 { 723 if (!point) 724 return; 725 726 if (point->meth->point_finish != 0) 727 point->meth->point_finish(point); 728 free(point); 729 } 730 731 732 void 733 EC_POINT_clear_free(EC_POINT * point) 734 { 735 if (!point) 736 return; 737 738 if (point->meth->point_clear_finish != 0) 739 point->meth->point_clear_finish(point); 740 else if (point->meth->point_finish != 0) 741 point->meth->point_finish(point); 742 freezero(point, sizeof *point); 743 } 744 745 746 int 747 EC_POINT_copy(EC_POINT * dest, const EC_POINT * src) 748 { 749 if (dest->meth->point_copy == 0) { 750 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 751 return 0; 752 } 753 if (dest->meth != src->meth) { 754 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 755 return 0; 756 } 757 if (dest == src) 758 return 1; 759 return dest->meth->point_copy(dest, src); 760 } 761 762 763 EC_POINT * 764 EC_POINT_dup(const EC_POINT * a, const EC_GROUP * group) 765 { 766 EC_POINT *t; 767 int r; 768 769 if (a == NULL) 770 return NULL; 771 772 t = EC_POINT_new(group); 773 if (t == NULL) 774 return (NULL); 775 r = EC_POINT_copy(t, a); 776 if (!r) { 777 EC_POINT_free(t); 778 return NULL; 779 } else 780 return t; 781 } 782 783 784 const EC_METHOD * 785 EC_POINT_method_of(const EC_POINT * point) 786 { 787 return point->meth; 788 } 789 790 791 int 792 EC_POINT_set_to_infinity(const EC_GROUP * group, EC_POINT * point) 793 { 794 if (group->meth->point_set_to_infinity == 0) { 795 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 796 return 0; 797 } 798 if (group->meth != point->meth) { 799 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 800 return 0; 801 } 802 return group->meth->point_set_to_infinity(group, point); 803 } 804 805 806 int 807 EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 808 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) 809 { 810 if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 811 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 812 return 0; 813 } 814 if (group->meth != point->meth) { 815 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 816 return 0; 817 } 818 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); 819 } 820 821 822 int 823 EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 824 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) 825 { 826 if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 827 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 828 return 0; 829 } 830 if (group->meth != point->meth) { 831 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 832 return 0; 833 } 834 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); 835 } 836 837 838 int 839 EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 840 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 841 { 842 if (group->meth->point_set_affine_coordinates == 0) { 843 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 844 return 0; 845 } 846 if (group->meth != point->meth) { 847 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 848 return 0; 849 } 850 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 851 } 852 853 #ifndef OPENSSL_NO_EC2M 854 int 855 EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, 856 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 857 { 858 if (group->meth->point_set_affine_coordinates == 0) { 859 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 860 return 0; 861 } 862 if (group->meth != point->meth) { 863 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 864 return 0; 865 } 866 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 867 } 868 #endif 869 870 int 871 EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 872 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 873 { 874 if (group->meth->point_get_affine_coordinates == 0) { 875 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 876 return 0; 877 } 878 if (group->meth != point->meth) { 879 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 880 return 0; 881 } 882 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 883 } 884 885 #ifndef OPENSSL_NO_EC2M 886 int 887 EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, 888 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 889 { 890 if (group->meth->point_get_affine_coordinates == 0) { 891 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 892 return 0; 893 } 894 if (group->meth != point->meth) { 895 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 896 return 0; 897 } 898 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 899 } 900 #endif 901 902 int 903 EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 904 const EC_POINT *b, BN_CTX *ctx) 905 { 906 if (group->meth->add == 0) { 907 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 908 return 0; 909 } 910 if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth)) { 911 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 912 return 0; 913 } 914 return group->meth->add(group, r, a, b, ctx); 915 } 916 917 918 int 919 EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) 920 { 921 if (group->meth->dbl == 0) { 922 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 923 return 0; 924 } 925 if ((group->meth != r->meth) || (r->meth != a->meth)) { 926 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 927 return 0; 928 } 929 return group->meth->dbl(group, r, a, ctx); 930 } 931 932 933 int 934 EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 935 { 936 if (group->meth->invert == 0) { 937 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 938 return 0; 939 } 940 if (group->meth != a->meth) { 941 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 942 return 0; 943 } 944 return group->meth->invert(group, a, ctx); 945 } 946 947 948 int 949 EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 950 { 951 if (group->meth->is_at_infinity == 0) { 952 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 953 return 0; 954 } 955 if (group->meth != point->meth) { 956 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 957 return 0; 958 } 959 return group->meth->is_at_infinity(group, point); 960 } 961 962 963 int 964 EC_POINT_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX * ctx) 965 { 966 if (group->meth->is_on_curve == 0) { 967 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 968 return 0; 969 } 970 if (group->meth != point->meth) { 971 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 972 return 0; 973 } 974 return group->meth->is_on_curve(group, point, ctx); 975 } 976 977 978 int 979 EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 980 BN_CTX * ctx) 981 { 982 if (group->meth->point_cmp == 0) { 983 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 984 return -1; 985 } 986 if ((group->meth != a->meth) || (a->meth != b->meth)) { 987 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 988 return -1; 989 } 990 return group->meth->point_cmp(group, a, b, ctx); 991 } 992 993 994 int 995 EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 996 { 997 if (group->meth->make_affine == 0) { 998 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 999 return 0; 1000 } 1001 if (group->meth != point->meth) { 1002 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1003 return 0; 1004 } 1005 return group->meth->make_affine(group, point, ctx); 1006 } 1007 1008 1009 int 1010 EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], 1011 BN_CTX *ctx) 1012 { 1013 size_t i; 1014 1015 if (group->meth->points_make_affine == 0) { 1016 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1017 return 0; 1018 } 1019 for (i = 0; i < num; i++) { 1020 if (group->meth != points[i]->meth) { 1021 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1022 return 0; 1023 } 1024 } 1025 return group->meth->points_make_affine(group, num, points, ctx); 1026 } 1027 1028 1029 /* Functions for point multiplication. 1030 * 1031 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c; 1032 * otherwise we dispatch through methods. 1033 */ 1034 1035 int 1036 EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1037 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) 1038 { 1039 if (group->meth->mul == 0) 1040 /* use default */ 1041 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1042 1043 return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1044 } 1045 1046 int 1047 EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1048 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1049 { 1050 /* just a convenient interface to EC_POINTs_mul() */ 1051 1052 const EC_POINT *points[1]; 1053 const BIGNUM *scalars[1]; 1054 1055 points[0] = point; 1056 scalars[0] = p_scalar; 1057 1058 return EC_POINTs_mul(group, r, g_scalar, 1059 (point != NULL && p_scalar != NULL), 1060 points, scalars, ctx); 1061 } 1062 1063 int 1064 EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx) 1065 { 1066 if (group->meth->mul == 0) 1067 /* use default */ 1068 return ec_wNAF_precompute_mult(group, ctx); 1069 1070 if (group->meth->precompute_mult != 0) 1071 return group->meth->precompute_mult(group, ctx); 1072 else 1073 return 1; /* nothing to do, so report success */ 1074 } 1075 1076 int 1077 EC_GROUP_have_precompute_mult(const EC_GROUP * group) 1078 { 1079 if (group->meth->mul == 0) 1080 /* use default */ 1081 return ec_wNAF_have_precompute_mult(group); 1082 1083 if (group->meth->have_precompute_mult != 0) 1084 return group->meth->have_precompute_mult(group); 1085 else 1086 return 0; /* cannot tell whether precomputation has 1087 * been performed */ 1088 } 1089 1090 EC_KEY * 1091 ECParameters_dup(EC_KEY *key) 1092 { 1093 unsigned char *p = NULL; 1094 EC_KEY *k = NULL; 1095 int len; 1096 1097 if (key == NULL) 1098 return (NULL); 1099 1100 if ((len = i2d_ECParameters(key, &p)) > 0) 1101 k = d2i_ECParameters(NULL, (const unsigned char **)&p, len); 1102 1103 return (k); 1104 } 1105