ec_lib.c revision 331638
1/* crypto/ec/ec_lib.c */ 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/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 * We ignore the return value because 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 ec_precompute_mont_data(group); 327 328 return 1; 329} 330 331const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 332{ 333 return group->generator; 334} 335 336BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group) 337{ 338 return EC_GROUP_VERSION(group) ? group->mont_data : NULL; 339} 340 341int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 342{ 343 if (!BN_copy(order, &group->order)) 344 return 0; 345 346 return !BN_is_zero(order); 347} 348 349int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 350 BN_CTX *ctx) 351{ 352 if (!BN_copy(cofactor, &group->cofactor)) 353 return 0; 354 355 return !BN_is_zero(&group->cofactor); 356} 357 358void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) 359{ 360 group->curve_name = nid; 361} 362 363int EC_GROUP_get_curve_name(const EC_GROUP *group) 364{ 365 return group->curve_name; 366} 367 368void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) 369{ 370 group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK; 371 group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK; 372} 373 374int EC_GROUP_get_asn1_flag(const EC_GROUP *group) 375{ 376 return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK; 377} 378 379void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 380 point_conversion_form_t form) 381{ 382 group->asn1_form = form; 383} 384 385point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP 386 *group) 387{ 388 return group->asn1_form; 389} 390 391size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) 392{ 393 if (group->seed) { 394 OPENSSL_free(group->seed); 395 group->seed = NULL; 396 group->seed_len = 0; 397 } 398 399 if (!len || !p) 400 return 1; 401 402 if ((group->seed = OPENSSL_malloc(len)) == NULL) 403 return 0; 404 memcpy(group->seed, p, len); 405 group->seed_len = len; 406 407 return len; 408} 409 410unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) 411{ 412 return group->seed; 413} 414 415size_t EC_GROUP_get_seed_len(const EC_GROUP *group) 416{ 417 return group->seed_len; 418} 419 420int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 421 const BIGNUM *b, BN_CTX *ctx) 422{ 423 if (group->meth->group_set_curve == 0) { 424 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 425 return 0; 426 } 427 return group->meth->group_set_curve(group, p, a, b, ctx); 428} 429 430int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 431 BIGNUM *b, BN_CTX *ctx) 432{ 433 if (group->meth->group_get_curve == 0) { 434 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 435 return 0; 436 } 437 return group->meth->group_get_curve(group, p, a, b, ctx); 438} 439 440#ifndef OPENSSL_NO_EC2M 441int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 442 const BIGNUM *b, BN_CTX *ctx) 443{ 444 if (group->meth->group_set_curve == 0) { 445 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, 446 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 447 return 0; 448 } 449 return group->meth->group_set_curve(group, p, a, b, ctx); 450} 451 452int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, 453 BIGNUM *b, BN_CTX *ctx) 454{ 455 if (group->meth->group_get_curve == 0) { 456 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, 457 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 458 return 0; 459 } 460 return group->meth->group_get_curve(group, p, a, b, ctx); 461} 462#endif 463 464int EC_GROUP_get_degree(const EC_GROUP *group) 465{ 466 if (group->meth->group_get_degree == 0) { 467 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 468 return 0; 469 } 470 return group->meth->group_get_degree(group); 471} 472 473int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 474{ 475 if (group->meth->group_check_discriminant == 0) { 476 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, 477 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 478 return 0; 479 } 480 return group->meth->group_check_discriminant(group, ctx); 481} 482 483int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) 484{ 485 int r = 0; 486 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; 487 BN_CTX *ctx_new = NULL; 488 489 /* compare the field types */ 490 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != 491 EC_METHOD_get_field_type(EC_GROUP_method_of(b))) 492 return 1; 493 /* compare the curve name (if present in both) */ 494 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && 495 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) 496 return 1; 497 498 if (!ctx) 499 ctx_new = ctx = BN_CTX_new(); 500 if (!ctx) 501 return -1; 502 503 BN_CTX_start(ctx); 504 a1 = BN_CTX_get(ctx); 505 a2 = BN_CTX_get(ctx); 506 a3 = BN_CTX_get(ctx); 507 b1 = BN_CTX_get(ctx); 508 b2 = BN_CTX_get(ctx); 509 b3 = BN_CTX_get(ctx); 510 if (!b3) { 511 BN_CTX_end(ctx); 512 if (ctx_new) 513 BN_CTX_free(ctx); 514 return -1; 515 } 516 517 /* 518 * XXX This approach assumes that the external representation of curves 519 * over the same field type is the same. 520 */ 521 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || 522 !b->meth->group_get_curve(b, b1, b2, b3, ctx)) 523 r = 1; 524 525 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) 526 r = 1; 527 528 /* XXX EC_POINT_cmp() assumes that the methods are equal */ 529 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), 530 EC_GROUP_get0_generator(b), ctx)) 531 r = 1; 532 533 if (!r) { 534 /* compare the order and cofactor */ 535 if (!EC_GROUP_get_order(a, a1, ctx) || 536 !EC_GROUP_get_order(b, b1, ctx) || 537 !EC_GROUP_get_cofactor(a, a2, ctx) || 538 !EC_GROUP_get_cofactor(b, b2, ctx)) { 539 BN_CTX_end(ctx); 540 if (ctx_new) 541 BN_CTX_free(ctx); 542 return -1; 543 } 544 if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) 545 r = 1; 546 } 547 548 BN_CTX_end(ctx); 549 if (ctx_new) 550 BN_CTX_free(ctx); 551 552 return r; 553} 554 555/* this has 'package' visibility */ 556int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, 557 void *(*dup_func) (void *), 558 void (*free_func) (void *), 559 void (*clear_free_func) (void *)) 560{ 561 EC_EXTRA_DATA *d; 562 563 if (ex_data == NULL) 564 return 0; 565 566 for (d = *ex_data; d != NULL; d = d->next) { 567 if (d->dup_func == dup_func && d->free_func == free_func 568 && d->clear_free_func == clear_free_func) { 569 ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); 570 return 0; 571 } 572 } 573 574 if (data == NULL) 575 /* no explicit entry needed */ 576 return 1; 577 578 d = OPENSSL_malloc(sizeof(*d)); 579 if (d == NULL) 580 return 0; 581 582 d->data = data; 583 d->dup_func = dup_func; 584 d->free_func = free_func; 585 d->clear_free_func = clear_free_func; 586 587 d->next = *ex_data; 588 *ex_data = d; 589 590 return 1; 591} 592 593/* this has 'package' visibility */ 594void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, 595 void *(*dup_func) (void *), 596 void (*free_func) (void *), 597 void (*clear_free_func) (void *)) 598{ 599 const EC_EXTRA_DATA *d; 600 601 for (d = ex_data; d != NULL; d = d->next) { 602 if (d->dup_func == dup_func && d->free_func == free_func 603 && d->clear_free_func == clear_free_func) 604 return d->data; 605 } 606 607 return NULL; 608} 609 610/* this has 'package' visibility */ 611void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, 612 void *(*dup_func) (void *), 613 void (*free_func) (void *), 614 void (*clear_free_func) (void *)) 615{ 616 EC_EXTRA_DATA **p; 617 618 if (ex_data == NULL) 619 return; 620 621 for (p = ex_data; *p != NULL; p = &((*p)->next)) { 622 if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 623 && (*p)->clear_free_func == clear_free_func) { 624 EC_EXTRA_DATA *next = (*p)->next; 625 626 (*p)->free_func((*p)->data); 627 OPENSSL_free(*p); 628 629 *p = next; 630 return; 631 } 632 } 633} 634 635/* this has 'package' visibility */ 636void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, 637 void *(*dup_func) (void *), 638 void (*free_func) (void *), 639 void (*clear_free_func) (void *)) 640{ 641 EC_EXTRA_DATA **p; 642 643 if (ex_data == NULL) 644 return; 645 646 for (p = ex_data; *p != NULL; p = &((*p)->next)) { 647 if ((*p)->dup_func == dup_func && (*p)->free_func == free_func 648 && (*p)->clear_free_func == clear_free_func) { 649 EC_EXTRA_DATA *next = (*p)->next; 650 651 (*p)->clear_free_func((*p)->data); 652 OPENSSL_free(*p); 653 654 *p = next; 655 return; 656 } 657 } 658} 659 660/* this has 'package' visibility */ 661void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) 662{ 663 EC_EXTRA_DATA *d; 664 665 if (ex_data == NULL) 666 return; 667 668 d = *ex_data; 669 while (d) { 670 EC_EXTRA_DATA *next = d->next; 671 672 d->free_func(d->data); 673 OPENSSL_free(d); 674 675 d = next; 676 } 677 *ex_data = NULL; 678} 679 680/* this has 'package' visibility */ 681void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) 682{ 683 EC_EXTRA_DATA *d; 684 685 if (ex_data == NULL) 686 return; 687 688 d = *ex_data; 689 while (d) { 690 EC_EXTRA_DATA *next = d->next; 691 692 d->clear_free_func(d->data); 693 OPENSSL_free(d); 694 695 d = next; 696 } 697 *ex_data = NULL; 698} 699 700/* functions for EC_POINT objects */ 701 702EC_POINT *EC_POINT_new(const EC_GROUP *group) 703{ 704 EC_POINT *ret; 705 706 if (group == NULL) { 707 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER); 708 return NULL; 709 } 710 if (group->meth->point_init == 0) { 711 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 712 return NULL; 713 } 714 715 ret = OPENSSL_malloc(sizeof(*ret)); 716 if (ret == NULL) { 717 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE); 718 return NULL; 719 } 720 721 ret->meth = group->meth; 722 723 if (!ret->meth->point_init(ret)) { 724 OPENSSL_free(ret); 725 return NULL; 726 } 727 728 return ret; 729} 730 731void EC_POINT_free(EC_POINT *point) 732{ 733 if (!point) 734 return; 735 736 if (point->meth->point_finish != 0) 737 point->meth->point_finish(point); 738 OPENSSL_free(point); 739} 740 741void EC_POINT_clear_free(EC_POINT *point) 742{ 743 if (!point) 744 return; 745 746 if (point->meth->point_clear_finish != 0) 747 point->meth->point_clear_finish(point); 748 else if (point->meth->point_finish != 0) 749 point->meth->point_finish(point); 750 OPENSSL_cleanse(point, sizeof(*point)); 751 OPENSSL_free(point); 752} 753 754int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) 755{ 756 if (dest->meth->point_copy == 0) { 757 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 758 return 0; 759 } 760 if (dest->meth != src->meth) { 761 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS); 762 return 0; 763 } 764 if (dest == src) 765 return 1; 766 return dest->meth->point_copy(dest, src); 767} 768 769EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) 770{ 771 EC_POINT *t; 772 int r; 773 774 if (a == NULL) 775 return NULL; 776 777 t = EC_POINT_new(group); 778 if (t == NULL) 779 return (NULL); 780 r = EC_POINT_copy(t, a); 781 if (!r) { 782 EC_POINT_free(t); 783 return NULL; 784 } else 785 return t; 786} 787 788const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 789{ 790 return point->meth; 791} 792 793int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 794{ 795 if (group->meth->point_set_to_infinity == 0) { 796 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, 797 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 798 return 0; 799 } 800 if (group->meth != point->meth) { 801 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 802 return 0; 803 } 804 return group->meth->point_set_to_infinity(group, point); 805} 806 807int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, 808 EC_POINT *point, const BIGNUM *x, 809 const BIGNUM *y, const BIGNUM *z, 810 BN_CTX *ctx) 811{ 812 if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { 813 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 814 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 815 return 0; 816 } 817 if (group->meth != point->meth) { 818 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, 819 EC_R_INCOMPATIBLE_OBJECTS); 820 return 0; 821 } 822 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, 823 y, z, ctx); 824} 825 826int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, 827 const EC_POINT *point, BIGNUM *x, 828 BIGNUM *y, BIGNUM *z, 829 BN_CTX *ctx) 830{ 831 if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { 832 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 833 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 834 return 0; 835 } 836 if (group->meth != point->meth) { 837 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, 838 EC_R_INCOMPATIBLE_OBJECTS); 839 return 0; 840 } 841 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, 842 y, z, ctx); 843} 844 845int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, 846 EC_POINT *point, const BIGNUM *x, 847 const BIGNUM *y, BN_CTX *ctx) 848{ 849 if (group->meth->point_set_affine_coordinates == 0) { 850 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 851 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 852 return 0; 853 } 854 if (group->meth != point->meth) { 855 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, 856 EC_R_INCOMPATIBLE_OBJECTS); 857 return 0; 858 } 859 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 860} 861 862#ifndef OPENSSL_NO_EC2M 863int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, 864 EC_POINT *point, const BIGNUM *x, 865 const BIGNUM *y, BN_CTX *ctx) 866{ 867 if (group->meth->point_set_affine_coordinates == 0) { 868 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 869 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 870 return 0; 871 } 872 if (group->meth != point->meth) { 873 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, 874 EC_R_INCOMPATIBLE_OBJECTS); 875 return 0; 876 } 877 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 878} 879#endif 880 881int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, 882 const EC_POINT *point, BIGNUM *x, 883 BIGNUM *y, BN_CTX *ctx) 884{ 885 if (group->meth->point_get_affine_coordinates == 0) { 886 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 887 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 888 return 0; 889 } 890 if (group->meth != point->meth) { 891 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, 892 EC_R_INCOMPATIBLE_OBJECTS); 893 return 0; 894 } 895 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 896} 897 898#ifndef OPENSSL_NO_EC2M 899int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, 900 const EC_POINT *point, BIGNUM *x, 901 BIGNUM *y, BN_CTX *ctx) 902{ 903 if (group->meth->point_get_affine_coordinates == 0) { 904 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 905 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 906 return 0; 907 } 908 if (group->meth != point->meth) { 909 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, 910 EC_R_INCOMPATIBLE_OBJECTS); 911 return 0; 912 } 913 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 914} 915#endif 916 917int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 918 const EC_POINT *b, BN_CTX *ctx) 919{ 920 if (group->meth->add == 0) { 921 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 922 return 0; 923 } 924 if ((group->meth != r->meth) || (r->meth != a->meth) 925 || (a->meth != b->meth)) { 926 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS); 927 return 0; 928 } 929 return group->meth->add(group, r, a, b, ctx); 930} 931 932int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 933 BN_CTX *ctx) 934{ 935 if (group->meth->dbl == 0) { 936 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 937 return 0; 938 } 939 if ((group->meth != r->meth) || (r->meth != a->meth)) { 940 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 941 return 0; 942 } 943 return group->meth->dbl(group, r, a, ctx); 944} 945 946int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) 947{ 948 if (group->meth->invert == 0) { 949 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 950 return 0; 951 } 952 if (group->meth != a->meth) { 953 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); 954 return 0; 955 } 956 return group->meth->invert(group, a, ctx); 957} 958 959int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 960{ 961 if (group->meth->is_at_infinity == 0) { 962 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, 963 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 964 return 0; 965 } 966 if (group->meth != point->meth) { 967 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS); 968 return 0; 969 } 970 return group->meth->is_at_infinity(group, point); 971} 972 973/* 974 * Check whether an EC_POINT is on the curve or not. Note that the return 975 * value for this function should NOT be treated as a boolean. Return values: 976 * 1: The point is on the curve 977 * 0: The point is not on the curve 978 * -1: An error occurred 979 */ 980int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 981 BN_CTX *ctx) 982{ 983 if (group->meth->is_on_curve == 0) { 984 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 985 return 0; 986 } 987 if (group->meth != point->meth) { 988 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS); 989 return 0; 990 } 991 return group->meth->is_on_curve(group, point, ctx); 992} 993 994int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 995 BN_CTX *ctx) 996{ 997 if (group->meth->point_cmp == 0) { 998 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 999 return -1; 1000 } 1001 if ((group->meth != a->meth) || (a->meth != b->meth)) { 1002 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); 1003 return -1; 1004 } 1005 return group->meth->point_cmp(group, a, b, ctx); 1006} 1007 1008int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 1009{ 1010 if (group->meth->make_affine == 0) { 1011 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1012 return 0; 1013 } 1014 if (group->meth != point->meth) { 1015 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1016 return 0; 1017 } 1018 return group->meth->make_affine(group, point, ctx); 1019} 1020 1021int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, 1022 EC_POINT *points[], BN_CTX *ctx) 1023{ 1024 size_t i; 1025 1026 if (group->meth->points_make_affine == 0) { 1027 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1028 return 0; 1029 } 1030 for (i = 0; i < num; i++) { 1031 if (group->meth != points[i]->meth) { 1032 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); 1033 return 0; 1034 } 1035 } 1036 return group->meth->points_make_affine(group, num, points, ctx); 1037} 1038 1039/* 1040 * Functions for point multiplication. If group->meth->mul is 0, we use the 1041 * wNAF-based implementations in ec_mult.c; otherwise we dispatch through 1042 * methods. 1043 */ 1044 1045int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 1046 size_t num, const EC_POINT *points[], 1047 const BIGNUM *scalars[], BN_CTX *ctx) 1048{ 1049 if (group->meth->mul == 0) 1050 /* use default */ 1051 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 1052 1053 return group->meth->mul(group, r, scalar, num, points, scalars, ctx); 1054} 1055 1056int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1057 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 1058{ 1059 /* just a convenient interface to EC_POINTs_mul() */ 1060 1061 const EC_POINT *points[1]; 1062 const BIGNUM *scalars[1]; 1063 1064 points[0] = point; 1065 scalars[0] = p_scalar; 1066 1067 return EC_POINTs_mul(group, r, g_scalar, 1068 (point != NULL 1069 && p_scalar != NULL), points, scalars, ctx); 1070} 1071 1072int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 1073{ 1074 if (group->meth->mul == 0) 1075 /* use default */ 1076 return ec_wNAF_precompute_mult(group, ctx); 1077 1078 if (group->meth->precompute_mult != 0) 1079 return group->meth->precompute_mult(group, ctx); 1080 else 1081 return 1; /* nothing to do, so report success */ 1082} 1083 1084int EC_GROUP_have_precompute_mult(const EC_GROUP *group) 1085{ 1086 if (group->meth->mul == 0) 1087 /* use default */ 1088 return ec_wNAF_have_precompute_mult(group); 1089 1090 if (group->meth->have_precompute_mult != 0) 1091 return group->meth->have_precompute_mult(group); 1092 else 1093 return 0; /* cannot tell whether precomputation has 1094 * been performed */ 1095} 1096 1097/* 1098 * ec_precompute_mont_data sets |group->mont_data| from |group->order| and 1099 * returns one on success. On error it returns zero. 1100 */ 1101int ec_precompute_mont_data(EC_GROUP *group) 1102{ 1103 BN_CTX *ctx = BN_CTX_new(); 1104 int ret = 0; 1105 1106 if (!EC_GROUP_VERSION(group)) 1107 goto err; 1108 1109 if (group->mont_data) { 1110 BN_MONT_CTX_free(group->mont_data); 1111 group->mont_data = NULL; 1112 } 1113 1114 if (ctx == NULL) 1115 goto err; 1116 1117 group->mont_data = BN_MONT_CTX_new(); 1118 if (!group->mont_data) 1119 goto err; 1120 1121 if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) { 1122 BN_MONT_CTX_free(group->mont_data); 1123 group->mont_data = NULL; 1124 goto err; 1125 } 1126 1127 ret = 1; 1128 1129 err: 1130 1131 if (ctx) 1132 BN_CTX_free(ctx); 1133 return ret; 1134} 1135