1 /* $NetBSD: opensslecdsa_link.c,v 1.7 2023/01/25 21:43:30 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #if !USE_PKCS11 19 20 #include <stdbool.h> 21 22 #include <openssl/bn.h> 23 #include <openssl/ecdsa.h> 24 #include <openssl/err.h> 25 #include <openssl/objects.h> 26 #if !defined(OPENSSL_NO_ENGINE) 27 #include <openssl/engine.h> 28 #endif 29 30 #include <isc/mem.h> 31 #include <isc/safe.h> 32 #include <isc/string.h> 33 #include <isc/util.h> 34 35 #include <dns/keyvalues.h> 36 37 #include <dst/result.h> 38 39 #include "dst_internal.h" 40 #include "dst_openssl.h" 41 #include "dst_parse.h" 42 43 #ifndef NID_X9_62_prime256v1 44 #error "P-256 group is not known (NID_X9_62_prime256v1)" 45 #endif /* ifndef NID_X9_62_prime256v1 */ 46 #ifndef NID_secp384r1 47 #error "P-384 group is not known (NID_secp384r1)" 48 #endif /* ifndef NID_secp384r1 */ 49 50 #define DST_RET(a) \ 51 { \ 52 ret = a; \ 53 goto err; \ 54 } 55 56 #if !HAVE_ECDSA_SIG_GET0 57 /* From OpenSSL 1.1 */ 58 static void 59 ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { 60 if (pr != NULL) { 61 *pr = sig->r; 62 } 63 if (ps != NULL) { 64 *ps = sig->s; 65 } 66 } 67 68 static int 69 ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { 70 if (r == NULL || s == NULL) { 71 return (0); 72 } 73 74 BN_clear_free(sig->r); 75 BN_clear_free(sig->s); 76 sig->r = r; 77 sig->s = s; 78 79 return (1); 80 } 81 #endif /* !HAVE_ECDSA_SIG_GET0 */ 82 83 static isc_result_t 84 opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) { 85 EVP_MD_CTX *evp_md_ctx; 86 const EVP_MD *type = NULL; 87 88 UNUSED(key); 89 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 90 dctx->key->key_alg == DST_ALG_ECDSA384); 91 92 evp_md_ctx = EVP_MD_CTX_create(); 93 if (evp_md_ctx == NULL) { 94 return (ISC_R_NOMEMORY); 95 } 96 if (dctx->key->key_alg == DST_ALG_ECDSA256) { 97 type = EVP_sha256(); 98 } else { 99 type = EVP_sha384(); 100 } 101 102 if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { 103 EVP_MD_CTX_destroy(evp_md_ctx); 104 return (dst__openssl_toresult3( 105 dctx->category, "EVP_DigestInit_ex", ISC_R_FAILURE)); 106 } 107 108 dctx->ctxdata.evp_md_ctx = evp_md_ctx; 109 110 return (ISC_R_SUCCESS); 111 } 112 113 static void 114 opensslecdsa_destroyctx(dst_context_t *dctx) { 115 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 116 117 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 118 dctx->key->key_alg == DST_ALG_ECDSA384); 119 120 if (evp_md_ctx != NULL) { 121 EVP_MD_CTX_destroy(evp_md_ctx); 122 dctx->ctxdata.evp_md_ctx = NULL; 123 } 124 } 125 126 static isc_result_t 127 opensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) { 128 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 129 130 REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 131 dctx->key->key_alg == DST_ALG_ECDSA384); 132 133 if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) { 134 return (dst__openssl_toresult3( 135 dctx->category, "EVP_DigestUpdate", ISC_R_FAILURE)); 136 } 137 138 return (ISC_R_SUCCESS); 139 } 140 141 static int 142 BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) { 143 int bytes = size - BN_num_bytes(bn); 144 145 while (bytes-- > 0) { 146 *buf++ = 0; 147 } 148 BN_bn2bin(bn, buf); 149 return (size); 150 } 151 152 static isc_result_t 153 opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { 154 isc_result_t ret; 155 dst_key_t *key = dctx->key; 156 isc_region_t region; 157 ECDSA_SIG *ecdsasig; 158 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 159 EVP_PKEY *pkey = key->keydata.pkey; 160 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 161 unsigned int dgstlen, siglen; 162 unsigned char digest[EVP_MAX_MD_SIZE]; 163 const BIGNUM *r, *s; 164 165 REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 166 key->key_alg == DST_ALG_ECDSA384); 167 168 if (eckey == NULL) { 169 return (ISC_R_FAILURE); 170 } 171 172 if (key->key_alg == DST_ALG_ECDSA256) { 173 siglen = DNS_SIG_ECDSA256SIZE; 174 } else { 175 siglen = DNS_SIG_ECDSA384SIZE; 176 } 177 178 isc_buffer_availableregion(sig, ®ion); 179 if (region.length < siglen) { 180 DST_RET(ISC_R_NOSPACE); 181 } 182 183 if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) { 184 DST_RET(dst__openssl_toresult3( 185 dctx->category, "EVP_DigestFinal_ex", ISC_R_FAILURE)); 186 } 187 188 ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey); 189 if (ecdsasig == NULL) { 190 DST_RET(dst__openssl_toresult3(dctx->category, "ECDSA_do_sign", 191 DST_R_SIGNFAILURE)); 192 } 193 ECDSA_SIG_get0(ecdsasig, &r, &s); 194 BN_bn2bin_fixed(r, region.base, siglen / 2); 195 isc_region_consume(®ion, siglen / 2); 196 BN_bn2bin_fixed(s, region.base, siglen / 2); 197 isc_region_consume(®ion, siglen / 2); 198 ECDSA_SIG_free(ecdsasig); 199 isc_buffer_add(sig, siglen); 200 ret = ISC_R_SUCCESS; 201 202 err: 203 EC_KEY_free(eckey); 204 return (ret); 205 } 206 207 static isc_result_t 208 opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { 209 isc_result_t ret; 210 dst_key_t *key = dctx->key; 211 int status; 212 unsigned char *cp = sig->base; 213 ECDSA_SIG *ecdsasig = NULL; 214 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 215 EVP_PKEY *pkey = key->keydata.pkey; 216 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 217 unsigned int dgstlen, siglen; 218 unsigned char digest[EVP_MAX_MD_SIZE]; 219 BIGNUM *r = NULL, *s = NULL; 220 221 REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 222 key->key_alg == DST_ALG_ECDSA384); 223 224 if (eckey == NULL) { 225 return (ISC_R_FAILURE); 226 } 227 228 if (key->key_alg == DST_ALG_ECDSA256) { 229 siglen = DNS_SIG_ECDSA256SIZE; 230 } else { 231 siglen = DNS_SIG_ECDSA384SIZE; 232 } 233 234 if (sig->length != siglen) { 235 DST_RET(DST_R_VERIFYFAILURE); 236 } 237 238 if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) { 239 DST_RET(dst__openssl_toresult3( 240 dctx->category, "EVP_DigestFinal_ex", ISC_R_FAILURE)); 241 } 242 243 ecdsasig = ECDSA_SIG_new(); 244 if (ecdsasig == NULL) { 245 DST_RET(ISC_R_NOMEMORY); 246 } 247 r = BN_bin2bn(cp, siglen / 2, NULL); 248 cp += siglen / 2; 249 s = BN_bin2bn(cp, siglen / 2, NULL); 250 ECDSA_SIG_set0(ecdsasig, r, s); 251 /* cp += siglen / 2; */ 252 253 status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey); 254 switch (status) { 255 case 1: 256 ret = ISC_R_SUCCESS; 257 break; 258 case 0: 259 ret = dst__openssl_toresult(DST_R_VERIFYFAILURE); 260 break; 261 default: 262 ret = dst__openssl_toresult3(dctx->category, "ECDSA_do_verify", 263 DST_R_VERIFYFAILURE); 264 break; 265 } 266 267 err: 268 if (ecdsasig != NULL) { 269 ECDSA_SIG_free(ecdsasig); 270 } 271 EC_KEY_free(eckey); 272 return (ret); 273 } 274 275 static bool 276 opensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) { 277 bool ret; 278 int status; 279 EVP_PKEY *pkey1 = key1->keydata.pkey; 280 EVP_PKEY *pkey2 = key2->keydata.pkey; 281 EC_KEY *eckey1 = NULL; 282 EC_KEY *eckey2 = NULL; 283 const BIGNUM *priv1, *priv2; 284 285 if (pkey1 == NULL && pkey2 == NULL) { 286 return (true); 287 } else if (pkey1 == NULL || pkey2 == NULL) { 288 return (false); 289 } 290 291 eckey1 = EVP_PKEY_get1_EC_KEY(pkey1); 292 eckey2 = EVP_PKEY_get1_EC_KEY(pkey2); 293 if (eckey1 == NULL && eckey2 == NULL) { 294 DST_RET(true); 295 } else if (eckey1 == NULL || eckey2 == NULL) { 296 DST_RET(false); 297 } 298 299 status = EVP_PKEY_cmp(pkey1, pkey2); 300 if (status != 1) { 301 DST_RET(false); 302 } 303 304 priv1 = EC_KEY_get0_private_key(eckey1); 305 priv2 = EC_KEY_get0_private_key(eckey2); 306 if (priv1 != NULL || priv2 != NULL) { 307 if (priv1 == NULL || priv2 == NULL) { 308 DST_RET(false); 309 } 310 if (BN_cmp(priv1, priv2) != 0) { 311 DST_RET(false); 312 } 313 } 314 ret = true; 315 316 err: 317 if (eckey1 != NULL) { 318 EC_KEY_free(eckey1); 319 } 320 if (eckey2 != NULL) { 321 EC_KEY_free(eckey2); 322 } 323 return (ret); 324 } 325 326 static isc_result_t 327 opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { 328 isc_result_t ret; 329 EVP_PKEY *pkey; 330 EC_KEY *eckey = NULL; 331 int group_nid; 332 333 REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 334 key->key_alg == DST_ALG_ECDSA384); 335 UNUSED(unused); 336 UNUSED(callback); 337 338 if (key->key_alg == DST_ALG_ECDSA256) { 339 group_nid = NID_X9_62_prime256v1; 340 key->key_size = DNS_KEY_ECDSA256SIZE * 4; 341 } else { 342 group_nid = NID_secp384r1; 343 key->key_size = DNS_KEY_ECDSA384SIZE * 4; 344 } 345 346 eckey = EC_KEY_new_by_curve_name(group_nid); 347 if (eckey == NULL) { 348 return (dst__openssl_toresult2("EC_KEY_new_by_curve_name", 349 DST_R_OPENSSLFAILURE)); 350 } 351 352 if (EC_KEY_generate_key(eckey) != 1) { 353 DST_RET(dst__openssl_toresult2("EC_KEY_generate_key", 354 DST_R_OPENSSLFAILURE)); 355 } 356 357 pkey = EVP_PKEY_new(); 358 if (pkey == NULL) { 359 DST_RET(ISC_R_NOMEMORY); 360 } 361 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 362 EVP_PKEY_free(pkey); 363 DST_RET(ISC_R_FAILURE); 364 } 365 key->keydata.pkey = pkey; 366 ret = ISC_R_SUCCESS; 367 368 err: 369 EC_KEY_free(eckey); 370 return (ret); 371 } 372 373 static bool 374 opensslecdsa_isprivate(const dst_key_t *key) { 375 bool ret; 376 EVP_PKEY *pkey = key->keydata.pkey; 377 EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 378 379 ret = (eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL); 380 if (eckey != NULL) { 381 EC_KEY_free(eckey); 382 } 383 return (ret); 384 } 385 386 static void 387 opensslecdsa_destroy(dst_key_t *key) { 388 EVP_PKEY *pkey = key->keydata.pkey; 389 390 EVP_PKEY_free(pkey); 391 key->keydata.pkey = NULL; 392 } 393 394 static isc_result_t 395 opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { 396 isc_result_t ret; 397 EVP_PKEY *pkey; 398 EC_KEY *eckey = NULL; 399 isc_region_t r; 400 int len; 401 unsigned char *cp; 402 unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 403 404 REQUIRE(key->keydata.pkey != NULL); 405 406 pkey = key->keydata.pkey; 407 eckey = EVP_PKEY_get1_EC_KEY(pkey); 408 if (eckey == NULL) { 409 return (dst__openssl_toresult(ISC_R_FAILURE)); 410 } 411 len = i2o_ECPublicKey(eckey, NULL); 412 /* skip form */ 413 len--; 414 415 isc_buffer_availableregion(data, &r); 416 if (r.length < (unsigned int)len) { 417 DST_RET(ISC_R_NOSPACE); 418 } 419 cp = buf; 420 if (!i2o_ECPublicKey(eckey, &cp)) { 421 DST_RET(dst__openssl_toresult(ISC_R_FAILURE)); 422 } 423 memmove(r.base, buf + 1, len); 424 isc_buffer_add(data, len); 425 ret = ISC_R_SUCCESS; 426 427 err: 428 EC_KEY_free(eckey); 429 return (ret); 430 } 431 432 static isc_result_t 433 opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 434 isc_result_t ret; 435 EVP_PKEY *pkey; 436 EC_KEY *eckey = NULL; 437 isc_region_t r; 438 int group_nid; 439 unsigned int len; 440 const unsigned char *cp; 441 unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 442 443 REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 444 key->key_alg == DST_ALG_ECDSA384); 445 446 if (key->key_alg == DST_ALG_ECDSA256) { 447 len = DNS_KEY_ECDSA256SIZE; 448 group_nid = NID_X9_62_prime256v1; 449 } else { 450 len = DNS_KEY_ECDSA384SIZE; 451 group_nid = NID_secp384r1; 452 } 453 454 isc_buffer_remainingregion(data, &r); 455 if (r.length == 0) { 456 return (ISC_R_SUCCESS); 457 } 458 if (r.length < len) { 459 return (DST_R_INVALIDPUBLICKEY); 460 } 461 462 eckey = EC_KEY_new_by_curve_name(group_nid); 463 if (eckey == NULL) { 464 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 465 } 466 467 buf[0] = POINT_CONVERSION_UNCOMPRESSED; 468 memmove(buf + 1, r.base, len); 469 cp = buf; 470 if (o2i_ECPublicKey(&eckey, (const unsigned char **)&cp, 471 (long)len + 1) == NULL) 472 { 473 DST_RET(dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 474 } 475 if (EC_KEY_check_key(eckey) != 1) { 476 DST_RET(dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 477 } 478 479 pkey = EVP_PKEY_new(); 480 if (pkey == NULL) { 481 DST_RET(ISC_R_NOMEMORY); 482 } 483 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 484 EVP_PKEY_free(pkey); 485 DST_RET(dst__openssl_toresult(ISC_R_FAILURE)); 486 } 487 488 isc_buffer_forward(data, len); 489 key->keydata.pkey = pkey; 490 key->key_size = len * 4; 491 ret = ISC_R_SUCCESS; 492 493 err: 494 if (eckey != NULL) { 495 EC_KEY_free(eckey); 496 } 497 return (ret); 498 } 499 500 static isc_result_t 501 opensslecdsa_tofile(const dst_key_t *key, const char *directory) { 502 isc_result_t ret; 503 EVP_PKEY *pkey; 504 EC_KEY *eckey = NULL; 505 const BIGNUM *privkey; 506 dst_private_t priv; 507 unsigned char *buf = NULL; 508 unsigned short i; 509 510 if (key->keydata.pkey == NULL) { 511 return (DST_R_NULLKEY); 512 } 513 514 if (key->external) { 515 priv.nelements = 0; 516 return (dst__privstruct_writefile(key, &priv, directory)); 517 } 518 519 pkey = key->keydata.pkey; 520 eckey = EVP_PKEY_get1_EC_KEY(pkey); 521 if (eckey == NULL) { 522 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 523 } 524 privkey = EC_KEY_get0_private_key(eckey); 525 if (privkey == NULL) { 526 ret = dst__openssl_toresult(DST_R_OPENSSLFAILURE); 527 goto err; 528 } 529 530 buf = isc_mem_get(key->mctx, BN_num_bytes(privkey)); 531 532 i = 0; 533 534 priv.elements[i].tag = TAG_ECDSA_PRIVATEKEY; 535 priv.elements[i].length = BN_num_bytes(privkey); 536 BN_bn2bin(privkey, buf); 537 priv.elements[i].data = buf; 538 i++; 539 540 if (key->engine != NULL) { 541 priv.elements[i].tag = TAG_ECDSA_ENGINE; 542 priv.elements[i].length = (unsigned short)strlen(key->engine) + 543 1; 544 priv.elements[i].data = (unsigned char *)key->engine; 545 i++; 546 } 547 548 if (key->label != NULL) { 549 priv.elements[i].tag = TAG_ECDSA_LABEL; 550 priv.elements[i].length = (unsigned short)strlen(key->label) + 551 1; 552 priv.elements[i].data = (unsigned char *)key->label; 553 i++; 554 } 555 556 priv.nelements = i; 557 ret = dst__privstruct_writefile(key, &priv, directory); 558 559 err: 560 EC_KEY_free(eckey); 561 if (buf != NULL) { 562 isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); 563 } 564 return (ret); 565 } 566 567 static isc_result_t 568 ecdsa_check(EC_KEY *eckey, EC_KEY *pubeckey) { 569 const EC_POINT *pubkey; 570 571 pubkey = EC_KEY_get0_public_key(eckey); 572 if (pubkey != NULL) { 573 return (ISC_R_SUCCESS); 574 } else if (pubeckey != NULL) { 575 pubkey = EC_KEY_get0_public_key(pubeckey); 576 if (pubkey == NULL) { 577 return (ISC_R_SUCCESS); 578 } 579 if (EC_KEY_set_public_key(eckey, pubkey) != 1) { 580 return (ISC_R_SUCCESS); 581 } 582 } 583 if (EC_KEY_check_key(eckey) == 1) { 584 return (ISC_R_SUCCESS); 585 } 586 return (ISC_R_FAILURE); 587 } 588 589 static isc_result_t 590 load_privkey_from_privstruct(EC_KEY *eckey, dst_private_t *priv) { 591 BIGNUM *privkey = BN_bin2bn(priv->elements[0].data, 592 priv->elements[0].length, NULL); 593 isc_result_t result = ISC_R_SUCCESS; 594 595 if (privkey == NULL) { 596 return (ISC_R_NOMEMORY); 597 } 598 599 if (!EC_KEY_set_private_key(eckey, privkey)) { 600 result = ISC_R_NOMEMORY; 601 } 602 603 BN_clear_free(privkey); 604 return (result); 605 } 606 607 static isc_result_t 608 eckey_to_pkey(EC_KEY *eckey, EVP_PKEY **pkey) { 609 REQUIRE(pkey != NULL && *pkey == NULL); 610 611 *pkey = EVP_PKEY_new(); 612 if (*pkey == NULL) { 613 return (ISC_R_NOMEMORY); 614 } 615 if (!EVP_PKEY_set1_EC_KEY(*pkey, eckey)) { 616 EVP_PKEY_free(*pkey); 617 *pkey = NULL; 618 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 619 } 620 return (ISC_R_SUCCESS); 621 } 622 623 static isc_result_t 624 finalize_eckey(dst_key_t *key, EC_KEY *eckey, const char *engine, 625 const char *label) { 626 isc_result_t result = ISC_R_SUCCESS; 627 EVP_PKEY *pkey = NULL; 628 629 result = eckey_to_pkey(eckey, &pkey); 630 if (result != ISC_R_SUCCESS) { 631 return (result); 632 } 633 634 key->keydata.pkey = pkey; 635 636 if (label != NULL) { 637 key->label = isc_mem_strdup(key->mctx, label); 638 key->engine = isc_mem_strdup(key->mctx, engine); 639 } 640 641 if (key->key_alg == DST_ALG_ECDSA256) { 642 key->key_size = DNS_KEY_ECDSA256SIZE * 4; 643 } else { 644 key->key_size = DNS_KEY_ECDSA384SIZE * 4; 645 } 646 647 return (ISC_R_SUCCESS); 648 } 649 650 static isc_result_t 651 dst__key_to_eckey(dst_key_t *key, EC_KEY **eckey) { 652 REQUIRE(eckey != NULL && *eckey == NULL); 653 654 int group_nid; 655 switch (key->key_alg) { 656 case DST_ALG_ECDSA256: 657 group_nid = NID_X9_62_prime256v1; 658 break; 659 case DST_ALG_ECDSA384: 660 group_nid = NID_secp384r1; 661 break; 662 default: 663 UNREACHABLE(); 664 } 665 *eckey = EC_KEY_new_by_curve_name(group_nid); 666 if (*eckey == NULL) { 667 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 668 } 669 return (ISC_R_SUCCESS); 670 } 671 672 static isc_result_t 673 opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label, 674 const char *pin); 675 676 static isc_result_t 677 opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { 678 dst_private_t priv; 679 isc_result_t result = ISC_R_SUCCESS; 680 EC_KEY *eckey = NULL; 681 EC_KEY *pubeckey = NULL; 682 const char *engine = NULL; 683 const char *label = NULL; 684 int i, privkey_index = -1; 685 bool finalize_key = false; 686 687 /* read private key file */ 688 result = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, key->mctx, 689 &priv); 690 if (result != ISC_R_SUCCESS) { 691 goto end; 692 } 693 694 if (key->external) { 695 if (priv.nelements != 0 || pub == NULL) { 696 result = DST_R_INVALIDPRIVATEKEY; 697 goto end; 698 } 699 key->keydata.pkey = pub->keydata.pkey; 700 pub->keydata.pkey = NULL; 701 goto end; 702 } 703 704 for (i = 0; i < priv.nelements; i++) { 705 switch (priv.elements[i].tag) { 706 case TAG_ECDSA_ENGINE: 707 engine = (char *)priv.elements[i].data; 708 break; 709 case TAG_ECDSA_LABEL: 710 label = (char *)priv.elements[i].data; 711 break; 712 case TAG_ECDSA_PRIVATEKEY: 713 privkey_index = i; 714 break; 715 default: 716 break; 717 } 718 } 719 720 if (privkey_index < 0) { 721 result = DST_R_INVALIDPRIVATEKEY; 722 goto end; 723 } 724 725 if (label != NULL) { 726 result = opensslecdsa_fromlabel(key, engine, label, NULL); 727 if (result != ISC_R_SUCCESS) { 728 goto end; 729 } 730 731 eckey = EVP_PKEY_get1_EC_KEY(key->keydata.pkey); 732 if (eckey == NULL) { 733 result = dst__openssl_toresult(DST_R_OPENSSLFAILURE); 734 goto end; 735 } 736 737 } else { 738 result = dst__key_to_eckey(key, &eckey); 739 if (result != ISC_R_SUCCESS) { 740 goto end; 741 } 742 743 result = load_privkey_from_privstruct(eckey, &priv); 744 if (result != ISC_R_SUCCESS) { 745 goto end; 746 } 747 748 finalize_key = true; 749 } 750 751 if (pub != NULL && pub->keydata.pkey != NULL) { 752 pubeckey = EVP_PKEY_get1_EC_KEY(pub->keydata.pkey); 753 } 754 755 if (ecdsa_check(eckey, pubeckey) != ISC_R_SUCCESS) { 756 result = DST_R_INVALIDPRIVATEKEY; 757 goto end; 758 } 759 760 if (finalize_key) { 761 result = finalize_eckey(key, eckey, engine, label); 762 } 763 764 end: 765 if (pubeckey != NULL) { 766 EC_KEY_free(pubeckey); 767 } 768 if (eckey != NULL) { 769 EC_KEY_free(eckey); 770 } 771 dst__privstruct_free(&priv, key->mctx); 772 isc_safe_memwipe(&priv, sizeof(priv)); 773 return (result); 774 } 775 776 static isc_result_t 777 opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label, 778 const char *pin) { 779 #if !defined(OPENSSL_NO_ENGINE) 780 isc_result_t ret = ISC_R_SUCCESS; 781 ENGINE *e; 782 EC_KEY *eckey = NULL; 783 EC_KEY *pubeckey = NULL; 784 EVP_PKEY *pkey = NULL; 785 EVP_PKEY *pubkey = NULL; 786 int group_nid = 0; 787 788 UNUSED(pin); 789 790 if (engine == NULL || label == NULL) { 791 return (DST_R_NOENGINE); 792 } 793 e = dst__openssl_getengine(engine); 794 if (e == NULL) { 795 return (DST_R_NOENGINE); 796 } 797 798 if (key->key_alg == DST_ALG_ECDSA256) { 799 group_nid = NID_X9_62_prime256v1; 800 } else { 801 group_nid = NID_secp384r1; 802 } 803 804 /* Load private key. */ 805 pkey = ENGINE_load_private_key(e, label, NULL, NULL); 806 if (pkey == NULL) { 807 return (dst__openssl_toresult2("ENGINE_load_private_key", 808 DST_R_OPENSSLFAILURE)); 809 } 810 /* Check base id, group nid */ 811 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { 812 DST_RET(DST_R_INVALIDPRIVATEKEY); 813 } 814 eckey = EVP_PKEY_get1_EC_KEY(pkey); 815 if (eckey == NULL) { 816 DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 817 } 818 if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) != group_nid) { 819 DST_RET(DST_R_INVALIDPRIVATEKEY); 820 } 821 822 /* Load public key. */ 823 pubkey = ENGINE_load_public_key(e, label, NULL, NULL); 824 if (pubkey == NULL) { 825 DST_RET(dst__openssl_toresult2("ENGINE_load_public_key", 826 DST_R_OPENSSLFAILURE)); 827 } 828 /* Check base id, group nid */ 829 if (EVP_PKEY_base_id(pubkey) != EVP_PKEY_EC) { 830 DST_RET(DST_R_INVALIDPUBLICKEY); 831 } 832 pubeckey = EVP_PKEY_get1_EC_KEY(pubkey); 833 if (pubeckey == NULL) { 834 DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 835 } 836 if (EC_GROUP_get_curve_name(EC_KEY_get0_group(pubeckey)) != group_nid) { 837 DST_RET(DST_R_INVALIDPUBLICKEY); 838 } 839 840 if (ecdsa_check(eckey, pubeckey) != ISC_R_SUCCESS) { 841 DST_RET(DST_R_INVALIDPRIVATEKEY); 842 } 843 844 key->label = isc_mem_strdup(key->mctx, label); 845 key->engine = isc_mem_strdup(key->mctx, engine); 846 key->key_size = EVP_PKEY_bits(pkey); 847 key->keydata.pkey = pkey; 848 pkey = NULL; 849 850 err: 851 if (pubkey != NULL) { 852 EVP_PKEY_free(pubkey); 853 } 854 if (pkey != NULL) { 855 EVP_PKEY_free(pkey); 856 } 857 if (pubeckey != NULL) { 858 EC_KEY_free(pubeckey); 859 } 860 if (eckey != NULL) { 861 EC_KEY_free(eckey); 862 } 863 864 return (ret); 865 #else 866 UNUSED(key); 867 UNUSED(engine); 868 UNUSED(label); 869 UNUSED(pin); 870 return (DST_R_NOENGINE); 871 #endif 872 } 873 874 static dst_func_t opensslecdsa_functions = { 875 opensslecdsa_createctx, 876 NULL, /*%< createctx2 */ 877 opensslecdsa_destroyctx, 878 opensslecdsa_adddata, 879 opensslecdsa_sign, 880 opensslecdsa_verify, 881 NULL, /*%< verify2 */ 882 NULL, /*%< computesecret */ 883 opensslecdsa_compare, 884 NULL, /*%< paramcompare */ 885 opensslecdsa_generate, 886 opensslecdsa_isprivate, 887 opensslecdsa_destroy, 888 opensslecdsa_todns, 889 opensslecdsa_fromdns, 890 opensslecdsa_tofile, 891 opensslecdsa_parse, 892 NULL, /*%< cleanup */ 893 opensslecdsa_fromlabel, /*%< fromlabel */ 894 NULL, /*%< dump */ 895 NULL, /*%< restore */ 896 }; 897 898 isc_result_t 899 dst__opensslecdsa_init(dst_func_t **funcp) { 900 REQUIRE(funcp != NULL); 901 if (*funcp == NULL) { 902 *funcp = &opensslecdsa_functions; 903 } 904 return (ISC_R_SUCCESS); 905 } 906 907 #endif /* !USE_PKCS11 */ 908