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