1 /*	$NetBSD: opensslecdsa_link.c,v 1.9 2015/09/03 07:33:34 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2012-2014  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <config.h>
20 
21 #if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA)
22 
23 #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384)
24 #error "ECDSA without EVP for SHA2?"
25 #endif
26 
27 #include <isc/entropy.h>
28 #include <isc/mem.h>
29 #include <isc/sha2.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
32 
33 #include <dns/keyvalues.h>
34 #include <dst/result.h>
35 
36 #include "dst_internal.h"
37 #include "dst_openssl.h"
38 #include "dst_parse.h"
39 
40 #include <openssl/err.h>
41 #include <openssl/objects.h>
42 #include <openssl/ecdsa.h>
43 #include <openssl/bn.h>
44 
45 #ifndef NID_X9_62_prime256v1
46 #error "P-256 group is not known (NID_X9_62_prime256v1)"
47 #endif
48 #ifndef NID_secp384r1
49 #error "P-384 group is not known (NID_secp384r1)"
50 #endif
51 
52 #define DST_RET(a) {ret = a; goto err;}
53 
54 static isc_result_t opensslecdsa_todns(const dst_key_t *key,
55 				       isc_buffer_t *data);
56 
57 static isc_result_t
opensslecdsa_createctx(dst_key_t * key,dst_context_t * dctx)58 opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
59 	EVP_MD_CTX *evp_md_ctx;
60 	const EVP_MD *type = NULL;
61 
62 	UNUSED(key);
63 	REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
64 		dctx->key->key_alg == DST_ALG_ECDSA384);
65 
66 	evp_md_ctx = EVP_MD_CTX_create();
67 	if (evp_md_ctx == NULL)
68 		return (ISC_R_NOMEMORY);
69 	if (dctx->key->key_alg == DST_ALG_ECDSA256)
70 		type = EVP_sha256();
71 	else
72 		type = EVP_sha384();
73 
74 	if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
75 		EVP_MD_CTX_destroy(evp_md_ctx);
76 		return (dst__openssl_toresult3(dctx->category,
77 					       "EVP_DigestInit_ex",
78 					       ISC_R_FAILURE));
79 	}
80 
81 	dctx->ctxdata.evp_md_ctx = evp_md_ctx;
82 
83 	return (ISC_R_SUCCESS);
84 }
85 
86 static void
opensslecdsa_destroyctx(dst_context_t * dctx)87 opensslecdsa_destroyctx(dst_context_t *dctx) {
88 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
89 
90 	REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
91 		dctx->key->key_alg == DST_ALG_ECDSA384);
92 
93 	if (evp_md_ctx != NULL) {
94 		EVP_MD_CTX_destroy(evp_md_ctx);
95 		dctx->ctxdata.evp_md_ctx = NULL;
96 	}
97 }
98 
99 static isc_result_t
opensslecdsa_adddata(dst_context_t * dctx,const isc_region_t * data)100 opensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
101 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
102 
103 	REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
104 		dctx->key->key_alg == DST_ALG_ECDSA384);
105 
106 	if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length))
107 		return (dst__openssl_toresult3(dctx->category,
108 					       "EVP_DigestUpdate",
109 					       ISC_R_FAILURE));
110 
111 	return (ISC_R_SUCCESS);
112 }
113 
114 static int
BN_bn2bin_fixed(BIGNUM * bn,unsigned char * buf,int size)115 BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
116 	int bytes = size - BN_num_bytes(bn);
117 
118 	while (bytes-- > 0)
119 		*buf++ = 0;
120 	BN_bn2bin(bn, buf);
121 	return (size);
122 }
123 
124 static isc_result_t
opensslecdsa_sign(dst_context_t * dctx,isc_buffer_t * sig)125 opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
126 	isc_result_t ret;
127 	dst_key_t *key = dctx->key;
128 	isc_region_t r;
129 	ECDSA_SIG *ecdsasig;
130 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
131 	EVP_PKEY *pkey = key->keydata.pkey;
132 	EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
133 	unsigned int dgstlen, siglen;
134 	unsigned char digest[EVP_MAX_MD_SIZE];
135 
136 	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
137 		key->key_alg == DST_ALG_ECDSA384);
138 
139 	if (eckey == NULL)
140 		return (ISC_R_FAILURE);
141 
142 	if (key->key_alg == DST_ALG_ECDSA256)
143 		siglen = DNS_SIG_ECDSA256SIZE;
144 	else
145 		siglen = DNS_SIG_ECDSA384SIZE;
146 
147 	isc_buffer_availableregion(sig, &r);
148 	if (r.length < siglen)
149 		DST_RET(ISC_R_NOSPACE);
150 
151 	if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen))
152 		DST_RET(dst__openssl_toresult3(dctx->category,
153 					       "EVP_DigestFinal",
154 					       ISC_R_FAILURE));
155 
156 	ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey);
157 	if (ecdsasig == NULL)
158 		DST_RET(dst__openssl_toresult3(dctx->category,
159 					       "ECDSA_do_sign",
160 					       DST_R_SIGNFAILURE));
161 	BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2);
162 	isc_region_consume(&r, siglen / 2);
163 	BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2);
164 	isc_region_consume(&r, siglen / 2);
165 	ECDSA_SIG_free(ecdsasig);
166 	isc_buffer_add(sig, siglen);
167 	ret = ISC_R_SUCCESS;
168 
169  err:
170 	if (eckey != NULL)
171 		EC_KEY_free(eckey);
172 	return (ret);
173 }
174 
175 static isc_result_t
opensslecdsa_verify(dst_context_t * dctx,const isc_region_t * sig)176 opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
177 	isc_result_t ret;
178 	dst_key_t *key = dctx->key;
179 	int status;
180 	unsigned char *cp = sig->base;
181 	ECDSA_SIG *ecdsasig = NULL;
182 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
183 	EVP_PKEY *pkey = key->keydata.pkey;
184 	EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
185 	unsigned int dgstlen, siglen;
186 	unsigned char digest[EVP_MAX_MD_SIZE];
187 
188 	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
189 		key->key_alg == DST_ALG_ECDSA384);
190 
191 	if (eckey == NULL)
192 		return (ISC_R_FAILURE);
193 
194 	if (key->key_alg == DST_ALG_ECDSA256)
195 		siglen = DNS_SIG_ECDSA256SIZE;
196 	else
197 		siglen = DNS_SIG_ECDSA384SIZE;
198 
199 	if (sig->length != siglen)
200 		return (DST_R_VERIFYFAILURE);
201 
202 	if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen))
203 		DST_RET (dst__openssl_toresult3(dctx->category,
204 						"EVP_DigestFinal_ex",
205 						ISC_R_FAILURE));
206 
207 	ecdsasig = ECDSA_SIG_new();
208 	if (ecdsasig == NULL)
209 		DST_RET (ISC_R_NOMEMORY);
210 	if (ecdsasig->r != NULL)
211 		BN_free(ecdsasig->r);
212 	ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL);
213 	cp += siglen / 2;
214 	if (ecdsasig->s != NULL)
215 		BN_free(ecdsasig->s);
216 	ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL);
217 	/* cp += siglen / 2; */
218 
219 	status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey);
220 	switch (status) {
221 	case 1:
222 		ret = ISC_R_SUCCESS;
223 		break;
224 	case 0:
225 		ret = dst__openssl_toresult(DST_R_VERIFYFAILURE);
226 		break;
227 	default:
228 		ret = dst__openssl_toresult3(dctx->category,
229 					     "ECDSA_do_verify",
230 					     DST_R_VERIFYFAILURE);
231 		break;
232 	}
233 
234  err:
235 	if (ecdsasig != NULL)
236 		ECDSA_SIG_free(ecdsasig);
237 	if (eckey != NULL)
238 		EC_KEY_free(eckey);
239 	return (ret);
240 }
241 
242 static isc_boolean_t
opensslecdsa_compare(const dst_key_t * key1,const dst_key_t * key2)243 opensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
244 	isc_boolean_t ret;
245 	int status;
246 	EVP_PKEY *pkey1 = key1->keydata.pkey;
247 	EVP_PKEY *pkey2 = key2->keydata.pkey;
248 	EC_KEY *eckey1 = NULL;
249 	EC_KEY *eckey2 = NULL;
250 	const BIGNUM *priv1, *priv2;
251 
252 	if (pkey1 == NULL && pkey2 == NULL)
253 		return (ISC_TRUE);
254 	else if (pkey1 == NULL || pkey2 == NULL)
255 		return (ISC_FALSE);
256 
257 	eckey1 = EVP_PKEY_get1_EC_KEY(pkey1);
258 	eckey2 = EVP_PKEY_get1_EC_KEY(pkey2);
259 	if (eckey1 == NULL && eckey2 == NULL) {
260 		DST_RET (ISC_TRUE);
261 	} else if (eckey1 == NULL || eckey2 == NULL)
262 		DST_RET (ISC_FALSE);
263 
264 	status = EVP_PKEY_cmp(pkey1, pkey2);
265 	if (status != 1)
266 		DST_RET (ISC_FALSE);
267 
268 	priv1 = EC_KEY_get0_private_key(eckey1);
269 	priv2 = EC_KEY_get0_private_key(eckey2);
270 	if (priv1 != NULL || priv2 != NULL) {
271 		if (priv1 == NULL || priv2 == NULL)
272 			DST_RET (ISC_FALSE);
273 		if (BN_cmp(priv1, priv2) != 0)
274 			DST_RET (ISC_FALSE);
275 	}
276 	ret = ISC_TRUE;
277 
278  err:
279 	if (eckey1 != NULL)
280 		EC_KEY_free(eckey1);
281 	if (eckey2 != NULL)
282 		EC_KEY_free(eckey2);
283 	return (ret);
284 }
285 
286 static isc_result_t
opensslecdsa_generate(dst_key_t * key,int unused,void (* callback)(int))287 opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
288 	isc_result_t ret;
289 	EVP_PKEY *pkey;
290 	EC_KEY *eckey = NULL;
291 	int group_nid;
292 
293 	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
294 		key->key_alg == DST_ALG_ECDSA384);
295 	UNUSED(unused);
296 	UNUSED(callback);
297 
298 	if (key->key_alg == DST_ALG_ECDSA256) {
299 		group_nid = NID_X9_62_prime256v1;
300 		key->key_size = DNS_KEY_ECDSA256SIZE * 4;
301 	} else {
302 		group_nid = NID_secp384r1;
303 		key->key_size = DNS_KEY_ECDSA384SIZE * 4;
304 	}
305 
306 	eckey = EC_KEY_new_by_curve_name(group_nid);
307 	if (eckey == NULL)
308 		return (dst__openssl_toresult2("EC_KEY_new_by_curve_name",
309 					       DST_R_OPENSSLFAILURE));
310 
311 	if (EC_KEY_generate_key(eckey) != 1)
312 		DST_RET (dst__openssl_toresult2("EC_KEY_generate_key",
313 						DST_R_OPENSSLFAILURE));
314 
315 	pkey = EVP_PKEY_new();
316 	if (pkey == NULL)
317 		DST_RET (ISC_R_NOMEMORY);
318 	if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
319 		EVP_PKEY_free(pkey);
320 		DST_RET (ISC_R_FAILURE);
321 	}
322 	key->keydata.pkey = pkey;
323 	ret = ISC_R_SUCCESS;
324 
325  err:
326 	if (eckey != NULL)
327 		EC_KEY_free(eckey);
328 	return (ret);
329 }
330 
331 static isc_boolean_t
opensslecdsa_isprivate(const dst_key_t * key)332 opensslecdsa_isprivate(const dst_key_t *key) {
333 	isc_boolean_t ret;
334 	EVP_PKEY *pkey = key->keydata.pkey;
335 	EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
336 
337 	ret = ISC_TF(eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL);
338 	if (eckey != NULL)
339 		EC_KEY_free(eckey);
340 	return (ret);
341 }
342 
343 static void
opensslecdsa_destroy(dst_key_t * key)344 opensslecdsa_destroy(dst_key_t *key) {
345 	EVP_PKEY *pkey = key->keydata.pkey;
346 
347 	EVP_PKEY_free(pkey);
348 	key->keydata.pkey = NULL;
349 }
350 
351 static isc_result_t
opensslecdsa_todns(const dst_key_t * key,isc_buffer_t * data)352 opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
353 	isc_result_t ret;
354 	EVP_PKEY *pkey;
355 	EC_KEY *eckey = NULL;
356 	isc_region_t r;
357 	int len;
358 	unsigned char *cp;
359 	unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
360 
361 	REQUIRE(key->keydata.pkey != NULL);
362 
363 	pkey = key->keydata.pkey;
364 	eckey = EVP_PKEY_get1_EC_KEY(pkey);
365 	if (eckey == NULL)
366 		return (dst__openssl_toresult(ISC_R_FAILURE));
367 	len = i2o_ECPublicKey(eckey, NULL);
368 	/* skip form */
369 	len--;
370 
371 	isc_buffer_availableregion(data, &r);
372 	if (r.length < (unsigned int) len)
373 		DST_RET (ISC_R_NOSPACE);
374 	cp = buf;
375 	if (!i2o_ECPublicKey(eckey, &cp))
376 		DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
377 	memmove(r.base, buf + 1, len);
378 	isc_buffer_add(data, len);
379 	ret = ISC_R_SUCCESS;
380 
381  err:
382 	if (eckey != NULL)
383 		EC_KEY_free(eckey);
384 	return (ret);
385 }
386 
387 static isc_result_t
opensslecdsa_fromdns(dst_key_t * key,isc_buffer_t * data)388 opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
389 	isc_result_t ret;
390 	EVP_PKEY *pkey;
391 	EC_KEY *eckey = NULL;
392 	isc_region_t r;
393 	int group_nid;
394 	unsigned int len;
395 	const unsigned char *cp;
396 	unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
397 
398 	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
399 		key->key_alg == DST_ALG_ECDSA384);
400 
401 	if (key->key_alg == DST_ALG_ECDSA256) {
402 		len = DNS_KEY_ECDSA256SIZE;
403 		group_nid = NID_X9_62_prime256v1;
404 	} else {
405 		len = DNS_KEY_ECDSA384SIZE;
406 		group_nid = NID_secp384r1;
407 	}
408 
409 	isc_buffer_remainingregion(data, &r);
410 	if (r.length == 0)
411 		return (ISC_R_SUCCESS);
412 	if (r.length < len)
413 		return (DST_R_INVALIDPUBLICKEY);
414 
415 	eckey = EC_KEY_new_by_curve_name(group_nid);
416 	if (eckey == NULL)
417 		return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
418 
419 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
420 	memmove(buf + 1, r.base, len);
421 	cp = buf;
422 	if (o2i_ECPublicKey(&eckey,
423 			    (const unsigned char **) &cp,
424 			    (long) len + 1) == NULL)
425 		DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
426 	if (EC_KEY_check_key(eckey) != 1)
427 		DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
428 
429 	pkey = EVP_PKEY_new();
430 	if (pkey == NULL)
431 		DST_RET (ISC_R_NOMEMORY);
432 	if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
433 		EVP_PKEY_free(pkey);
434 		DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
435 	}
436 
437 	isc_buffer_forward(data, len);
438 	key->keydata.pkey = pkey;
439 	key->key_size = len * 4;
440 	ret = ISC_R_SUCCESS;
441 
442  err:
443 	if (eckey != NULL)
444 		EC_KEY_free(eckey);
445 	return (ret);
446 }
447 
448 static isc_result_t
opensslecdsa_tofile(const dst_key_t * key,const char * directory)449 opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
450 	isc_result_t ret;
451 	EVP_PKEY *pkey;
452 	EC_KEY *eckey = NULL;
453 	const BIGNUM *privkey;
454 	dst_private_t priv;
455 	unsigned char *buf = NULL;
456 
457 	if (key->keydata.pkey == NULL)
458 		return (DST_R_NULLKEY);
459 
460 	if (key->external) {
461 		priv.nelements = 0;
462 		return (dst__privstruct_writefile(key, &priv, directory));
463 	}
464 
465 	pkey = key->keydata.pkey;
466 	eckey = EVP_PKEY_get1_EC_KEY(pkey);
467 	if (eckey == NULL)
468 		return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
469 	privkey = EC_KEY_get0_private_key(eckey);
470 	if (privkey == NULL)
471 		DST_RET (ISC_R_FAILURE);
472 
473 	buf = isc_mem_get(key->mctx, BN_num_bytes(privkey));
474 	if (buf == NULL)
475 		DST_RET (ISC_R_NOMEMORY);
476 
477 	priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY;
478 	priv.elements[0].length = BN_num_bytes(privkey);
479 	BN_bn2bin(privkey, buf);
480 	priv.elements[0].data = buf;
481 	priv.nelements = 1;
482 	ret = dst__privstruct_writefile(key, &priv, directory);
483 
484  err:
485 	if (eckey != NULL)
486 		EC_KEY_free(eckey);
487 	if (buf != NULL)
488 		isc_mem_put(key->mctx, buf, BN_num_bytes(privkey));
489 	return (ret);
490 }
491 
492 static isc_result_t
ecdsa_check(EC_KEY * eckey,dst_key_t * pub)493 ecdsa_check(EC_KEY *eckey, dst_key_t *pub)
494 {
495 	isc_result_t ret = ISC_R_FAILURE;
496 	EVP_PKEY *pkey;
497 	EC_KEY *pubeckey = NULL;
498 	const EC_POINT *pubkey;
499 
500 	if (pub == NULL)
501 		return (ISC_R_SUCCESS);
502 	pkey = pub->keydata.pkey;
503 	if (pkey == NULL)
504 		return (ISC_R_SUCCESS);
505 	pubeckey = EVP_PKEY_get1_EC_KEY(pkey);
506 	if (pubeckey == NULL)
507 		return (ISC_R_SUCCESS);
508 	pubkey = EC_KEY_get0_public_key(pubeckey);
509 	if (pubkey == NULL)
510 		DST_RET (ISC_R_SUCCESS);
511 	if (EC_KEY_set_public_key(eckey, pubkey) != 1)
512 		DST_RET (ISC_R_SUCCESS);
513 	if (EC_KEY_check_key(eckey) == 1)
514 		DST_RET (ISC_R_SUCCESS);
515 
516  err:
517 	if (pubeckey != NULL)
518 		EC_KEY_free(pubeckey);
519 	return (ret);
520 }
521 
522 static isc_result_t
opensslecdsa_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)523 opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
524 	dst_private_t priv;
525 	isc_result_t ret;
526 	EVP_PKEY *pkey;
527 	EC_KEY *eckey = NULL;
528 	BIGNUM *privkey = NULL;
529 	int group_nid;
530 	isc_mem_t *mctx = key->mctx;
531 
532 	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
533 		key->key_alg == DST_ALG_ECDSA384);
534 
535 	/* read private key file */
536 	ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
537 	if (ret != ISC_R_SUCCESS)
538 		goto err;
539 
540 	if (key->external) {
541 		if (priv.nelements != 0)
542 			DST_RET(DST_R_INVALIDPRIVATEKEY);
543 		if (pub == NULL)
544 			DST_RET(DST_R_INVALIDPRIVATEKEY);
545 		key->keydata.pkey = pub->keydata.pkey;
546 		pub->keydata.pkey = NULL;
547 		dst__privstruct_free(&priv, mctx);
548 		memset(&priv, 0, sizeof(priv));
549 		return (ISC_R_SUCCESS);
550 	}
551 
552 	if (key->key_alg == DST_ALG_ECDSA256)
553 		group_nid = NID_X9_62_prime256v1;
554 	else
555 		group_nid = NID_secp384r1;
556 
557 	eckey = EC_KEY_new_by_curve_name(group_nid);
558 	if (eckey == NULL)
559 		return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
560 
561 	privkey = BN_bin2bn(priv.elements[0].data,
562 			    priv.elements[0].length, NULL);
563 	if (privkey == NULL)
564 		DST_RET(ISC_R_NOMEMORY);
565 	if (!EC_KEY_set_private_key(eckey, privkey))
566 		DST_RET(ISC_R_NOMEMORY);
567 	if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
568 		DST_RET(DST_R_INVALIDPRIVATEKEY);
569 
570 	pkey = EVP_PKEY_new();
571 	if (pkey == NULL)
572 		DST_RET (ISC_R_NOMEMORY);
573 	if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
574 		EVP_PKEY_free(pkey);
575 		DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
576 	}
577 	key->keydata.pkey = pkey;
578 	if (key->key_alg == DST_ALG_ECDSA256)
579 		key->key_size = DNS_KEY_ECDSA256SIZE * 4;
580 	else
581 		key->key_size = DNS_KEY_ECDSA384SIZE * 4;
582 	ret = ISC_R_SUCCESS;
583 
584  err:
585 	if (privkey != NULL)
586 		BN_clear_free(privkey);
587 	if (eckey != NULL)
588 		EC_KEY_free(eckey);
589 	dst__privstruct_free(&priv, mctx);
590 	memset(&priv, 0, sizeof(priv));
591 	return (ret);
592 }
593 
594 static dst_func_t opensslecdsa_functions = {
595 	opensslecdsa_createctx,
596 	NULL, /*%< createctx2 */
597 	opensslecdsa_destroyctx,
598 	opensslecdsa_adddata,
599 	opensslecdsa_sign,
600 	opensslecdsa_verify,
601 	NULL, /*%< verify2 */
602 	NULL, /*%< computesecret */
603 	opensslecdsa_compare,
604 	NULL, /*%< paramcompare */
605 	opensslecdsa_generate,
606 	opensslecdsa_isprivate,
607 	opensslecdsa_destroy,
608 	opensslecdsa_todns,
609 	opensslecdsa_fromdns,
610 	opensslecdsa_tofile,
611 	opensslecdsa_parse,
612 	NULL, /*%< cleanup */
613 	NULL, /*%< fromlabel */
614 	NULL, /*%< dump */
615 	NULL, /*%< restore */
616 };
617 
618 isc_result_t
dst__opensslecdsa_init(dst_func_t ** funcp)619 dst__opensslecdsa_init(dst_func_t **funcp) {
620 	REQUIRE(funcp != NULL);
621 	if (*funcp == NULL)
622 		*funcp = &opensslecdsa_functions;
623 	return (ISC_R_SUCCESS);
624 }
625 
626 #else /* HAVE_OPENSSL_ECDSA */
627 
628 #include <isc/util.h>
629 
630 EMPTY_TRANSLATION_UNIT
631 
632 #endif /* HAVE_OPENSSL_ECDSA */
633 /*! \file */
634