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