1 /* $OpenBSD: ec_ameth.c,v 1.25 2018/08/24 20:22:15 tb Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 2006. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2006 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 * licensing@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 #include <stdio.h> 60 61 #include <openssl/opensslconf.h> 62 63 #include <openssl/bn.h> 64 #include <openssl/ec.h> 65 #include <openssl/err.h> 66 #include <openssl/x509.h> 67 68 69 #include "asn1_locl.h" 70 71 static int 72 eckey_param2type(int *pptype, void **ppval, EC_KEY * ec_key) 73 { 74 const EC_GROUP *group; 75 int nid; 76 if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { 77 ECerror(EC_R_MISSING_PARAMETERS); 78 return 0; 79 } 80 if (EC_GROUP_get_asn1_flag(group) && 81 (nid = EC_GROUP_get_curve_name(group))) { 82 /* we have a 'named curve' => just set the OID */ 83 *ppval = OBJ_nid2obj(nid); 84 *pptype = V_ASN1_OBJECT; 85 } else { 86 /* explicit parameters */ 87 ASN1_STRING *pstr = NULL; 88 pstr = ASN1_STRING_new(); 89 if (!pstr) 90 return 0; 91 pstr->length = i2d_ECParameters(ec_key, &pstr->data); 92 if (pstr->length <= 0) { 93 ASN1_STRING_free(pstr); 94 ECerror(ERR_R_EC_LIB); 95 return 0; 96 } 97 *ppval = pstr; 98 *pptype = V_ASN1_SEQUENCE; 99 } 100 return 1; 101 } 102 103 static int 104 eckey_pub_encode(X509_PUBKEY * pk, const EVP_PKEY * pkey) 105 { 106 EC_KEY *ec_key = pkey->pkey.ec; 107 void *pval = NULL; 108 int ptype; 109 unsigned char *penc = NULL, *p; 110 int penclen; 111 112 if (!eckey_param2type(&ptype, &pval, ec_key)) { 113 ECerror(ERR_R_EC_LIB); 114 return 0; 115 } 116 penclen = i2o_ECPublicKey(ec_key, NULL); 117 if (penclen <= 0) 118 goto err; 119 penc = malloc(penclen); 120 if (!penc) 121 goto err; 122 p = penc; 123 penclen = i2o_ECPublicKey(ec_key, &p); 124 if (penclen <= 0) 125 goto err; 126 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), 127 ptype, pval, penc, penclen)) 128 return 1; 129 err: 130 if (ptype == V_ASN1_OBJECT) 131 ASN1_OBJECT_free(pval); 132 else 133 ASN1_STRING_free(pval); 134 free(penc); 135 return 0; 136 } 137 138 static EC_KEY * 139 eckey_type2param(int ptype, const void *pval) 140 { 141 EC_KEY *eckey = NULL; 142 143 if (ptype == V_ASN1_SEQUENCE) { 144 const ASN1_STRING *pstr = pval; 145 const unsigned char *pm = NULL; 146 int pmlen; 147 148 pm = pstr->data; 149 pmlen = pstr->length; 150 if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) { 151 ECerror(EC_R_DECODE_ERROR); 152 goto ecerr; 153 } 154 } else if (ptype == V_ASN1_OBJECT) { 155 const ASN1_OBJECT *poid = pval; 156 EC_GROUP *group; 157 158 /* 159 * type == V_ASN1_OBJECT => the parameters are given by an 160 * asn1 OID 161 */ 162 if ((eckey = EC_KEY_new()) == NULL) { 163 ECerror(ERR_R_MALLOC_FAILURE); 164 goto ecerr; 165 } 166 group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); 167 if (group == NULL) 168 goto ecerr; 169 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); 170 if (EC_KEY_set_group(eckey, group) == 0) 171 goto ecerr; 172 EC_GROUP_free(group); 173 } else { 174 ECerror(EC_R_DECODE_ERROR); 175 goto ecerr; 176 } 177 178 return eckey; 179 180 ecerr: 181 if (eckey) 182 EC_KEY_free(eckey); 183 return NULL; 184 } 185 186 static int 187 eckey_pub_decode(EVP_PKEY * pkey, X509_PUBKEY * pubkey) 188 { 189 const unsigned char *p = NULL; 190 const void *pval; 191 int ptype, pklen; 192 EC_KEY *eckey = NULL; 193 X509_ALGOR *palg; 194 195 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) 196 return 0; 197 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 198 199 eckey = eckey_type2param(ptype, pval); 200 201 if (!eckey) { 202 ECerror(ERR_R_EC_LIB); 203 return 0; 204 } 205 /* We have parameters now set public key */ 206 if (!o2i_ECPublicKey(&eckey, &p, pklen)) { 207 ECerror(EC_R_DECODE_ERROR); 208 goto ecerr; 209 } 210 EVP_PKEY_assign_EC_KEY(pkey, eckey); 211 return 1; 212 213 ecerr: 214 if (eckey) 215 EC_KEY_free(eckey); 216 return 0; 217 } 218 219 static int 220 eckey_pub_cmp(const EVP_PKEY * a, const EVP_PKEY * b) 221 { 222 int r; 223 const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); 224 const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), *pb = EC_KEY_get0_public_key(b->pkey.ec); 225 226 r = EC_POINT_cmp(group, pa, pb, NULL); 227 if (r == 0) 228 return 1; 229 if (r == 1) 230 return 0; 231 return -2; 232 } 233 234 static int 235 eckey_priv_decode(EVP_PKEY * pkey, const PKCS8_PRIV_KEY_INFO * p8) 236 { 237 const unsigned char *p = NULL; 238 const void *pval; 239 int ptype, pklen; 240 EC_KEY *eckey = NULL; 241 const X509_ALGOR *palg; 242 243 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) 244 return 0; 245 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 246 247 eckey = eckey_type2param(ptype, pval); 248 249 if (!eckey) 250 goto ecliberr; 251 252 /* We have parameters now set private key */ 253 if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { 254 ECerror(EC_R_DECODE_ERROR); 255 goto ecerr; 256 } 257 /* calculate public key (if necessary) */ 258 if (EC_KEY_get0_public_key(eckey) == NULL) { 259 const BIGNUM *priv_key; 260 const EC_GROUP *group; 261 EC_POINT *pub_key; 262 /* 263 * the public key was not included in the SEC1 private key => 264 * calculate the public key 265 */ 266 group = EC_KEY_get0_group(eckey); 267 pub_key = EC_POINT_new(group); 268 if (pub_key == NULL) { 269 ECerror(ERR_R_EC_LIB); 270 goto ecliberr; 271 } 272 if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { 273 EC_POINT_free(pub_key); 274 ECerror(ERR_R_EC_LIB); 275 goto ecliberr; 276 } 277 priv_key = EC_KEY_get0_private_key(eckey); 278 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { 279 EC_POINT_free(pub_key); 280 ECerror(ERR_R_EC_LIB); 281 goto ecliberr; 282 } 283 if (EC_KEY_set_public_key(eckey, pub_key) == 0) { 284 EC_POINT_free(pub_key); 285 ECerror(ERR_R_EC_LIB); 286 goto ecliberr; 287 } 288 EC_POINT_free(pub_key); 289 } 290 EVP_PKEY_assign_EC_KEY(pkey, eckey); 291 return 1; 292 293 ecliberr: 294 ECerror(ERR_R_EC_LIB); 295 ecerr: 296 if (eckey) 297 EC_KEY_free(eckey); 298 return 0; 299 } 300 301 static int 302 eckey_priv_encode(PKCS8_PRIV_KEY_INFO * p8, const EVP_PKEY * pkey) 303 { 304 EC_KEY *ec_key; 305 unsigned char *ep, *p; 306 int eplen, ptype; 307 void *pval; 308 unsigned int tmp_flags, old_flags; 309 310 ec_key = pkey->pkey.ec; 311 312 if (!eckey_param2type(&ptype, &pval, ec_key)) { 313 ECerror(EC_R_DECODE_ERROR); 314 return 0; 315 } 316 /* set the private key */ 317 318 /* 319 * do not include the parameters in the SEC1 private key see PKCS#11 320 * 12.11 321 */ 322 old_flags = EC_KEY_get_enc_flags(ec_key); 323 tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; 324 EC_KEY_set_enc_flags(ec_key, tmp_flags); 325 eplen = i2d_ECPrivateKey(ec_key, NULL); 326 if (!eplen) { 327 EC_KEY_set_enc_flags(ec_key, old_flags); 328 ECerror(ERR_R_EC_LIB); 329 return 0; 330 } 331 ep = malloc(eplen); 332 if (!ep) { 333 EC_KEY_set_enc_flags(ec_key, old_flags); 334 ECerror(ERR_R_MALLOC_FAILURE); 335 return 0; 336 } 337 p = ep; 338 if (!i2d_ECPrivateKey(ec_key, &p)) { 339 EC_KEY_set_enc_flags(ec_key, old_flags); 340 free(ep); 341 ECerror(ERR_R_EC_LIB); 342 return 0; 343 } 344 /* restore old encoding flags */ 345 EC_KEY_set_enc_flags(ec_key, old_flags); 346 347 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, 348 ptype, pval, ep, eplen)) 349 return 0; 350 351 return 1; 352 } 353 354 static int 355 int_ec_size(const EVP_PKEY * pkey) 356 { 357 return ECDSA_size(pkey->pkey.ec); 358 } 359 360 static int 361 ec_bits(const EVP_PKEY * pkey) 362 { 363 BIGNUM *order = BN_new(); 364 const EC_GROUP *group; 365 int ret; 366 367 if (!order) { 368 ERR_clear_error(); 369 return 0; 370 } 371 group = EC_KEY_get0_group(pkey->pkey.ec); 372 if (!EC_GROUP_get_order(group, order, NULL)) { 373 BN_free(order); 374 ERR_clear_error(); 375 return 0; 376 } 377 ret = BN_num_bits(order); 378 BN_free(order); 379 return ret; 380 } 381 382 static int 383 ec_missing_parameters(const EVP_PKEY * pkey) 384 { 385 if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) 386 return 1; 387 return 0; 388 } 389 390 static int 391 ec_copy_parameters(EVP_PKEY * to, const EVP_PKEY * from) 392 { 393 return EC_KEY_set_group(to->pkey.ec, EC_KEY_get0_group(from->pkey.ec)); 394 } 395 396 static int 397 ec_cmp_parameters(const EVP_PKEY * a, const EVP_PKEY * b) 398 { 399 const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), *group_b = EC_KEY_get0_group(b->pkey.ec); 400 if (EC_GROUP_cmp(group_a, group_b, NULL)) 401 return 0; 402 else 403 return 1; 404 } 405 406 static void 407 int_ec_free(EVP_PKEY * pkey) 408 { 409 EC_KEY_free(pkey->pkey.ec); 410 } 411 412 static int 413 do_EC_KEY_print(BIO * bp, const EC_KEY * x, int off, int ktype) 414 { 415 unsigned char *buffer = NULL; 416 const char *ecstr; 417 size_t buf_len = 0, i; 418 int ret = 0, reason = ERR_R_BIO_LIB; 419 BIGNUM *pub_key = NULL, *order = NULL; 420 BN_CTX *ctx = NULL; 421 const EC_GROUP *group; 422 const EC_POINT *public_key; 423 const BIGNUM *priv_key; 424 425 if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { 426 reason = ERR_R_PASSED_NULL_PARAMETER; 427 goto err; 428 } 429 ctx = BN_CTX_new(); 430 if (ctx == NULL) { 431 reason = ERR_R_MALLOC_FAILURE; 432 goto err; 433 } 434 if (ktype > 0) { 435 public_key = EC_KEY_get0_public_key(x); 436 if (public_key != NULL) { 437 if ((pub_key = EC_POINT_point2bn(group, public_key, 438 EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) { 439 reason = ERR_R_EC_LIB; 440 goto err; 441 } 442 if (pub_key) 443 buf_len = (size_t) BN_num_bytes(pub_key); 444 } 445 } 446 if (ktype == 2) { 447 priv_key = EC_KEY_get0_private_key(x); 448 if (priv_key && (i = (size_t) BN_num_bytes(priv_key)) > buf_len) 449 buf_len = i; 450 } else 451 priv_key = NULL; 452 453 if (ktype > 0) { 454 buf_len += 10; 455 if ((buffer = malloc(buf_len)) == NULL) { 456 reason = ERR_R_MALLOC_FAILURE; 457 goto err; 458 } 459 } 460 if (ktype == 2) 461 ecstr = "Private-Key"; 462 else if (ktype == 1) 463 ecstr = "Public-Key"; 464 else 465 ecstr = "ECDSA-Parameters"; 466 467 if (!BIO_indent(bp, off, 128)) 468 goto err; 469 if ((order = BN_new()) == NULL) 470 goto err; 471 if (!EC_GROUP_get_order(group, order, NULL)) 472 goto err; 473 if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, 474 BN_num_bits(order)) <= 0) 475 goto err; 476 477 if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, 478 buffer, off)) 479 goto err; 480 if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, 481 buffer, off)) 482 goto err; 483 if (!ECPKParameters_print(bp, group, off)) 484 goto err; 485 ret = 1; 486 err: 487 if (!ret) 488 ECerror(reason); 489 BN_free(pub_key); 490 BN_free(order); 491 BN_CTX_free(ctx); 492 free(buffer); 493 return (ret); 494 } 495 496 static int 497 eckey_param_decode(EVP_PKEY * pkey, 498 const unsigned char **pder, int derlen) 499 { 500 EC_KEY *eckey; 501 if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) { 502 ECerror(ERR_R_EC_LIB); 503 return 0; 504 } 505 EVP_PKEY_assign_EC_KEY(pkey, eckey); 506 return 1; 507 } 508 509 static int 510 eckey_param_encode(const EVP_PKEY * pkey, unsigned char **pder) 511 { 512 return i2d_ECParameters(pkey->pkey.ec, pder); 513 } 514 515 static int 516 eckey_param_print(BIO * bp, const EVP_PKEY * pkey, int indent, 517 ASN1_PCTX * ctx) 518 { 519 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); 520 } 521 522 static int 523 eckey_pub_print(BIO * bp, const EVP_PKEY * pkey, int indent, 524 ASN1_PCTX * ctx) 525 { 526 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); 527 } 528 529 530 static int 531 eckey_priv_print(BIO * bp, const EVP_PKEY * pkey, int indent, 532 ASN1_PCTX * ctx) 533 { 534 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); 535 } 536 537 static int 538 old_ec_priv_decode(EVP_PKEY * pkey, 539 const unsigned char **pder, int derlen) 540 { 541 EC_KEY *ec; 542 if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) { 543 ECerror(EC_R_DECODE_ERROR); 544 return 0; 545 } 546 EVP_PKEY_assign_EC_KEY(pkey, ec); 547 return 1; 548 } 549 550 static int 551 old_ec_priv_encode(const EVP_PKEY * pkey, unsigned char **pder) 552 { 553 return i2d_ECPrivateKey(pkey->pkey.ec, pder); 554 } 555 556 static int 557 ec_pkey_ctrl(EVP_PKEY * pkey, int op, long arg1, void *arg2) 558 { 559 switch (op) { 560 case ASN1_PKEY_CTRL_PKCS7_SIGN: 561 if (arg1 == 0) { 562 int snid, hnid; 563 X509_ALGOR *alg1, *alg2; 564 PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); 565 if (alg1 == NULL || alg1->algorithm == NULL) 566 return -1; 567 hnid = OBJ_obj2nid(alg1->algorithm); 568 if (hnid == NID_undef) 569 return -1; 570 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) 571 return -1; 572 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); 573 } 574 return 1; 575 576 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 577 *(int *) arg2 = NID_sha1; 578 return 2; 579 580 default: 581 return -2; 582 583 } 584 585 } 586 587 const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { 588 .pkey_id = EVP_PKEY_EC, 589 .pkey_base_id = EVP_PKEY_EC, 590 591 .pem_str = "EC", 592 .info = "OpenSSL EC algorithm", 593 594 .pub_decode = eckey_pub_decode, 595 .pub_encode = eckey_pub_encode, 596 .pub_cmp = eckey_pub_cmp, 597 .pub_print = eckey_pub_print, 598 599 .priv_decode = eckey_priv_decode, 600 .priv_encode = eckey_priv_encode, 601 .priv_print = eckey_priv_print, 602 603 .pkey_size = int_ec_size, 604 .pkey_bits = ec_bits, 605 606 .param_decode = eckey_param_decode, 607 .param_encode = eckey_param_encode, 608 .param_missing = ec_missing_parameters, 609 .param_copy = ec_copy_parameters, 610 .param_cmp = ec_cmp_parameters, 611 .param_print = eckey_param_print, 612 613 .pkey_free = int_ec_free, 614 .pkey_ctrl = ec_pkey_ctrl, 615 .old_priv_decode = old_ec_priv_decode, 616 .old_priv_encode = old_ec_priv_encode 617 }; 618