1 /* $OpenBSD: ec_key.c,v 1.39 2023/11/29 21:35:57 tb Exp $ */ 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 66 #include <openssl/opensslconf.h> 67 68 #include <openssl/err.h> 69 70 #include "bn_local.h" 71 #include "ec_local.h" 72 73 EC_KEY * 74 EC_KEY_new(void) 75 { 76 return EC_KEY_new_method(NULL); 77 } 78 LCRYPTO_ALIAS(EC_KEY_new); 79 80 EC_KEY * 81 EC_KEY_new_by_curve_name(int nid) 82 { 83 EC_KEY *ret = EC_KEY_new(); 84 if (ret == NULL) 85 return NULL; 86 ret->group = EC_GROUP_new_by_curve_name(nid); 87 if (ret->group == NULL) { 88 EC_KEY_free(ret); 89 return NULL; 90 } 91 if (ret->meth->set_group != NULL && 92 ret->meth->set_group(ret, ret->group) == 0) { 93 EC_KEY_free(ret); 94 return NULL; 95 } 96 return ret; 97 } 98 LCRYPTO_ALIAS(EC_KEY_new_by_curve_name); 99 100 void 101 EC_KEY_free(EC_KEY *r) 102 { 103 int i; 104 105 if (r == NULL) 106 return; 107 108 i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC); 109 if (i > 0) 110 return; 111 112 if (r->meth != NULL && r->meth->finish != NULL) 113 r->meth->finish(r); 114 115 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); 116 117 EC_GROUP_free(r->group); 118 EC_POINT_free(r->pub_key); 119 BN_free(r->priv_key); 120 121 freezero(r, sizeof(EC_KEY)); 122 } 123 LCRYPTO_ALIAS(EC_KEY_free); 124 125 EC_KEY * 126 EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) 127 { 128 if (dest == NULL || src == NULL) { 129 ECerror(ERR_R_PASSED_NULL_PARAMETER); 130 return NULL; 131 } 132 if (src->meth != dest->meth) { 133 if (dest->meth != NULL && dest->meth->finish != NULL) 134 dest->meth->finish(dest); 135 } 136 /* copy the parameters */ 137 if (src->group) { 138 const EC_METHOD *meth = EC_GROUP_method_of(src->group); 139 /* clear the old group */ 140 EC_GROUP_free(dest->group); 141 dest->group = EC_GROUP_new(meth); 142 if (dest->group == NULL) 143 return NULL; 144 if (!EC_GROUP_copy(dest->group, src->group)) 145 return NULL; 146 } 147 /* copy the public key */ 148 if (src->pub_key && src->group) { 149 EC_POINT_free(dest->pub_key); 150 dest->pub_key = EC_POINT_new(src->group); 151 if (dest->pub_key == NULL) 152 return NULL; 153 if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 154 return NULL; 155 } 156 /* copy the private key */ 157 if (src->priv_key) { 158 if (dest->priv_key == NULL) { 159 dest->priv_key = BN_new(); 160 if (dest->priv_key == NULL) 161 return NULL; 162 } 163 if (!bn_copy(dest->priv_key, src->priv_key)) 164 return NULL; 165 } 166 167 /* copy the rest */ 168 dest->enc_flag = src->enc_flag; 169 dest->conv_form = src->conv_form; 170 dest->version = src->version; 171 dest->flags = src->flags; 172 173 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, 174 &((EC_KEY *)src)->ex_data)) /* XXX const */ 175 return NULL; 176 177 if (src->meth != dest->meth) { 178 dest->meth = src->meth; 179 } 180 181 if (src->meth != NULL && src->meth->copy != NULL && 182 src->meth->copy(dest, src) == 0) 183 return 0; 184 185 return dest; 186 } 187 LCRYPTO_ALIAS(EC_KEY_copy); 188 189 EC_KEY * 190 EC_KEY_dup(const EC_KEY *ec_key) 191 { 192 EC_KEY *ret; 193 194 if ((ret = EC_KEY_new_method(NULL)) == NULL) 195 return NULL; 196 if (EC_KEY_copy(ret, ec_key) == NULL) { 197 EC_KEY_free(ret); 198 return NULL; 199 } 200 return ret; 201 } 202 LCRYPTO_ALIAS(EC_KEY_dup); 203 204 int 205 EC_KEY_up_ref(EC_KEY *r) 206 { 207 int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); 208 return ((i > 1) ? 1 : 0); 209 } 210 LCRYPTO_ALIAS(EC_KEY_up_ref); 211 212 int 213 EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg) 214 { 215 return CRYPTO_set_ex_data(&r->ex_data, idx, arg); 216 } 217 LCRYPTO_ALIAS(EC_KEY_set_ex_data); 218 219 void * 220 EC_KEY_get_ex_data(const EC_KEY *r, int idx) 221 { 222 return CRYPTO_get_ex_data(&r->ex_data, idx); 223 } 224 LCRYPTO_ALIAS(EC_KEY_get_ex_data); 225 226 int 227 EC_KEY_generate_key(EC_KEY *eckey) 228 { 229 if (eckey->meth->keygen != NULL) 230 return eckey->meth->keygen(eckey); 231 ECerror(EC_R_NOT_IMPLEMENTED); 232 return 0; 233 } 234 LCRYPTO_ALIAS(EC_KEY_generate_key); 235 236 int 237 ec_key_gen(EC_KEY *eckey) 238 { 239 BIGNUM *priv_key = NULL; 240 EC_POINT *pub_key = NULL; 241 const BIGNUM *order; 242 int ret = 0; 243 244 if (eckey == NULL || eckey->group == NULL) { 245 ECerror(ERR_R_PASSED_NULL_PARAMETER); 246 goto err; 247 } 248 249 if ((priv_key = BN_new()) == NULL) 250 goto err; 251 if ((pub_key = EC_POINT_new(eckey->group)) == NULL) 252 goto err; 253 254 if ((order = EC_GROUP_get0_order(eckey->group)) == NULL) 255 goto err; 256 if (!bn_rand_interval(priv_key, 1, order)) 257 goto err; 258 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL)) 259 goto err; 260 261 BN_free(eckey->priv_key); 262 eckey->priv_key = priv_key; 263 priv_key = NULL; 264 265 EC_POINT_free(eckey->pub_key); 266 eckey->pub_key = pub_key; 267 pub_key = NULL; 268 269 ret = 1; 270 271 err: 272 EC_POINT_free(pub_key); 273 BN_free(priv_key); 274 275 return ret; 276 } 277 278 int 279 EC_KEY_check_key(const EC_KEY *eckey) 280 { 281 BN_CTX *ctx = NULL; 282 EC_POINT *point = NULL; 283 const BIGNUM *order; 284 int ret = 0; 285 286 if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { 287 ECerror(ERR_R_PASSED_NULL_PARAMETER); 288 goto err; 289 } 290 291 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) { 292 ECerror(EC_R_POINT_AT_INFINITY); 293 goto err; 294 } 295 296 if ((ctx = BN_CTX_new()) == NULL) 297 goto err; 298 299 if ((point = EC_POINT_new(eckey->group)) == NULL) 300 goto err; 301 302 /* Ensure public key is on the elliptic curve. */ 303 if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { 304 ECerror(EC_R_POINT_IS_NOT_ON_CURVE); 305 goto err; 306 } 307 308 /* Ensure public key multiplied by the order is the point at infinity. */ 309 if ((order = EC_GROUP_get0_order(eckey->group)) == NULL) { 310 ECerror(EC_R_INVALID_GROUP_ORDER); 311 goto err; 312 } 313 if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { 314 ECerror(ERR_R_EC_LIB); 315 goto err; 316 } 317 if (EC_POINT_is_at_infinity(eckey->group, point) <= 0) { 318 ECerror(EC_R_WRONG_ORDER); 319 goto err; 320 } 321 322 /* 323 * If the private key is present, ensure that the private key multiplied 324 * by the generator matches the public key. 325 */ 326 if (eckey->priv_key != NULL) { 327 if (BN_cmp(eckey->priv_key, order) >= 0) { 328 ECerror(EC_R_WRONG_ORDER); 329 goto err; 330 } 331 if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, 332 NULL, ctx)) { 333 ECerror(ERR_R_EC_LIB); 334 goto err; 335 } 336 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 337 ctx) != 0) { 338 ECerror(EC_R_INVALID_PRIVATE_KEY); 339 goto err; 340 } 341 } 342 343 ret = 1; 344 345 err: 346 BN_CTX_free(ctx); 347 EC_POINT_free(point); 348 349 return ret; 350 } 351 LCRYPTO_ALIAS(EC_KEY_check_key); 352 353 int 354 EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) 355 { 356 BN_CTX *ctx = NULL; 357 EC_POINT *point = NULL; 358 BIGNUM *tx, *ty; 359 int ret = 0; 360 361 if (key == NULL || key->group == NULL || x == NULL || y == NULL) { 362 ECerror(ERR_R_PASSED_NULL_PARAMETER); 363 goto err; 364 } 365 366 if ((ctx = BN_CTX_new()) == NULL) 367 goto err; 368 369 BN_CTX_start(ctx); 370 371 if ((tx = BN_CTX_get(ctx)) == NULL) 372 goto err; 373 if ((ty = BN_CTX_get(ctx)) == NULL) 374 goto err; 375 376 if ((point = EC_POINT_new(key->group)) == NULL) 377 goto err; 378 379 if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) 380 goto err; 381 if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) 382 goto err; 383 384 /* 385 * Check if retrieved coordinates match originals: if not values are 386 * out of range. 387 */ 388 if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) { 389 ECerror(EC_R_COORDINATES_OUT_OF_RANGE); 390 goto err; 391 } 392 if (!EC_KEY_set_public_key(key, point)) 393 goto err; 394 if (EC_KEY_check_key(key) == 0) 395 goto err; 396 397 ret = 1; 398 399 err: 400 BN_CTX_end(ctx); 401 BN_CTX_free(ctx); 402 EC_POINT_free(point); 403 404 return ret; 405 } 406 LCRYPTO_ALIAS(EC_KEY_set_public_key_affine_coordinates); 407 408 const EC_GROUP * 409 EC_KEY_get0_group(const EC_KEY *key) 410 { 411 return key->group; 412 } 413 LCRYPTO_ALIAS(EC_KEY_get0_group); 414 415 int 416 EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) 417 { 418 if (key->meth->set_group != NULL && 419 key->meth->set_group(key, group) == 0) 420 return 0; 421 EC_GROUP_free(key->group); 422 key->group = EC_GROUP_dup(group); 423 return (key->group == NULL) ? 0 : 1; 424 } 425 LCRYPTO_ALIAS(EC_KEY_set_group); 426 427 const BIGNUM * 428 EC_KEY_get0_private_key(const EC_KEY *key) 429 { 430 return key->priv_key; 431 } 432 LCRYPTO_ALIAS(EC_KEY_get0_private_key); 433 434 int 435 EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) 436 { 437 if (key->meth->set_private != NULL && 438 key->meth->set_private(key, priv_key) == 0) 439 return 0; 440 441 BN_free(key->priv_key); 442 if ((key->priv_key = BN_dup(priv_key)) == NULL) 443 return 0; 444 445 return 1; 446 } 447 LCRYPTO_ALIAS(EC_KEY_set_private_key); 448 449 const EC_POINT * 450 EC_KEY_get0_public_key(const EC_KEY *key) 451 { 452 return key->pub_key; 453 } 454 LCRYPTO_ALIAS(EC_KEY_get0_public_key); 455 456 int 457 EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) 458 { 459 if (key->meth->set_public != NULL && 460 key->meth->set_public(key, pub_key) == 0) 461 return 0; 462 463 EC_POINT_free(key->pub_key); 464 if ((key->pub_key = EC_POINT_dup(pub_key, key->group)) == NULL) 465 return 0; 466 467 return 1; 468 } 469 LCRYPTO_ALIAS(EC_KEY_set_public_key); 470 471 unsigned int 472 EC_KEY_get_enc_flags(const EC_KEY *key) 473 { 474 return key->enc_flag; 475 } 476 LCRYPTO_ALIAS(EC_KEY_get_enc_flags); 477 478 void 479 EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) 480 { 481 key->enc_flag = flags; 482 } 483 LCRYPTO_ALIAS(EC_KEY_set_enc_flags); 484 485 point_conversion_form_t 486 EC_KEY_get_conv_form(const EC_KEY *key) 487 { 488 return key->conv_form; 489 } 490 LCRYPTO_ALIAS(EC_KEY_get_conv_form); 491 492 void 493 EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) 494 { 495 key->conv_form = cform; 496 if (key->group != NULL) 497 EC_GROUP_set_point_conversion_form(key->group, cform); 498 } 499 LCRYPTO_ALIAS(EC_KEY_set_conv_form); 500 501 void 502 EC_KEY_set_asn1_flag(EC_KEY *key, int flag) 503 { 504 if (key->group != NULL) 505 EC_GROUP_set_asn1_flag(key->group, flag); 506 } 507 LCRYPTO_ALIAS(EC_KEY_set_asn1_flag); 508 509 int 510 EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) 511 { 512 if (key->group == NULL) 513 return 0; 514 return EC_GROUP_precompute_mult(key->group, ctx); 515 } 516 LCRYPTO_ALIAS(EC_KEY_precompute_mult); 517 518 int 519 EC_KEY_get_flags(const EC_KEY *key) 520 { 521 return key->flags; 522 } 523 LCRYPTO_ALIAS(EC_KEY_get_flags); 524 525 void 526 EC_KEY_set_flags(EC_KEY *key, int flags) 527 { 528 key->flags |= flags; 529 } 530 LCRYPTO_ALIAS(EC_KEY_set_flags); 531 532 void 533 EC_KEY_clear_flags(EC_KEY *key, int flags) 534 { 535 key->flags &= ~flags; 536 } 537 LCRYPTO_ALIAS(EC_KEY_clear_flags); 538