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/ecdsa.h> 74 #include <openssl/engine.h> 75 #include <openssl/err.h> 76 #include <openssl/ex_data.h> 77 #include <openssl/mem.h> 78 #include <openssl/thread.h> 79 80 #include "internal.h" 81 #include "../delocate.h" 82 #include "../../internal.h" 83 84 85 DEFINE_STATIC_EX_DATA_CLASS(g_ec_ex_data_class); 86 87 EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); } 88 89 EC_KEY *EC_KEY_new_method(const ENGINE *engine) { 90 EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY)); 91 if (ret == NULL) { 92 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 93 return NULL; 94 } 95 96 OPENSSL_memset(ret, 0, sizeof(EC_KEY)); 97 98 if (engine) { 99 ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine); 100 } 101 if (ret->ecdsa_meth) { 102 METHOD_ref(ret->ecdsa_meth); 103 } 104 105 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; 106 ret->references = 1; 107 108 CRYPTO_new_ex_data(&ret->ex_data); 109 110 if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) { 111 CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), ret, &ret->ex_data); 112 if (ret->ecdsa_meth) { 113 METHOD_unref(ret->ecdsa_meth); 114 } 115 OPENSSL_free(ret); 116 return NULL; 117 } 118 119 return ret; 120 } 121 122 EC_KEY *EC_KEY_new_by_curve_name(int nid) { 123 EC_KEY *ret = EC_KEY_new(); 124 if (ret == NULL) { 125 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 126 return NULL; 127 } 128 ret->group = EC_GROUP_new_by_curve_name(nid); 129 if (ret->group == NULL) { 130 EC_KEY_free(ret); 131 return NULL; 132 } 133 return ret; 134 } 135 136 void EC_KEY_free(EC_KEY *r) { 137 if (r == NULL) { 138 return; 139 } 140 141 if (!CRYPTO_refcount_dec_and_test_zero(&r->references)) { 142 return; 143 } 144 145 if (r->ecdsa_meth) { 146 if (r->ecdsa_meth->finish) { 147 r->ecdsa_meth->finish(r); 148 } 149 METHOD_unref(r->ecdsa_meth); 150 } 151 152 EC_GROUP_free(r->group); 153 EC_POINT_free(r->pub_key); 154 BN_clear_free(r->priv_key); 155 BN_free(r->fixed_k); 156 157 CRYPTO_free_ex_data(g_ec_ex_data_class_bss_get(), r, &r->ex_data); 158 159 OPENSSL_free(r); 160 } 161 162 EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) { 163 if (dest == NULL || src == NULL) { 164 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 165 return NULL; 166 } 167 // Copy the parameters. 168 if (src->group) { 169 // TODO(fork): duplicating the group seems wasteful. 170 EC_GROUP_free(dest->group); 171 dest->group = EC_GROUP_dup(src->group); 172 if (dest->group == NULL) { 173 return NULL; 174 } 175 } 176 177 // Copy the public key. 178 if (src->pub_key && src->group) { 179 EC_POINT_free(dest->pub_key); 180 dest->pub_key = EC_POINT_dup(src->pub_key, src->group); 181 if (dest->pub_key == NULL) { 182 return NULL; 183 } 184 } 185 186 // copy the private key 187 if (src->priv_key) { 188 if (dest->priv_key == NULL) { 189 dest->priv_key = BN_new(); 190 if (dest->priv_key == NULL) { 191 return NULL; 192 } 193 } 194 if (!BN_copy(dest->priv_key, src->priv_key)) { 195 return NULL; 196 } 197 } 198 // copy method/extra data 199 if (src->ecdsa_meth) { 200 METHOD_unref(dest->ecdsa_meth); 201 dest->ecdsa_meth = src->ecdsa_meth; 202 METHOD_ref(dest->ecdsa_meth); 203 } 204 205 // copy the rest 206 dest->enc_flag = src->enc_flag; 207 dest->conv_form = src->conv_form; 208 209 return dest; 210 } 211 212 EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) { 213 EC_KEY *ret = EC_KEY_new(); 214 if (ret == NULL) { 215 return NULL; 216 } 217 if (EC_KEY_copy(ret, ec_key) == NULL) { 218 EC_KEY_free(ret); 219 return NULL; 220 } 221 return ret; 222 } 223 224 int EC_KEY_up_ref(EC_KEY *r) { 225 CRYPTO_refcount_inc(&r->references); 226 return 1; 227 } 228 229 int EC_KEY_is_opaque(const EC_KEY *key) { 230 return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE); 231 } 232 233 const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; } 234 235 int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) { 236 // If |key| already has a group, it is an error to switch to another one. 237 if (key->group != NULL) { 238 if (EC_GROUP_cmp(key->group, group, NULL) != 0) { 239 OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); 240 return 0; 241 } 242 return 1; 243 } 244 245 assert(key->priv_key == NULL); 246 assert(key->pub_key == NULL); 247 248 EC_GROUP_free(key->group); 249 key->group = EC_GROUP_dup(group); 250 return key->group != NULL; 251 } 252 253 const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) { 254 return key->priv_key; 255 } 256 257 int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) { 258 if (key->group == NULL) { 259 OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); 260 return 0; 261 } 262 263 // XXX: |BN_cmp| is not constant time. 264 if (BN_is_negative(priv_key) || 265 BN_cmp(priv_key, EC_GROUP_get0_order(key->group)) >= 0) { 266 OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); 267 return 0; 268 } 269 BN_clear_free(key->priv_key); 270 key->priv_key = BN_dup(priv_key); 271 return (key->priv_key == NULL) ? 0 : 1; 272 } 273 274 const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) { 275 return key->pub_key; 276 } 277 278 int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) { 279 if (key->group == NULL) { 280 OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS); 281 return 0; 282 } 283 284 if (EC_GROUP_cmp(key->group, pub_key->group, NULL) != 0) { 285 OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH); 286 return 0; 287 } 288 289 EC_POINT_free(key->pub_key); 290 key->pub_key = EC_POINT_dup(pub_key, key->group); 291 return (key->pub_key == NULL) ? 0 : 1; 292 } 293 294 unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; } 295 296 void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) { 297 key->enc_flag = flags; 298 } 299 300 point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) { 301 return key->conv_form; 302 } 303 304 void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) { 305 key->conv_form = cform; 306 } 307 308 int EC_KEY_check_key(const EC_KEY *eckey) { 309 int ok = 0; 310 BN_CTX *ctx = NULL; 311 EC_POINT *point = NULL; 312 313 if (!eckey || !eckey->group || !eckey->pub_key) { 314 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 315 return 0; 316 } 317 318 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { 319 OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); 320 goto err; 321 } 322 323 ctx = BN_CTX_new(); 324 325 if (ctx == NULL) { 326 goto err; 327 } 328 329 // testing whether the pub_key is on the elliptic curve 330 if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) { 331 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); 332 goto err; 333 } 334 // in case the priv_key is present : 335 // check if generator * priv_key == pub_key 336 if (eckey->priv_key) { 337 // XXX: |BN_cmp| is not constant time. 338 if (BN_is_negative(eckey->priv_key) || 339 BN_cmp(eckey->priv_key, EC_GROUP_get0_order(eckey->group)) >= 0) { 340 OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER); 341 goto err; 342 } 343 point = EC_POINT_new(eckey->group); 344 if (point == NULL || 345 !EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) { 346 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); 347 goto err; 348 } 349 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { 350 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_PRIVATE_KEY); 351 goto err; 352 } 353 } 354 ok = 1; 355 356 err: 357 BN_CTX_free(ctx); 358 EC_POINT_free(point); 359 return ok; 360 } 361 362 int EC_KEY_check_fips(const EC_KEY *key) { 363 if (EC_KEY_is_opaque(key)) { 364 // Opaque keys can't be checked. 365 OPENSSL_PUT_ERROR(EC, EC_R_PUBLIC_KEY_VALIDATION_FAILED); 366 return 0; 367 } 368 369 if (!EC_KEY_check_key(key)) { 370 return 0; 371 } 372 373 if (key->priv_key) { 374 uint8_t data[16] = {0}; 375 ECDSA_SIG *sig = ECDSA_do_sign(data, sizeof(data), key); 376 #if defined(BORINGSSL_FIPS_BREAK_ECDSA_PWCT) 377 data[0] = ~data[0]; 378 #endif 379 int ok = sig != NULL && 380 ECDSA_do_verify(data, sizeof(data), sig, key); 381 ECDSA_SIG_free(sig); 382 if (!ok) { 383 OPENSSL_PUT_ERROR(EC, EC_R_PUBLIC_KEY_VALIDATION_FAILED); 384 return 0; 385 } 386 } 387 388 return 1; 389 } 390 391 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, 392 BIGNUM *y) { 393 EC_POINT *point = NULL; 394 int ok = 0; 395 396 if (!key || !key->group || !x || !y) { 397 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 398 return 0; 399 } 400 401 point = EC_POINT_new(key->group); 402 if (point == NULL || 403 !EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, NULL) || 404 !EC_KEY_set_public_key(key, point) || 405 !EC_KEY_check_key(key)) { 406 goto err; 407 } 408 409 ok = 1; 410 411 err: 412 EC_POINT_free(point); 413 return ok; 414 } 415 416 int EC_KEY_generate_key(EC_KEY *eckey) { 417 int ok = 0; 418 BIGNUM *priv_key = NULL; 419 EC_POINT *pub_key = NULL; 420 421 if (!eckey || !eckey->group) { 422 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 423 return 0; 424 } 425 426 if (eckey->priv_key == NULL) { 427 priv_key = BN_new(); 428 if (priv_key == NULL) { 429 goto err; 430 } 431 } else { 432 priv_key = eckey->priv_key; 433 } 434 435 const BIGNUM *order = EC_GROUP_get0_order(eckey->group); 436 437 // Check that the size of the group order is FIPS compliant (FIPS 186-4 438 // B.4.2). 439 if (BN_num_bits(order) < 160) { 440 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); 441 goto err; 442 } 443 444 // Generate the private key by testing candidates (FIPS 186-4 B.4.2). 445 if (!BN_rand_range_ex(priv_key, 1, order)) { 446 goto err; 447 } 448 449 if (eckey->pub_key == NULL) { 450 pub_key = EC_POINT_new(eckey->group); 451 if (pub_key == NULL) { 452 goto err; 453 } 454 } else { 455 pub_key = eckey->pub_key; 456 } 457 458 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL)) { 459 goto err; 460 } 461 462 eckey->priv_key = priv_key; 463 eckey->pub_key = pub_key; 464 465 ok = 1; 466 467 err: 468 if (eckey->pub_key == NULL) { 469 EC_POINT_free(pub_key); 470 } 471 if (eckey->priv_key == NULL) { 472 BN_free(priv_key); 473 } 474 return ok; 475 } 476 477 int EC_KEY_generate_key_fips(EC_KEY *eckey) { 478 return EC_KEY_generate_key(eckey) && EC_KEY_check_fips(eckey); 479 } 480 481 int EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, 482 CRYPTO_EX_dup *dup_unused, 483 CRYPTO_EX_free *free_func) { 484 int index; 485 if (!CRYPTO_get_ex_new_index(g_ec_ex_data_class_bss_get(), &index, argl, argp, 486 free_func)) { 487 return -1; 488 } 489 return index; 490 } 491 492 int EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) { 493 return CRYPTO_set_ex_data(&d->ex_data, idx, arg); 494 } 495 496 void *EC_KEY_get_ex_data(const EC_KEY *d, int idx) { 497 return CRYPTO_get_ex_data(&d->ex_data, idx); 498 } 499 500 void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {} 501