1160814Ssimon/* crypto/ec/ec_key.c */ 2160814Ssimon/* 3160814Ssimon * Written by Nils Larsch for the OpenSSL project. 4160814Ssimon */ 5160814Ssimon/* ==================================================================== 6160814Ssimon * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 7160814Ssimon * 8160814Ssimon * Redistribution and use in source and binary forms, with or without 9160814Ssimon * modification, are permitted provided that the following conditions 10160814Ssimon * are met: 11160814Ssimon * 12160814Ssimon * 1. Redistributions of source code must retain the above copyright 13296465Sdelphij * notice, this list of conditions and the following disclaimer. 14160814Ssimon * 15160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 16160814Ssimon * notice, this list of conditions and the following disclaimer in 17160814Ssimon * the documentation and/or other materials provided with the 18160814Ssimon * distribution. 19160814Ssimon * 20160814Ssimon * 3. All advertising materials mentioning features or use of this 21160814Ssimon * software must display the following acknowledgment: 22160814Ssimon * "This product includes software developed by the OpenSSL Project 23160814Ssimon * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24160814Ssimon * 25160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26160814Ssimon * endorse or promote products derived from this software without 27160814Ssimon * prior written permission. For written permission, please contact 28160814Ssimon * openssl-core@openssl.org. 29160814Ssimon * 30160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 31160814Ssimon * nor may "OpenSSL" appear in their names without prior written 32160814Ssimon * permission of the OpenSSL Project. 33160814Ssimon * 34160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 35160814Ssimon * acknowledgment: 36160814Ssimon * "This product includes software developed by the OpenSSL Project 37160814Ssimon * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38160814Ssimon * 39160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 51160814Ssimon * ==================================================================== 52160814Ssimon * 53160814Ssimon * This product includes cryptographic software written by Eric Young 54160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 55160814Ssimon * Hudson (tjh@cryptsoft.com). 56160814Ssimon * 57160814Ssimon */ 58160814Ssimon/* ==================================================================== 59160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60296465Sdelphij * Portions originally developed by SUN MICROSYSTEMS, INC., and 61160814Ssimon * contributed to the OpenSSL project. 62160814Ssimon */ 63160814Ssimon 64160814Ssimon#include <string.h> 65160814Ssimon#include "ec_lcl.h" 66160814Ssimon#include <openssl/err.h> 67160814Ssimon 68160814SsimonEC_KEY *EC_KEY_new(void) 69296465Sdelphij{ 70296465Sdelphij EC_KEY *ret; 71160814Ssimon 72296465Sdelphij ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); 73296465Sdelphij if (ret == NULL) { 74296465Sdelphij ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); 75296465Sdelphij return (NULL); 76296465Sdelphij } 77160814Ssimon 78296465Sdelphij ret->version = 1; 79296465Sdelphij ret->group = NULL; 80296465Sdelphij ret->pub_key = NULL; 81296465Sdelphij ret->priv_key = NULL; 82296465Sdelphij ret->enc_flag = 0; 83296465Sdelphij ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 84296465Sdelphij ret->references = 1; 85296465Sdelphij ret->method_data = NULL; 86296465Sdelphij return (ret); 87296465Sdelphij} 88160814Ssimon 89160814SsimonEC_KEY *EC_KEY_new_by_curve_name(int nid) 90296465Sdelphij{ 91296465Sdelphij EC_KEY *ret = EC_KEY_new(); 92296465Sdelphij if (ret == NULL) 93296465Sdelphij return NULL; 94296465Sdelphij ret->group = EC_GROUP_new_by_curve_name(nid); 95296465Sdelphij if (ret->group == NULL) { 96296465Sdelphij EC_KEY_free(ret); 97296465Sdelphij return NULL; 98296465Sdelphij } 99296465Sdelphij return ret; 100296465Sdelphij} 101160814Ssimon 102160814Ssimonvoid EC_KEY_free(EC_KEY *r) 103296465Sdelphij{ 104296465Sdelphij int i; 105160814Ssimon 106296465Sdelphij if (r == NULL) 107296465Sdelphij return; 108160814Ssimon 109296465Sdelphij i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC); 110160814Ssimon#ifdef REF_PRINT 111296465Sdelphij REF_PRINT("EC_KEY", r); 112160814Ssimon#endif 113296465Sdelphij if (i > 0) 114296465Sdelphij return; 115160814Ssimon#ifdef REF_CHECK 116296465Sdelphij if (i < 0) { 117296465Sdelphij fprintf(stderr, "EC_KEY_free, bad reference count\n"); 118296465Sdelphij abort(); 119296465Sdelphij } 120160814Ssimon#endif 121160814Ssimon 122296465Sdelphij if (r->group != NULL) 123296465Sdelphij EC_GROUP_free(r->group); 124296465Sdelphij if (r->pub_key != NULL) 125296465Sdelphij EC_POINT_free(r->pub_key); 126296465Sdelphij if (r->priv_key != NULL) 127296465Sdelphij BN_clear_free(r->priv_key); 128160814Ssimon 129296465Sdelphij EC_EX_DATA_free_all_data(&r->method_data); 130160814Ssimon 131296465Sdelphij OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); 132160814Ssimon 133296465Sdelphij OPENSSL_free(r); 134296465Sdelphij} 135160814Ssimon 136160814SsimonEC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) 137296465Sdelphij{ 138296465Sdelphij EC_EXTRA_DATA *d; 139160814Ssimon 140296465Sdelphij if (dest == NULL || src == NULL) { 141296465Sdelphij ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); 142296465Sdelphij return NULL; 143296465Sdelphij } 144296465Sdelphij /* copy the parameters */ 145296465Sdelphij if (src->group) { 146296465Sdelphij const EC_METHOD *meth = EC_GROUP_method_of(src->group); 147296465Sdelphij /* clear the old group */ 148296465Sdelphij if (dest->group) 149296465Sdelphij EC_GROUP_free(dest->group); 150296465Sdelphij dest->group = EC_GROUP_new(meth); 151296465Sdelphij if (dest->group == NULL) 152296465Sdelphij return NULL; 153296465Sdelphij if (!EC_GROUP_copy(dest->group, src->group)) 154296465Sdelphij return NULL; 155296465Sdelphij } 156296465Sdelphij /* copy the public key */ 157296465Sdelphij if (src->pub_key && src->group) { 158296465Sdelphij if (dest->pub_key) 159296465Sdelphij EC_POINT_free(dest->pub_key); 160296465Sdelphij dest->pub_key = EC_POINT_new(src->group); 161296465Sdelphij if (dest->pub_key == NULL) 162296465Sdelphij return NULL; 163296465Sdelphij if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 164296465Sdelphij return NULL; 165296465Sdelphij } 166296465Sdelphij /* copy the private key */ 167296465Sdelphij if (src->priv_key) { 168296465Sdelphij if (dest->priv_key == NULL) { 169296465Sdelphij dest->priv_key = BN_new(); 170296465Sdelphij if (dest->priv_key == NULL) 171296465Sdelphij return NULL; 172296465Sdelphij } 173296465Sdelphij if (!BN_copy(dest->priv_key, src->priv_key)) 174296465Sdelphij return NULL; 175296465Sdelphij } 176296465Sdelphij /* copy method/extra data */ 177296465Sdelphij EC_EX_DATA_free_all_data(&dest->method_data); 178160814Ssimon 179296465Sdelphij for (d = src->method_data; d != NULL; d = d->next) { 180296465Sdelphij void *t = d->dup_func(d->data); 181160814Ssimon 182296465Sdelphij if (t == NULL) 183296465Sdelphij return 0; 184296465Sdelphij if (!EC_EX_DATA_set_data 185296465Sdelphij (&dest->method_data, t, d->dup_func, d->free_func, 186296465Sdelphij d->clear_free_func)) 187296465Sdelphij return 0; 188296465Sdelphij } 189160814Ssimon 190296465Sdelphij /* copy the rest */ 191296465Sdelphij dest->enc_flag = src->enc_flag; 192296465Sdelphij dest->conv_form = src->conv_form; 193296465Sdelphij dest->version = src->version; 194160814Ssimon 195296465Sdelphij return dest; 196296465Sdelphij} 197296465Sdelphij 198160814SsimonEC_KEY *EC_KEY_dup(const EC_KEY *ec_key) 199296465Sdelphij{ 200296465Sdelphij EC_KEY *ret = EC_KEY_new(); 201296465Sdelphij if (ret == NULL) 202296465Sdelphij return NULL; 203296465Sdelphij if (EC_KEY_copy(ret, ec_key) == NULL) { 204296465Sdelphij EC_KEY_free(ret); 205296465Sdelphij return NULL; 206296465Sdelphij } 207296465Sdelphij return ret; 208296465Sdelphij} 209160814Ssimon 210160814Ssimonint EC_KEY_up_ref(EC_KEY *r) 211296465Sdelphij{ 212296465Sdelphij int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); 213160814Ssimon#ifdef REF_PRINT 214296465Sdelphij REF_PRINT("EC_KEY", r); 215160814Ssimon#endif 216160814Ssimon#ifdef REF_CHECK 217296465Sdelphij if (i < 2) { 218296465Sdelphij fprintf(stderr, "EC_KEY_up, bad reference count\n"); 219296465Sdelphij abort(); 220296465Sdelphij } 221160814Ssimon#endif 222296465Sdelphij return ((i > 1) ? 1 : 0); 223296465Sdelphij} 224160814Ssimon 225160814Ssimonint EC_KEY_generate_key(EC_KEY *eckey) 226296465Sdelphij{ 227296465Sdelphij int ok = 0; 228296465Sdelphij BN_CTX *ctx = NULL; 229296465Sdelphij BIGNUM *priv_key = NULL, *order = NULL; 230296465Sdelphij EC_POINT *pub_key = NULL; 231160814Ssimon 232296465Sdelphij if (!eckey || !eckey->group) { 233296465Sdelphij ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); 234296465Sdelphij return 0; 235296465Sdelphij } 236160814Ssimon 237296465Sdelphij if ((order = BN_new()) == NULL) 238296465Sdelphij goto err; 239296465Sdelphij if ((ctx = BN_CTX_new()) == NULL) 240296465Sdelphij goto err; 241160814Ssimon 242296465Sdelphij if (eckey->priv_key == NULL) { 243296465Sdelphij priv_key = BN_new(); 244296465Sdelphij if (priv_key == NULL) 245296465Sdelphij goto err; 246296465Sdelphij } else 247296465Sdelphij priv_key = eckey->priv_key; 248160814Ssimon 249296465Sdelphij if (!EC_GROUP_get_order(eckey->group, order, ctx)) 250296465Sdelphij goto err; 251160814Ssimon 252296465Sdelphij do 253296465Sdelphij if (!BN_rand_range(priv_key, order)) 254296465Sdelphij goto err; 255296465Sdelphij while (BN_is_zero(priv_key)) ; 256160814Ssimon 257296465Sdelphij if (eckey->pub_key == NULL) { 258296465Sdelphij pub_key = EC_POINT_new(eckey->group); 259296465Sdelphij if (pub_key == NULL) 260296465Sdelphij goto err; 261296465Sdelphij } else 262296465Sdelphij pub_key = eckey->pub_key; 263160814Ssimon 264296465Sdelphij if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) 265296465Sdelphij goto err; 266160814Ssimon 267296465Sdelphij eckey->priv_key = priv_key; 268296465Sdelphij eckey->pub_key = pub_key; 269160814Ssimon 270296465Sdelphij ok = 1; 271160814Ssimon 272296465Sdelphij err: 273296465Sdelphij if (order) 274296465Sdelphij BN_free(order); 275296465Sdelphij if (pub_key != NULL && eckey->pub_key == NULL) 276296465Sdelphij EC_POINT_free(pub_key); 277296465Sdelphij if (priv_key != NULL && eckey->priv_key == NULL) 278296465Sdelphij BN_free(priv_key); 279296465Sdelphij if (ctx != NULL) 280296465Sdelphij BN_CTX_free(ctx); 281296465Sdelphij return (ok); 282296465Sdelphij} 283160814Ssimon 284160814Ssimonint EC_KEY_check_key(const EC_KEY *eckey) 285296465Sdelphij{ 286296465Sdelphij int ok = 0; 287296465Sdelphij BN_CTX *ctx = NULL; 288296465Sdelphij const BIGNUM *order = NULL; 289296465Sdelphij EC_POINT *point = NULL; 290160814Ssimon 291296465Sdelphij if (!eckey || !eckey->group || !eckey->pub_key) { 292296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); 293296465Sdelphij return 0; 294296465Sdelphij } 295237998Sjkim 296296465Sdelphij if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 297296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); 298296465Sdelphij goto err; 299296465Sdelphij } 300237998Sjkim 301296465Sdelphij if ((ctx = BN_CTX_new()) == NULL) 302296465Sdelphij goto err; 303296465Sdelphij if ((point = EC_POINT_new(eckey->group)) == NULL) 304296465Sdelphij goto err; 305160814Ssimon 306296465Sdelphij /* testing whether the pub_key is on the elliptic curve */ 307296465Sdelphij if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { 308296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); 309296465Sdelphij goto err; 310296465Sdelphij } 311296465Sdelphij /* testing whether pub_key * order is the point at infinity */ 312296465Sdelphij order = &eckey->group->order; 313296465Sdelphij if (BN_is_zero(order)) { 314296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); 315296465Sdelphij goto err; 316296465Sdelphij } 317296465Sdelphij if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { 318296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 319296465Sdelphij goto err; 320296465Sdelphij } 321296465Sdelphij if (!EC_POINT_is_at_infinity(eckey->group, point)) { 322296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 323296465Sdelphij goto err; 324296465Sdelphij } 325296465Sdelphij /* 326296465Sdelphij * in case the priv_key is present : check if generator * priv_key == 327296465Sdelphij * pub_key 328296465Sdelphij */ 329296465Sdelphij if (eckey->priv_key) { 330296465Sdelphij if (BN_cmp(eckey->priv_key, order) >= 0) { 331296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); 332296465Sdelphij goto err; 333296465Sdelphij } 334296465Sdelphij if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, 335296465Sdelphij NULL, NULL, ctx)) { 336296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); 337296465Sdelphij goto err; 338296465Sdelphij } 339296465Sdelphij if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 340296465Sdelphij ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); 341296465Sdelphij goto err; 342296465Sdelphij } 343296465Sdelphij } 344296465Sdelphij ok = 1; 345296465Sdelphij err: 346296465Sdelphij if (ctx != NULL) 347296465Sdelphij BN_CTX_free(ctx); 348296465Sdelphij if (point != NULL) 349296465Sdelphij EC_POINT_free(point); 350296465Sdelphij return (ok); 351296465Sdelphij} 352160814Ssimon 353160814Ssimonconst EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) 354296465Sdelphij{ 355296465Sdelphij return key->group; 356296465Sdelphij} 357160814Ssimon 358160814Ssimonint EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) 359296465Sdelphij{ 360296465Sdelphij if (key->group != NULL) 361296465Sdelphij EC_GROUP_free(key->group); 362296465Sdelphij key->group = EC_GROUP_dup(group); 363296465Sdelphij return (key->group == NULL) ? 0 : 1; 364296465Sdelphij} 365160814Ssimon 366160814Ssimonconst BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) 367296465Sdelphij{ 368296465Sdelphij return key->priv_key; 369296465Sdelphij} 370160814Ssimon 371160814Ssimonint EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) 372296465Sdelphij{ 373296465Sdelphij if (key->priv_key) 374296465Sdelphij BN_clear_free(key->priv_key); 375296465Sdelphij key->priv_key = BN_dup(priv_key); 376296465Sdelphij return (key->priv_key == NULL) ? 0 : 1; 377296465Sdelphij} 378160814Ssimon 379160814Ssimonconst EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) 380296465Sdelphij{ 381296465Sdelphij return key->pub_key; 382296465Sdelphij} 383160814Ssimon 384160814Ssimonint EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) 385296465Sdelphij{ 386296465Sdelphij if (key->pub_key != NULL) 387296465Sdelphij EC_POINT_free(key->pub_key); 388296465Sdelphij key->pub_key = EC_POINT_dup(pub_key, key->group); 389296465Sdelphij return (key->pub_key == NULL) ? 0 : 1; 390296465Sdelphij} 391160814Ssimon 392160814Ssimonunsigned int EC_KEY_get_enc_flags(const EC_KEY *key) 393296465Sdelphij{ 394296465Sdelphij return key->enc_flag; 395296465Sdelphij} 396160814Ssimon 397160814Ssimonvoid EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) 398296465Sdelphij{ 399296465Sdelphij key->enc_flag = flags; 400296465Sdelphij} 401160814Ssimon 402160814Ssimonpoint_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) 403296465Sdelphij{ 404296465Sdelphij return key->conv_form; 405296465Sdelphij} 406160814Ssimon 407160814Ssimonvoid EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) 408296465Sdelphij{ 409296465Sdelphij key->conv_form = cform; 410296465Sdelphij if (key->group != NULL) 411296465Sdelphij EC_GROUP_set_point_conversion_form(key->group, cform); 412296465Sdelphij} 413160814Ssimon 414160814Ssimonvoid *EC_KEY_get_key_method_data(EC_KEY *key, 415296465Sdelphij void *(*dup_func) (void *), 416296465Sdelphij void (*free_func) (void *), 417296465Sdelphij void (*clear_free_func) (void *)) 418296465Sdelphij{ 419296465Sdelphij void *ret; 420248272Sdelphij 421296465Sdelphij CRYPTO_r_lock(CRYPTO_LOCK_EC); 422296465Sdelphij ret = 423296465Sdelphij EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 424296465Sdelphij clear_free_func); 425296465Sdelphij CRYPTO_r_unlock(CRYPTO_LOCK_EC); 426248272Sdelphij 427296465Sdelphij return ret; 428296465Sdelphij} 429160814Ssimon 430248272Sdelphijvoid *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, 431296465Sdelphij void *(*dup_func) (void *), 432296465Sdelphij void (*free_func) (void *), 433296465Sdelphij void (*clear_free_func) (void *)) 434296465Sdelphij{ 435296465Sdelphij EC_EXTRA_DATA *ex_data; 436248272Sdelphij 437296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_EC); 438296465Sdelphij ex_data = 439296465Sdelphij EC_EX_DATA_get_data(key->method_data, dup_func, free_func, 440296465Sdelphij clear_free_func); 441296465Sdelphij if (ex_data == NULL) 442296465Sdelphij EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, 443296465Sdelphij clear_free_func); 444296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_EC); 445248272Sdelphij 446296465Sdelphij return ex_data; 447296465Sdelphij} 448160814Ssimon 449160814Ssimonvoid EC_KEY_set_asn1_flag(EC_KEY *key, int flag) 450296465Sdelphij{ 451296465Sdelphij if (key->group != NULL) 452296465Sdelphij EC_GROUP_set_asn1_flag(key->group, flag); 453296465Sdelphij} 454160814Ssimon 455160814Ssimonint EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) 456296465Sdelphij{ 457296465Sdelphij if (key->group == NULL) 458296465Sdelphij return 0; 459296465Sdelphij return EC_GROUP_precompute_mult(key->group, ctx); 460296465Sdelphij} 461