1 /* Originally written by Bodo Moeller for the OpenSSL project. 2 * ==================================================================== 3 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core (at) openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay (at) cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh (at) cryptsoft.com). 53 * 54 */ 55 /* ==================================================================== 56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 57 * 58 * Portions of the attached software ("Contribution") are developed by 59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 60 * 61 * The Contribution is licensed pursuant to the OpenSSL open source 62 * license provided above. 63 * 64 * The elliptic curve binary polynomial software is originally written by 65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 66 * Laboratories. */ 67 68 #include <openssl/ec_key.h> 69 70 #include <string.h> 71 72 #include <openssl/ec.h> 73 #include <openssl/engine.h> 74 #include <openssl/err.h> 75 #include <openssl/ex_data.h> 76 #include <openssl/mem.h> 77 #include <openssl/thread.h> 78 79 #include "internal.h" 80 #include "../internal.h" 81 82 83 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT; 84 85 EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } 86 87 EC_KEY *EC_KEY_new_method(const ENGINE *engine) { 88 EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY)); 89 if (ret == NULL) { 90 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 91 return NULL; 92 } 93 94 OPENSSL_memset(ret, 0, sizeof(EC_KEY)); 95 96 if (engine) { 97 ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine); 98 } 99 if (ret->ecdsa_meth) { 100 METHOD_ref(ret->ecdsa_meth); 101 } 102 103 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 104 ret->references = 1; 105 106 CRYPTO_new_ex_data(&ret->ex_data); 107 108 if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) { 109 CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data); 110 if (ret->ecdsa_meth) { 111 METHOD_unref(ret->ecdsa_meth); 112 } 113 OPENSSL_free(ret); 114 return NULL; 115 } 116 117 return ret; 118 } 119 120 EC_KEY *EC_KEY_new_by_curve_name(int nid) { 121 EC_KEY *ret = EC_KEY_new(); 122 if (ret == NULL) { 123 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 124 return NULL; 125 } 126 ret->group = EC_GROUP_new_by_curve_name(nid); 127 if (ret->group == NULL) { 128 EC_KEY_free(ret); 129 return NULL; 130 } 131 return ret; 132 } 133 134 void EC_KEY_free(EC_KEY *r) { 135 if (r == NULL) { 136 return; 137 } 138 139 if (!CRYPTO_refcount_dec_and_test_zero(&r->references)) { 140 return; 141 } 142 143 if (r->ecdsa_meth) { 144 if (r->ecdsa_meth->finish) { 145 r->ecdsa_meth->finish(r); 146 } 147 METHOD_unref(r->ecdsa_meth); 148 } 149 150 EC_GROUP_free(r->group); 151 EC_POINT_free(r->pub_key); 152 BN_clear_free(r->priv_key); 153 154 CRYPTO_free_ex_data(&g_ex_data_class, r, &r->ex_data); 155 156 OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); 157 OPENSSL_free(r); 158 } 159 160 EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { 161 if (dest == NULL || src == NULL) { 162 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 163 return NULL; 164 } 165 /* Copy the parameters. */ 166 if (src->group) { 167 /* TODO(fork): duplicating the group seems wasteful. */ 168 EC_GROUP_free(dest->group); 169 dest->group = EC_GROUP_dup(src->group); 170 if (dest->group == NULL) { 171 return NULL; 172 } 173 } 174 175 /* Copy the public key. */ 176 if (src->pub_key && src->group) { 177 EC_POINT_free(dest->pub_key); 178 dest->pub_key = EC_POINT_dup(src->pub_key, src->group); 179 if (dest->pub_key == NULL) { 180 return NULL; 181 } 182 } 183 184 /* copy the private key */ 185 if (src->priv_key) { 186 if (dest->priv_key == NULL) { 187 dest->priv_key = BN_new(); 188 if (dest->priv_key == NULL) { 189 return NULL; 190 } 191 } 192 if (!BN_copy(dest->priv_key, src->priv_key)) { 193 return NULL; 194 } 195 } 196 /* copy method/extra data */ 197 if (src->ecdsa_meth) { 198 METHOD_unref(dest->ecdsa_meth); 199 dest->ecdsa_meth = src->ecdsa_meth; 200 METHOD_ref(dest->ecdsa_meth); 201 } 202 CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data); 203 if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data, 204 &src->ex_data)) { 205 return NULL; 206 } 207 208 /* copy the rest */ 209 dest->enc_flag = src->enc_flag; 210 dest->conv_form = src->conv_form; 211 212 return dest; 213 } 214 215 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) { 216 EC_KEY *ret = EC_KEY_new(); 217 if (ret == NULL) { 218 return NULL; 219 } 220 if (EC_KEY_copy(ret, ec_key) == NULL) { 221 EC_KEY_free(ret); 222 return NULL; 223 } 224 return ret; 225 } 226 227 int EC_KEY_up_ref(EC_KEY *r) { 228 CRYPTO_refcount_inc(&r->references); 229 return 1; 230 } 231 232 int EC_KEY_is_opaque(const EC_KEY *key) { 233 return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE); 234 } 235 236 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; } 237 238 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { 239 EC_GROUP_free(key->group); 240 /* TODO(fork): duplicating the group seems wasteful but see 241 * |EC_KEY_set_conv_form|. */ 242 key->group = EC_GROUP_dup(group); 243 if (key->group == NULL) { 244 return 0; 245 } 246 /* XXX: |BN_cmp| is not constant time. */ 247 if (key->priv_key != NULL && 248 BN_cmp(key->priv_key, EC_GROUP_get0_order(group)) >= 0) { 249 return 0; 250 } 251 return 1; 252 } 253 254 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { 255 return key->priv_key; 256 } 257 258 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) { 259 /* XXX: |BN_cmp| is not constant time. */ 260 if (key->group != NULL && 261 BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) { 262 OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); 263 return 0; 264 } 265 BN_clear_free(key->priv_key); 266 key->priv_key = BN_dup(priv_key); 267 return (key->priv_key == NULL) ? 0 : 1; 268 } 269 270 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { 271 return key->pub_key; 272 } 273 274 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) { 275 EC_POINT_free(key->pub_key); 276 key->pub_key = EC_POINT_dup(pub_key, key->group); 277 return (key->pub_key == NULL) ? 0 : 1; 278 } 279 280 unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; } 281 282 void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) { 283 key->enc_flag = flags; 284 } 285 286 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) { 287 return key->conv_form; 288 } 289 290 void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) { 291 key->conv_form = cform; 292 } 293 294 int EC_KEY_check_key(const EC_KEY *eckey) { 295 int ok = 0; 296 BN_CTX *ctx = NULL; 297 EC_POINT *point = NULL; 298 299 if (!eckey || !eckey->group || !eckey->pub_key) { 300 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 301 return 0; 302 } 303 304 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 305 OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); 306 goto err; 307 } 308 309 ctx = BN_CTX_new(); 310 311 if (ctx == NULL) { 312 goto err; 313 } 314 315 /* testing whether the pub_key is on the elliptic curve */ 316 if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) { 317 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); 318 goto err; 319 } 320 /* in case the priv_key is present : 321 * check if generator * priv_key == pub_key 322 */ 323 if (eckey->priv_key) { 324 /* XXX: |BN_cmp| is not constant time. */ 325 if (BN_cmp(eckey->priv_key, EC_GROUP_get0_order(eckey->group)) >= 0) { 326 OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); 327 goto err; 328 } 329 point = EC_POINT_new(eckey->group); 330 if (point == NULL || 331 !EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { 332 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); 333 goto err; 334 } 335 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 336 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); 337 goto err; 338 } 339 } 340 ok = 1; 341 342 err: 343 BN_CTX_free(ctx); 344 EC_POINT_free(point); 345 return ok; 346 } 347 348 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, 349 BIGNUM *y) { 350 BN_CTX *ctx = NULL; 351 BIGNUM *tx, *ty; 352 EC_POINT *point = NULL; 353 int ok = 0; 354 355 if (!key || !key->group || !x || !y) { 356 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 357 return 0; 358 } 359 ctx = BN_CTX_new(); 360 361 if (ctx == NULL) { 362 return 0; 363 } 364 365 BN_CTX_start(ctx); 366 point = EC_POINT_new(key->group); 367 368 if (point == NULL) { 369 goto err; 370 } 371 372 tx = BN_CTX_get(ctx); 373 ty = BN_CTX_get(ctx); 374 if (tx == NULL || 375 ty == NULL) { 376 goto err; 377 } 378 379 if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) || 380 !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) { 381 goto err; 382 } 383 384 /* Check if retrieved coordinates match originals: if not values 385 * are out of range. */ 386 if (BN_cmp(x, tx) || BN_cmp(y, ty)) { 387 OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); 388 goto err; 389 } 390 391 if (!EC_KEY_set_public_key(key, point)) { 392 goto err; 393 } 394 395 if (EC_KEY_check_key(key) == 0) { 396 goto err; 397 } 398 399 ok = 1; 400 401 err: 402 BN_CTX_end(ctx); 403 BN_CTX_free(ctx); 404 EC_POINT_free(point); 405 return ok; 406 } 407 408 int EC_KEY_generate_key(EC_KEY *eckey) { 409 int ok = 0; 410 BIGNUM *priv_key = NULL; 411 EC_POINT *pub_key = NULL; 412 413 if (!eckey || !eckey->group) { 414 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 415 return 0; 416 } 417 418 if (eckey->priv_key == NULL) { 419 priv_key = BN_new(); 420 if (priv_key == NULL) { 421 goto err; 422 } 423 } else { 424 priv_key = eckey->priv_key; 425 } 426 427 const BIGNUM *order = EC_GROUP_get0_order(eckey->group); 428 if (!BN_rand_range_ex(priv_key, 1, order)) { 429 goto err; 430 } 431 432 if (eckey->pub_key == NULL) { 433 pub_key = EC_POINT_new(eckey->group); 434 if (pub_key == NULL) { 435 goto err; 436 } 437 } else { 438 pub_key = eckey->pub_key; 439 } 440 441 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL)) { 442 goto err; 443 } 444 445 eckey->priv_key = priv_key; 446 eckey->pub_key = pub_key; 447 448 ok = 1; 449 450 err: 451 if (eckey->pub_key == NULL) { 452 EC_POINT_free(pub_key); 453 } 454 if (eckey->priv_key == NULL) { 455 BN_free(priv_key); 456 } 457 return ok; 458 } 459 460 int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, 461 CRYPTO_EX_dup *dup_func, 462 CRYPTO_EX_free *free_func) { 463 int index; 464 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func, 465 free_func)) { 466 return -1; 467 } 468 return index; 469 } 470 471 int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) { 472 return CRYPTO_set_ex_data(&d->ex_data, idx, arg); 473 } 474 475 void *EC_KEY_get_ex_data(const EC_KEY *d, int idx) { 476 return CRYPTO_get_ex_data(&d->ex_data, idx); 477 } 478 479 void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {} 480