[331] | 1 | /*
|
---|
| 2 | * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
| 5 | * this file except in compliance with the License. You can obtain a copy
|
---|
| 6 | * in the file LICENSE in the source distribution or at
|
---|
| 7 | * https://www.openssl.org/source/license.html
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 | /* ====================================================================
|
---|
| 11 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
---|
| 12 | * Binary polynomial ECC support in OpenSSL originally developed by
|
---|
| 13 | * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
|
---|
| 14 | */
|
---|
| 15 |
|
---|
| 16 | #include <string.h>
|
---|
| 17 |
|
---|
| 18 | #include <openssl/err.h>
|
---|
| 19 | #include <openssl/opensslv.h>
|
---|
| 20 |
|
---|
| 21 | #include "ec_lcl.h"
|
---|
| 22 |
|
---|
| 23 | /* functions for EC_GROUP objects */
|
---|
| 24 |
|
---|
| 25 | EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
|
---|
| 26 | {
|
---|
| 27 | EC_GROUP *ret;
|
---|
| 28 |
|
---|
| 29 | if (meth == NULL) {
|
---|
| 30 | ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
|
---|
| 31 | return NULL;
|
---|
| 32 | }
|
---|
| 33 | if (meth->group_init == 0) {
|
---|
| 34 | ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 35 | return NULL;
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | ret = OPENSSL_zalloc(sizeof(*ret));
|
---|
| 39 | if (ret == NULL) {
|
---|
| 40 | ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
|
---|
| 41 | return NULL;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | ret->meth = meth;
|
---|
| 45 | if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
|
---|
| 46 | ret->order = BN_new();
|
---|
| 47 | if (ret->order == NULL)
|
---|
| 48 | goto err;
|
---|
| 49 | ret->cofactor = BN_new();
|
---|
| 50 | if (ret->cofactor == NULL)
|
---|
| 51 | goto err;
|
---|
| 52 | }
|
---|
| 53 | ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
|
---|
| 54 | ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
|
---|
| 55 | if (!meth->group_init(ret))
|
---|
| 56 | goto err;
|
---|
| 57 | return ret;
|
---|
| 58 |
|
---|
| 59 | err:
|
---|
| 60 | BN_free(ret->order);
|
---|
| 61 | BN_free(ret->cofactor);
|
---|
| 62 | OPENSSL_free(ret);
|
---|
| 63 | return NULL;
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | void EC_pre_comp_free(EC_GROUP *group)
|
---|
| 67 | {
|
---|
| 68 | switch (group->pre_comp_type) {
|
---|
| 69 | default:
|
---|
| 70 | break;
|
---|
| 71 | #ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
|
---|
| 72 | case PCT_nistz256:
|
---|
| 73 | EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
|
---|
| 74 | break;
|
---|
| 75 | #endif
|
---|
| 76 | #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
---|
| 77 | case PCT_nistp224:
|
---|
| 78 | EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
|
---|
| 79 | break;
|
---|
| 80 | case PCT_nistp256:
|
---|
| 81 | EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
|
---|
| 82 | break;
|
---|
| 83 | case PCT_nistp521:
|
---|
| 84 | EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
|
---|
| 85 | break;
|
---|
| 86 | #endif
|
---|
| 87 | case PCT_ec:
|
---|
| 88 | EC_ec_pre_comp_free(group->pre_comp.ec);
|
---|
| 89 | break;
|
---|
| 90 | }
|
---|
| 91 | group->pre_comp.ec = NULL;
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | void EC_GROUP_free(EC_GROUP *group)
|
---|
| 95 | {
|
---|
| 96 | if (!group)
|
---|
| 97 | return;
|
---|
| 98 |
|
---|
| 99 | if (group->meth->group_finish != 0)
|
---|
| 100 | group->meth->group_finish(group);
|
---|
| 101 |
|
---|
| 102 | EC_pre_comp_free(group);
|
---|
| 103 | BN_MONT_CTX_free(group->mont_data);
|
---|
| 104 | EC_POINT_free(group->generator);
|
---|
| 105 | BN_free(group->order);
|
---|
| 106 | BN_free(group->cofactor);
|
---|
| 107 | OPENSSL_free(group->seed);
|
---|
| 108 | OPENSSL_free(group);
|
---|
| 109 | }
|
---|
| 110 |
|
---|
| 111 | void EC_GROUP_clear_free(EC_GROUP *group)
|
---|
| 112 | {
|
---|
| 113 | if (!group)
|
---|
| 114 | return;
|
---|
| 115 |
|
---|
| 116 | if (group->meth->group_clear_finish != 0)
|
---|
| 117 | group->meth->group_clear_finish(group);
|
---|
| 118 | else if (group->meth->group_finish != 0)
|
---|
| 119 | group->meth->group_finish(group);
|
---|
| 120 |
|
---|
| 121 | EC_pre_comp_free(group);
|
---|
| 122 | BN_MONT_CTX_free(group->mont_data);
|
---|
| 123 | EC_POINT_clear_free(group->generator);
|
---|
| 124 | BN_clear_free(group->order);
|
---|
| 125 | BN_clear_free(group->cofactor);
|
---|
| 126 | OPENSSL_clear_free(group->seed, group->seed_len);
|
---|
| 127 | OPENSSL_clear_free(group, sizeof(*group));
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
|
---|
| 131 | {
|
---|
| 132 | if (dest->meth->group_copy == 0) {
|
---|
| 133 | ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 134 | return 0;
|
---|
| 135 | }
|
---|
| 136 | if (dest->meth != src->meth) {
|
---|
| 137 | ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 138 | return 0;
|
---|
| 139 | }
|
---|
| 140 | if (dest == src)
|
---|
| 141 | return 1;
|
---|
| 142 |
|
---|
| 143 | /* Copy precomputed */
|
---|
| 144 | dest->pre_comp_type = src->pre_comp_type;
|
---|
| 145 | switch (src->pre_comp_type) {
|
---|
| 146 | default:
|
---|
| 147 | dest->pre_comp.ec = NULL;
|
---|
| 148 | break;
|
---|
| 149 | #ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
|
---|
| 150 | case PCT_nistz256:
|
---|
| 151 | dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
|
---|
| 152 | break;
|
---|
| 153 | #endif
|
---|
| 154 | #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
---|
| 155 | case PCT_nistp224:
|
---|
| 156 | dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
|
---|
| 157 | break;
|
---|
| 158 | case PCT_nistp256:
|
---|
| 159 | dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
|
---|
| 160 | break;
|
---|
| 161 | case PCT_nistp521:
|
---|
| 162 | dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
|
---|
| 163 | break;
|
---|
| 164 | #endif
|
---|
| 165 | case PCT_ec:
|
---|
| 166 | dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
|
---|
| 167 | break;
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | if (src->mont_data != NULL) {
|
---|
| 171 | if (dest->mont_data == NULL) {
|
---|
| 172 | dest->mont_data = BN_MONT_CTX_new();
|
---|
| 173 | if (dest->mont_data == NULL)
|
---|
| 174 | return 0;
|
---|
| 175 | }
|
---|
| 176 | if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
|
---|
| 177 | return 0;
|
---|
| 178 | } else {
|
---|
| 179 | /* src->generator == NULL */
|
---|
| 180 | BN_MONT_CTX_free(dest->mont_data);
|
---|
| 181 | dest->mont_data = NULL;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 | if (src->generator != NULL) {
|
---|
| 185 | if (dest->generator == NULL) {
|
---|
| 186 | dest->generator = EC_POINT_new(dest);
|
---|
| 187 | if (dest->generator == NULL)
|
---|
| 188 | return 0;
|
---|
| 189 | }
|
---|
| 190 | if (!EC_POINT_copy(dest->generator, src->generator))
|
---|
| 191 | return 0;
|
---|
| 192 | } else {
|
---|
| 193 | /* src->generator == NULL */
|
---|
| 194 | EC_POINT_clear_free(dest->generator);
|
---|
| 195 | dest->generator = NULL;
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 | if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
|
---|
| 199 | if (!BN_copy(dest->order, src->order))
|
---|
| 200 | return 0;
|
---|
| 201 | if (!BN_copy(dest->cofactor, src->cofactor))
|
---|
| 202 | return 0;
|
---|
| 203 | }
|
---|
| 204 |
|
---|
| 205 | dest->curve_name = src->curve_name;
|
---|
| 206 | dest->asn1_flag = src->asn1_flag;
|
---|
| 207 | dest->asn1_form = src->asn1_form;
|
---|
| 208 |
|
---|
| 209 | if (src->seed) {
|
---|
| 210 | OPENSSL_free(dest->seed);
|
---|
| 211 | dest->seed = OPENSSL_malloc(src->seed_len);
|
---|
| 212 | if (dest->seed == NULL)
|
---|
| 213 | return 0;
|
---|
| 214 | if (!memcpy(dest->seed, src->seed, src->seed_len))
|
---|
| 215 | return 0;
|
---|
| 216 | dest->seed_len = src->seed_len;
|
---|
| 217 | } else {
|
---|
| 218 | OPENSSL_free(dest->seed);
|
---|
| 219 | dest->seed = NULL;
|
---|
| 220 | dest->seed_len = 0;
|
---|
| 221 | }
|
---|
| 222 |
|
---|
| 223 | return dest->meth->group_copy(dest, src);
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
|
---|
| 227 | {
|
---|
| 228 | EC_GROUP *t = NULL;
|
---|
| 229 | int ok = 0;
|
---|
| 230 |
|
---|
| 231 | if (a == NULL)
|
---|
| 232 | return NULL;
|
---|
| 233 |
|
---|
| 234 | if ((t = EC_GROUP_new(a->meth)) == NULL)
|
---|
| 235 | return (NULL);
|
---|
| 236 | if (!EC_GROUP_copy(t, a))
|
---|
| 237 | goto err;
|
---|
| 238 |
|
---|
| 239 | ok = 1;
|
---|
| 240 |
|
---|
| 241 | err:
|
---|
| 242 | if (!ok) {
|
---|
| 243 | EC_GROUP_free(t);
|
---|
| 244 | return NULL;
|
---|
| 245 | }
|
---|
| 246 | return t;
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
|
---|
| 250 | {
|
---|
| 251 | return group->meth;
|
---|
| 252 | }
|
---|
| 253 |
|
---|
| 254 | int EC_METHOD_get_field_type(const EC_METHOD *meth)
|
---|
| 255 | {
|
---|
| 256 | return meth->field_type;
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
|
---|
| 260 | const BIGNUM *order, const BIGNUM *cofactor)
|
---|
| 261 | {
|
---|
| 262 | if (generator == NULL) {
|
---|
| 263 | ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
|
---|
| 264 | return 0;
|
---|
| 265 | }
|
---|
| 266 |
|
---|
| 267 | if (group->generator == NULL) {
|
---|
| 268 | group->generator = EC_POINT_new(group);
|
---|
| 269 | if (group->generator == NULL)
|
---|
| 270 | return 0;
|
---|
| 271 | }
|
---|
| 272 | if (!EC_POINT_copy(group->generator, generator))
|
---|
| 273 | return 0;
|
---|
| 274 |
|
---|
| 275 | if (order != NULL) {
|
---|
| 276 | if (!BN_copy(group->order, order))
|
---|
| 277 | return 0;
|
---|
| 278 | } else
|
---|
| 279 | BN_zero(group->order);
|
---|
| 280 |
|
---|
| 281 | if (cofactor != NULL) {
|
---|
| 282 | if (!BN_copy(group->cofactor, cofactor))
|
---|
| 283 | return 0;
|
---|
| 284 | } else
|
---|
| 285 | BN_zero(group->cofactor);
|
---|
| 286 |
|
---|
| 287 | /*
|
---|
| 288 | * Some groups have an order with
|
---|
| 289 | * factors of two, which makes the Montgomery setup fail.
|
---|
| 290 | * |group->mont_data| will be NULL in this case.
|
---|
| 291 | */
|
---|
| 292 | if (BN_is_odd(group->order)) {
|
---|
| 293 | return ec_precompute_mont_data(group);
|
---|
| 294 | }
|
---|
| 295 |
|
---|
| 296 | BN_MONT_CTX_free(group->mont_data);
|
---|
| 297 | group->mont_data = NULL;
|
---|
| 298 | return 1;
|
---|
| 299 | }
|
---|
| 300 |
|
---|
| 301 | const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
|
---|
| 302 | {
|
---|
| 303 | return group->generator;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
|
---|
| 307 | {
|
---|
| 308 | return group->mont_data;
|
---|
| 309 | }
|
---|
| 310 |
|
---|
| 311 | int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
|
---|
| 312 | {
|
---|
| 313 | if (group->order == NULL)
|
---|
| 314 | return 0;
|
---|
| 315 | if (!BN_copy(order, group->order))
|
---|
| 316 | return 0;
|
---|
| 317 |
|
---|
| 318 | return !BN_is_zero(order);
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
|
---|
| 322 | {
|
---|
| 323 | return group->order;
|
---|
| 324 | }
|
---|
| 325 |
|
---|
| 326 | int EC_GROUP_order_bits(const EC_GROUP *group)
|
---|
| 327 | {
|
---|
| 328 | OPENSSL_assert(group->meth->group_order_bits != NULL);
|
---|
| 329 | return group->meth->group_order_bits(group);
|
---|
| 330 | }
|
---|
| 331 |
|
---|
| 332 | int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
|
---|
| 333 | BN_CTX *ctx)
|
---|
| 334 | {
|
---|
| 335 |
|
---|
| 336 | if (group->cofactor == NULL)
|
---|
| 337 | return 0;
|
---|
| 338 | if (!BN_copy(cofactor, group->cofactor))
|
---|
| 339 | return 0;
|
---|
| 340 |
|
---|
| 341 | return !BN_is_zero(group->cofactor);
|
---|
| 342 | }
|
---|
| 343 |
|
---|
| 344 | const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
|
---|
| 345 | {
|
---|
| 346 | return group->cofactor;
|
---|
| 347 | }
|
---|
| 348 |
|
---|
| 349 | void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
|
---|
| 350 | {
|
---|
| 351 | group->curve_name = nid;
|
---|
| 352 | }
|
---|
| 353 |
|
---|
| 354 | int EC_GROUP_get_curve_name(const EC_GROUP *group)
|
---|
| 355 | {
|
---|
| 356 | return group->curve_name;
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 | void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
|
---|
| 360 | {
|
---|
| 361 | group->asn1_flag = flag;
|
---|
| 362 | }
|
---|
| 363 |
|
---|
| 364 | int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
|
---|
| 365 | {
|
---|
| 366 | return group->asn1_flag;
|
---|
| 367 | }
|
---|
| 368 |
|
---|
| 369 | void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
|
---|
| 370 | point_conversion_form_t form)
|
---|
| 371 | {
|
---|
| 372 | group->asn1_form = form;
|
---|
| 373 | }
|
---|
| 374 |
|
---|
| 375 | point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
|
---|
| 376 | *group)
|
---|
| 377 | {
|
---|
| 378 | return group->asn1_form;
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 | size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
|
---|
| 382 | {
|
---|
| 383 | OPENSSL_free(group->seed);
|
---|
| 384 | group->seed = NULL;
|
---|
| 385 | group->seed_len = 0;
|
---|
| 386 |
|
---|
| 387 | if (!len || !p)
|
---|
| 388 | return 1;
|
---|
| 389 |
|
---|
| 390 | if ((group->seed = OPENSSL_malloc(len)) == NULL)
|
---|
| 391 | return 0;
|
---|
| 392 | memcpy(group->seed, p, len);
|
---|
| 393 | group->seed_len = len;
|
---|
| 394 |
|
---|
| 395 | return len;
|
---|
| 396 | }
|
---|
| 397 |
|
---|
| 398 | unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
|
---|
| 399 | {
|
---|
| 400 | return group->seed;
|
---|
| 401 | }
|
---|
| 402 |
|
---|
| 403 | size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
|
---|
| 404 | {
|
---|
| 405 | return group->seed_len;
|
---|
| 406 | }
|
---|
| 407 |
|
---|
| 408 | int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
|
---|
| 409 | const BIGNUM *b, BN_CTX *ctx)
|
---|
| 410 | {
|
---|
| 411 | if (group->meth->group_set_curve == 0) {
|
---|
| 412 | ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 413 | return 0;
|
---|
| 414 | }
|
---|
| 415 | return group->meth->group_set_curve(group, p, a, b, ctx);
|
---|
| 416 | }
|
---|
| 417 |
|
---|
| 418 | int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
|
---|
| 419 | BIGNUM *b, BN_CTX *ctx)
|
---|
| 420 | {
|
---|
| 421 | if (group->meth->group_get_curve == 0) {
|
---|
| 422 | ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 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,
|
---|
| 430 | const BIGNUM *b, BN_CTX *ctx)
|
---|
| 431 | {
|
---|
| 432 | if (group->meth->group_set_curve == 0) {
|
---|
| 433 | ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
|
---|
| 434 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 435 | return 0;
|
---|
| 436 | }
|
---|
| 437 | return group->meth->group_set_curve(group, p, a, b, ctx);
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
|
---|
| 441 | BIGNUM *b, BN_CTX *ctx)
|
---|
| 442 | {
|
---|
| 443 | if (group->meth->group_get_curve == 0) {
|
---|
| 444 | ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
|
---|
| 445 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 446 | return 0;
|
---|
| 447 | }
|
---|
| 448 | return group->meth->group_get_curve(group, p, a, b, ctx);
|
---|
| 449 | }
|
---|
| 450 | #endif
|
---|
| 451 |
|
---|
| 452 | int EC_GROUP_get_degree(const EC_GROUP *group)
|
---|
| 453 | {
|
---|
| 454 | if (group->meth->group_get_degree == 0) {
|
---|
| 455 | ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 456 | return 0;
|
---|
| 457 | }
|
---|
| 458 | return group->meth->group_get_degree(group);
|
---|
| 459 | }
|
---|
| 460 |
|
---|
| 461 | int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
|
---|
| 462 | {
|
---|
| 463 | if (group->meth->group_check_discriminant == 0) {
|
---|
| 464 | ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
|
---|
| 465 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 466 | return 0;
|
---|
| 467 | }
|
---|
| 468 | return group->meth->group_check_discriminant(group, ctx);
|
---|
| 469 | }
|
---|
| 470 |
|
---|
| 471 | int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
|
---|
| 472 | {
|
---|
| 473 | int r = 0;
|
---|
| 474 | BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
|
---|
| 475 | BN_CTX *ctx_new = NULL;
|
---|
| 476 |
|
---|
| 477 | /* compare the field types */
|
---|
| 478 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
|
---|
| 479 | EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
|
---|
| 480 | return 1;
|
---|
| 481 | /* compare the curve name (if present in both) */
|
---|
| 482 | if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
|
---|
| 483 | EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
|
---|
| 484 | return 1;
|
---|
| 485 | if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
|
---|
| 486 | return 0;
|
---|
| 487 |
|
---|
| 488 | if (ctx == NULL)
|
---|
| 489 | ctx_new = ctx = BN_CTX_new();
|
---|
| 490 | if (ctx == NULL)
|
---|
| 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 == NULL) {
|
---|
| 501 | BN_CTX_end(ctx);
|
---|
| 502 | BN_CTX_free(ctx_new);
|
---|
| 503 | return -1;
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | /*
|
---|
| 507 | * XXX This approach assumes that the external representation of curves
|
---|
| 508 | * over the same field type is the same.
|
---|
| 509 | */
|
---|
| 510 | if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
|
---|
| 511 | !b->meth->group_get_curve(b, b1, b2, b3, ctx))
|
---|
| 512 | r = 1;
|
---|
| 513 |
|
---|
| 514 | if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
|
---|
| 515 | r = 1;
|
---|
| 516 |
|
---|
| 517 | /* XXX EC_POINT_cmp() assumes that the methods are equal */
|
---|
| 518 | if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
|
---|
| 519 | EC_GROUP_get0_generator(b), ctx))
|
---|
| 520 | r = 1;
|
---|
| 521 |
|
---|
| 522 | if (!r) {
|
---|
| 523 | const BIGNUM *ao, *bo, *ac, *bc;
|
---|
| 524 | /* compare the order and cofactor */
|
---|
| 525 | ao = EC_GROUP_get0_order(a);
|
---|
| 526 | bo = EC_GROUP_get0_order(b);
|
---|
| 527 | ac = EC_GROUP_get0_cofactor(a);
|
---|
| 528 | bc = EC_GROUP_get0_cofactor(b);
|
---|
| 529 | if (ao == NULL || bo == NULL) {
|
---|
| 530 | BN_CTX_end(ctx);
|
---|
| 531 | BN_CTX_free(ctx_new);
|
---|
| 532 | return -1;
|
---|
| 533 | }
|
---|
| 534 | if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
|
---|
| 535 | r = 1;
|
---|
| 536 | }
|
---|
| 537 |
|
---|
| 538 | BN_CTX_end(ctx);
|
---|
| 539 | BN_CTX_free(ctx_new);
|
---|
| 540 |
|
---|
| 541 | return r;
|
---|
| 542 | }
|
---|
| 543 |
|
---|
| 544 | /* functions for EC_POINT objects */
|
---|
| 545 |
|
---|
| 546 | EC_POINT *EC_POINT_new(const EC_GROUP *group)
|
---|
| 547 | {
|
---|
| 548 | EC_POINT *ret;
|
---|
| 549 |
|
---|
| 550 | if (group == NULL) {
|
---|
| 551 | ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
|
---|
| 552 | return NULL;
|
---|
| 553 | }
|
---|
| 554 | if (group->meth->point_init == 0) {
|
---|
| 555 | ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 556 | return NULL;
|
---|
| 557 | }
|
---|
| 558 |
|
---|
| 559 | ret = OPENSSL_zalloc(sizeof(*ret));
|
---|
| 560 | if (ret == NULL) {
|
---|
| 561 | ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
|
---|
| 562 | return NULL;
|
---|
| 563 | }
|
---|
| 564 |
|
---|
| 565 | ret->meth = group->meth;
|
---|
| 566 |
|
---|
| 567 | if (!ret->meth->point_init(ret)) {
|
---|
| 568 | OPENSSL_free(ret);
|
---|
| 569 | return NULL;
|
---|
| 570 | }
|
---|
| 571 |
|
---|
| 572 | return ret;
|
---|
| 573 | }
|
---|
| 574 |
|
---|
| 575 | void EC_POINT_free(EC_POINT *point)
|
---|
| 576 | {
|
---|
| 577 | if (!point)
|
---|
| 578 | return;
|
---|
| 579 |
|
---|
| 580 | if (point->meth->point_finish != 0)
|
---|
| 581 | point->meth->point_finish(point);
|
---|
| 582 | OPENSSL_free(point);
|
---|
| 583 | }
|
---|
| 584 |
|
---|
| 585 | void EC_POINT_clear_free(EC_POINT *point)
|
---|
| 586 | {
|
---|
| 587 | if (!point)
|
---|
| 588 | return;
|
---|
| 589 |
|
---|
| 590 | if (point->meth->point_clear_finish != 0)
|
---|
| 591 | point->meth->point_clear_finish(point);
|
---|
| 592 | else if (point->meth->point_finish != 0)
|
---|
| 593 | point->meth->point_finish(point);
|
---|
| 594 | OPENSSL_clear_free(point, sizeof(*point));
|
---|
| 595 | }
|
---|
| 596 |
|
---|
| 597 | int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
|
---|
| 598 | {
|
---|
| 599 | if (dest->meth->point_copy == 0) {
|
---|
| 600 | ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 601 | return 0;
|
---|
| 602 | }
|
---|
| 603 | if (dest->meth != src->meth) {
|
---|
| 604 | ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 605 | return 0;
|
---|
| 606 | }
|
---|
| 607 | if (dest == src)
|
---|
| 608 | return 1;
|
---|
| 609 | return dest->meth->point_copy(dest, src);
|
---|
| 610 | }
|
---|
| 611 |
|
---|
| 612 | EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
|
---|
| 613 | {
|
---|
| 614 | EC_POINT *t;
|
---|
| 615 | int r;
|
---|
| 616 |
|
---|
| 617 | if (a == NULL)
|
---|
| 618 | return NULL;
|
---|
| 619 |
|
---|
| 620 | t = EC_POINT_new(group);
|
---|
| 621 | if (t == NULL)
|
---|
| 622 | return (NULL);
|
---|
| 623 | r = EC_POINT_copy(t, a);
|
---|
| 624 | if (!r) {
|
---|
| 625 | EC_POINT_free(t);
|
---|
| 626 | return NULL;
|
---|
| 627 | }
|
---|
| 628 | return t;
|
---|
| 629 | }
|
---|
| 630 |
|
---|
| 631 | const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
|
---|
| 632 | {
|
---|
| 633 | return point->meth;
|
---|
| 634 | }
|
---|
| 635 |
|
---|
| 636 | int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
|
---|
| 637 | {
|
---|
| 638 | if (group->meth->point_set_to_infinity == 0) {
|
---|
| 639 | ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
|
---|
| 640 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 641 | return 0;
|
---|
| 642 | }
|
---|
| 643 | if (group->meth != point->meth) {
|
---|
| 644 | ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 645 | return 0;
|
---|
| 646 | }
|
---|
| 647 | return group->meth->point_set_to_infinity(group, point);
|
---|
| 648 | }
|
---|
| 649 |
|
---|
| 650 | int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
|
---|
| 651 | EC_POINT *point, const BIGNUM *x,
|
---|
| 652 | const BIGNUM *y, const BIGNUM *z,
|
---|
| 653 | BN_CTX *ctx)
|
---|
| 654 | {
|
---|
| 655 | if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
|
---|
| 656 | ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
|
---|
| 657 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 658 | return 0;
|
---|
| 659 | }
|
---|
| 660 | if (group->meth != point->meth) {
|
---|
| 661 | ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
|
---|
| 662 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 663 | return 0;
|
---|
| 664 | }
|
---|
| 665 | return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
|
---|
| 666 | y, z, ctx);
|
---|
| 667 | }
|
---|
| 668 |
|
---|
| 669 | int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
|
---|
| 670 | const EC_POINT *point, BIGNUM *x,
|
---|
| 671 | BIGNUM *y, BIGNUM *z,
|
---|
| 672 | BN_CTX *ctx)
|
---|
| 673 | {
|
---|
| 674 | if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
|
---|
| 675 | ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
|
---|
| 676 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 677 | return 0;
|
---|
| 678 | }
|
---|
| 679 | if (group->meth != point->meth) {
|
---|
| 680 | ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
|
---|
| 681 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 682 | return 0;
|
---|
| 683 | }
|
---|
| 684 | return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
|
---|
| 685 | y, z, ctx);
|
---|
| 686 | }
|
---|
| 687 |
|
---|
| 688 | int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
|
---|
| 689 | EC_POINT *point, const BIGNUM *x,
|
---|
| 690 | const BIGNUM *y, BN_CTX *ctx)
|
---|
| 691 | {
|
---|
| 692 | if (group->meth->point_set_affine_coordinates == 0) {
|
---|
| 693 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
|
---|
| 694 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 695 | return 0;
|
---|
| 696 | }
|
---|
| 697 | if (group->meth != point->meth) {
|
---|
| 698 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
|
---|
| 699 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 700 | return 0;
|
---|
| 701 | }
|
---|
| 702 | if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
|
---|
| 703 | return 0;
|
---|
| 704 |
|
---|
| 705 | if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
|
---|
| 706 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
|
---|
| 707 | EC_R_POINT_IS_NOT_ON_CURVE);
|
---|
| 708 | return 0;
|
---|
| 709 | }
|
---|
| 710 | return 1;
|
---|
| 711 | }
|
---|
| 712 |
|
---|
| 713 | #ifndef OPENSSL_NO_EC2M
|
---|
| 714 | int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
|
---|
| 715 | EC_POINT *point, const BIGNUM *x,
|
---|
| 716 | const BIGNUM *y, BN_CTX *ctx)
|
---|
| 717 | {
|
---|
| 718 | if (group->meth->point_set_affine_coordinates == 0) {
|
---|
| 719 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
|
---|
| 720 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 721 | return 0;
|
---|
| 722 | }
|
---|
| 723 | if (group->meth != point->meth) {
|
---|
| 724 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
|
---|
| 725 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 726 | return 0;
|
---|
| 727 | }
|
---|
| 728 | if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
|
---|
| 729 | return 0;
|
---|
| 730 |
|
---|
| 731 | if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
|
---|
| 732 | ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
|
---|
| 733 | EC_R_POINT_IS_NOT_ON_CURVE);
|
---|
| 734 | return 0;
|
---|
| 735 | }
|
---|
| 736 | return 1;
|
---|
| 737 | }
|
---|
| 738 | #endif
|
---|
| 739 |
|
---|
| 740 | int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
|
---|
| 741 | const EC_POINT *point, BIGNUM *x,
|
---|
| 742 | BIGNUM *y, BN_CTX *ctx)
|
---|
| 743 | {
|
---|
| 744 | if (group->meth->point_get_affine_coordinates == 0) {
|
---|
| 745 | ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
|
---|
| 746 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 747 | return 0;
|
---|
| 748 | }
|
---|
| 749 | if (group->meth != point->meth) {
|
---|
| 750 | ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
|
---|
| 751 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 752 | return 0;
|
---|
| 753 | }
|
---|
| 754 | return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
|
---|
| 755 | }
|
---|
| 756 |
|
---|
| 757 | #ifndef OPENSSL_NO_EC2M
|
---|
| 758 | int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
|
---|
| 759 | const EC_POINT *point, BIGNUM *x,
|
---|
| 760 | BIGNUM *y, BN_CTX *ctx)
|
---|
| 761 | {
|
---|
| 762 | if (group->meth->point_get_affine_coordinates == 0) {
|
---|
| 763 | ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
|
---|
| 764 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 765 | return 0;
|
---|
| 766 | }
|
---|
| 767 | if (group->meth != point->meth) {
|
---|
| 768 | ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
|
---|
| 769 | EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 770 | return 0;
|
---|
| 771 | }
|
---|
| 772 | return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
|
---|
| 773 | }
|
---|
| 774 | #endif
|
---|
| 775 |
|
---|
| 776 | int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
---|
| 777 | const EC_POINT *b, BN_CTX *ctx)
|
---|
| 778 | {
|
---|
| 779 | if (group->meth->add == 0) {
|
---|
| 780 | ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 781 | return 0;
|
---|
| 782 | }
|
---|
| 783 | if ((group->meth != r->meth) || (r->meth != a->meth)
|
---|
| 784 | || (a->meth != b->meth)) {
|
---|
| 785 | ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 786 | return 0;
|
---|
| 787 | }
|
---|
| 788 | return group->meth->add(group, r, a, b, ctx);
|
---|
| 789 | }
|
---|
| 790 |
|
---|
| 791 | int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
---|
| 792 | BN_CTX *ctx)
|
---|
| 793 | {
|
---|
| 794 | if (group->meth->dbl == 0) {
|
---|
| 795 | ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 796 | return 0;
|
---|
| 797 | }
|
---|
| 798 | if ((group->meth != r->meth) || (r->meth != a->meth)) {
|
---|
| 799 | ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 800 | return 0;
|
---|
| 801 | }
|
---|
| 802 | return group->meth->dbl(group, r, a, ctx);
|
---|
| 803 | }
|
---|
| 804 |
|
---|
| 805 | int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
|
---|
| 806 | {
|
---|
| 807 | if (group->meth->invert == 0) {
|
---|
| 808 | ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 809 | return 0;
|
---|
| 810 | }
|
---|
| 811 | if (group->meth != a->meth) {
|
---|
| 812 | ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 813 | return 0;
|
---|
| 814 | }
|
---|
| 815 | return group->meth->invert(group, a, ctx);
|
---|
| 816 | }
|
---|
| 817 |
|
---|
| 818 | int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
|
---|
| 819 | {
|
---|
| 820 | if (group->meth->is_at_infinity == 0) {
|
---|
| 821 | ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
|
---|
| 822 | ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 823 | return 0;
|
---|
| 824 | }
|
---|
| 825 | if (group->meth != point->meth) {
|
---|
| 826 | ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 827 | return 0;
|
---|
| 828 | }
|
---|
| 829 | return group->meth->is_at_infinity(group, point);
|
---|
| 830 | }
|
---|
| 831 |
|
---|
| 832 | /*
|
---|
| 833 | * Check whether an EC_POINT is on the curve or not. Note that the return
|
---|
| 834 | * value for this function should NOT be treated as a boolean. Return values:
|
---|
| 835 | * 1: The point is on the curve
|
---|
| 836 | * 0: The point is not on the curve
|
---|
| 837 | * -1: An error occurred
|
---|
| 838 | */
|
---|
| 839 | int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
|
---|
| 840 | BN_CTX *ctx)
|
---|
| 841 | {
|
---|
| 842 | if (group->meth->is_on_curve == 0) {
|
---|
| 843 | ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 844 | return 0;
|
---|
| 845 | }
|
---|
| 846 | if (group->meth != point->meth) {
|
---|
| 847 | ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 848 | return 0;
|
---|
| 849 | }
|
---|
| 850 | return group->meth->is_on_curve(group, point, ctx);
|
---|
| 851 | }
|
---|
| 852 |
|
---|
| 853 | int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
|
---|
| 854 | BN_CTX *ctx)
|
---|
| 855 | {
|
---|
| 856 | if (group->meth->point_cmp == 0) {
|
---|
| 857 | ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 858 | return -1;
|
---|
| 859 | }
|
---|
| 860 | if ((group->meth != a->meth) || (a->meth != b->meth)) {
|
---|
| 861 | ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 862 | return -1;
|
---|
| 863 | }
|
---|
| 864 | return group->meth->point_cmp(group, a, b, ctx);
|
---|
| 865 | }
|
---|
| 866 |
|
---|
| 867 | int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
|
---|
| 868 | {
|
---|
| 869 | if (group->meth->make_affine == 0) {
|
---|
| 870 | ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 871 | return 0;
|
---|
| 872 | }
|
---|
| 873 | if (group->meth != point->meth) {
|
---|
| 874 | ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 875 | return 0;
|
---|
| 876 | }
|
---|
| 877 | return group->meth->make_affine(group, point, ctx);
|
---|
| 878 | }
|
---|
| 879 |
|
---|
| 880 | int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
|
---|
| 881 | EC_POINT *points[], BN_CTX *ctx)
|
---|
| 882 | {
|
---|
| 883 | size_t i;
|
---|
| 884 |
|
---|
| 885 | if (group->meth->points_make_affine == 0) {
|
---|
| 886 | ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
---|
| 887 | return 0;
|
---|
| 888 | }
|
---|
| 889 | for (i = 0; i < num; i++) {
|
---|
| 890 | if (group->meth != points[i]->meth) {
|
---|
| 891 | ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
|
---|
| 892 | return 0;
|
---|
| 893 | }
|
---|
| 894 | }
|
---|
| 895 | return group->meth->points_make_affine(group, num, points, ctx);
|
---|
| 896 | }
|
---|
| 897 |
|
---|
| 898 | /*
|
---|
| 899 | * Functions for point multiplication. If group->meth->mul is 0, we use the
|
---|
| 900 | * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
|
---|
| 901 | * methods.
|
---|
| 902 | */
|
---|
| 903 |
|
---|
| 904 | int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
---|
| 905 | size_t num, const EC_POINT *points[],
|
---|
| 906 | const BIGNUM *scalars[], BN_CTX *ctx)
|
---|
| 907 | {
|
---|
| 908 | if (group->meth->mul == 0)
|
---|
| 909 | /* use default */
|
---|
| 910 | return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
---|
| 911 |
|
---|
| 912 | return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
---|
| 913 | }
|
---|
| 914 |
|
---|
| 915 | int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
|
---|
| 916 | const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
|
---|
| 917 | {
|
---|
| 918 | /* just a convenient interface to EC_POINTs_mul() */
|
---|
| 919 |
|
---|
| 920 | const EC_POINT *points[1];
|
---|
| 921 | const BIGNUM *scalars[1];
|
---|
| 922 |
|
---|
| 923 | points[0] = point;
|
---|
| 924 | scalars[0] = p_scalar;
|
---|
| 925 |
|
---|
| 926 | return EC_POINTs_mul(group, r, g_scalar,
|
---|
| 927 | (point != NULL
|
---|
| 928 | && p_scalar != NULL), points, scalars, ctx);
|
---|
| 929 | }
|
---|
| 930 |
|
---|
| 931 | int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
|
---|
| 932 | {
|
---|
| 933 | if (group->meth->mul == 0)
|
---|
| 934 | /* use default */
|
---|
| 935 | return ec_wNAF_precompute_mult(group, ctx);
|
---|
| 936 |
|
---|
| 937 | if (group->meth->precompute_mult != 0)
|
---|
| 938 | return group->meth->precompute_mult(group, ctx);
|
---|
| 939 | else
|
---|
| 940 | return 1; /* nothing to do, so report success */
|
---|
| 941 | }
|
---|
| 942 |
|
---|
| 943 | int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
|
---|
| 944 | {
|
---|
| 945 | if (group->meth->mul == 0)
|
---|
| 946 | /* use default */
|
---|
| 947 | return ec_wNAF_have_precompute_mult(group);
|
---|
| 948 |
|
---|
| 949 | if (group->meth->have_precompute_mult != 0)
|
---|
| 950 | return group->meth->have_precompute_mult(group);
|
---|
| 951 | else
|
---|
| 952 | return 0; /* cannot tell whether precomputation has
|
---|
| 953 | * been performed */
|
---|
| 954 | }
|
---|
| 955 |
|
---|
| 956 | /*
|
---|
| 957 | * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
|
---|
| 958 | * returns one on success. On error it returns zero.
|
---|
| 959 | */
|
---|
| 960 | int ec_precompute_mont_data(EC_GROUP *group)
|
---|
| 961 | {
|
---|
| 962 | BN_CTX *ctx = BN_CTX_new();
|
---|
| 963 | int ret = 0;
|
---|
| 964 |
|
---|
| 965 | BN_MONT_CTX_free(group->mont_data);
|
---|
| 966 | group->mont_data = NULL;
|
---|
| 967 |
|
---|
| 968 | if (ctx == NULL)
|
---|
| 969 | goto err;
|
---|
| 970 |
|
---|
| 971 | group->mont_data = BN_MONT_CTX_new();
|
---|
| 972 | if (group->mont_data == NULL)
|
---|
| 973 | goto err;
|
---|
| 974 |
|
---|
| 975 | if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
|
---|
| 976 | BN_MONT_CTX_free(group->mont_data);
|
---|
| 977 | group->mont_data = NULL;
|
---|
| 978 | goto err;
|
---|
| 979 | }
|
---|
| 980 |
|
---|
| 981 | ret = 1;
|
---|
| 982 |
|
---|
| 983 | err:
|
---|
| 984 |
|
---|
| 985 | BN_CTX_free(ctx);
|
---|
| 986 | return ret;
|
---|
| 987 | }
|
---|
| 988 |
|
---|
| 989 | int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
|
---|
| 990 | {
|
---|
| 991 | return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
|
---|
| 992 | }
|
---|
| 993 |
|
---|
| 994 | void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
|
---|
| 995 | {
|
---|
| 996 | return CRYPTO_get_ex_data(&key->ex_data, idx);
|
---|
| 997 | }
|
---|
| 998 |
|
---|
| 999 | int ec_group_simple_order_bits(const EC_GROUP *group)
|
---|
| 1000 | {
|
---|
| 1001 | if (group->order == NULL)
|
---|
| 1002 | return 0;
|
---|
| 1003 | return BN_num_bits(group->order);
|
---|
| 1004 | }
|
---|