/* Define to 1 if you have the `daemon' function. */
#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
if you don't. */
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
/* define this to enable debug checks. */
#undef UNBOUND_DEBUG
+/* Define this to enable ECDSA support. */
+#undef USE_ECDSA
+
/* Define this to enable GOST support. */
#undef USE_GOST
with_ssl
enable_sha2
enable_gost
+enable_ecdsa
with_libevent
with_libexpat
enable_static_exe
purposes
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
--disable-gost Disable GOST support
+ --enable-ecdsa Enable ECDSA support, experimental
--enable-static-exe enable to compile executables statically against
event, ldns libs, for debug purposes
--enable-lock-checks enable to check lock and unlock calls, for debug
;;
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 whether --with-libevent was given.
else
ac_cv_func_ldns_key_EVP_load_gost_id="yes"
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
do :
ac_fn_c_check_header_compile "$LINENO" "ldns/ldns.h" "ac_cv_header_ldns_ldns_h" "$ac_includes_default
-a $ac_cv_func_ldns_get_random = yes \
-a $ac_cv_header_ldns_ldns_h = 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
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
;;
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
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.]),
else
ac_cv_func_ldns_key_EVP_load_gost_id="yes"
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_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
-a $ac_cv_func_ldns_get_random = yes \
-a $ac_cv_header_ldns_ldns_h = 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
:
else
+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
- fix for windows, rename() is not posix compliant on windows.
printf("-p file playback text file\n");
printf("-2 detect SHA256 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("-o str unbound commandline options separated by spaces.\n");
printf("Version %s\n", PACKAGE_VERSION);
pass_argc = 1;
pass_argv[0] = "unbound";
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) {
case 's':
free(pass_argv[1]);
#else
printf("SHA256 not supported\n");
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
break;
case 'g':
if(ldns_key_EVP_load_gost_id())
verifytest_file("testdata/test_sigs.gost", "20090807060504");
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
dstest_file("testdata/test_ds.sha1");
nsectest();
--- /dev/null
+;
+; 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
+
--- /dev/null
+; 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
+
--- /dev/null
+; 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
+
if(EVP_get_digestbyname("md_gost94"))
return 32;
else return 0;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_SHA384:
+ return SHA384_DIGEST_LENGTH;
#endif
default: break;
}
if(do_gost94((unsigned char*)ldns_buffer_begin(b),
ldns_buffer_limit(b), (unsigned char*)digest))
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
default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
#endif
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
case LDNS_RSASHA512:
+#endif
+#ifdef USE_ECDSA
+ case LDNS_ECDSAP256SHA256:
+ case LDNS_ECDSAP384SHA384:
#endif
return 1;
#ifdef USE_GOST
* Setup DSA key digest in DER encoding ...
* @param sig: input is signature output alloced ptr (unless failure).
* 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.
*/
static int
*sig = NULL;
newlen = i2d_DSA_SIG(dsasig, sig);
if(newlen < 0) {
+ DSA_SIG_free(dsasig);
free(*sig);
return 0;
}
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.
*
return 0;
}
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
default:
verbose(VERB_QUERY, "verify: unknown algorithm %d",
return sec_status_bogus;
}
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 */
EVP_MD_CTX_init(&ctx);
if(dofree) free(sigblock);
return sec_status_unchecked;
}
-
+
res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
if(EVP_MD_CTX_cleanup(&ctx) == 0) {
verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");