opensslecdsa_link.c revision 262706
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/* $Id$ */ 18243885Serwin 19243885Serwin#include <config.h> 20243885Serwin 21243885Serwin#ifdef HAVE_OPENSSL_ECDSA 22243885Serwin 23243885Serwin#if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384) 24243885Serwin#error "ECDSA without EVP for SHA2?" 25243885Serwin#endif 26243885Serwin 27243885Serwin#include <isc/entropy.h> 28243885Serwin#include <isc/mem.h> 29243885Serwin#include <isc/sha2.h> 30243885Serwin#include <isc/string.h> 31243885Serwin#include <isc/util.h> 32243885Serwin 33243885Serwin#include <dns/keyvalues.h> 34243885Serwin#include <dst/result.h> 35243885Serwin 36243885Serwin#include "dst_internal.h" 37243885Serwin#include "dst_openssl.h" 38243885Serwin#include "dst_parse.h" 39243885Serwin 40243885Serwin#include <openssl/err.h> 41243885Serwin#include <openssl/objects.h> 42243885Serwin#include <openssl/ecdsa.h> 43243885Serwin#include <openssl/bn.h> 44243885Serwin 45243885Serwin#ifndef NID_X9_62_prime256v1 46243885Serwin#error "P-256 group is not known (NID_X9_62_prime256v1)" 47243885Serwin#endif 48243885Serwin#ifndef NID_secp384r1 49243885Serwin#error "P-384 group is not known (NID_secp384r1)" 50243885Serwin#endif 51243885Serwin 52243885Serwin#define DST_RET(a) {ret = a; goto err;} 53243885Serwin 54243885Serwinstatic isc_result_t opensslecdsa_todns(const dst_key_t *key, 55243885Serwin isc_buffer_t *data); 56243885Serwin 57243885Serwinstatic isc_result_t 58243885Serwinopensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) { 59243885Serwin EVP_MD_CTX *evp_md_ctx; 60243885Serwin const EVP_MD *type = NULL; 61243885Serwin 62243885Serwin UNUSED(key); 63243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 64243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 65243885Serwin 66243885Serwin evp_md_ctx = EVP_MD_CTX_create(); 67243885Serwin if (evp_md_ctx == NULL) 68243885Serwin return (ISC_R_NOMEMORY); 69243885Serwin if (dctx->key->key_alg == DST_ALG_ECDSA256) 70243885Serwin type = EVP_sha256(); 71243885Serwin else 72243885Serwin type = EVP_sha384(); 73243885Serwin 74243885Serwin if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { 75243885Serwin EVP_MD_CTX_destroy(evp_md_ctx); 76254402Serwin return (dst__openssl_toresult3(dctx->category, 77254402Serwin "EVP_DigestInit_ex", 78243885Serwin ISC_R_FAILURE)); 79243885Serwin } 80243885Serwin 81243885Serwin dctx->ctxdata.evp_md_ctx = evp_md_ctx; 82243885Serwin 83243885Serwin return (ISC_R_SUCCESS); 84243885Serwin} 85243885Serwin 86243885Serwinstatic void 87243885Serwinopensslecdsa_destroyctx(dst_context_t *dctx) { 88243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 89243885Serwin 90243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 91243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 92243885Serwin 93243885Serwin if (evp_md_ctx != NULL) { 94243885Serwin EVP_MD_CTX_destroy(evp_md_ctx); 95243885Serwin dctx->ctxdata.evp_md_ctx = NULL; 96243885Serwin } 97243885Serwin} 98243885Serwin 99243885Serwinstatic isc_result_t 100243885Serwinopensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) { 101243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 102243885Serwin 103243885Serwin REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || 104243885Serwin dctx->key->key_alg == DST_ALG_ECDSA384); 105243885Serwin 106243885Serwin if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) 107254402Serwin return (dst__openssl_toresult3(dctx->category, 108254402Serwin "EVP_DigestUpdate", 109243885Serwin ISC_R_FAILURE)); 110243885Serwin 111243885Serwin return (ISC_R_SUCCESS); 112243885Serwin} 113243885Serwin 114243885Serwinstatic int 115243885SerwinBN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) { 116243885Serwin int bytes = size - BN_num_bytes(bn); 117243885Serwin 118243885Serwin while (bytes-- > 0) 119243885Serwin *buf++ = 0; 120243885Serwin BN_bn2bin(bn, buf); 121243885Serwin return (size); 122243885Serwin} 123243885Serwin 124243885Serwinstatic isc_result_t 125243885Serwinopensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { 126243885Serwin isc_result_t ret; 127243885Serwin dst_key_t *key = dctx->key; 128243885Serwin isc_region_t r; 129243885Serwin ECDSA_SIG *ecdsasig; 130243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 131243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 132243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 133243885Serwin unsigned int dgstlen, siglen; 134243885Serwin unsigned char digest[EVP_MAX_MD_SIZE]; 135243885Serwin 136243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 137243885Serwin key->key_alg == DST_ALG_ECDSA384); 138243885Serwin 139243885Serwin if (eckey == NULL) 140243885Serwin return (ISC_R_FAILURE); 141243885Serwin 142243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 143243885Serwin siglen = DNS_SIG_ECDSA256SIZE; 144243885Serwin else 145243885Serwin siglen = DNS_SIG_ECDSA384SIZE; 146243885Serwin 147243885Serwin isc_buffer_availableregion(sig, &r); 148243885Serwin if (r.length < siglen) 149243885Serwin DST_RET(ISC_R_NOSPACE); 150243885Serwin 151243885Serwin if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen)) 152254402Serwin DST_RET(dst__openssl_toresult3(dctx->category, 153254402Serwin "EVP_DigestFinal", 154243885Serwin ISC_R_FAILURE)); 155243885Serwin 156243885Serwin ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey); 157243885Serwin if (ecdsasig == NULL) 158254402Serwin DST_RET(dst__openssl_toresult3(dctx->category, 159254402Serwin "ECDSA_do_sign", 160243885Serwin DST_R_SIGNFAILURE)); 161243885Serwin BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2); 162243885Serwin r.base += siglen / 2; 163243885Serwin BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2); 164243885Serwin r.base += siglen / 2; 165243885Serwin ECDSA_SIG_free(ecdsasig); 166243885Serwin isc_buffer_add(sig, siglen); 167243885Serwin ret = ISC_R_SUCCESS; 168243885Serwin 169243885Serwin err: 170243885Serwin if (eckey != NULL) 171243885Serwin EC_KEY_free(eckey); 172243885Serwin return (ret); 173243885Serwin} 174243885Serwin 175243885Serwinstatic isc_result_t 176243885Serwinopensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { 177243885Serwin isc_result_t ret; 178243885Serwin dst_key_t *key = dctx->key; 179243885Serwin int status; 180243885Serwin unsigned char *cp = sig->base; 181243885Serwin ECDSA_SIG *ecdsasig = NULL; 182243885Serwin EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; 183243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 184243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 185243885Serwin unsigned int dgstlen, siglen; 186243885Serwin unsigned char digest[EVP_MAX_MD_SIZE]; 187243885Serwin 188243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 189243885Serwin key->key_alg == DST_ALG_ECDSA384); 190243885Serwin 191243885Serwin if (eckey == NULL) 192243885Serwin return (ISC_R_FAILURE); 193243885Serwin 194243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 195243885Serwin siglen = DNS_SIG_ECDSA256SIZE; 196243885Serwin else 197243885Serwin siglen = DNS_SIG_ECDSA384SIZE; 198243885Serwin 199243885Serwin if (sig->length != siglen) 200243885Serwin return (DST_R_VERIFYFAILURE); 201243885Serwin 202243885Serwin if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) 203254402Serwin DST_RET (dst__openssl_toresult3(dctx->category, 204254402Serwin "EVP_DigestFinal_ex", 205243885Serwin ISC_R_FAILURE)); 206243885Serwin 207243885Serwin ecdsasig = ECDSA_SIG_new(); 208243885Serwin if (ecdsasig == NULL) 209243885Serwin DST_RET (ISC_R_NOMEMORY); 210254402Serwin if (ecdsasig->r != NULL) 211254402Serwin BN_free(ecdsasig->r); 212243885Serwin ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL); 213243885Serwin cp += siglen / 2; 214254402Serwin if (ecdsasig->s != NULL) 215254402Serwin BN_free(ecdsasig->s); 216243885Serwin ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL); 217243885Serwin /* cp += siglen / 2; */ 218243885Serwin 219243885Serwin status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey); 220243885Serwin switch (status) { 221243885Serwin case 1: 222243885Serwin ret = ISC_R_SUCCESS; 223243885Serwin break; 224243885Serwin case 0: 225243885Serwin ret = dst__openssl_toresult(DST_R_VERIFYFAILURE); 226243885Serwin break; 227243885Serwin default: 228254402Serwin ret = dst__openssl_toresult3(dctx->category, 229254402Serwin "ECDSA_do_verify", 230243885Serwin DST_R_VERIFYFAILURE); 231243885Serwin break; 232243885Serwin } 233243885Serwin 234243885Serwin err: 235243885Serwin if (ecdsasig != NULL) 236243885Serwin ECDSA_SIG_free(ecdsasig); 237243885Serwin if (eckey != NULL) 238243885Serwin EC_KEY_free(eckey); 239243885Serwin return (ret); 240243885Serwin} 241243885Serwin 242243885Serwinstatic isc_boolean_t 243243885Serwinopensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) { 244243885Serwin isc_boolean_t ret; 245243885Serwin int status; 246243885Serwin EVP_PKEY *pkey1 = key1->keydata.pkey; 247243885Serwin EVP_PKEY *pkey2 = key2->keydata.pkey; 248243885Serwin EC_KEY *eckey1 = NULL; 249243885Serwin EC_KEY *eckey2 = NULL; 250243885Serwin const BIGNUM *priv1, *priv2; 251243885Serwin 252243885Serwin if (pkey1 == NULL && pkey2 == NULL) 253243885Serwin return (ISC_TRUE); 254243885Serwin else if (pkey1 == NULL || pkey2 == NULL) 255243885Serwin return (ISC_FALSE); 256243885Serwin 257243885Serwin eckey1 = EVP_PKEY_get1_EC_KEY(pkey1); 258243885Serwin eckey2 = EVP_PKEY_get1_EC_KEY(pkey2); 259243885Serwin if (eckey1 == NULL && eckey2 == NULL) { 260243885Serwin DST_RET (ISC_TRUE); 261243885Serwin } else if (eckey1 == NULL || eckey2 == NULL) 262243885Serwin DST_RET (ISC_FALSE); 263243885Serwin 264243885Serwin status = EVP_PKEY_cmp(pkey1, pkey2); 265243885Serwin if (status != 1) 266243885Serwin DST_RET (ISC_FALSE); 267243885Serwin 268243885Serwin priv1 = EC_KEY_get0_private_key(eckey1); 269243885Serwin priv2 = EC_KEY_get0_private_key(eckey2); 270243885Serwin if (priv1 != NULL || priv2 != NULL) { 271243885Serwin if (priv1 == NULL || priv2 == NULL) 272243885Serwin DST_RET (ISC_FALSE); 273243885Serwin if (BN_cmp(priv1, priv2) != 0) 274243885Serwin DST_RET (ISC_FALSE); 275243885Serwin } 276243885Serwin ret = ISC_TRUE; 277243885Serwin 278243885Serwin err: 279243885Serwin if (eckey1 != NULL) 280243885Serwin EC_KEY_free(eckey1); 281243885Serwin if (eckey2 != NULL) 282243885Serwin EC_KEY_free(eckey2); 283243885Serwin return (ret); 284243885Serwin} 285243885Serwin 286243885Serwinstatic isc_result_t 287243885Serwinopensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { 288243885Serwin isc_result_t ret; 289243885Serwin EVP_PKEY *pkey; 290243885Serwin EC_KEY *eckey = NULL; 291243885Serwin int group_nid; 292243885Serwin 293243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 294243885Serwin key->key_alg == DST_ALG_ECDSA384); 295243885Serwin UNUSED(unused); 296243885Serwin UNUSED(callback); 297243885Serwin 298243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 299243885Serwin group_nid = NID_X9_62_prime256v1; 300243885Serwin else 301243885Serwin group_nid = NID_secp384r1; 302243885Serwin 303243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 304243885Serwin if (eckey == NULL) 305243885Serwin return (dst__openssl_toresult2("EC_KEY_new_by_curve_name", 306243885Serwin DST_R_OPENSSLFAILURE)); 307243885Serwin 308243885Serwin if (EC_KEY_generate_key(eckey) != 1) 309243885Serwin DST_RET (dst__openssl_toresult2("EC_KEY_generate_key", 310243885Serwin DST_R_OPENSSLFAILURE)); 311243885Serwin 312243885Serwin pkey = EVP_PKEY_new(); 313243885Serwin if (pkey == NULL) 314243885Serwin DST_RET (ISC_R_NOMEMORY); 315243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 316243885Serwin EVP_PKEY_free(pkey); 317243885Serwin DST_RET (ISC_R_FAILURE); 318243885Serwin } 319243885Serwin key->keydata.pkey = pkey; 320243885Serwin ret = ISC_R_SUCCESS; 321243885Serwin 322243885Serwin err: 323243885Serwin if (eckey != NULL) 324243885Serwin EC_KEY_free(eckey); 325243885Serwin return (ret); 326243885Serwin} 327243885Serwin 328243885Serwinstatic isc_boolean_t 329243885Serwinopensslecdsa_isprivate(const dst_key_t *key) { 330243885Serwin isc_boolean_t ret; 331243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 332243885Serwin EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); 333243885Serwin 334243885Serwin ret = ISC_TF(eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL); 335243885Serwin if (eckey != NULL) 336243885Serwin EC_KEY_free(eckey); 337243885Serwin return (ret); 338243885Serwin} 339243885Serwin 340243885Serwinstatic void 341243885Serwinopensslecdsa_destroy(dst_key_t *key) { 342243885Serwin EVP_PKEY *pkey = key->keydata.pkey; 343243885Serwin 344243885Serwin EVP_PKEY_free(pkey); 345243885Serwin key->keydata.pkey = NULL; 346243885Serwin} 347243885Serwin 348243885Serwinstatic isc_result_t 349243885Serwinopensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { 350243885Serwin isc_result_t ret; 351243885Serwin EVP_PKEY *pkey; 352243885Serwin EC_KEY *eckey = NULL; 353243885Serwin isc_region_t r; 354243885Serwin int len; 355243885Serwin unsigned char *cp; 356243885Serwin unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 357243885Serwin 358243885Serwin REQUIRE(key->keydata.pkey != NULL); 359243885Serwin 360243885Serwin pkey = key->keydata.pkey; 361243885Serwin eckey = EVP_PKEY_get1_EC_KEY(pkey); 362243885Serwin if (eckey == NULL) 363243885Serwin return (dst__openssl_toresult(ISC_R_FAILURE)); 364243885Serwin len = i2o_ECPublicKey(eckey, NULL); 365243885Serwin /* skip form */ 366243885Serwin len--; 367243885Serwin 368243885Serwin isc_buffer_availableregion(data, &r); 369243885Serwin if (r.length < (unsigned int) len) 370243885Serwin DST_RET (ISC_R_NOSPACE); 371243885Serwin cp = buf; 372243885Serwin if (!i2o_ECPublicKey(eckey, &cp)) 373243885Serwin DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); 374262706Serwin memmove(r.base, buf + 1, len); 375243885Serwin isc_buffer_add(data, len); 376243885Serwin ret = ISC_R_SUCCESS; 377243885Serwin 378243885Serwin err: 379243885Serwin if (eckey != NULL) 380243885Serwin EC_KEY_free(eckey); 381243885Serwin return (ret); 382243885Serwin} 383243885Serwin 384243885Serwinstatic isc_result_t 385243885Serwinopensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { 386243885Serwin isc_result_t ret; 387243885Serwin EVP_PKEY *pkey; 388243885Serwin EC_KEY *eckey = NULL; 389243885Serwin isc_region_t r; 390243885Serwin int group_nid; 391243885Serwin unsigned int len; 392243885Serwin const unsigned char *cp; 393243885Serwin unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; 394243885Serwin 395243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 396243885Serwin key->key_alg == DST_ALG_ECDSA384); 397243885Serwin 398243885Serwin if (key->key_alg == DST_ALG_ECDSA256) { 399243885Serwin len = DNS_KEY_ECDSA256SIZE; 400243885Serwin group_nid = NID_X9_62_prime256v1; 401243885Serwin } else { 402243885Serwin len = DNS_KEY_ECDSA384SIZE; 403243885Serwin group_nid = NID_secp384r1; 404243885Serwin } 405243885Serwin 406243885Serwin isc_buffer_remainingregion(data, &r); 407243885Serwin if (r.length == 0) 408243885Serwin return (ISC_R_SUCCESS); 409243885Serwin if (r.length < len) 410243885Serwin return (DST_R_INVALIDPUBLICKEY); 411243885Serwin 412243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 413243885Serwin if (eckey == NULL) 414243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 415243885Serwin 416243885Serwin buf[0] = POINT_CONVERSION_UNCOMPRESSED; 417262706Serwin memmove(buf + 1, r.base, len); 418243885Serwin cp = buf; 419243885Serwin if (o2i_ECPublicKey(&eckey, 420243885Serwin (const unsigned char **) &cp, 421243885Serwin (long) len + 1) == NULL) 422243885Serwin DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 423243885Serwin if (EC_KEY_check_key(eckey) != 1) 424243885Serwin DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); 425243885Serwin 426243885Serwin pkey = EVP_PKEY_new(); 427243885Serwin if (pkey == NULL) 428243885Serwin DST_RET (ISC_R_NOMEMORY); 429243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 430243885Serwin EVP_PKEY_free(pkey); 431243885Serwin DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); 432243885Serwin } 433243885Serwin 434243885Serwin isc_buffer_forward(data, len); 435243885Serwin key->keydata.pkey = pkey; 436243885Serwin ret = ISC_R_SUCCESS; 437243885Serwin 438243885Serwin err: 439243885Serwin if (eckey != NULL) 440243885Serwin EC_KEY_free(eckey); 441243885Serwin return (ret); 442243885Serwin} 443243885Serwin 444243885Serwinstatic isc_result_t 445243885Serwinopensslecdsa_tofile(const dst_key_t *key, const char *directory) { 446243885Serwin isc_result_t ret; 447243885Serwin EVP_PKEY *pkey; 448243885Serwin EC_KEY *eckey = NULL; 449243885Serwin const BIGNUM *privkey; 450243885Serwin dst_private_t priv; 451243885Serwin unsigned char *buf = NULL; 452243885Serwin 453243885Serwin if (key->keydata.pkey == NULL) 454243885Serwin return (DST_R_NULLKEY); 455243885Serwin 456262706Serwin if (key->external) { 457262706Serwin priv.nelements = 0; 458262706Serwin return (dst__privstruct_writefile(key, &priv, directory)); 459262706Serwin } 460262706Serwin 461243885Serwin pkey = key->keydata.pkey; 462243885Serwin eckey = EVP_PKEY_get1_EC_KEY(pkey); 463243885Serwin if (eckey == NULL) 464243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 465243885Serwin privkey = EC_KEY_get0_private_key(eckey); 466243885Serwin if (privkey == NULL) 467243885Serwin DST_RET (ISC_R_FAILURE); 468243885Serwin 469243885Serwin buf = isc_mem_get(key->mctx, BN_num_bytes(privkey)); 470243885Serwin if (buf == NULL) 471243885Serwin DST_RET (ISC_R_NOMEMORY); 472243885Serwin 473243885Serwin priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY; 474243885Serwin priv.elements[0].length = BN_num_bytes(privkey); 475243885Serwin BN_bn2bin(privkey, buf); 476243885Serwin priv.elements[0].data = buf; 477243885Serwin priv.nelements = ECDSA_NTAGS; 478243885Serwin ret = dst__privstruct_writefile(key, &priv, directory); 479243885Serwin 480243885Serwin err: 481243885Serwin if (eckey != NULL) 482243885Serwin EC_KEY_free(eckey); 483243885Serwin if (buf != NULL) 484243885Serwin isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); 485243885Serwin return (ret); 486243885Serwin} 487243885Serwin 488243885Serwinstatic isc_result_t 489243885Serwinecdsa_check(EC_KEY *eckey, dst_key_t *pub) 490243885Serwin{ 491243885Serwin isc_result_t ret = ISC_R_FAILURE; 492243885Serwin EVP_PKEY *pkey; 493243885Serwin EC_KEY *pubeckey = NULL; 494243885Serwin const EC_POINT *pubkey; 495243885Serwin 496243885Serwin if (pub == NULL) 497243885Serwin return (ISC_R_SUCCESS); 498243885Serwin pkey = pub->keydata.pkey; 499243885Serwin if (pkey == NULL) 500243885Serwin return (ISC_R_SUCCESS); 501243885Serwin pubeckey = EVP_PKEY_get1_EC_KEY(pkey); 502243885Serwin if (pubeckey == NULL) 503243885Serwin return (ISC_R_SUCCESS); 504243885Serwin pubkey = EC_KEY_get0_public_key(pubeckey); 505243885Serwin if (pubkey == NULL) 506243885Serwin DST_RET (ISC_R_SUCCESS); 507243885Serwin if (EC_KEY_set_public_key(eckey, pubkey) != 1) 508243885Serwin DST_RET (ISC_R_SUCCESS); 509243885Serwin if (EC_KEY_check_key(eckey) == 1) 510243885Serwin DST_RET (ISC_R_SUCCESS); 511243885Serwin 512243885Serwin err: 513243885Serwin if (pubeckey != NULL) 514243885Serwin EC_KEY_free(pubeckey); 515243885Serwin return (ret); 516243885Serwin} 517243885Serwin 518243885Serwinstatic isc_result_t 519243885Serwinopensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { 520243885Serwin dst_private_t priv; 521243885Serwin isc_result_t ret; 522262706Serwin EVP_PKEY *pkey, *pubpkey; 523262706Serwin EC_KEY *eckey = NULL, *pubeckey = NULL; 524262706Serwin const EC_POINT *pubkey; 525243885Serwin BIGNUM *privkey; 526243885Serwin int group_nid; 527243885Serwin isc_mem_t *mctx = key->mctx; 528243885Serwin 529243885Serwin REQUIRE(key->key_alg == DST_ALG_ECDSA256 || 530243885Serwin key->key_alg == DST_ALG_ECDSA384); 531243885Serwin 532243885Serwin if (key->key_alg == DST_ALG_ECDSA256) 533243885Serwin group_nid = NID_X9_62_prime256v1; 534243885Serwin else 535243885Serwin group_nid = NID_secp384r1; 536243885Serwin 537243885Serwin eckey = EC_KEY_new_by_curve_name(group_nid); 538243885Serwin if (eckey == NULL) 539243885Serwin return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 540243885Serwin 541243885Serwin /* read private key file */ 542243885Serwin ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); 543243885Serwin if (ret != ISC_R_SUCCESS) 544243885Serwin goto err; 545243885Serwin 546262706Serwin if (key->external) { 547262706Serwin /* 548262706Serwin * Copy the public key to this new key. 549262706Serwin */ 550262706Serwin if (pub == NULL) 551262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 552262706Serwin pubpkey = pub->keydata.pkey; 553262706Serwin pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey); 554262706Serwin if (pubeckey == NULL) 555262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 556262706Serwin pubkey = EC_KEY_get0_public_key(pubeckey); 557262706Serwin if (pubkey == NULL) 558262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 559262706Serwin if (EC_KEY_set_public_key(eckey, pubkey) != 1) 560262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 561262706Serwin if (EC_KEY_check_key(eckey) != 1) 562262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 563262706Serwin } else { 564262706Serwin privkey = BN_bin2bn(priv.elements[0].data, 565262706Serwin priv.elements[0].length, NULL); 566262706Serwin if (privkey == NULL) 567262706Serwin DST_RET(ISC_R_NOMEMORY); 568262706Serwin if (!EC_KEY_set_private_key(eckey, privkey)) 569262706Serwin DST_RET(ISC_R_NOMEMORY); 570262706Serwin if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) 571262706Serwin DST_RET(DST_R_INVALIDPRIVATEKEY); 572262706Serwin dst__privstruct_free(&priv, mctx); 573262706Serwin memset(&priv, 0, sizeof(priv)); 574262706Serwin } 575243885Serwin 576243885Serwin pkey = EVP_PKEY_new(); 577243885Serwin if (pkey == NULL) 578243885Serwin DST_RET (ISC_R_NOMEMORY); 579243885Serwin if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 580243885Serwin EVP_PKEY_free(pkey); 581243885Serwin DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); 582243885Serwin } 583243885Serwin key->keydata.pkey = pkey; 584243885Serwin ret = ISC_R_SUCCESS; 585243885Serwin 586243885Serwin err: 587243885Serwin if (eckey != NULL) 588243885Serwin EC_KEY_free(eckey); 589262706Serwin if (pubeckey != NULL) 590262706Serwin EC_KEY_free(pubeckey); 591243885Serwin dst__privstruct_free(&priv, mctx); 592243885Serwin memset(&priv, 0, sizeof(priv)); 593243885Serwin return (ret); 594243885Serwin} 595243885Serwin 596243885Serwinstatic dst_func_t opensslecdsa_functions = { 597243885Serwin opensslecdsa_createctx, 598243885Serwin opensslecdsa_destroyctx, 599243885Serwin opensslecdsa_adddata, 600243885Serwin opensslecdsa_sign, 601243885Serwin opensslecdsa_verify, 602254897Serwin NULL, /*%< verify2 */ 603243885Serwin NULL, /*%< computesecret */ 604243885Serwin opensslecdsa_compare, 605243885Serwin NULL, /*%< paramcompare */ 606243885Serwin opensslecdsa_generate, 607243885Serwin opensslecdsa_isprivate, 608243885Serwin opensslecdsa_destroy, 609243885Serwin opensslecdsa_todns, 610243885Serwin opensslecdsa_fromdns, 611243885Serwin opensslecdsa_tofile, 612243885Serwin opensslecdsa_parse, 613243885Serwin NULL, /*%< cleanup */ 614243885Serwin NULL, /*%< fromlabel */ 615243885Serwin NULL, /*%< dump */ 616243885Serwin NULL, /*%< restore */ 617243885Serwin}; 618243885Serwin 619243885Serwinisc_result_t 620243885Serwindst__opensslecdsa_init(dst_func_t **funcp) { 621243885Serwin REQUIRE(funcp != NULL); 622243885Serwin if (*funcp == NULL) 623243885Serwin *funcp = &opensslecdsa_functions; 624243885Serwin return (ISC_R_SUCCESS); 625243885Serwin} 626243885Serwin 627243885Serwin#else /* HAVE_OPENSSL_ECDSA */ 628243885Serwin 629243885Serwin#include <isc/util.h> 630243885Serwin 631243885SerwinEMPTY_TRANSLATION_UNIT 632243885Serwin 633243885Serwin#endif /* HAVE_OPENSSL_ECDSA */ 634243885Serwin/*! \file */ 635