- implement draft-ietf-dnsext-ecdsa-04; which is in IETF LC; This

implementation is experimental at this time and not recommended
  for use on the public internet (the protocol numbers have not
  been assigned).  Needs recent ldns with --enable-ecdsa.
- fix memory leak in errorcase for DSA signatures.


git-svn-id: file:///svn/unbound/trunk@2606 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2012-02-08 13:22:44 +00:00
parent 8c2f658cd1
commit 924789d877
10 changed files with 353 additions and 6 deletions

View File

@ -51,6 +51,14 @@
/* Define to 1 if you have the `daemon' function. */ /* Define to 1 if you have the `daemon' function. */
#undef HAVE_DAEMON #undef HAVE_DAEMON
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
don't. */
#undef HAVE_DECL_NID_SECP384R1
/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
if you don't. */
#undef HAVE_DECL_NID_X9_62_PRIME256V1
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 /* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
if you don't. */ if you don't. */
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE #undef HAVE_DECL_SK_SSL_COMP_POP_FREE
@ -479,6 +487,9 @@
/* define this to enable debug checks. */ /* define this to enable debug checks. */
#undef UNBOUND_DEBUG #undef UNBOUND_DEBUG
/* Define this to enable ECDSA support. */
#undef USE_ECDSA
/* Define this to enable GOST support. */ /* Define this to enable GOST support. */
#undef USE_GOST #undef USE_GOST

101
configure vendored
View File

@ -791,6 +791,7 @@ with_pythonmodule
with_ssl with_ssl
enable_sha2 enable_sha2
enable_gost enable_gost
enable_ecdsa
with_libevent with_libevent
with_libexpat with_libexpat
enable_static_exe enable_static_exe
@ -1445,6 +1446,7 @@ Optional Features:
purposes purposes
--disable-sha2 Disable SHA256 and SHA512 RRSIG support --disable-sha2 Disable SHA256 and SHA512 RRSIG support
--disable-gost Disable GOST support --disable-gost Disable GOST support
--enable-ecdsa Enable ECDSA support, experimental
--enable-static-exe enable to compile executables statically against --enable-static-exe enable to compile executables statically against
event, ldns libs, for debug purposes event, ldns libs, for debug purposes
--enable-lock-checks enable to check lock and unlock calls, for debug --enable-lock-checks enable to check lock and unlock calls, for debug
@ -16553,6 +16555,89 @@ $as_echo "#define USE_GOST 1" >>confdefs.h
;; ;;
esac esac
# Check whether --enable-ecdsa was given.
if test "${enable_ecdsa+set}" = set; then :
enableval=$enable_ecdsa;
fi
use_ecdsa="no"
case "$enable_ecdsa" in
yes)
ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign"
if test "x$ac_cv_func_ECDSA_sign" = xyes; then :
else
as_fn_error $? "OpenSSL does not support ECDSA" "$LINENO" 5
fi
ac_fn_c_check_func "$LINENO" "SHA384_Init" "ac_cv_func_SHA384_Init"
if test "x$ac_cv_func_SHA384_Init" = xyes; then :
else
as_fn_error $? "OpenSSL does not support SHA384" "$LINENO" 5
fi
ac_fn_c_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default
#include <openssl/evp.h>
"
if test "x$ac_cv_have_decl_NID_X9_62_prime256v1" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_NID_X9_62_PRIME256V1 $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :
else
as_fn_error $? "OpenSSL does not support the ECDSA curves" "$LINENO" 5
fi
ac_fn_c_check_decl "$LINENO" "NID_secp384r1" "ac_cv_have_decl_NID_secp384r1" "$ac_includes_default
#include <openssl/evp.h>
"
if test "x$ac_cv_have_decl_NID_secp384r1" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_NID_SECP384R1 $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :
else
as_fn_error $? "OpenSSL does not support the ECDSA curves" "$LINENO" 5
fi
# we now know we have ECDSA and the required curves.
cat >>confdefs.h <<_ACEOF
#define USE_ECDSA 1
_ACEOF
use_ecdsa="yes"
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
*****************************************************************
*** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
*** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
*****************************************************************" >&5
$as_echo "$as_me: WARNING:
*****************************************************************
*** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
*** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
*****************************************************************" >&2;}
;;
no)
;;
*)
;;
esac
# check for libevent # check for libevent
# Check whether --with-libevent was given. # Check whether --with-libevent was given.
@ -17701,6 +17786,19 @@ done
else else
ac_cv_func_ldns_key_EVP_load_gost_id="yes" ac_cv_func_ldns_key_EVP_load_gost_id="yes"
fi fi
if test x$use_ecdsa = xyes; then
ac_fn_c_check_decl "$LINENO" "LDNS_ECDSAP384SHA384" "ac_cv_have_decl_LDNS_ECDSAP384SHA384" "
$ac_includes_default
#include <ldns/ldns.h>
"
if test "x$ac_cv_have_decl_LDNS_ECDSAP384SHA384" = xyes; then :
fi
else
ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes"
fi
for ac_header in ldns/ldns.h for ac_header in ldns/ldns.h
do : do :
ac_fn_c_check_header_compile "$LINENO" "ldns/ldns.h" "ac_cv_header_ldns_ldns_h" "$ac_includes_default ac_fn_c_check_header_compile "$LINENO" "ldns/ldns.h" "ac_cv_header_ldns_ldns_h" "$ac_includes_default
@ -17743,7 +17841,8 @@ if test $ac_cv_func_ldns_buffer_copy = yes \
-a $ac_cv_func_ldns_get_random = yes \ -a $ac_cv_func_ldns_get_random = yes \
-a $ac_cv_header_ldns_ldns_h = yes \ -a $ac_cv_header_ldns_ldns_h = yes \
-a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \ -a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes; then -a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \
-a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then
: :
else else
as_fn_error $? "ldns library is not recent, update the ldns library, install it into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Package libldns or download source http://www.nlnetlabs.nl/projects/ldns" "$LINENO" 5 as_fn_error $? "ldns library is not recent, update the ldns library, install it into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Package libldns or download source http://www.nlnetlabs.nl/projects/ldns" "$LINENO" 5

View File

@ -658,6 +658,30 @@ case "$enable_gost" in
;; ;;
esac esac
AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--enable-ecdsa], [Enable ECDSA support, experimental]))
use_ecdsa="no"
case "$enable_ecdsa" in
yes)
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA])])
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384])])
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves])], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h>
])
# we now know we have ECDSA and the required curves.
AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.])
use_ecdsa="yes"
AC_WARN([
*****************************************************************
*** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME ***
*** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET ***
*****************************************************************])
;;
no)
;;
*)
;;
esac
# check for libevent # check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname], AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]), [use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]),
@ -942,6 +966,14 @@ if test x$use_gost = xyes; then
else else
ac_cv_func_ldns_key_EVP_load_gost_id="yes" ac_cv_func_ldns_key_EVP_load_gost_id="yes"
fi fi
if test x$use_ecdsa = xyes; then
AC_CHECK_DECL([LDNS_ECDSAP384SHA384], [], [], [
AC_INCLUDES_DEFAULT
#include <ldns/ldns.h>
])
else
ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes"
fi
AC_CHECK_HEADERS([ldns/ldns.h],,[ AC_CHECK_HEADERS([ldns/ldns.h],,[
AC_MSG_ERROR([No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns]) AC_MSG_ERROR([No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns])
], [AC_INCLUDES_DEFAULT ], [AC_INCLUDES_DEFAULT
@ -970,7 +1002,8 @@ if test $ac_cv_func_ldns_buffer_copy = yes \
-a $ac_cv_func_ldns_get_random = yes \ -a $ac_cv_func_ldns_get_random = yes \
-a $ac_cv_header_ldns_ldns_h = yes \ -a $ac_cv_header_ldns_ldns_h = yes \
-a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \ -a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \
-a $ac_cv_func_ldns_key_EVP_load_gost_id = yes; then -a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \
-a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then
dnl ldns was found dnl ldns was found
: :
else else

View File

@ -1,3 +1,10 @@
8 February 2012: Wouter
- implement draft-ietf-dnsext-ecdsa-04; which is in IETF LC; This
implementation is experimental at this time and not recommended
for use on the public internet (the protocol numbers have not
been assigned). Needs recent ldns with --enable-ecdsa.
- fix memory leak in errorcase for DSA signatures.
3 February 2012: Wouter 3 February 2012: Wouter
- fix for windows, rename() is not posix compliant on windows. - fix for windows, rename() is not posix compliant on windows.

View File

@ -70,6 +70,7 @@ testbound_usage()
printf("-p file playback text file\n"); printf("-p file playback text file\n");
printf("-2 detect SHA256 support (exit code 0 or 1)\n"); printf("-2 detect SHA256 support (exit code 0 or 1)\n");
printf("-g detect GOST support (exit code 0 or 1)\n"); printf("-g detect GOST support (exit code 0 or 1)\n");
printf("-e detect ECDSA support (exit code 0 or 1)\n");
printf("-s testbound self-test - unit test of testbound parts.\n"); printf("-s testbound self-test - unit test of testbound parts.\n");
printf("-o str unbound commandline options separated by spaces.\n"); printf("-o str unbound commandline options separated by spaces.\n");
printf("Version %s\n", PACKAGE_VERSION); printf("Version %s\n", PACKAGE_VERSION);
@ -272,7 +273,7 @@ main(int argc, char* argv[])
pass_argc = 1; pass_argc = 1;
pass_argv[0] = "unbound"; pass_argv[0] = "unbound";
add_opts("-d", &pass_argc, pass_argv); add_opts("-d", &pass_argc, pass_argv);
while( (c=getopt(argc, argv, "2gho:p:s")) != -1) { while( (c=getopt(argc, argv, "2egho:p:s")) != -1) {
switch(c) { switch(c) {
case 's': case 's':
free(pass_argv[1]); free(pass_argv[1]);
@ -286,6 +287,15 @@ main(int argc, char* argv[])
#else #else
printf("SHA256 not supported\n"); printf("SHA256 not supported\n");
exit(1); exit(1);
#endif
break;
case 'e':
#if defined(USE_ECDSA)
printf("ECDSA supported\n");
exit(0);
#else
printf("ECDSA not supported\n");
exit(1);
#endif #endif
break; break;
case 'g': case 'g':

View File

@ -519,6 +519,11 @@ verify_test(void)
if(ldns_key_EVP_load_gost_id()) if(ldns_key_EVP_load_gost_id())
verifytest_file("testdata/test_sigs.gost", "20090807060504"); verifytest_file("testdata/test_sigs.gost", "20090807060504");
else printf("Warning: skipped GOST, openssl does not provide gost.\n"); else printf("Warning: skipped GOST, openssl does not provide gost.\n");
#endif
#ifdef USE_ECDSA
verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
dstest_file("testdata/test_ds.sha384");
#endif #endif
dstest_file("testdata/test_ds.sha1"); dstest_file("testdata/test_ds.sha1");
nsectest(); nsectest();

45
testdata/test_ds.sha384 vendored Normal file
View File

@ -0,0 +1,45 @@
;
; DS match test file.
; test matching of DS hash against DNSKEYs.
;
; enter ENTRYs with a DS and a DNSKEY.
; These are matched against another.
; If the query name starts with 'yes' then it must match.
; If the query name starts with 'no' then it must not match.
; These are SHA256 and SHA384 tests from the draft-ietf-dnsext-ecdsa-04
ENTRY_BEGIN
SECTION QUESTION
yes. IN A
SECTION ANSWER
example.net. 3600 IN DS 55648 13 2 ( b4c8c1fe2e7477127b27115656ad6256f424625bf5c1 e2770ce6d6e37df61d17 )
example.net. 3600 IN DNSKEY 257 3 13 ( GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )
ENTRY_END
ENTRY_BEGIN
SECTION QUESTION
yes. IN A
SECTION ANSWER
example.net. 3600 IN DS 10771 14 4 ( 72d7b62976ce06438e9c0bf319013cf801f09ecc84b8 d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94 6df983d6 )
example.net. 3600 IN DNSKEY 257 3 14 ( xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )
ENTRY_END
; same entry as above, but corrupted by a change in the DS, MUST fail
ENTRY_BEGIN
SECTION QUESTION
no. IN A
SECTION ANSWER
example.net. 3600 IN DS 55648 13 2 ( b4c8c1fe2e7477126b27115656ad6256f424625bf5c1 e2770ce6d6e37df61d17 )
example.net. 3600 IN DNSKEY 257 3 13 ( GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )
ENTRY_END
; same entry as above, but corrupted by a change in the DS, MUST fail
ENTRY_BEGIN
SECTION QUESTION
no. IN A
SECTION ANSWER
example.net. 3600 IN DS 10771 14 4 ( 72d7b62976ce06438e9c0cf319013cf801f09ecc84b8 d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94 6df983d6 )
example.net. 3600 IN DNSKEY 257 3 14 ( xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )
ENTRY_END

23
testdata/test_sigs.ecdsa_p256 vendored Normal file
View File

@ -0,0 +1,23 @@
; Signature test file
; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
; later entries are verified with it.
; Test ECDSA P256 signatures from draft-ietf-dnsext-ecdsa-04
ENTRY_BEGIN
SECTION QUESTION
example.net. IN DNSKEY
SECTION ANSWER
example.net. 3600 IN DNSKEY 257 3 13 ( GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )
ENTRY_END
; entry to test
ENTRY_BEGIN
SECTION QUESTION
www.example.net. IN A
SECTION ANSWER
www.example.net. 3600 IN A 192.0.2.1
www.example.net. 3600 IN RRSIG A 13 3 3600 ( 20100909100439 20100812100439 55648 example.net. qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )
ENTRY_END

23
testdata/test_sigs.ecdsa_p384 vendored Normal file
View File

@ -0,0 +1,23 @@
; Signature test file
; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
; later entries are verified with it.
; Test ECDSA P384 signatures from draft-ietf-dnsext-ecdsa-04
ENTRY_BEGIN
SECTION QUESTION
example.net. IN DNSKEY
SECTION ANSWER
example.net. 3600 IN DNSKEY 257 3 14 ( xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )
ENTRY_END
; entry to test
ENTRY_BEGIN
SECTION QUESTION
www.example.net. IN A
SECTION ANSWER
www.example.net. 3600 IN A 192.0.2.1
www.example.net. 3600 IN RRSIG A 14 3 3600 ( 20100909102025 20100812102025 10771 example.net. /L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP 95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm )
ENTRY_END

View File

@ -279,6 +279,10 @@ ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx)
if(EVP_get_digestbyname("md_gost94")) if(EVP_get_digestbyname("md_gost94"))
return 32; return 32;
else return 0; else return 0;
#endif
#ifdef USE_ECDSA
case LDNS_SHA384:
return SHA384_DIGEST_LENGTH;
#endif #endif
default: break; default: break;
} }
@ -347,6 +351,12 @@ ds_create_dnskey_digest(struct module_env* env,
if(do_gost94((unsigned char*)ldns_buffer_begin(b), if(do_gost94((unsigned char*)ldns_buffer_begin(b),
ldns_buffer_limit(b), (unsigned char*)digest)) ldns_buffer_limit(b), (unsigned char*)digest))
return 1; return 1;
#endif
#ifdef USE_ECDSA
case LDNS_SHA384:
(void)SHA384((unsigned char*)ldns_buffer_begin(b),
ldns_buffer_limit(b), (unsigned char*)digest);
return 1;
#endif #endif
default: default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d", verbose(VERB_QUERY, "unknown DS digest algorithm %d",
@ -417,6 +427,10 @@ dnskey_algo_id_is_supported(int id)
#endif #endif
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
case LDNS_RSASHA512: case LDNS_RSASHA512:
#endif
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
#endif #endif
return 1; return 1;
#ifdef USE_GOST #ifdef USE_GOST
@ -1321,7 +1335,7 @@ log_crypto_error(const char* str, unsigned long e)
* Setup DSA key digest in DER encoding ... * Setup DSA key digest in DER encoding ...
* @param sig: input is signature output alloced ptr (unless failure). * @param sig: input is signature output alloced ptr (unless failure).
* caller must free alloced ptr if this routine returns true. * caller must free alloced ptr if this routine returns true.
* @param len: intput is initial siglen, output is output len. * @param len: input is initial siglen, output is output len.
* @return false on failure. * @return false on failure.
*/ */
static int static int
@ -1350,6 +1364,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
*sig = NULL; *sig = NULL;
newlen = i2d_DSA_SIG(dsasig, sig); newlen = i2d_DSA_SIG(dsasig, sig);
if(newlen < 0) { if(newlen < 0) {
DSA_SIG_free(dsasig);
free(*sig); free(*sig);
return 0; return 0;
} }
@ -1358,6 +1373,48 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
return 1; return 1;
} }
#ifdef USE_ECDSA
/**
* Setup the ECDSA signature in its encoding that the library wants.
* Converts from plain numbers to ASN formatted.
* @param sig: input is signature, output alloced ptr (unless failure).
* caller must free alloced ptr if this routine returns true.
* @param len: input is initial siglen, output is output len.
* @return false on failure.
*/
static int
setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
{
ECDSA_SIG* ecdsa_sig;
int newlen;
unsigned int bnsize = (*len)/2;
/* if too short or not even length, fails */
if(*len < 16 || bnsize*2 != *len)
return 0;
/* use the raw data to parse two evenly long BIGNUMs, "r | s". */
ecdsa_sig = ECDSA_SIG_new();
if(!ecdsa_sig) return 0;
ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
if(!ecdsa_sig->r || !ecdsa_sig->s) {
ECDSA_SIG_free(ecdsa_sig);
return 0;
}
/* spool it into ASN format */
*sig = NULL;
newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
if(newlen <= 0) {
ECDSA_SIG_free(ecdsa_sig);
free(*sig);
return 0;
}
*len = (unsigned int)newlen;
ECDSA_SIG_free(ecdsa_sig);
return 1;
}
#endif /* USE_ECDSA */
/** /**
* Setup key and digest for verification. Adjust sig if necessary. * Setup key and digest for verification. Adjust sig if necessary.
* *
@ -1471,6 +1528,28 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0; return 0;
} }
break; break;
#endif
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
*evp_key = ldns_ecdsa2pkey_raw(key, keylen,
LDNS_ECDSAP256SHA256);
if(!*evp_key) {
verbose(VERB_QUERY, "verify: "
"ldns_ecdsa2pkey_raw failed");
return 0;
}
*digest_type = EVP_sha256();
break;
case LDNS_ECDSAP384SHA384:
*evp_key = ldns_ecdsa2pkey_raw(key, keylen,
LDNS_ECDSAP384SHA384);
if(!*evp_key) {
verbose(VERB_QUERY, "verify: "
"ldns_ecdsa2pkey_raw failed");
return 0;
}
*digest_type = EVP_sha384();
break;
#endif #endif
default: default:
verbose(VERB_QUERY, "verify: unknown algorithm %d", verbose(VERB_QUERY, "verify: unknown algorithm %d",
@ -1519,7 +1598,19 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus; return sec_status_bogus;
} }
dofree = 1; dofree = 1;
} }
#ifdef USE_ECDSA
else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
/* EVP uses ASN prefix on sig, which is not in the wire data */
if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
*reason = "use of signature for ECDSA crypto failed";
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
dofree = 1;
}
#endif /* USE_ECDSA */
/* do the signature cryptography work */ /* do the signature cryptography work */
EVP_MD_CTX_init(&ctx); EVP_MD_CTX_init(&ctx);
@ -1536,7 +1627,7 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
if(dofree) free(sigblock); if(dofree) free(sigblock);
return sec_status_unchecked; return sec_status_unchecked;
} }
res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key); res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
if(EVP_MD_CTX_cleanup(&ctx) == 0) { if(EVP_MD_CTX_cleanup(&ctx) == 0) {
verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed"); verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");