ec_key.c revision 296465
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 68EC_KEY *EC_KEY_new(void) 69{ 70 EC_KEY *ret; 71 72 ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); 73 if (ret == NULL) { 74 ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); 75 return (NULL); 76 } 77 78 ret->version = 1; 79 ret->group = NULL; 80 ret->pub_key = NULL; 81 ret->priv_key = NULL; 82 ret->enc_flag = 0; 83 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 84 ret->references = 1; 85 ret->method_data = NULL; 86 return (ret); 87} 88 89EC_KEY *EC_KEY_new_by_curve_name(int nid) 90{ 91 EC_KEY *ret = EC_KEY_new(); 92 if (ret == NULL) 93 return NULL; 94 ret->group = EC_GROUP_new_by_curve_name(nid); 95 if (ret->group == NULL) { 96 EC_KEY_free(ret); 97 return NULL; 98 } 99 return ret; 100} 101 102void EC_KEY_free(EC_KEY *r) 103{ 104 int i; 105 106 if (r == NULL) 107 return; 108 109 i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC); 110#ifdef REF_PRINT 111 REF_PRINT("EC_KEY", r); 112#endif 113 if (i > 0) 114 return; 115#ifdef REF_CHECK 116 if (i < 0) { 117 fprintf(stderr, "EC_KEY_free, bad reference count\n"); 118 abort(); 119 } 120#endif 121 122 if (r->group != NULL) 123 EC_GROUP_free(r->group); 124 if (r->pub_key != NULL) 125 EC_POINT_free(r->pub_key); 126 if (r->priv_key != NULL) 127 BN_clear_free(r->priv_key); 128 129 EC_EX_DATA_free_all_data(&r->method_data); 130 131 OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); 132 133 OPENSSL_free(r); 134} 135 136EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) 137{ 138 EC_EXTRA_DATA *d; 139 140 if (dest == NULL || src == NULL) { 141 ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); 142 return NULL; 143 } 144 /* copy the parameters */ 145 if (src->group) { 146 const EC_METHOD *meth = EC_GROUP_method_of(src->group); 147 /* clear the old group */ 148 if (dest->group) 149 EC_GROUP_free(dest->group); 150 dest->group = EC_GROUP_new(meth); 151 if (dest->group == NULL) 152 return NULL; 153 if (!EC_GROUP_copy(dest->group, src->group)) 154 return NULL; 155 } 156 /* copy the public key */ 157 if (src->pub_key && src->group) { 158 if (dest->pub_key) 159 EC_POINT_free(dest->pub_key); 160 dest->pub_key = EC_POINT_new(src->group); 161 if (dest->pub_key == NULL) 162 return NULL; 163 if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 164 return NULL; 165 } 166 /* copy the private key */ 167 if (src->priv_key) { 168 if (dest->priv_key == NULL) { 169 dest->priv_key = BN_new(); 170 if (dest->priv_key == NULL) 171 return NULL; 172 } 173 if (!BN_copy(dest->priv_key, src->priv_key)) 174 return NULL; 175 } 176 /* copy method/extra data */ 177 EC_EX_DATA_free_all_data(&dest->method_data); 178 179 for (d = src->method_data; d != NULL; d = d->next) { 180 void *t = d->dup_func(d->data); 181 182 if (t == NULL) 183 return 0; 184 if (!EC_EX_DATA_set_data 185 (&dest->method_data, t, d->dup_func, d->free_func, 186 d->clear_free_func)) 187 return 0; 188 } 189 190 /* copy the rest */ 191 dest->enc_flag = src->enc_flag; 192 dest->conv_form = src->conv_form; 193 dest->version = src->version; 194 195 return dest; 196} 197 198EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) 199{ 200 EC_KEY *ret = EC_KEY_new(); 201 if (ret == NULL) 202 return NULL; 203 if (EC_KEY_copy(ret, ec_key) == NULL) { 204 EC_KEY_free(ret); 205 return NULL; 206 } 207 return ret; 208} 209 210int EC_KEY_up_ref(EC_KEY *r) 211{ 212 int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); 213#ifdef REF_PRINT 214 REF_PRINT("EC_KEY", r); 215#endif 216#ifdef REF_CHECK 217 if (i < 2) { 218 fprintf(stderr, "EC_KEY_up, bad reference count\n"); 219 abort(); 220 } 221#endif 222 return ((i > 1) ? 1 : 0); 223} 224 225int EC_KEY_generate_key(EC_KEY *eckey) 226{ 227 int ok = 0; 228 BN_CTX *ctx = NULL; 229 BIGNUM *priv_key = NULL, *order = NULL; 230 EC_POINT *pub_key = NULL; 231 232 if (!eckey || !eckey->group) { 233 ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); 234 return 0; 235 } 236 237 if ((order = BN_new()) == NULL) 238 goto err; 239 if ((ctx = BN_CTX_new()) == NULL) 240 goto err; 241 242 if (eckey->priv_key == NULL) { 243 priv_key = BN_new(); 244 if (priv_key == NULL) 245 goto err; 246 } else 247 priv_key = eckey->priv_key; 248 249 if (!EC_GROUP_get_order(eckey->group, order, ctx)) 250 goto err; 251 252 do 253 if (!BN_rand_range(priv_key, order)) 254 goto err; 255 while (BN_is_zero(priv_key)) ; 256 257 if (eckey->pub_key == NULL) { 258 pub_key = EC_POINT_new(eckey->group); 259 if (pub_key == NULL) 260 goto err; 261 } else 262 pub_key = eckey->pub_key; 263 264 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) 265 goto err; 266 267 eckey->priv_key = priv_key; 268 eckey->pub_key = pub_key; 269 270 ok = 1; 271 272 err: 273 if (order) 274 BN_free(order); 275 if (pub_key != NULL && eckey->pub_key == NULL) 276 EC_POINT_free(pub_key); 277 if (priv_key != NULL && eckey->priv_key == NULL) 278 BN_free(priv_key); 279 if (ctx != NULL) 280 BN_CTX_free(ctx); 281 return (ok); 282} 283 284int EC_KEY_check_key(const EC_KEY *eckey) 285{ 286 int ok = 0; 287 BN_CTX *ctx = NULL; 288 const BIGNUM *order = NULL; 289 EC_POINT *point = NULL; 290 291 if (!eckey || !eckey->group || !eckey->pub_key) { 292 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); 293 return 0; 294 } 295 296 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 297 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); 298 goto err; 299 } 300 301 if ((ctx = BN_CTX_new()) == NULL) 302 goto err; 303 if ((point = EC_POINT_new(eckey->group)) == NULL) 304 goto err; 305 306 /* testing whether the pub_key is on the elliptic curve */ 307 if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { 308 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); 309 goto err; 310 } 311 /* testing whether pub_key * order is the point at infinity */ 312 order = &eckey->group->order; 313 if (BN_is_zero(order)) { 314 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); 315 goto err; 316 } 317 if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { 318 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 319 goto err; 320 } 321 if (!EC_POINT_is_at_infinity(eckey->group, point)) { 322 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 323 goto err; 324 } 325 /* 326 * in case the priv_key is present : check if generator * priv_key == 327 * pub_key 328 */ 329 if (eckey->priv_key) { 330 if (BN_cmp(eckey->priv_key, order) >= 0) { 331 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 332 goto err; 333 } 334 if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, 335 NULL, NULL, ctx)) { 336 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 337 goto err; 338 } 339 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 340 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); 341 goto err; 342 } 343 } 344 ok = 1; 345 err: 346 if (ctx != NULL) 347 BN_CTX_free(ctx); 348 if (point != NULL) 349 EC_POINT_free(point); 350 return (ok); 351} 352 353const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) 354{ 355 return key->group; 356} 357 358int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) 359{ 360 if (key->group != NULL) 361 EC_GROUP_free(key->group); 362 key->group = EC_GROUP_dup(group); 363 return (key->group == NULL) ? 0 : 1; 364} 365 366const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) 367{ 368 return key->priv_key; 369} 370 371int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) 372{ 373 if (key->priv_key) 374 BN_clear_free(key->priv_key); 375 key->priv_key = BN_dup(priv_key); 376 return (key->priv_key == NULL) ? 0 : 1; 377} 378 379const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) 380{ 381 return key->pub_key; 382} 383 384int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) 385{ 386 if (key->pub_key != NULL) 387 EC_POINT_free(key->pub_key); 388 key->pub_key = EC_POINT_dup(pub_key, key->group); 389 return (key->pub_key == NULL) ? 0 : 1; 390} 391 392unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) 393{ 394 return key->enc_flag; 395} 396 397void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) 398{ 399 key->enc_flag = flags; 400} 401 402point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) 403{ 404 return key->conv_form; 405} 406 407void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) 408{ 409 key->conv_form = cform; 410 if (key->group != NULL) 411 EC_GROUP_set_point_conversion_form(key->group, cform); 412} 413 414void *EC_KEY_get_key_method_data(EC_KEY *key, 415 void *(*dup_func) (void *), 416 void (*free_func) (void *), 417 void (*clear_free_func) (void *)) 418{ 419 void *ret; 420 421 CRYPTO_r_lock(CRYPTO_LOCK_EC); 422 ret = 423 EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 424 clear_free_func); 425 CRYPTO_r_unlock(CRYPTO_LOCK_EC); 426 427 return ret; 428} 429 430void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, 431 void *(*dup_func) (void *), 432 void (*free_func) (void *), 433 void (*clear_free_func) (void *)) 434{ 435 EC_EXTRA_DATA *ex_data; 436 437 CRYPTO_w_lock(CRYPTO_LOCK_EC); 438 ex_data = 439 EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 440 clear_free_func); 441 if (ex_data == NULL) 442 EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, 443 clear_free_func); 444 CRYPTO_w_unlock(CRYPTO_LOCK_EC); 445 446 return ex_data; 447} 448 449void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) 450{ 451 if (key->group != NULL) 452 EC_GROUP_set_asn1_flag(key->group, flag); 453} 454 455int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) 456{ 457 if (key->group == NULL) 458 return 0; 459 return EC_GROUP_precompute_mult(key->group, ctx); 460} 461