1/* crypto/ec/ec_key.c */ 2/* 3 * Written by Nils Larsch for the OpenSSL project. 4 */ 5/* ==================================================================== 6 * Copyright (c) 1998-2005 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 * Portions originally developed by SUN MICROSYSTEMS, INC., and 61 * contributed to the OpenSSL project. 62 */ 63 64#include <string.h> 65#include "ec_lcl.h" 66#include <openssl/err.h> 67#ifdef OPENSSL_FIPS 68# include <openssl/fips.h> 69#endif 70 71EC_KEY *EC_KEY_new(void) 72{ 73 EC_KEY *ret; 74 75 ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); 76 if (ret == NULL) { 77 ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); 78 return (NULL); 79 } 80 81 ret->version = 1; 82 ret->flags = 0; 83 ret->group = NULL; 84 ret->pub_key = NULL; 85 ret->priv_key = NULL; 86 ret->enc_flag = 0; 87 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 88 ret->references = 1; 89 ret->method_data = NULL; 90 return (ret); 91} 92 93EC_KEY *EC_KEY_new_by_curve_name(int nid) 94{ 95 EC_KEY *ret = EC_KEY_new(); 96 if (ret == NULL) 97 return NULL; 98 ret->group = EC_GROUP_new_by_curve_name(nid); 99 if (ret->group == NULL) { 100 EC_KEY_free(ret); 101 return NULL; 102 } 103 return ret; 104} 105 106void EC_KEY_free(EC_KEY *r) 107{ 108 int i; 109 110 if (r == NULL) 111 return; 112 113 i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC); 114#ifdef REF_PRINT 115 REF_PRINT("EC_KEY", r); 116#endif 117 if (i > 0) 118 return; 119#ifdef REF_CHECK 120 if (i < 0) { 121 fprintf(stderr, "EC_KEY_free, bad reference count\n"); 122 abort(); 123 } 124#endif 125 126 if (r->group != NULL) 127 EC_GROUP_free(r->group); 128 if (r->pub_key != NULL) 129 EC_POINT_free(r->pub_key); 130 if (r->priv_key != NULL) 131 BN_clear_free(r->priv_key); 132 133 EC_EX_DATA_free_all_data(&r->method_data); 134 135 OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); 136 137 OPENSSL_free(r); 138} 139 140EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) 141{ 142 EC_EXTRA_DATA *d; 143 144 if (dest == NULL || src == NULL) { 145 ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); 146 return NULL; 147 } 148 /* copy the parameters */ 149 if (src->group) { 150 const EC_METHOD *meth = EC_GROUP_method_of(src->group); 151 /* clear the old group */ 152 if (dest->group) 153 EC_GROUP_free(dest->group); 154 dest->group = EC_GROUP_new(meth); 155 if (dest->group == NULL) 156 return NULL; 157 if (!EC_GROUP_copy(dest->group, src->group)) 158 return NULL; 159 } 160 /* copy the public key */ 161 if (src->pub_key && src->group) { 162 if (dest->pub_key) 163 EC_POINT_free(dest->pub_key); 164 dest->pub_key = EC_POINT_new(src->group); 165 if (dest->pub_key == NULL) 166 return NULL; 167 if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 168 return NULL; 169 } 170 /* copy the private key */ 171 if (src->priv_key) { 172 if (dest->priv_key == NULL) { 173 dest->priv_key = BN_new(); 174 if (dest->priv_key == NULL) 175 return NULL; 176 } 177 if (!BN_copy(dest->priv_key, src->priv_key)) 178 return NULL; 179 } 180 /* copy method/extra data */ 181 EC_EX_DATA_free_all_data(&dest->method_data); 182 183 for (d = src->method_data; d != NULL; d = d->next) { 184 void *t = d->dup_func(d->data); 185 186 if (t == NULL) 187 return 0; 188 if (!EC_EX_DATA_set_data 189 (&dest->method_data, t, d->dup_func, d->free_func, 190 d->clear_free_func)) 191 return 0; 192 } 193 194 /* copy the rest */ 195 dest->enc_flag = src->enc_flag; 196 dest->conv_form = src->conv_form; 197 dest->version = src->version; 198 dest->flags = src->flags; 199 200 return dest; 201} 202 203EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) 204{ 205 EC_KEY *ret = EC_KEY_new(); 206 if (ret == NULL) 207 return NULL; 208 if (EC_KEY_copy(ret, ec_key) == NULL) { 209 EC_KEY_free(ret); 210 return NULL; 211 } 212 return ret; 213} 214 215int EC_KEY_up_ref(EC_KEY *r) 216{ 217 int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); 218#ifdef REF_PRINT 219 REF_PRINT("EC_KEY", r); 220#endif 221#ifdef REF_CHECK 222 if (i < 2) { 223 fprintf(stderr, "EC_KEY_up, bad reference count\n"); 224 abort(); 225 } 226#endif 227 return ((i > 1) ? 1 : 0); 228} 229 230int EC_KEY_generate_key(EC_KEY *eckey) 231{ 232 int ok = 0; 233 BN_CTX *ctx = NULL; 234 BIGNUM *priv_key = NULL, *order = NULL; 235 EC_POINT *pub_key = NULL; 236 237#ifdef OPENSSL_FIPS 238 if (FIPS_mode()) 239 return FIPS_ec_key_generate_key(eckey); 240#endif 241 242 if (!eckey || !eckey->group) { 243 ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); 244 return 0; 245 } 246 247 if ((order = BN_new()) == NULL) 248 goto err; 249 if ((ctx = BN_CTX_new()) == NULL) 250 goto err; 251 252 if (eckey->priv_key == NULL) { 253 priv_key = BN_new(); 254 if (priv_key == NULL) 255 goto err; 256 } else 257 priv_key = eckey->priv_key; 258 259 if (!EC_GROUP_get_order(eckey->group, order, ctx)) 260 goto err; 261 262 do 263 if (!BN_rand_range(priv_key, order)) 264 goto err; 265 while (BN_is_zero(priv_key)) ; 266 267 if (eckey->pub_key == NULL) { 268 pub_key = EC_POINT_new(eckey->group); 269 if (pub_key == NULL) 270 goto err; 271 } else 272 pub_key = eckey->pub_key; 273 274 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) 275 goto err; 276 277 eckey->priv_key = priv_key; 278 eckey->pub_key = pub_key; 279 280 ok = 1; 281 282 err: 283 if (order) 284 BN_free(order); 285 if (pub_key != NULL && eckey->pub_key == NULL) 286 EC_POINT_free(pub_key); 287 if (priv_key != NULL && eckey->priv_key == NULL) 288 BN_free(priv_key); 289 if (ctx != NULL) 290 BN_CTX_free(ctx); 291 return (ok); 292} 293 294int EC_KEY_check_key(const EC_KEY *eckey) 295{ 296 int ok = 0; 297 BN_CTX *ctx = NULL; 298 const BIGNUM *order = NULL; 299 EC_POINT *point = NULL; 300 301 if (!eckey || !eckey->group || !eckey->pub_key) { 302 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); 303 return 0; 304 } 305 306 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 307 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); 308 goto err; 309 } 310 311 if ((ctx = BN_CTX_new()) == NULL) 312 goto err; 313 if ((point = EC_POINT_new(eckey->group)) == NULL) 314 goto err; 315 316 /* testing whether the pub_key is on the elliptic curve */ 317 if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { 318 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); 319 goto err; 320 } 321 /* testing whether pub_key * order is the point at infinity */ 322 order = &eckey->group->order; 323 if (BN_is_zero(order)) { 324 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); 325 goto err; 326 } 327 if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { 328 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 329 goto err; 330 } 331 if (!EC_POINT_is_at_infinity(eckey->group, point)) { 332 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 333 goto err; 334 } 335 /* 336 * in case the priv_key is present : check if generator * priv_key == 337 * pub_key 338 */ 339 if (eckey->priv_key) { 340 if (BN_cmp(eckey->priv_key, order) >= 0) { 341 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 342 goto err; 343 } 344 if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, 345 NULL, NULL, ctx)) { 346 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 347 goto err; 348 } 349 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 350 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); 351 goto err; 352 } 353 } 354 ok = 1; 355 err: 356 if (ctx != NULL) 357 BN_CTX_free(ctx); 358 if (point != NULL) 359 EC_POINT_free(point); 360 return (ok); 361} 362 363int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, 364 BIGNUM *y) 365{ 366 BN_CTX *ctx = NULL; 367 BIGNUM *tx, *ty; 368 EC_POINT *point = NULL; 369 int ok = 0, tmp_nid, is_char_two = 0; 370 371 if (!key || !key->group || !x || !y) { 372 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 373 ERR_R_PASSED_NULL_PARAMETER); 374 return 0; 375 } 376 ctx = BN_CTX_new(); 377 if (!ctx) 378 goto err; 379 380 point = EC_POINT_new(key->group); 381 382 if (!point) 383 goto err; 384 385 tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); 386 387 if (tmp_nid == NID_X9_62_characteristic_two_field) 388 is_char_two = 1; 389 390 tx = BN_CTX_get(ctx); 391 ty = BN_CTX_get(ctx); 392#ifndef OPENSSL_NO_EC2M 393 if (is_char_two) { 394 if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, 395 x, y, ctx)) 396 goto err; 397 if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, 398 tx, ty, ctx)) 399 goto err; 400 } else 401#endif 402 { 403 if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, 404 x, y, ctx)) 405 goto err; 406 if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, 407 tx, ty, ctx)) 408 goto err; 409 } 410 /* 411 * Check if retrieved coordinates match originals: if not values are out 412 * of range. 413 */ 414 if (BN_cmp(x, tx) || BN_cmp(y, ty)) { 415 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, 416 EC_R_COORDINATES_OUT_OF_RANGE); 417 goto err; 418 } 419 420 if (!EC_KEY_set_public_key(key, point)) 421 goto err; 422 423 if (EC_KEY_check_key(key) == 0) 424 goto err; 425 426 ok = 1; 427 428 err: 429 if (ctx) 430 BN_CTX_free(ctx); 431 if (point) 432 EC_POINT_free(point); 433 return ok; 434 435} 436 437const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) 438{ 439 return key->group; 440} 441 442int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) 443{ 444 if (key->group != NULL) 445 EC_GROUP_free(key->group); 446 key->group = EC_GROUP_dup(group); 447 return (key->group == NULL) ? 0 : 1; 448} 449 450const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) 451{ 452 return key->priv_key; 453} 454 455int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) 456{ 457 if (key->priv_key) 458 BN_clear_free(key->priv_key); 459 key->priv_key = BN_dup(priv_key); 460 return (key->priv_key == NULL) ? 0 : 1; 461} 462 463const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) 464{ 465 return key->pub_key; 466} 467 468int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) 469{ 470 if (key->pub_key != NULL) 471 EC_POINT_free(key->pub_key); 472 key->pub_key = EC_POINT_dup(pub_key, key->group); 473 return (key->pub_key == NULL) ? 0 : 1; 474} 475 476unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) 477{ 478 return key->enc_flag; 479} 480 481void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) 482{ 483 key->enc_flag = flags; 484} 485 486point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) 487{ 488 return key->conv_form; 489} 490 491void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) 492{ 493 key->conv_form = cform; 494 if (key->group != NULL) 495 EC_GROUP_set_point_conversion_form(key->group, cform); 496} 497 498void *EC_KEY_get_key_method_data(EC_KEY *key, 499 void *(*dup_func) (void *), 500 void (*free_func) (void *), 501 void (*clear_free_func) (void *)) 502{ 503 void *ret; 504 505 CRYPTO_r_lock(CRYPTO_LOCK_EC); 506 ret = 507 EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 508 clear_free_func); 509 CRYPTO_r_unlock(CRYPTO_LOCK_EC); 510 511 return ret; 512} 513 514void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, 515 void *(*dup_func) (void *), 516 void (*free_func) (void *), 517 void (*clear_free_func) (void *)) 518{ 519 EC_EXTRA_DATA *ex_data; 520 521 CRYPTO_w_lock(CRYPTO_LOCK_EC); 522 ex_data = 523 EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 524 clear_free_func); 525 if (ex_data == NULL) 526 EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, 527 clear_free_func); 528 CRYPTO_w_unlock(CRYPTO_LOCK_EC); 529 530 return ex_data; 531} 532 533void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) 534{ 535 if (key->group != NULL) 536 EC_GROUP_set_asn1_flag(key->group, flag); 537} 538 539int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) 540{ 541 if (key->group == NULL) 542 return 0; 543 return EC_GROUP_precompute_mult(key->group, ctx); 544} 545 546int EC_KEY_get_flags(const EC_KEY *key) 547{ 548 return key->flags; 549} 550 551void EC_KEY_set_flags(EC_KEY *key, int flags) 552{ 553 key->flags |= flags; 554} 555 556void EC_KEY_clear_flags(EC_KEY *key, int flags) 557{ 558 key->flags &= ~flags; 559} 560