From 1f4222aa946b40adda475bda148942727be6f1e2 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Thu, 6 Aug 2009 13:38:55 +0000 Subject: [PATCH] GOST support with --enable-gost. git-svn-id: file:///svn/unbound/trunk@1747 be551aaa-1e26-0410-a405-d3ace91eadb9 --- config.h.in | 3 ++ configure | 51 +++++++++++++++++-------- configure.ac | 11 +++++- daemon/daemon.c | 3 ++ doc/Changelog | 4 ++ doc/README | 4 +- testcode/testbound.c | 12 +++++- testcode/unitmain.c | 3 ++ testcode/unitverify.c | 3 ++ testdata/test_signatures.15 | 40 +++++++++++++++++++ validator/val_sigcrypt.c | 76 +++++++++++++++++++++++++++++++------ 11 files changed, 179 insertions(+), 31 deletions(-) create mode 100644 testdata/test_signatures.15 diff --git a/config.h.in b/config.h.in index e897584a6..5a75ffa13 100644 --- a/config.h.in +++ b/config.h.in @@ -401,6 +401,9 @@ /* define this to enable debug checks. */ #undef UNBOUND_DEBUG +/* Define this to enable GOST support. */ +#undef USE_GOST + /* Define if you want to use internal select based events */ #undef USE_MINI_EVENT diff --git a/configure b/configure index abacd0bef..325a8a7d7 100755 --- a/configure +++ b/configure @@ -926,6 +926,7 @@ with_pyunbound with_pythonmodule with_ssl enable_sha2 +enable_gost with_libevent enable_staticexe enable_lock_checks @@ -1580,6 +1581,7 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --disable-rpath disable hardcoded rpath (default=enabled) --enable-sha2 Enable SHA256 and SHA512 RRSIG support + --enable-gost Enable GOST support --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 @@ -7260,13 +7262,13 @@ if test "${lt_cv_nm_interface+set}" = set; then else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:7263: $ac_compile\"" >&5) + (eval echo "\"\$as_me:7265: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:7266: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:7268: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:7269: output\"" >&5) + (eval echo "\"\$as_me:7271: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -8471,7 +8473,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 8474 "configure"' > conftest.$ac_ext + echo '#line 8476 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -9838,11 +9840,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9841: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9843: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9845: \$? = $ac_status" >&5 + echo "$as_me:9847: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -10177,11 +10179,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10180: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10182: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:10184: \$? = $ac_status" >&5 + echo "$as_me:10186: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -10282,11 +10284,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10285: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10287: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10289: \$? = $ac_status" >&5 + echo "$as_me:10291: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10337,11 +10339,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10340: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10342: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10344: \$? = $ac_status" >&5 + echo "$as_me:10346: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13140,7 +13142,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13143 "configure" +#line 13145 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13236,7 +13238,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13239 "configure" +#line 13241 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17679,8 +17681,25 @@ fi case "$enable_sha2" in yes) -cat >>confdefs.h <<_ACEOF -#define USE_SHA2 /**/ +cat >>confdefs.h <<\_ACEOF +#define USE_SHA2 1 +_ACEOF + + ;; + no|*) + ;; +esac + +# Check whether --enable-gost was given. +if test "${enable_gost+set}" = set; then + enableval=$enable_gost; +fi + +case "$enable_gost" in + yes) + +cat >>confdefs.h <<\_ACEOF +#define USE_GOST 1 _ACEOF ;; diff --git a/configure.ac b/configure.ac index 40622b5f7..51f24af96 100644 --- a/configure.ac +++ b/configure.ac @@ -356,7 +356,16 @@ AC_CHECK_FUNCS([EVP_sha1 EVP_sha256 EVP_sha512 ENGINE_load_gost]) AC_ARG_ENABLE(sha2, AC_HELP_STRING([--enable-sha2], [Enable SHA256 and SHA512 RRSIG support])) case "$enable_sha2" in yes) - AC_DEFINE_UNQUOTED([USE_SHA2], [], [Define this to enable SHA256 and SHA512 support.]) + AC_DEFINE([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.]) + ;; + no|*) + ;; +esac + +AC_ARG_ENABLE(gost, AC_HELP_STRING([--enable-gost], [Enable GOST support])) +case "$enable_gost" in + yes) + AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.]) ;; no|*) ;; diff --git a/daemon/daemon.c b/daemon/daemon.c index d3ad913e2..b0712e76d 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -165,6 +165,9 @@ daemon_init() checklock_start(); ERR_load_crypto_strings(); ERR_load_SSL_strings(); +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + (void)ldns_key_EVP_load_gost_id(); +#endif OpenSSL_add_all_algorithms(); (void)SSL_library_init(); #ifdef HAVE_TZSET diff --git a/doc/Changelog b/doc/Changelog index 92978cbb1..671751ba8 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +6 August 2009: Wouter + - configure --enable-gost for GOST support, experimental + implementation of draft-dolmatov-dnsext-dnssec-gost-01. + 5 August 2009: Wouter - trunk moved to 1.3.4. diff --git a/doc/README b/doc/README index edef5a6e3..bb6c8276b 100644 --- a/doc/README +++ b/doc/README @@ -64,7 +64,9 @@ This software is under BSD license, see LICENSE for details. * --with-pythonmodule Compile the python module that processes responses in the server. * --enable-sha2 - Enable draft support for RSASHA256 and RSASHA512. + Enable draft support for RSASHA256 and RSASHA512 crypto. + * --enable-gost + Enable draft support for GOST crypto. * 'make test' attempts to run a series of tests, depending on the support programs that are installed. diff --git a/testcode/testbound.c b/testcode/testbound.c index 3c62f1737..d41ef7e7b 100644 --- a/testcode/testbound.c +++ b/testcode/testbound.c @@ -66,6 +66,7 @@ testbound_usage() printf("-h this help\n"); 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("-o str unbound commandline options separated by spaces.\n"); printf("Version %s\n", PACKAGE_VERSION); printf("BSD licensed, see LICENSE file in source package.\n"); @@ -224,7 +225,7 @@ main(int argc, char* argv[]) pass_argc = 1; pass_argv[0] = "unbound"; add_opts("-d", &pass_argc, pass_argv); - while( (c=getopt(argc, argv, "2ho:p:")) != -1) { + while( (c=getopt(argc, argv, "2gho:p:")) != -1) { switch(c) { case '2': #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) @@ -233,6 +234,15 @@ main(int argc, char* argv[]) #else printf("SHA256 not supported\n"); exit(1); +#endif + break; + case 'g': +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + printf("GOST supported\n"); + exit(0); +#else + printf("GOST not supported\n"); + exit(1); #endif break; case 'p': diff --git a/testcode/unitmain.c b/testcode/unitmain.c index fdd21bbe8..6acd6bdbc 100644 --- a/testcode/unitmain.c +++ b/testcode/unitmain.c @@ -432,6 +432,9 @@ main(int argc, char* argv[]) } printf("Start of %s unit test.\n", PACKAGE_STRING); ERR_load_crypto_strings(); +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + (void)ldns_key_EVP_load_gost_id(); +#endif checklock_start(); neg_test(); rnd_test(); diff --git a/testcode/unitverify.c b/testcode/unitverify.c index fec56c982..175331158 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -484,6 +484,9 @@ verify_test() #endif verifytest_file("testdata/test_signatures.12", "20090107100022"); verifytest_file("testdata/test_signatures.13", "20080414005004"); +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + verifytest_file("testdata/test_signatures.15", "20090807060504"); +#endif dstest_file("testdata/test_ds_sig.1"); nsectest(); nsec3_hash_test("testdata/test_nsec3_hash.1"); diff --git a/testdata/test_signatures.15 b/testdata/test_signatures.15 new file mode 100644 index 000000000..5eccebef7 --- /dev/null +++ b/testdata/test_signatures.15 @@ -0,0 +1,40 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test GOST signatures using algo number 11. + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. 3600 IN DNSKEY 256 3 11 Z7JC2FSJ0KQPAflOrM25v5XGVfZDEY54Zz1uslvmHgEL92nBbki3p2dzuiKqjov0iB33XvscfKb44CajJWeH8w== ;{id = 1952 (zsk), size = 512b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN A +SECTION ANSWER +open.nlnetlabs.nl. 600 IN A 213.154.224.1 +open.nlnetlabs.nl. 600 IN RRSIG A 11 3 600 20090903100515 20090806100515 1952 nlnetlabs.nl. jpKiYiSfGhROoZ5b+dqoxVefwCWN0lkAdkspKlbqz6GsZPfiQMU3UYWmZvTQm9hkwPqI9EKbaBJCw2i0ucBi8g== ;{id = 1952} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN AAAA +SECTION ANSWER +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53 +open.nlnetlabs.nl. 600 IN RRSIG AAAA 11 3 600 20090903100515 20090806100515 1952 nlnetlabs.nl. rGY+31Hdr5mxYrII+RGdBpbeZhJ9JccnHKocl9v/oMU7aBFl0CC7fWmFS18/AMvxWhNLqxPboir4q/nPpwkNhw== ;{id = 1952} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN NSEC +SECTION ANSWER +open.nlnetlabs.nl. 3600 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC +open.nlnetlabs.nl. 3600 IN RRSIG NSEC 11 3 3600 20090903100515 20090806100515 1952 nlnetlabs.nl. wq9NbqmdcasWb9APEPrrT9Z7dcK/1MJ0Pr0iYYv/2QHmRU3gDhyS/ss5I81YS7aePolNwNoASdoU3CCpU0dKTg== ;{id = 1952} +ENTRY_END + diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index 11b2f7850..13f894708 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -255,12 +255,28 @@ ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx) #ifdef HAVE_EVP_SHA256 case LDNS_SHA256: return SHA256_DIGEST_LENGTH; +#endif +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + case LDNS_HASH_GOST94: + return 32; #endif default: break; } return 0; } +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) +/** Perform GOST94 hash */ +static int +do_gost94(unsigned char* data, size_t len, unsigned char* dest) +{ + const EVP_MD* md = EVP_get_digestbyname("md_gost94"); + if(!md) + return 0; + return ldns_digest_evp(data, len, dest, md); +} +#endif + /** * Create a DS digest for a DNSKEY entry. * @@ -305,6 +321,12 @@ ds_create_dnskey_digest(struct module_env* env, (void)SHA256((unsigned char*)ldns_buffer_begin(b), ldns_buffer_limit(b), (unsigned char*)digest); return 1; +#endif +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + case LDNS_HASH_GOST94: + if(do_gost94((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", @@ -375,6 +397,9 @@ dnskey_algo_id_is_supported(int id) #endif #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) case LDNS_RSASHA512: +#endif +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + case LDNS_GOST: #endif return 1; default: @@ -1202,14 +1227,14 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len) * Setup key and digest for verification. Adjust sig if necessary. * * @param algo: key algorithm - * @param evp_key: EVP PKEY public key to update. + * @param evp_key: EVP PKEY public key to create. * @param digest_type: digest type to use * @param key: key to setup for. * @param keylen: length of key. * @return false on failure. */ static int -setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, +setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, unsigned char* key, size_t keylen) { DSA* dsa; @@ -1218,13 +1243,18 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, switch(algo) { case LDNS_DSA: case LDNS_DSA_NSEC3: + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } dsa = ldns_key_buf2dsa_raw(key, keylen); if(!dsa) { verbose(VERB_QUERY, "verify: " "ldns_key_buf2dsa_raw failed"); return 0; } - if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) { + if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) { verbose(VERB_QUERY, "verify: " "EVP_PKEY_assign_DSA failed"); return 0; @@ -1240,13 +1270,18 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) case LDNS_RSASHA512: #endif + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } rsa = ldns_key_buf2rsa_raw(key, keylen); if(!rsa) { verbose(VERB_QUERY, "verify: " "ldns_key_buf2rsa_raw SHA failed"); return 0; } - if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) { + if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { verbose(VERB_QUERY, "verify: " "EVP_PKEY_assign_RSA SHA failed"); return 0; @@ -1267,13 +1302,18 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, break; case LDNS_RSAMD5: + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } rsa = ldns_key_buf2rsa_raw(key, keylen); if(!rsa) { verbose(VERB_QUERY, "verify: " "ldns_key_buf2rsa_raw MD5 failed"); return 0; } - if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) { + if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { verbose(VERB_QUERY, "verify: " "EVP_PKEY_assign_RSA MD5 failed"); return 0; @@ -1281,6 +1321,22 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, *digest_type = EVP_md5(); break; +#if defined(HAVE_ENGINE_LOAD_GOST) && defined(USE_GOST) + case LDNS_GOST: + *evp_key = ldns_gost2pkey_raw(key, keylen); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "ldns_gost2pkey_raw failed"); + return 0; + } + *digest_type = EVP_get_digestbyname("md_gost94"); + if(!*digest_type) { + verbose(VERB_QUERY, "verify: " + "EVP_getdigest md_gost94 failed"); + return 0; + } + break; +#endif default: verbose(VERB_QUERY, "verify: unknown algorithm %d", algo); @@ -1308,13 +1364,9 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, const EVP_MD *digest_type; EVP_MD_CTX ctx; int res, dofree = 0; - EVP_PKEY *evp_key = EVP_PKEY_new(); - if(!evp_key) { - log_err("verify: malloc failure in crypto"); - return sec_status_unchecked; - } - - if(!setup_key_digest(algo, evp_key, &digest_type, key, keylen)) { + EVP_PKEY *evp_key = NULL; + + if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { verbose(VERB_QUERY, "verify: failed to setup key"); EVP_PKEY_free(evp_key); return sec_status_bogus; -- 2.47.3