1 /* $NetBSD: opensslecdsa_link.c,v 1.9 2015/09/03 07:33:34 christos Exp $ */
4 * Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
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.
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.
21 #if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA)
23 #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384)
24 #error "ECDSA without EVP for SHA2?"
27 #include <isc/entropy.h>
30 #include <isc/string.h>
33 #include <dns/keyvalues.h>
34 #include <dst/result.h>
36 #include "dst_internal.h"
37 #include "dst_openssl.h"
38 #include "dst_parse.h"
40 #include <openssl/err.h>
41 #include <openssl/objects.h>
42 #include <openssl/ecdsa.h>
43 #include <openssl/bn.h>
45 #ifndef NID_X9_62_prime256v1
46 #error "P-256 group is not known (NID_X9_62_prime256v1)"
49 #error "P-384 group is not known (NID_secp384r1)"
52 #define DST_RET(a) {ret = a; goto err;}
54 static isc_result_t
opensslecdsa_todns(const dst_key_t
*key
,
58 opensslecdsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
59 EVP_MD_CTX
*evp_md_ctx
;
60 const EVP_MD
*type
= NULL
;
63 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
64 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
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
)
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
,
81 dctx
->ctxdata
.evp_md_ctx
= evp_md_ctx
;
83 return (ISC_R_SUCCESS
);
87 opensslecdsa_destroyctx(dst_context_t
*dctx
) {
88 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
90 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
91 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
93 if (evp_md_ctx
!= NULL
) {
94 EVP_MD_CTX_destroy(evp_md_ctx
);
95 dctx
->ctxdata
.evp_md_ctx
= NULL
;
100 opensslecdsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
101 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
103 REQUIRE(dctx
->key
->key_alg
== DST_ALG_ECDSA256
||
104 dctx
->key
->key_alg
== DST_ALG_ECDSA384
);
106 if (!EVP_DigestUpdate(evp_md_ctx
, data
->base
, data
->length
))
107 return (dst__openssl_toresult3(dctx
->category
,
111 return (ISC_R_SUCCESS
);
115 BN_bn2bin_fixed(BIGNUM
*bn
, unsigned char *buf
, int size
) {
116 int bytes
= size
- BN_num_bytes(bn
);
125 opensslecdsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
127 dst_key_t
*key
= dctx
->key
;
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
];
136 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
137 key
->key_alg
== DST_ALG_ECDSA384
);
140 return (ISC_R_FAILURE
);
142 if (key
->key_alg
== DST_ALG_ECDSA256
)
143 siglen
= DNS_SIG_ECDSA256SIZE
;
145 siglen
= DNS_SIG_ECDSA384SIZE
;
147 isc_buffer_availableregion(sig
, &r
);
148 if (r
.length
< siglen
)
149 DST_RET(ISC_R_NOSPACE
);
151 if (!EVP_DigestFinal(evp_md_ctx
, digest
, &dgstlen
))
152 DST_RET(dst__openssl_toresult3(dctx
->category
,
156 ecdsasig
= ECDSA_do_sign(digest
, dgstlen
, eckey
);
157 if (ecdsasig
== NULL
)
158 DST_RET(dst__openssl_toresult3(dctx
->category
,
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
);
176 opensslecdsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
178 dst_key_t
*key
= dctx
->key
;
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
];
188 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
189 key
->key_alg
== DST_ALG_ECDSA384
);
192 return (ISC_R_FAILURE
);
194 if (key
->key_alg
== DST_ALG_ECDSA256
)
195 siglen
= DNS_SIG_ECDSA256SIZE
;
197 siglen
= DNS_SIG_ECDSA384SIZE
;
199 if (sig
->length
!= siglen
)
200 return (DST_R_VERIFYFAILURE
);
202 if (!EVP_DigestFinal_ex(evp_md_ctx
, digest
, &dgstlen
))
203 DST_RET (dst__openssl_toresult3(dctx
->category
,
204 "EVP_DigestFinal_ex",
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
);
214 if (ecdsasig
->s
!= NULL
)
215 BN_free(ecdsasig
->s
);
216 ecdsasig
->s
= BN_bin2bn(cp
, siglen
/ 2, NULL
);
217 /* cp += siglen / 2; */
219 status
= ECDSA_do_verify(digest
, dgstlen
, ecdsasig
, eckey
);
225 ret
= dst__openssl_toresult(DST_R_VERIFYFAILURE
);
228 ret
= dst__openssl_toresult3(dctx
->category
,
230 DST_R_VERIFYFAILURE
);
235 if (ecdsasig
!= NULL
)
236 ECDSA_SIG_free(ecdsasig
);
243 opensslecdsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
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
;
252 if (pkey1
== NULL
&& pkey2
== NULL
)
254 else if (pkey1
== NULL
|| pkey2
== NULL
)
257 eckey1
= EVP_PKEY_get1_EC_KEY(pkey1
);
258 eckey2
= EVP_PKEY_get1_EC_KEY(pkey2
);
259 if (eckey1
== NULL
&& eckey2
== NULL
) {
261 } else if (eckey1
== NULL
|| eckey2
== NULL
)
264 status
= EVP_PKEY_cmp(pkey1
, pkey2
);
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
)
273 if (BN_cmp(priv1
, priv2
) != 0)
287 opensslecdsa_generate(dst_key_t
*key
, int unused
, void (*callback
)(int)) {
290 EC_KEY
*eckey
= NULL
;
293 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
294 key
->key_alg
== DST_ALG_ECDSA384
);
298 if (key
->key_alg
== DST_ALG_ECDSA256
) {
299 group_nid
= NID_X9_62_prime256v1
;
300 key
->key_size
= DNS_KEY_ECDSA256SIZE
* 4;
302 group_nid
= NID_secp384r1
;
303 key
->key_size
= DNS_KEY_ECDSA384SIZE
* 4;
306 eckey
= EC_KEY_new_by_curve_name(group_nid
);
308 return (dst__openssl_toresult2("EC_KEY_new_by_curve_name",
309 DST_R_OPENSSLFAILURE
));
311 if (EC_KEY_generate_key(eckey
) != 1)
312 DST_RET (dst__openssl_toresult2("EC_KEY_generate_key",
313 DST_R_OPENSSLFAILURE
));
315 pkey
= EVP_PKEY_new();
317 DST_RET (ISC_R_NOMEMORY
);
318 if (!EVP_PKEY_set1_EC_KEY(pkey
, eckey
)) {
320 DST_RET (ISC_R_FAILURE
);
322 key
->keydata
.pkey
= pkey
;
332 opensslecdsa_isprivate(const dst_key_t
*key
) {
334 EVP_PKEY
*pkey
= key
->keydata
.pkey
;
335 EC_KEY
*eckey
= EVP_PKEY_get1_EC_KEY(pkey
);
337 ret
= ISC_TF(eckey
!= NULL
&& EC_KEY_get0_private_key(eckey
) != NULL
);
344 opensslecdsa_destroy(dst_key_t
*key
) {
345 EVP_PKEY
*pkey
= key
->keydata
.pkey
;
348 key
->keydata
.pkey
= NULL
;
352 opensslecdsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
355 EC_KEY
*eckey
= NULL
;
359 unsigned char buf
[DNS_KEY_ECDSA384SIZE
+ 1];
361 REQUIRE(key
->keydata
.pkey
!= NULL
);
363 pkey
= key
->keydata
.pkey
;
364 eckey
= EVP_PKEY_get1_EC_KEY(pkey
);
366 return (dst__openssl_toresult(ISC_R_FAILURE
));
367 len
= i2o_ECPublicKey(eckey
, NULL
);
371 isc_buffer_availableregion(data
, &r
);
372 if (r
.length
< (unsigned int) len
)
373 DST_RET (ISC_R_NOSPACE
);
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
);
388 opensslecdsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
391 EC_KEY
*eckey
= NULL
;
395 const unsigned char *cp
;
396 unsigned char buf
[DNS_KEY_ECDSA384SIZE
+ 1];
398 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
399 key
->key_alg
== DST_ALG_ECDSA384
);
401 if (key
->key_alg
== DST_ALG_ECDSA256
) {
402 len
= DNS_KEY_ECDSA256SIZE
;
403 group_nid
= NID_X9_62_prime256v1
;
405 len
= DNS_KEY_ECDSA384SIZE
;
406 group_nid
= NID_secp384r1
;
409 isc_buffer_remainingregion(data
, &r
);
411 return (ISC_R_SUCCESS
);
413 return (DST_R_INVALIDPUBLICKEY
);
415 eckey
= EC_KEY_new_by_curve_name(group_nid
);
417 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
419 buf
[0] = POINT_CONVERSION_UNCOMPRESSED
;
420 memmove(buf
+ 1, r
.base
, len
);
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
));
429 pkey
= EVP_PKEY_new();
431 DST_RET (ISC_R_NOMEMORY
);
432 if (!EVP_PKEY_set1_EC_KEY(pkey
, eckey
)) {
434 DST_RET (dst__openssl_toresult(ISC_R_FAILURE
));
437 isc_buffer_forward(data
, len
);
438 key
->keydata
.pkey
= pkey
;
439 key
->key_size
= len
* 4;
449 opensslecdsa_tofile(const dst_key_t
*key
, const char *directory
) {
452 EC_KEY
*eckey
= NULL
;
453 const BIGNUM
*privkey
;
455 unsigned char *buf
= NULL
;
457 if (key
->keydata
.pkey
== NULL
)
458 return (DST_R_NULLKEY
);
462 return (dst__privstruct_writefile(key
, &priv
, directory
));
465 pkey
= key
->keydata
.pkey
;
466 eckey
= EVP_PKEY_get1_EC_KEY(pkey
);
468 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
469 privkey
= EC_KEY_get0_private_key(eckey
);
471 DST_RET (ISC_R_FAILURE
);
473 buf
= isc_mem_get(key
->mctx
, BN_num_bytes(privkey
));
475 DST_RET (ISC_R_NOMEMORY
);
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
;
482 ret
= dst__privstruct_writefile(key
, &priv
, directory
);
488 isc_mem_put(key
->mctx
, buf
, BN_num_bytes(privkey
));
493 ecdsa_check(EC_KEY
*eckey
, dst_key_t
*pub
)
495 isc_result_t ret
= ISC_R_FAILURE
;
497 EC_KEY
*pubeckey
= NULL
;
498 const EC_POINT
*pubkey
;
501 return (ISC_R_SUCCESS
);
502 pkey
= pub
->keydata
.pkey
;
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
);
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
);
517 if (pubeckey
!= NULL
)
518 EC_KEY_free(pubeckey
);
523 opensslecdsa_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
527 EC_KEY
*eckey
= NULL
;
528 BIGNUM
*privkey
= NULL
;
530 isc_mem_t
*mctx
= key
->mctx
;
532 REQUIRE(key
->key_alg
== DST_ALG_ECDSA256
||
533 key
->key_alg
== DST_ALG_ECDSA384
);
535 /* read private key file */
536 ret
= dst__privstruct_parse(key
, DST_ALG_ECDSA256
, lexer
, mctx
, &priv
);
537 if (ret
!= ISC_R_SUCCESS
)
541 if (priv
.nelements
!= 0)
542 DST_RET(DST_R_INVALIDPRIVATEKEY
);
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
);
552 if (key
->key_alg
== DST_ALG_ECDSA256
)
553 group_nid
= NID_X9_62_prime256v1
;
555 group_nid
= NID_secp384r1
;
557 eckey
= EC_KEY_new_by_curve_name(group_nid
);
559 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
561 privkey
= BN_bin2bn(priv
.elements
[0].data
,
562 priv
.elements
[0].length
, 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
);
570 pkey
= EVP_PKEY_new();
572 DST_RET (ISC_R_NOMEMORY
);
573 if (!EVP_PKEY_set1_EC_KEY(pkey
, eckey
)) {
575 DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
577 key
->keydata
.pkey
= pkey
;
578 if (key
->key_alg
== DST_ALG_ECDSA256
)
579 key
->key_size
= DNS_KEY_ECDSA256SIZE
* 4;
581 key
->key_size
= DNS_KEY_ECDSA384SIZE
* 4;
586 BN_clear_free(privkey
);
589 dst__privstruct_free(&priv
, mctx
);
590 memset(&priv
, 0, sizeof(priv
));
594 static dst_func_t opensslecdsa_functions
= {
595 opensslecdsa_createctx
,
596 NULL
, /*%< createctx2 */
597 opensslecdsa_destroyctx
,
598 opensslecdsa_adddata
,
601 NULL
, /*%< verify2 */
602 NULL
, /*%< computesecret */
603 opensslecdsa_compare
,
604 NULL
, /*%< paramcompare */
605 opensslecdsa_generate
,
606 opensslecdsa_isprivate
,
607 opensslecdsa_destroy
,
609 opensslecdsa_fromdns
,
612 NULL
, /*%< cleanup */
613 NULL
, /*%< fromlabel */
615 NULL
, /*%< restore */
619 dst__opensslecdsa_init(dst_func_t
**funcp
) {
620 REQUIRE(funcp
!= NULL
);
622 *funcp
= &opensslecdsa_functions
;
623 return (ISC_R_SUCCESS
);
626 #else /* HAVE_OPENSSL_ECDSA */
628 #include <isc/util.h>
630 EMPTY_TRANSLATION_UNIT
632 #endif /* HAVE_OPENSSL_ECDSA */