ec_ameth.c revision 325335
1/* 2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3 * 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#include "cryptlib.h" 61#include <openssl/x509.h> 62#include <openssl/ec.h> 63#include <openssl/bn.h> 64#ifndef OPENSSL_NO_CMS 65# include <openssl/cms.h> 66#endif 67#include <openssl/asn1t.h> 68#include "asn1_locl.h" 69#include "ec_lcl.h" 70 71#ifndef OPENSSL_NO_CMS 72static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); 73static int ecdh_cms_encrypt(CMS_RecipientInfo *ri); 74#endif 75 76static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) 77{ 78 const EC_GROUP *group; 79 int nid; 80 if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { 81 ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); 82 return 0; 83 } 84 if (EC_GROUP_get_asn1_flag(group) 85 && (nid = EC_GROUP_get_curve_name(group))) 86 /* we have a 'named curve' => just set the OID */ 87 { 88 *ppval = OBJ_nid2obj(nid); 89 *pptype = V_ASN1_OBJECT; 90 } else { /* explicit parameters */ 91 92 ASN1_STRING *pstr = NULL; 93 pstr = ASN1_STRING_new(); 94 if (!pstr) 95 return 0; 96 pstr->length = i2d_ECParameters(ec_key, &pstr->data); 97 if (pstr->length <= 0) { 98 ASN1_STRING_free(pstr); 99 ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); 100 return 0; 101 } 102 *ppval = pstr; 103 *pptype = V_ASN1_SEQUENCE; 104 } 105 return 1; 106} 107 108static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) 109{ 110 EC_KEY *ec_key = pkey->pkey.ec; 111 void *pval = NULL; 112 int ptype; 113 unsigned char *penc = NULL, *p; 114 int penclen; 115 116 if (!eckey_param2type(&ptype, &pval, ec_key)) { 117 ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); 118 return 0; 119 } 120 penclen = i2o_ECPublicKey(ec_key, NULL); 121 if (penclen <= 0) 122 goto err; 123 penc = OPENSSL_malloc(penclen); 124 if (!penc) 125 goto err; 126 p = penc; 127 penclen = i2o_ECPublicKey(ec_key, &p); 128 if (penclen <= 0) 129 goto err; 130 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), 131 ptype, pval, penc, penclen)) 132 return 1; 133 err: 134 if (ptype == V_ASN1_OBJECT) 135 ASN1_OBJECT_free(pval); 136 else 137 ASN1_STRING_free(pval); 138 if (penc) 139 OPENSSL_free(penc); 140 return 0; 141} 142 143static EC_KEY *eckey_type2param(int ptype, void *pval) 144{ 145 EC_KEY *eckey = NULL; 146 if (ptype == V_ASN1_SEQUENCE) { 147 ASN1_STRING *pstr = pval; 148 const unsigned char *pm = NULL; 149 int pmlen; 150 pm = pstr->data; 151 pmlen = pstr->length; 152 if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) { 153 ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); 154 goto ecerr; 155 } 156 } else if (ptype == V_ASN1_OBJECT) { 157 ASN1_OBJECT *poid = pval; 158 EC_GROUP *group; 159 160 /* 161 * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID 162 */ 163 if ((eckey = EC_KEY_new()) == NULL) { 164 ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); 165 goto ecerr; 166 } 167 group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); 168 if (group == NULL) 169 goto ecerr; 170 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); 171 if (EC_KEY_set_group(eckey, group) == 0) 172 goto ecerr; 173 EC_GROUP_free(group); 174 } else { 175 ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); 176 goto ecerr; 177 } 178 179 return eckey; 180 181 ecerr: 182 if (eckey) 183 EC_KEY_free(eckey); 184 return NULL; 185} 186 187static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) 188{ 189 const unsigned char *p = NULL; 190 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 ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); 203 return 0; 204 } 205 206 /* We have parameters now set public key */ 207 if (!o2i_ECPublicKey(&eckey, &p, pklen)) { 208 ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); 209 goto ecerr; 210 } 211 212 EVP_PKEY_assign_EC_KEY(pkey, eckey); 213 return 1; 214 215 ecerr: 216 if (eckey) 217 EC_KEY_free(eckey); 218 return 0; 219} 220 221static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 222{ 223 int r; 224 const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); 225 const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), 226 *pb = EC_KEY_get0_public_key(b->pkey.ec); 227 if (group == NULL || pa == NULL || pb == NULL) 228 return -2; 229 r = EC_POINT_cmp(group, pa, pb, NULL); 230 if (r == 0) 231 return 1; 232 if (r == 1) 233 return 0; 234 return -2; 235} 236 237static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) 238{ 239 const unsigned char *p = NULL; 240 void *pval; 241 int ptype, pklen; 242 EC_KEY *eckey = NULL; 243 X509_ALGOR *palg; 244 245 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) 246 return 0; 247 X509_ALGOR_get0(NULL, &ptype, &pval, palg); 248 249 eckey = eckey_type2param(ptype, pval); 250 251 if (!eckey) 252 goto ecliberr; 253 254 /* We have parameters now set private key */ 255 if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { 256 ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); 257 goto ecerr; 258 } 259 260 /* calculate public key (if necessary) */ 261 if (EC_KEY_get0_public_key(eckey) == NULL) { 262 const BIGNUM *priv_key; 263 const EC_GROUP *group; 264 EC_POINT *pub_key; 265 /* 266 * the public key was not included in the SEC1 private key => 267 * calculate the public key 268 */ 269 group = EC_KEY_get0_group(eckey); 270 pub_key = EC_POINT_new(group); 271 if (pub_key == NULL) { 272 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); 273 goto ecliberr; 274 } 275 if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { 276 EC_POINT_free(pub_key); 277 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); 278 goto ecliberr; 279 } 280 priv_key = EC_KEY_get0_private_key(eckey); 281 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { 282 EC_POINT_free(pub_key); 283 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); 284 goto ecliberr; 285 } 286 if (EC_KEY_set_public_key(eckey, pub_key) == 0) { 287 EC_POINT_free(pub_key); 288 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); 289 goto ecliberr; 290 } 291 EC_POINT_free(pub_key); 292 } 293 294 EVP_PKEY_assign_EC_KEY(pkey, eckey); 295 return 1; 296 297 ecliberr: 298 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); 299 ecerr: 300 if (eckey) 301 EC_KEY_free(eckey); 302 return 0; 303} 304 305static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) 306{ 307 EC_KEY ec_key = *(pkey->pkey.ec); 308 unsigned char *ep, *p; 309 int eplen, ptype; 310 void *pval; 311 unsigned int old_flags; 312 313 if (!eckey_param2type(&ptype, &pval, &ec_key)) { 314 ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); 315 return 0; 316 } 317 318 /* set the private key */ 319 320 /* 321 * do not include the parameters in the SEC1 private key see PKCS#11 322 * 12.11 323 */ 324 old_flags = EC_KEY_get_enc_flags(&ec_key); 325 EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); 326 327 eplen = i2d_ECPrivateKey(&ec_key, NULL); 328 if (!eplen) { 329 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); 330 return 0; 331 } 332 ep = (unsigned char *)OPENSSL_malloc(eplen); 333 if (!ep) { 334 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); 335 return 0; 336 } 337 p = ep; 338 if (!i2d_ECPrivateKey(&ec_key, &p)) { 339 OPENSSL_free(ep); 340 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); 341 return 0; 342 } 343 344 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, 345 ptype, pval, ep, eplen)) { 346 OPENSSL_free(ep); 347 return 0; 348 } 349 350 return 1; 351} 352 353static int int_ec_size(const EVP_PKEY *pkey) 354{ 355 return ECDSA_size(pkey->pkey.ec); 356} 357 358static int ec_bits(const EVP_PKEY *pkey) 359{ 360 BIGNUM *order = BN_new(); 361 const EC_GROUP *group; 362 int ret; 363 364 if (!order) { 365 ERR_clear_error(); 366 return 0; 367 } 368 group = EC_KEY_get0_group(pkey->pkey.ec); 369 if (!EC_GROUP_get_order(group, order, NULL)) { 370 ERR_clear_error(); 371 return 0; 372 } 373 374 ret = BN_num_bits(order); 375 BN_free(order); 376 return ret; 377} 378 379static int ec_missing_parameters(const EVP_PKEY *pkey) 380{ 381 if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) 382 return 1; 383 return 0; 384} 385 386static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) 387{ 388 EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); 389 if (group == NULL) 390 return 0; 391 if (EC_KEY_set_group(to->pkey.ec, group) == 0) 392 return 0; 393 EC_GROUP_free(group); 394 return 1; 395} 396 397static int 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), 400 *group_b = EC_KEY_get0_group(b->pkey.ec); 401 if (group_a == NULL || group_b == NULL) 402 return -2; 403 if (EC_GROUP_cmp(group_a, group_b, NULL)) 404 return 0; 405 else 406 return 1; 407} 408 409static void int_ec_free(EVP_PKEY *pkey) 410{ 411 EC_KEY_free(pkey->pkey.ec); 412} 413 414static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) 415{ 416 unsigned char *buffer = NULL; 417 const char *ecstr; 418 size_t buf_len = 0, i; 419 int ret = 0, reason = ERR_R_BIO_LIB; 420 BIGNUM *pub_key = NULL, *order = NULL; 421 BN_CTX *ctx = NULL; 422 const EC_GROUP *group; 423 const EC_POINT *public_key; 424 const BIGNUM *priv_key; 425 426 if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { 427 reason = ERR_R_PASSED_NULL_PARAMETER; 428 goto err; 429 } 430 431 ctx = BN_CTX_new(); 432 if (ctx == NULL) { 433 reason = ERR_R_MALLOC_FAILURE; 434 goto err; 435 } 436 437 if (ktype > 0) { 438 public_key = EC_KEY_get0_public_key(x); 439 if (public_key != NULL) { 440 if ((pub_key = EC_POINT_point2bn(group, public_key, 441 EC_KEY_get_conv_form(x), NULL, 442 ctx)) == NULL) { 443 reason = ERR_R_EC_LIB; 444 goto err; 445 } 446 buf_len = (size_t)BN_num_bytes(pub_key); 447 } 448 } 449 450 if (ktype == 2) { 451 priv_key = EC_KEY_get0_private_key(x); 452 if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) 453 buf_len = i; 454 } else 455 priv_key = NULL; 456 457 if (ktype > 0) { 458 buf_len += 10; 459 if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { 460 reason = ERR_R_MALLOC_FAILURE; 461 goto err; 462 } 463 } 464 if (ktype == 2) 465 ecstr = "Private-Key"; 466 else if (ktype == 1) 467 ecstr = "Public-Key"; 468 else 469 ecstr = "ECDSA-Parameters"; 470 471 if (!BIO_indent(bp, off, 128)) 472 goto err; 473 if ((order = BN_new()) == NULL) 474 goto err; 475 if (!EC_GROUP_get_order(group, order, NULL)) 476 goto err; 477 if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) 478 goto err; 479 480 if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, 481 buffer, off)) 482 goto err; 483 if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, 484 buffer, off)) 485 goto err; 486 if (!ECPKParameters_print(bp, group, off)) 487 goto err; 488 ret = 1; 489 err: 490 if (!ret) 491 ECerr(EC_F_DO_EC_KEY_PRINT, reason); 492 if (pub_key) 493 BN_free(pub_key); 494 if (order) 495 BN_free(order); 496 if (ctx) 497 BN_CTX_free(ctx); 498 if (buffer != NULL) 499 OPENSSL_free(buffer); 500 return (ret); 501} 502 503static int eckey_param_decode(EVP_PKEY *pkey, 504 const unsigned char **pder, int derlen) 505{ 506 EC_KEY *eckey; 507 if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) { 508 ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); 509 return 0; 510 } 511 EVP_PKEY_assign_EC_KEY(pkey, eckey); 512 return 1; 513} 514 515static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 516{ 517 return i2d_ECParameters(pkey->pkey.ec, pder); 518} 519 520static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, 521 ASN1_PCTX *ctx) 522{ 523 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); 524} 525 526static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, 527 ASN1_PCTX *ctx) 528{ 529 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); 530} 531 532static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, 533 ASN1_PCTX *ctx) 534{ 535 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); 536} 537 538static int 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 ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); 544 return 0; 545 } 546 EVP_PKEY_assign_EC_KEY(pkey, ec); 547 return 1; 548} 549 550static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) 551{ 552 return i2d_ECPrivateKey(pkey->pkey.ec, pder); 553} 554 555static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) 556{ 557 switch (op) { 558 case ASN1_PKEY_CTRL_PKCS7_SIGN: 559 if (arg1 == 0) { 560 int snid, hnid; 561 X509_ALGOR *alg1, *alg2; 562 PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); 563 if (alg1 == NULL || alg1->algorithm == NULL) 564 return -1; 565 hnid = OBJ_obj2nid(alg1->algorithm); 566 if (hnid == NID_undef) 567 return -1; 568 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) 569 return -1; 570 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); 571 } 572 return 1; 573#ifndef OPENSSL_NO_CMS 574 case ASN1_PKEY_CTRL_CMS_SIGN: 575 if (arg1 == 0) { 576 int snid, hnid; 577 X509_ALGOR *alg1, *alg2; 578 CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); 579 if (alg1 == NULL || alg1->algorithm == NULL) 580 return -1; 581 hnid = OBJ_obj2nid(alg1->algorithm); 582 if (hnid == NID_undef) 583 return -1; 584 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) 585 return -1; 586 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); 587 } 588 return 1; 589 590 case ASN1_PKEY_CTRL_CMS_ENVELOPE: 591 if (arg1 == 1) 592 return ecdh_cms_decrypt(arg2); 593 else if (arg1 == 0) 594 return ecdh_cms_encrypt(arg2); 595 return -2; 596 597 case ASN1_PKEY_CTRL_CMS_RI_TYPE: 598 *(int *)arg2 = CMS_RECIPINFO_AGREE; 599 return 1; 600#endif 601 602 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 603 *(int *)arg2 = NID_sha256; 604 return 2; 605 606 default: 607 return -2; 608 609 } 610 611} 612 613const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { 614 EVP_PKEY_EC, 615 EVP_PKEY_EC, 616 0, 617 "EC", 618 "OpenSSL EC algorithm", 619 620 eckey_pub_decode, 621 eckey_pub_encode, 622 eckey_pub_cmp, 623 eckey_pub_print, 624 625 eckey_priv_decode, 626 eckey_priv_encode, 627 eckey_priv_print, 628 629 int_ec_size, 630 ec_bits, 631 632 eckey_param_decode, 633 eckey_param_encode, 634 ec_missing_parameters, 635 ec_copy_parameters, 636 ec_cmp_parameters, 637 eckey_param_print, 638 0, 639 640 int_ec_free, 641 ec_pkey_ctrl, 642 old_ec_priv_decode, 643 old_ec_priv_encode 644}; 645 646#ifndef OPENSSL_NO_CMS 647 648static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, 649 X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) 650{ 651 ASN1_OBJECT *aoid; 652 int atype; 653 void *aval; 654 int rv = 0; 655 EVP_PKEY *pkpeer = NULL; 656 EC_KEY *ecpeer = NULL; 657 const unsigned char *p; 658 int plen; 659 X509_ALGOR_get0(&aoid, &atype, &aval, alg); 660 if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey) 661 goto err; 662 /* If absent parameters get group from main key */ 663 if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) { 664 const EC_GROUP *grp; 665 EVP_PKEY *pk; 666 pk = EVP_PKEY_CTX_get0_pkey(pctx); 667 if (!pk) 668 goto err; 669 grp = EC_KEY_get0_group(pk->pkey.ec); 670 ecpeer = EC_KEY_new(); 671 if (!ecpeer) 672 goto err; 673 if (!EC_KEY_set_group(ecpeer, grp)) 674 goto err; 675 } else { 676 ecpeer = eckey_type2param(atype, aval); 677 if (!ecpeer) 678 goto err; 679 } 680 /* We have parameters now set public key */ 681 plen = ASN1_STRING_length(pubkey); 682 p = ASN1_STRING_data(pubkey); 683 if (!p || !plen) 684 goto err; 685 if (!o2i_ECPublicKey(&ecpeer, &p, plen)) 686 goto err; 687 pkpeer = EVP_PKEY_new(); 688 if (!pkpeer) 689 goto err; 690 EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer); 691 if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) 692 rv = 1; 693 err: 694 if (ecpeer) 695 EC_KEY_free(ecpeer); 696 if (pkpeer) 697 EVP_PKEY_free(pkpeer); 698 return rv; 699} 700 701/* Set KDF parameters based on KDF NID */ 702static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) 703{ 704 int kdf_nid, kdfmd_nid, cofactor; 705 const EVP_MD *kdf_md; 706 if (eckdf_nid == NID_undef) 707 return 0; 708 709 /* Lookup KDF type, cofactor mode and digest */ 710 if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid)) 711 return 0; 712 713 if (kdf_nid == NID_dh_std_kdf) 714 cofactor = 0; 715 else if (kdf_nid == NID_dh_cofactor_kdf) 716 cofactor = 1; 717 else 718 return 0; 719 720 if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) 721 return 0; 722 723 if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0) 724 return 0; 725 726 kdf_md = EVP_get_digestbynid(kdfmd_nid); 727 if (!kdf_md) 728 return 0; 729 730 if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) 731 return 0; 732 return 1; 733} 734 735static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) 736{ 737 int rv = 0; 738 739 X509_ALGOR *alg, *kekalg = NULL; 740 ASN1_OCTET_STRING *ukm; 741 const unsigned char *p; 742 unsigned char *der = NULL; 743 int plen, keylen; 744 const EVP_CIPHER *kekcipher; 745 EVP_CIPHER_CTX *kekctx; 746 747 if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm)) 748 return 0; 749 750 if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) { 751 ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR); 752 return 0; 753 } 754 755 if (alg->parameter->type != V_ASN1_SEQUENCE) 756 return 0; 757 758 p = alg->parameter->value.sequence->data; 759 plen = alg->parameter->value.sequence->length; 760 kekalg = d2i_X509_ALGOR(NULL, &p, plen); 761 if (!kekalg) 762 goto err; 763 kekctx = CMS_RecipientInfo_kari_get0_ctx(ri); 764 if (!kekctx) 765 goto err; 766 kekcipher = EVP_get_cipherbyobj(kekalg->algorithm); 767 if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE) 768 goto err; 769 if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) 770 goto err; 771 if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) 772 goto err; 773 774 keylen = EVP_CIPHER_CTX_key_length(kekctx); 775 if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) 776 goto err; 777 778 plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen); 779 780 if (!plen) 781 goto err; 782 783 if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0) 784 goto err; 785 der = NULL; 786 787 rv = 1; 788 err: 789 if (kekalg) 790 X509_ALGOR_free(kekalg); 791 if (der) 792 OPENSSL_free(der); 793 return rv; 794} 795 796static int ecdh_cms_decrypt(CMS_RecipientInfo *ri) 797{ 798 EVP_PKEY_CTX *pctx; 799 pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 800 if (!pctx) 801 return 0; 802 /* See if we need to set peer key */ 803 if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { 804 X509_ALGOR *alg; 805 ASN1_BIT_STRING *pubkey; 806 if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey, 807 NULL, NULL, NULL)) 808 return 0; 809 if (!alg || !pubkey) 810 return 0; 811 if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) { 812 ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR); 813 return 0; 814 } 815 } 816 /* Set ECDH derivation parameters and initialise unwrap context */ 817 if (!ecdh_cms_set_shared_info(pctx, ri)) { 818 ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR); 819 return 0; 820 } 821 return 1; 822} 823 824static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) 825{ 826 EVP_PKEY_CTX *pctx; 827 EVP_PKEY *pkey; 828 EVP_CIPHER_CTX *ctx; 829 int keylen; 830 X509_ALGOR *talg, *wrap_alg = NULL; 831 ASN1_OBJECT *aoid; 832 ASN1_BIT_STRING *pubkey; 833 ASN1_STRING *wrap_str; 834 ASN1_OCTET_STRING *ukm; 835 unsigned char *penc = NULL; 836 int penclen; 837 int rv = 0; 838 int ecdh_nid, kdf_type, kdf_nid, wrap_nid; 839 const EVP_MD *kdf_md; 840 pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 841 if (!pctx) 842 return 0; 843 /* Get ephemeral key */ 844 pkey = EVP_PKEY_CTX_get0_pkey(pctx); 845 if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, 846 NULL, NULL, NULL)) 847 goto err; 848 X509_ALGOR_get0(&aoid, NULL, NULL, talg); 849 /* Is everything uninitialised? */ 850 if (aoid == OBJ_nid2obj(NID_undef)) { 851 852 EC_KEY *eckey = pkey->pkey.ec; 853 /* Set the key */ 854 unsigned char *p; 855 856 penclen = i2o_ECPublicKey(eckey, NULL); 857 if (penclen <= 0) 858 goto err; 859 penc = OPENSSL_malloc(penclen); 860 if (!penc) 861 goto err; 862 p = penc; 863 penclen = i2o_ECPublicKey(eckey, &p); 864 if (penclen <= 0) 865 goto err; 866 ASN1_STRING_set0(pubkey, penc, penclen); 867 pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); 868 pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; 869 870 penc = NULL; 871 X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 872 V_ASN1_UNDEF, NULL); 873 } 874 875 /* See if custom paraneters set */ 876 kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); 877 if (kdf_type <= 0) 878 goto err; 879 if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) 880 goto err; 881 ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); 882 if (ecdh_nid < 0) 883 goto err; 884 else if (ecdh_nid == 0) 885 ecdh_nid = NID_dh_std_kdf; 886 else if (ecdh_nid == 1) 887 ecdh_nid = NID_dh_cofactor_kdf; 888 889 if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { 890 kdf_type = EVP_PKEY_ECDH_KDF_X9_62; 891 if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) 892 goto err; 893 } else 894 /* Uknown KDF */ 895 goto err; 896 if (kdf_md == NULL) { 897 /* Fixme later for better MD */ 898 kdf_md = EVP_sha1(); 899 if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) 900 goto err; 901 } 902 903 if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) 904 goto err; 905 906 /* Lookup NID for KDF+cofactor+digest */ 907 908 if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) 909 goto err; 910 /* Get wrap NID */ 911 ctx = CMS_RecipientInfo_kari_get0_ctx(ri); 912 wrap_nid = EVP_CIPHER_CTX_type(ctx); 913 keylen = EVP_CIPHER_CTX_key_length(ctx); 914 915 /* Package wrap algorithm in an AlgorithmIdentifier */ 916 917 wrap_alg = X509_ALGOR_new(); 918 if (!wrap_alg) 919 goto err; 920 wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); 921 wrap_alg->parameter = ASN1_TYPE_new(); 922 if (!wrap_alg->parameter) 923 goto err; 924 if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) 925 goto err; 926 if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { 927 ASN1_TYPE_free(wrap_alg->parameter); 928 wrap_alg->parameter = NULL; 929 } 930 931 if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) 932 goto err; 933 934 penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); 935 936 if (!penclen) 937 goto err; 938 939 if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) 940 goto err; 941 penc = NULL; 942 943 /* 944 * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter 945 * of another AlgorithmIdentifier. 946 */ 947 penclen = i2d_X509_ALGOR(wrap_alg, &penc); 948 if (!penc || !penclen) 949 goto err; 950 wrap_str = ASN1_STRING_new(); 951 if (!wrap_str) 952 goto err; 953 ASN1_STRING_set0(wrap_str, penc, penclen); 954 penc = NULL; 955 X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); 956 957 rv = 1; 958 959 err: 960 if (penc) 961 OPENSSL_free(penc); 962 if (wrap_alg) 963 X509_ALGOR_free(wrap_alg); 964 return rv; 965} 966 967#endif 968