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