From fbae76885aeaa32046de4d15b09dfdaebc9adb1a Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 23 Mar 2016 08:19:49 +0000 Subject: [PATCH] - OpenSSL 1.1.0 portability, --disable-dsa configure option. git-svn-id: file:///svn/unbound/trunk@3689 be551aaa-1e26-0410-a405-d3ace91eadb9 --- config.h.in | 6 ++ configure | 33 ++++++++++- configure.ac | 17 +++++- daemon/daemon.c | 6 ++ doc/Changelog | 3 + testcode/petal.c | 1 - testcode/unitverify.c | 2 + util/net_help.c | 6 +- validator/val_anchor.c | 2 + validator/val_secalgo.c | 120 +++++++++++++++++++++++++++++----------- 10 files changed, 159 insertions(+), 37 deletions(-) diff --git a/config.h.in b/config.h.in index e9223139d..011357b06 100644 --- a/config.h.in +++ b/config.h.in @@ -128,6 +128,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_EVENT_H +/* Define to 1 if you have the `EVP_MD_CTX_new' function. */ +#undef HAVE_EVP_MD_CTX_NEW + /* Define to 1 if you have the `EVP_sha1' function. */ #undef HAVE_EVP_SHA1 @@ -586,6 +589,9 @@ /* Define to 1 to enable dnstap support */ #undef USE_DNSTAP +/* Define this to enable DSA support. */ +#undef USE_DSA + /* Define this to enable ECDSA support. */ #undef USE_ECDSA diff --git a/configure b/configure index 7b72be122..96f8d0eff 100755 --- a/configure +++ b/configure @@ -832,6 +832,7 @@ with_ssl enable_sha2 enable_gost enable_ecdsa +enable_dsa enable_event_api with_libevent with_libexpat @@ -1495,6 +1496,7 @@ Optional Features: --disable-sha2 Disable SHA256 and SHA512 RRSIG support --disable-gost Disable GOST support --disable-ecdsa Disable ECDSA support + --disable-dsa Disable DSA support --enable-event-api Enable (experimental) pluggable event base libunbound API installed to unbound-event.h --enable-static-exe enable to compile executables statically against @@ -17483,7 +17485,7 @@ fi done -for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode +for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -17850,6 +17852,35 @@ _ACEOF ;; esac +# Check whether --enable-dsa was given. +if test "${enable_dsa+set}" = set; then : + enableval=$enable_dsa; +fi + +use_dsa="no" +case "$enable_ecdsa" in + no) + ;; + *) + # detect if DSA is supported, and turn it off if not. + ac_fn_c_check_func "$LINENO" "EVP_dss1" "ac_cv_func_EVP_dss1" +if test "x$ac_cv_func_EVP_dss1" = xyes; then : + + +cat >>confdefs.h <<_ACEOF +#define USE_DSA 1 +_ACEOF + + +else + if test "x$enable_dsa" = "xyes"; then as_fn_error $? "OpenSSL does not support DSA and you used --enable-dsa." "$LINENO" 5 + fi +fi + + ;; +esac + + # Check whether --enable-event-api was given. if test "${enable_event_api+set}" = set; then : enableval=$enable_event_api; diff --git a/configure.ac b/configure.ac index 4f2996343..aa1fb92fb 100644 --- a/configure.ac +++ b/configure.ac @@ -658,7 +658,7 @@ else fi AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode]) +AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new]) AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [ AC_INCLUDES_DEFAULT #ifdef HAVE_OPENSSL_ERR_H @@ -840,6 +840,21 @@ case "$enable_ecdsa" in ;; esac +AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support])) +use_dsa="no" +case "$enable_ecdsa" in + no) + ;; + *) + # detect if DSA is supported, and turn it off if not. + AC_CHECK_FUNC(EVP_dss1, [ + AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.]) + ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.]) + fi ]) + ;; +esac + + AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h])) case "$enable_event_api" in yes) diff --git a/daemon/daemon.c b/daemon/daemon.c index 7edff800c..1036fcde2 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -644,17 +644,23 @@ daemon_delete(struct daemon* daemon) # endif # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE # ifndef S_SPLINT_S +# if OPENSSL_VERSION_NUMBER < 0x10100000 sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); +# endif # endif # endif # ifdef HAVE_OPENSSL_CONFIG EVP_cleanup(); +# if OPENSSL_VERSION_NUMBER < 0x10100000 ENGINE_cleanup(); +# endif CONF_modules_free(); # endif CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ ERR_free_strings(); +# if OPENSSL_VERSION_NUMBER < 0x10100000 RAND_cleanup(); +# endif # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) ub_openssl_lock_delete(); # endif diff --git a/doc/Changelog b/doc/Changelog index 878536659..f99103811 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +23 March 2016: Wouter + - OpenSSL 1.1.0 portability, --disable-dsa configure option. + 21 March 2016: Wouter - Fix compile of getentropy_linux for SLES11 servicepack 4. - Fix dnstap-log-resolver-response-messages, from Nikolay Edigaryev. diff --git a/testcode/petal.c b/testcode/petal.c index 269b109b8..24d94a556 100644 --- a/testcode/petal.c +++ b/testcode/petal.c @@ -643,6 +643,5 @@ int main(int argc, char* argv[]) CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); - RAND_cleanup(); return 0; } diff --git a/testcode/unitverify.c b/testcode/unitverify.c index 9cb0eb99e..f6445e281 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -497,12 +497,14 @@ verify_test(void) { unit_show_feature("signature verify"); verifytest_file("testdata/test_signatures.1", "20070818005004"); +#ifdef USE_DSA verifytest_file("testdata/test_signatures.2", "20080414005004"); verifytest_file("testdata/test_signatures.3", "20080416005004"); verifytest_file("testdata/test_signatures.4", "20080416005004"); verifytest_file("testdata/test_signatures.5", "20080416005004"); verifytest_file("testdata/test_signatures.6", "20080416005004"); verifytest_file("testdata/test_signatures.7", "20070829144150"); +#endif /* USE_DSA */ verifytest_file("testdata/test_signatures.8", "20070829144150"); #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) verifytest_file("testdata/test_sigs.rsasha256", "20070829144150"); diff --git a/util/net_help.c b/util/net_help.c index eb03cd0ae..5d6c033d6 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -783,7 +783,7 @@ void* outgoing_ssl_fd(void* sslctx, int fd) #endif } -#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) +#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) /** global lock list for openssl locks */ static lock_basic_t *ub_openssl_locks = NULL; @@ -808,7 +808,7 @@ ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file), int ub_openssl_lock_init(void) { -#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) +#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) int i; ub_openssl_locks = (lock_basic_t*)reallocarray( NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_t)); @@ -825,7 +825,7 @@ int ub_openssl_lock_init(void) void ub_openssl_lock_delete(void) { -#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) +#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) int i; if(!ub_openssl_locks) return; diff --git a/validator/val_anchor.c b/validator/val_anchor.c index bc9f8b877..4d470b692 100644 --- a/validator/val_anchor.c +++ b/validator/val_anchor.c @@ -1030,6 +1030,8 @@ anchors_assemble_rrsets(struct val_anchors* anchors) ")", b); (void)rbtree_delete(anchors->tree, &ta->node); lock_basic_unlock(&ta->lock); + if(anchors->dlv_anchor == ta) + anchors->dlv_anchor = NULL; anchors_delfunc(&ta->node, NULL); ta = next; continue; diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c index baa4dae1a..be5ba6319 100644 --- a/validator/val_secalgo.c +++ b/validator/val_secalgo.c @@ -186,8 +186,10 @@ dnskey_algo_id_is_supported(int id) case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ return 0; +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: +#endif case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) @@ -227,6 +229,7 @@ log_crypto_error(const char* str, unsigned long e) log_err("%s crypto %s", str, buf); } +#ifdef USE_DSA /** * Setup DSA key digest in DER encoding ... * @param sig: input is signature output alloced ptr (unless failure). @@ -268,6 +271,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len) DSA_SIG_free(dsasig); return 1; } +#endif /* USE_DSA */ #ifdef USE_ECDSA /** @@ -281,32 +285,61 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len) static int setup_ecdsa_sig(unsigned char** sig, unsigned int* len) { - ECDSA_SIG* ecdsa_sig; - int newlen; + /* convert from two BIGNUMs in the rdata buffer, to ASN notation. + * ASN preable: 30440220 0220 + * the '20' is the length of that field (=bnsize). +i * the '44' is the total remaining length. + * if negative, start with leading zero. + * if starts with 00s, remove them from the number. + */ + uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; + int pre_len = 4; + uint8_t mid[] = {0x02, 0x20}; + int mid_len = 2; + int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0; int bnsize = (int)((*len)/2); + unsigned char* d = *sig; + unsigned char* p; /* if too short or not even length, fails */ if(*len < 16 || bnsize*2 != (int)*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); + /* strip leading zeroes from r (but not last one) */ + while(r_rem < bnsize-1 && d[r_rem] == 0) + r_rem++; + /* strip leading zeroes from s (but not last one) */ + while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0) + s_rem++; + + r_high = ((d[0+r_rem]&0x80)?1:0); + s_high = ((d[bnsize+s_rem]&0x80)?1:0); + raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len + + s_high + bnsize - s_rem; + *sig = (unsigned char*)malloc(raw_sig_len); + if(!*sig) return 0; + p = *sig; + p[0] = pre[0]; + p[1] = raw_sig_len-2; + p[2] = pre[2]; + p[3] = bnsize + r_high - r_rem; + p += 4; + if(r_high) { + *p = 0; + p += 1; } - *len = (unsigned int)newlen; - ECDSA_SIG_free(ecdsa_sig); + memmove(p, d+r_rem, bnsize-r_rem); + p += bnsize-r_rem; + memmove(p, mid, mid_len-1); + p += mid_len-1; + *p = bnsize + s_high - s_rem; + p += 1; + if(s_high) { + *p = 0; + p += 1; + } + memmove(p, d+bnsize+s_rem, bnsize-s_rem); + *len = (unsigned int)raw_sig_len; return 1; } #endif /* USE_ECDSA */ @@ -325,10 +358,13 @@ static int setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, unsigned char* key, size_t keylen) { +#ifdef USE_DSA DSA* dsa; +#endif RSA* rsa; switch(algo) { +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: *evp_key = EVP_PKEY_new(); @@ -350,6 +386,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, *digest_type = EVP_dss1(); break; +#endif /* USE_DSA */ case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) @@ -508,7 +545,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, char** reason) { const EVP_MD *digest_type; - EVP_MD_CTX ctx; + EVP_MD_CTX* ctx; int res, dofree = 0; EVP_PKEY *evp_key = NULL; @@ -518,6 +555,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); return sec_status_bogus; } +#ifdef USE_DSA /* if it is a DSA signature in bind format, convert to DER format */ if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && sigblock_len == 1+2*SHA_DIGEST_LENGTH) { @@ -529,8 +567,12 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, } dofree = 1; } +#endif +#if defined(USE_ECDSA) && defined(USE_DSA) + else +#endif #ifdef USE_ECDSA - else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) { + 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"); @@ -543,14 +585,25 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, #endif /* USE_ECDSA */ /* do the signature cryptography work */ - EVP_MD_CTX_init(&ctx); - if(EVP_VerifyInit(&ctx, digest_type) == 0) { +#ifdef HAVE_EVP_MD_CTX_NEW + ctx = EVP_MD_CTX_new(); +#else + ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); + if(ctx) EVP_MD_CTX_init(ctx); +#endif + if(!ctx) { + log_err("EVP_MD_CTX_new: malloc failure"); + EVP_PKEY_free(evp_key); + if(dofree) free(sigblock); + return sec_status_unchecked; + } + if(EVP_VerifyInit(ctx, digest_type) == 0) { verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); return sec_status_unchecked; } - if(EVP_VerifyUpdate(&ctx, (unsigned char*)sldns_buffer_begin(buf), + if(EVP_VerifyUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf)) == 0) { verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); EVP_PKEY_free(evp_key); @@ -558,13 +611,8 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* 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"); - EVP_PKEY_free(evp_key); - if(dofree) free(sigblock); - return sec_status_unchecked; - } + res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); + EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) @@ -678,8 +726,10 @@ dnskey_algo_id_is_supported(int id) case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ return 0; +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: +#endif case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: #ifdef USE_SHA2 @@ -920,6 +970,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, */ switch(algo) { +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: *pubkey = nss_buf2dsa(key, keylen); @@ -930,6 +981,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, *htype = HASH_AlgSHA1; /* no prefix for DSA verification */ break; +#endif case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: #ifdef USE_SHA2 @@ -1046,6 +1098,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, return sec_status_bogus; } +#ifdef USE_DSA /* need to convert DSA, ECDSA signatures? */ if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { if(sigblock_len == 1+2*SHA1_LENGTH) { @@ -1068,6 +1121,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, SECITEM_FreeItem(p, PR_TRUE); } } +#endif /* USE_DSA */ /* do the signature cryptography work */ /* hash the data */ @@ -1263,8 +1317,10 @@ dnskey_algo_id_is_supported(int id) { /* uses libnettle */ switch(id) { +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: +#endif case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: #ifdef USE_SHA2 @@ -1541,6 +1597,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, } switch(algo) { +#ifdef USE_DSA case LDNS_DSA: case LDNS_DSA_NSEC3: *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); @@ -1548,6 +1605,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, return sec_status_bogus; else return sec_status_secure; +#endif /* USE_DSA */ case LDNS_RSASHA1: case LDNS_RSASHA1_NSEC3: