1243885Serwin/* 2262706Serwin * Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC") 3243885Serwin * 4243885Serwin * Permission to use, copy, modify, and/or distribute this software for any 5243885Serwin * purpose with or without fee is hereby granted, provided that the above 6243885Serwin * copyright notice and this permission notice appear in all copies. 7243885Serwin * 8243885Serwin * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9243885Serwin * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10243885Serwin * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11243885Serwin * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12243885Serwin * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13243885Serwin * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14243885Serwin * PERFORMANCE OF THIS SOFTWARE. 15243885Serwin */ 16243885Serwin 17243885Serwin#include <config.h> 18243885Serwin 19243885Serwin#ifdef HAVE_OPENSSL_ECDSA 20243885Serwin 21243885Serwin#if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384) 22243885Serwin#error "ECDSA without EVP for SHA2?" 23243885Serwin#endif 24243885Serwin 25243885Serwin#include <isc/entropy.h> 26243885Serwin#include <isc/mem.h> 27243885Serwin#include <isc/sha2.h> 28243885Serwin#include <isc/string.h> 29243885Serwin#include <isc/util.h> 30243885Serwin 31243885Serwin#include <dns/keyvalues.h> 32243885Serwin#include <dst/result.h> 33243885Serwin 34243885Serwin#include "dst_internal.h" 35243885Serwin#include "dst_openssl.h" 36243885Serwin#include "dst_parse.h" 37243885Serwin 38243885Serwin#include <openssl/err.h> 39243885Serwin#include <openssl/objects.h> 40243885Serwin#include <openssl/ecdsa.h> 41243885Serwin#include <openssl/bn.h> 42243885Serwin 43243885Serwin#ifndef NID_X9_62_prime256v1 44243885Serwin#error "P-256 group is not known (NID_X9_62_prime256v1)" 45243885Serwin#endif 46243885Serwin#ifndef NID_secp384r1 47243885Serwin#error "P-384 group is not known (NID_secp384r1)" 48243885Serwin#endif 49243885Serwin 50243885Serwin#define DST_RET(a) {ret = a; goto err;} 51243885Serwin 52243885Serwinstatic isc_result_t opensslecdsa_todns(const dst_key_t *key, 53243885Serwin isc_buffer_t *data); 54243885Serwin 55243885Serwinstatic isc_result_t 56243885Serwinopensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) { 57243885Serwin EVP_MD_CTX *evp_md_ctx; 58243885Serwin const EVP_MD *type = NULL; 59243885Serwin 60243885Serwin UNUSED(key); 61243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 62243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 63243885Serwin 64243885Serwin evp_md_ctx = EVP_MD_CTX_create(); 65243885Serwin if (evp_md_ctx == NULL) 66243885Serwin return (ISC_R_NOMEMORY); 67243885Serwin if (dctx->key->key_alg == DST_ALG_ECDSA256) 68243885Serwin type = EVP_sha256(); 69243885Serwin else 70243885Serwin type = EVP_sha384(); 71243885Serwin 72243885Serwin if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { 73243885Serwin EVP_MD_CTX_destroy(evp_md_ctx); 74254402Serwin return (dst__openssl_toresult3(dctx->category, 75254402Serwin "EVP_DigestInit_ex", 76243885Serwin ISC_R_FAILURE)); 77243885Serwin } 78243885Serwin 79243885Serwin dctx->ctxdata.evp_md_ctx = evp_md_ctx; 80243885Serwin 81243885Serwin return (ISC_R_SUCCESS); 82243885Serwin} 83243885Serwin 84243885Serwinstatic void 85243885Serwinopensslecdsa_destroyctx(dst_context_t *dctx) { 86243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 87243885Serwin 88243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 89243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 90243885Serwin 91243885Serwin if (evp_md_ctx != NULL) { 92243885Serwin EVP_MD_CTX_destroy(evp_md_ctx); 93243885Serwin dctx->ctxdata.evp_md_ctx = NULL; 94243885Serwin } 95243885Serwin} 96243885Serwin 97243885Serwinstatic isc_result_t 98243885Serwinopensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) { 99243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 100243885Serwin 101243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 102243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 103243885Serwin 104243885Serwin if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) 105254402Serwin return (dst__openssl_toresult3(dctx->category, 106254402Serwin "EVP_DigestUpdate", 107243885Serwin ISC_R_FAILURE)); 108243885Serwin 109243885Serwin return (ISC_R_SUCCESS); 110243885Serwin} 111243885Serwin 112243885Serwinstatic int 113243885SerwinBN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) { 114243885Serwin int bytes = size - BN_num_bytes(bn); 115243885Serwin 116243885Serwin while (bytes-- > 0) 117243885Serwin *buf++ = 0; 118243885Serwin BN_bn2bin(bn, buf); 119243885Serwin return (size); 120243885Serwin} 121243885Serwin 122243885Serwinstatic isc_result_t 123243885Serwinopensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { 124243885Serwin isc_result_t ret; 125243885Serwin dst_key_t *key = dctx->key; 126243885Serwin isc_region_t r; 127243885Serwin ECDSA_SIG *ecdsasig; 128243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 129243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 130243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 131243885Serwin unsigned int dgstlen, siglen; 132243885Serwin unsigned char digest[EVP_MAX_MD_SIZE]; 133243885Serwin 134243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 135243885Serwin key->key_alg == DST_ALG_ECDSA384); 136243885Serwin 137243885Serwin if (eckey == NULL) 138243885Serwin return (ISC_R_FAILURE); 139243885Serwin 140243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 141243885Serwin siglen = DNS_SIG_ECDSA256SIZE; 142243885Serwin else 143243885Serwin siglen = DNS_SIG_ECDSA384SIZE; 144243885Serwin 145243885Serwin isc_buffer_availableregion(sig, &r); 146243885Serwin if (r.length < siglen) 147243885Serwin DST_RET(ISC_R_NOSPACE); 148243885Serwin 149243885Serwin if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen)) 150254402Serwin DST_RET(dst__openssl_toresult3(dctx->category, 151254402Serwin "EVP_DigestFinal", 152243885Serwin ISC_R_FAILURE)); 153243885Serwin 154243885Serwin ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey); 155243885Serwin if (ecdsasig == NULL) 156254402Serwin DST_RET(dst__openssl_toresult3(dctx->category, 157254402Serwin "ECDSA_do_sign", 158243885Serwin DST_R_SIGNFAILURE)); 159243885Serwin BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2); 160287410Sdelphij isc_region_consume(&r, siglen / 2); 161243885Serwin BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2); 162287410Sdelphij isc_region_consume(&r, siglen / 2); 163243885Serwin ECDSA_SIG_free(ecdsasig); 164243885Serwin isc_buffer_add(sig, siglen); 165243885Serwin ret = ISC_R_SUCCESS; 166243885Serwin 167243885Serwin err: 168243885Serwin if (eckey != NULL) 169243885Serwin EC_KEY_free(eckey); 170243885Serwin return (ret); 171243885Serwin} 172243885Serwin 173243885Serwinstatic isc_result_t 174243885Serwinopensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { 175243885Serwin isc_result_t ret; 176243885Serwin dst_key_t *key = dctx->key; 177243885Serwin int status; 178243885Serwin unsigned char *cp = sig->base; 179243885Serwin ECDSA_SIG *ecdsasig = NULL; 180243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 181243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 182243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 183243885Serwin unsigned int dgstlen, siglen; 184243885Serwin unsigned char digest[EVP_MAX_MD_SIZE]; 185243885Serwin 186243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 187243885Serwin key->key_alg == DST_ALG_ECDSA384); 188243885Serwin 189243885Serwin if (eckey == NULL) 190243885Serwin return (ISC_R_FAILURE); 191243885Serwin 192243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 193243885Serwin siglen = DNS_SIG_ECDSA256SIZE; 194243885Serwin else 195243885Serwin siglen = DNS_SIG_ECDSA384SIZE; 196243885Serwin 197243885Serwin if (sig->length != siglen) 198243885Serwin return (DST_R_VERIFYFAILURE); 199243885Serwin 200243885Serwin if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) 201254402Serwin DST_RET (dst__openssl_toresult3(dctx->category, 202254402Serwin "EVP_DigestFinal_ex", 203243885Serwin ISC_R_FAILURE)); 204243885Serwin 205243885Serwin ecdsasig = ECDSA_SIG_new(); 206243885Serwin if (ecdsasig == NULL) 207243885Serwin DST_RET (ISC_R_NOMEMORY); 208254402Serwin if (ecdsasig->r != NULL) 209254402Serwin BN_free(ecdsasig->r); 210243885Serwin ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL); 211243885Serwin cp += siglen / 2; 212254402Serwin if (ecdsasig->s != NULL) 213254402Serwin BN_free(ecdsasig->s); 214243885Serwin ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL); 215243885Serwin /* cp += siglen / 2; */ 216243885Serwin 217243885Serwin status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey); 218243885Serwin switch (status) { 219243885Serwin case 1: 220243885Serwin ret = ISC_R_SUCCESS; 221243885Serwin break; 222243885Serwin case 0: 223243885Serwin ret = dst__openssl_toresult(DST_R_VERIFYFAILURE); 224243885Serwin break; 225243885Serwin default: 226254402Serwin ret = dst__openssl_toresult3(dctx->category, 227254402Serwin "ECDSA_do_verify", 228243885Serwin DST_R_VERIFYFAILURE); 229243885Serwin break; 230243885Serwin } 231243885Serwin 232243885Serwin err: 233243885Serwin if (ecdsasig != NULL) 234243885Serwin ECDSA_SIG_free(ecdsasig); 235243885Serwin if (eckey != NULL) 236243885Serwin EC_KEY_free(eckey); 237243885Serwin return (ret); 238243885Serwin} 239243885Serwin 240243885Serwinstatic isc_boolean_t 241243885Serwinopensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) { 242243885Serwin isc_boolean_t ret; 243243885Serwin int status; 244243885Serwin EVP_PKEY *pkey1 = key1->keydata.pkey; 245243885Serwin EVP_PKEY *pkey2 = key2->keydata.pkey; 246243885Serwin EC_KEY *eckey1 = NULL; 247243885Serwin EC_KEY *eckey2 = NULL; 248243885Serwin const BIGNUM *priv1, *priv2; 249243885Serwin 250243885Serwin if (pkey1 == NULL && pkey2 == NULL) 251243885Serwin return (ISC_TRUE); 252243885Serwin else if (pkey1 == NULL || pkey2 == NULL) 253243885Serwin return (ISC_FALSE); 254243885Serwin 255243885Serwin eckey1 = EVP_PKEY_get1_EC_KEY(pkey1); 256243885Serwin eckey2 = EVP_PKEY_get1_EC_KEY(pkey2); 257243885Serwin if (eckey1 == NULL && eckey2 == NULL) { 258243885Serwin DST_RET (ISC_TRUE); 259243885Serwin } else if (eckey1 == NULL || eckey2 == NULL) 260243885Serwin DST_RET (ISC_FALSE); 261243885Serwin 262243885Serwin status = EVP_PKEY_cmp(pkey1, pkey2); 263243885Serwin if (status != 1) 264243885Serwin DST_RET (ISC_FALSE); 265243885Serwin 266243885Serwin priv1 = EC_KEY_get0_private_key(eckey1); 267243885Serwin priv2 = EC_KEY_get0_private_key(eckey2); 268243885Serwin if (priv1 != NULL || priv2 != NULL) { 269243885Serwin if (priv1 == NULL || priv2 == NULL) 270243885Serwin DST_RET (ISC_FALSE); 271243885Serwin if (BN_cmp(priv1, priv2) != 0) 272243885Serwin DST_RET (ISC_FALSE); 273243885Serwin } 274243885Serwin ret = ISC_TRUE; 275243885Serwin 276243885Serwin err: 277243885Serwin if (eckey1 != NULL) 278243885Serwin EC_KEY_free(eckey1); 279243885Serwin if (eckey2 != NULL) 280243885Serwin EC_KEY_free(eckey2); 281243885Serwin return (ret); 282243885Serwin} 283243885Serwin 284243885Serwinstatic isc_result_t 285243885Serwinopensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { 286243885Serwin isc_result_t ret; 287243885Serwin EVP_PKEY *pkey; 288243885Serwin EC_KEY *eckey = NULL; 289243885Serwin int group_nid; 290243885Serwin 291243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 292243885Serwin key->key_alg == DST_ALG_ECDSA384); 293243885Serwin UNUSED(unused); 294243885Serwin UNUSED(callback); 295243885Serwin 296243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 297243885Serwin group_nid = NID_X9_62_prime256v1; 298243885Serwin else 299243885Serwin group_nid = NID_secp384r1; 300243885Serwin 301243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 302243885Serwin if (eckey == NULL) 303243885Serwin return (dst__openssl_toresult2("EC_KEY_new_by_curve_name", 304243885Serwin DST_R_OPENSSLFAILURE)); 305243885Serwin 306243885Serwin if (EC_KEY_generate_key(eckey) != 1) 307243885Serwin DST_RET (dst__openssl_toresult2("EC_KEY_generate_key", 308243885Serwin DST_R_OPENSSLFAILURE)); 309243885Serwin 310243885Serwin pkey = EVP_PKEY_new(); 311243885Serwin if (pkey == NULL) 312243885Serwin DST_RET (ISC_R_NOMEMORY); 313243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 314243885Serwin EVP_PKEY_free(pkey); 315243885Serwin DST_RET (ISC_R_FAILURE); 316243885Serwin } 317243885Serwin key->keydata.pkey = pkey; 318243885Serwin ret = ISC_R_SUCCESS; 319243885Serwin 320243885Serwin err: 321243885Serwin if (eckey != NULL) 322243885Serwin EC_KEY_free(eckey); 323243885Serwin return (ret); 324243885Serwin} 325243885Serwin 326243885Serwinstatic isc_boolean_t 327243885Serwinopensslecdsa_isprivate(const dst_key_t *key) { 328243885Serwin isc_boolean_t ret; 329243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 330243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 331243885Serwin 332243885Serwin ret = ISC_TF(eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL); 333243885Serwin if (eckey != NULL) 334243885Serwin EC_KEY_free(eckey); 335243885Serwin return (ret); 336243885Serwin} 337243885Serwin 338243885Serwinstatic void 339243885Serwinopensslecdsa_destroy(dst_key_t *key) { 340243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 341243885Serwin 342243885Serwin EVP_PKEY_free(pkey); 343243885Serwin key->keydata.pkey = NULL; 344243885Serwin} 345243885Serwin 346243885Serwinstatic isc_result_t 347243885Serwinopensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { 348243885Serwin isc_result_t ret; 349243885Serwin EVP_PKEY *pkey; 350243885Serwin EC_KEY *eckey = NULL; 351243885Serwin isc_region_t r; 352243885Serwin int len; 353243885Serwin unsigned char *cp; 354243885Serwin unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 355243885Serwin 356243885Serwin REQUIRE(key->keydata.pkey != NULL); 357243885Serwin 358243885Serwin pkey = key->keydata.pkey; 359243885Serwin eckey = EVP_PKEY_get1_EC_KEY(pkey); 360243885Serwin if (eckey == NULL) 361243885Serwin return (dst__openssl_toresult(ISC_R_FAILURE)); 362243885Serwin len = i2o_ECPublicKey(eckey, NULL); 363243885Serwin /* skip form */ 364243885Serwin len--; 365243885Serwin 366243885Serwin isc_buffer_availableregion(data, &r); 367243885Serwin if (r.length < (unsigned int) len) 368243885Serwin DST_RET (ISC_R_NOSPACE); 369243885Serwin cp = buf; 370243885Serwin if (!i2o_ECPublicKey(eckey, &cp)) 371243885Serwin DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); 372262706Serwin memmove(r.base, buf + 1, len); 373243885Serwin isc_buffer_add(data, len); 374243885Serwin ret = ISC_R_SUCCESS; 375243885Serwin 376243885Serwin err: 377243885Serwin if (eckey != NULL) 378243885Serwin EC_KEY_free(eckey); 379243885Serwin return (ret); 380243885Serwin} 381243885Serwin 382243885Serwinstatic isc_result_t 383243885Serwinopensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 384243885Serwin isc_result_t ret; 385243885Serwin EVP_PKEY *pkey; 386243885Serwin EC_KEY *eckey = NULL; 387243885Serwin isc_region_t r; 388243885Serwin int group_nid; 389243885Serwin unsigned int len; 390243885Serwin const unsigned char *cp; 391243885Serwin unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 392243885Serwin 393243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 394243885Serwin key->key_alg == DST_ALG_ECDSA384); 395243885Serwin 396243885Serwin if (key->key_alg == DST_ALG_ECDSA256) { 397243885Serwin len = DNS_KEY_ECDSA256SIZE; 398243885Serwin group_nid = NID_X9_62_prime256v1; 399243885Serwin } else { 400243885Serwin len = DNS_KEY_ECDSA384SIZE; 401243885Serwin group_nid = NID_secp384r1; 402243885Serwin } 403243885Serwin 404243885Serwin isc_buffer_remainingregion(data, &r); 405243885Serwin if (r.length == 0) 406243885Serwin return (ISC_R_SUCCESS); 407243885Serwin if (r.length < len) 408243885Serwin return (DST_R_INVALIDPUBLICKEY); 409243885Serwin 410243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 411243885Serwin if (eckey == NULL) 412243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 413243885Serwin 414243885Serwin buf[0] = POINT_CONVERSION_UNCOMPRESSED; 415262706Serwin memmove(buf + 1, r.base, len); 416243885Serwin cp = buf; 417243885Serwin if (o2i_ECPublicKey(&eckey, 418243885Serwin (const unsigned char **) &cp, 419243885Serwin (long) len + 1) == NULL) 420243885Serwin DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 421243885Serwin if (EC_KEY_check_key(eckey) != 1) 422243885Serwin DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 423243885Serwin 424243885Serwin pkey = EVP_PKEY_new(); 425243885Serwin if (pkey == NULL) 426243885Serwin DST_RET (ISC_R_NOMEMORY); 427243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 428243885Serwin EVP_PKEY_free(pkey); 429243885Serwin DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); 430243885Serwin } 431243885Serwin 432243885Serwin isc_buffer_forward(data, len); 433243885Serwin key->keydata.pkey = pkey; 434243885Serwin ret = ISC_R_SUCCESS; 435243885Serwin 436243885Serwin err: 437243885Serwin if (eckey != NULL) 438243885Serwin EC_KEY_free(eckey); 439243885Serwin return (ret); 440243885Serwin} 441243885Serwin 442243885Serwinstatic isc_result_t 443243885Serwinopensslecdsa_tofile(const dst_key_t *key, const char *directory) { 444243885Serwin isc_result_t ret; 445243885Serwin EVP_PKEY *pkey; 446243885Serwin EC_KEY *eckey = NULL; 447243885Serwin const BIGNUM *privkey; 448243885Serwin dst_private_t priv; 449243885Serwin unsigned char *buf = NULL; 450243885Serwin 451243885Serwin if (key->keydata.pkey == NULL) 452243885Serwin return (DST_R_NULLKEY); 453243885Serwin 454262706Serwin if (key->external) { 455262706Serwin priv.nelements = 0; 456262706Serwin return (dst__privstruct_writefile(key, &priv, directory)); 457262706Serwin } 458262706Serwin 459243885Serwin pkey = key->keydata.pkey; 460243885Serwin eckey = EVP_PKEY_get1_EC_KEY(pkey); 461243885Serwin if (eckey == NULL) 462243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 463243885Serwin privkey = EC_KEY_get0_private_key(eckey); 464243885Serwin if (privkey == NULL) 465243885Serwin DST_RET (ISC_R_FAILURE); 466243885Serwin 467243885Serwin buf = isc_mem_get(key->mctx, BN_num_bytes(privkey)); 468243885Serwin if (buf == NULL) 469243885Serwin DST_RET (ISC_R_NOMEMORY); 470243885Serwin 471243885Serwin priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY; 472243885Serwin priv.elements[0].length = BN_num_bytes(privkey); 473243885Serwin BN_bn2bin(privkey, buf); 474243885Serwin priv.elements[0].data = buf; 475243885Serwin priv.nelements = ECDSA_NTAGS; 476243885Serwin ret = dst__privstruct_writefile(key, &priv, directory); 477243885Serwin 478243885Serwin err: 479243885Serwin if (eckey != NULL) 480243885Serwin EC_KEY_free(eckey); 481243885Serwin if (buf != NULL) 482243885Serwin isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); 483243885Serwin return (ret); 484243885Serwin} 485243885Serwin 486243885Serwinstatic isc_result_t 487243885Serwinecdsa_check(EC_KEY *eckey, dst_key_t *pub) 488243885Serwin{ 489243885Serwin isc_result_t ret = ISC_R_FAILURE; 490243885Serwin EVP_PKEY *pkey; 491243885Serwin EC_KEY *pubeckey = NULL; 492243885Serwin const EC_POINT *pubkey; 493243885Serwin 494243885Serwin if (pub == NULL) 495243885Serwin return (ISC_R_SUCCESS); 496243885Serwin pkey = pub->keydata.pkey; 497243885Serwin if (pkey == NULL) 498243885Serwin return (ISC_R_SUCCESS); 499243885Serwin pubeckey = EVP_PKEY_get1_EC_KEY(pkey); 500243885Serwin if (pubeckey == NULL) 501243885Serwin return (ISC_R_SUCCESS); 502243885Serwin pubkey = EC_KEY_get0_public_key(pubeckey); 503243885Serwin if (pubkey == NULL) 504243885Serwin DST_RET (ISC_R_SUCCESS); 505243885Serwin if (EC_KEY_set_public_key(eckey, pubkey) != 1) 506243885Serwin DST_RET (ISC_R_SUCCESS); 507243885Serwin if (EC_KEY_check_key(eckey) == 1) 508243885Serwin DST_RET (ISC_R_SUCCESS); 509243885Serwin 510243885Serwin err: 511243885Serwin if (pubeckey != NULL) 512243885Serwin EC_KEY_free(pubeckey); 513243885Serwin return (ret); 514243885Serwin} 515243885Serwin 516243885Serwinstatic isc_result_t 517243885Serwinopensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { 518243885Serwin dst_private_t priv; 519243885Serwin isc_result_t ret; 520262706Serwin EVP_PKEY *pkey, *pubpkey; 521262706Serwin EC_KEY *eckey = NULL, *pubeckey = NULL; 522262706Serwin const EC_POINT *pubkey; 523243885Serwin BIGNUM *privkey; 524243885Serwin int group_nid; 525243885Serwin isc_mem_t *mctx = key->mctx; 526243885Serwin 527243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 528243885Serwin key->key_alg == DST_ALG_ECDSA384); 529243885Serwin 530243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 531243885Serwin group_nid = NID_X9_62_prime256v1; 532243885Serwin else 533243885Serwin group_nid = NID_secp384r1; 534243885Serwin 535243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 536243885Serwin if (eckey == NULL) 537243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 538243885Serwin 539243885Serwin /* read private key file */ 540243885Serwin ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); 541243885Serwin if (ret != ISC_R_SUCCESS) 542243885Serwin goto err; 543243885Serwin 544262706Serwin if (key->external) { 545262706Serwin /* 546262706Serwin * Copy the public key to this new key. 547262706Serwin */ 548262706Serwin if (pub == NULL) 549262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 550262706Serwin pubpkey = pub->keydata.pkey; 551262706Serwin pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey); 552262706Serwin if (pubeckey == NULL) 553262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 554262706Serwin pubkey = EC_KEY_get0_public_key(pubeckey); 555262706Serwin if (pubkey == NULL) 556262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 557262706Serwin if (EC_KEY_set_public_key(eckey, pubkey) != 1) 558262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 559262706Serwin if (EC_KEY_check_key(eckey) != 1) 560262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 561262706Serwin } else { 562262706Serwin privkey = BN_bin2bn(priv.elements[0].data, 563262706Serwin priv.elements[0].length, NULL); 564262706Serwin if (privkey == NULL) 565262706Serwin DST_RET(ISC_R_NOMEMORY); 566262706Serwin if (!EC_KEY_set_private_key(eckey, privkey)) 567262706Serwin DST_RET(ISC_R_NOMEMORY); 568262706Serwin if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) 569262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 570262706Serwin dst__privstruct_free(&priv, mctx); 571262706Serwin memset(&priv, 0, sizeof(priv)); 572262706Serwin } 573243885Serwin 574243885Serwin pkey = EVP_PKEY_new(); 575243885Serwin if (pkey == NULL) 576243885Serwin DST_RET (ISC_R_NOMEMORY); 577243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 578243885Serwin EVP_PKEY_free(pkey); 579243885Serwin DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 580243885Serwin } 581243885Serwin key->keydata.pkey = pkey; 582243885Serwin ret = ISC_R_SUCCESS; 583243885Serwin 584243885Serwin err: 585243885Serwin if (eckey != NULL) 586243885Serwin EC_KEY_free(eckey); 587262706Serwin if (pubeckey != NULL) 588262706Serwin EC_KEY_free(pubeckey); 589243885Serwin dst__privstruct_free(&priv, mctx); 590243885Serwin memset(&priv, 0, sizeof(priv)); 591243885Serwin return (ret); 592243885Serwin} 593243885Serwin 594243885Serwinstatic dst_func_t opensslecdsa_functions = { 595243885Serwin opensslecdsa_createctx, 596243885Serwin opensslecdsa_destroyctx, 597243885Serwin opensslecdsa_adddata, 598243885Serwin opensslecdsa_sign, 599243885Serwin opensslecdsa_verify, 600254897Serwin NULL, /*%< verify2 */ 601243885Serwin NULL, /*%< computesecret */ 602243885Serwin opensslecdsa_compare, 603243885Serwin NULL, /*%< paramcompare */ 604243885Serwin opensslecdsa_generate, 605243885Serwin opensslecdsa_isprivate, 606243885Serwin opensslecdsa_destroy, 607243885Serwin opensslecdsa_todns, 608243885Serwin opensslecdsa_fromdns, 609243885Serwin opensslecdsa_tofile, 610243885Serwin opensslecdsa_parse, 611243885Serwin NULL, /*%< cleanup */ 612243885Serwin NULL, /*%< fromlabel */ 613243885Serwin NULL, /*%< dump */ 614243885Serwin NULL, /*%< restore */ 615243885Serwin}; 616243885Serwin 617243885Serwinisc_result_t 618243885Serwindst__opensslecdsa_init(dst_func_t **funcp) { 619243885Serwin REQUIRE(funcp != NULL); 620243885Serwin if (*funcp == NULL) 621243885Serwin *funcp = &opensslecdsa_functions; 622243885Serwin return (ISC_R_SUCCESS); 623243885Serwin} 624243885Serwin 625243885Serwin#else /* HAVE_OPENSSL_ECDSA */ 626243885Serwin 627243885Serwin#include <isc/util.h> 628243885Serwin 629243885SerwinEMPTY_TRANSLATION_UNIT 630243885Serwin 631243885Serwin#endif /* HAVE_OPENSSL_ECDSA */ 632243885Serwin/*! \file */ 633