]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Fix for openssl 1.1.0, --disable-dsa feature.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 21 Mar 2016 14:26:33 +0000 (15:26 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 21 Mar 2016 14:26:33 +0000 (15:26 +0100)
configure.ac
dnssec.c
dnssec_sign.c
dnssec_verify.c
drill/drill.c
examples/ldns-dane.c
examples/ldns-signzone.c
keys.c

index d6b28b60625deecd2c08ff2a568b97a2062324b7..025f35fd9d7184df190f2dda5ab4ab474bb2d3de 100644 (file)
@@ -301,7 +301,7 @@ tmp_LIBS=$LIBS
 
 ACX_WITH_SSL_OPTIONAL
 
-AC_CHECK_FUNCS([EVP_sha256 ENGINE_load_cryptodev])
+AC_CHECK_FUNCS([EVP_sha256 ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0])
 
 # for macosx, see if glibtool exists and use that
 # BSD's need to know the version...
@@ -357,6 +357,34 @@ case "$enable_ecdsa" in
       ;;
 esac
 
+AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
+case "$enable_dsa" in
+    no)
+      ;;
+    *) dnl default
+      # 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(ed25519, AC_HELP_STRING([--enable-ed25519], [Enable ed25519 support (experimental)]))
+case "$enable_ed25519" in
+    yes)
+      if test "x$HAVE_SSL" != "xyes"; then
+        AC_MSG_ERROR([DSA enabled, but no SSL support])
+      fi
+      AC_CHECK_DECLS([NID_X25519], [], [AC_MSG_ERROR([OpenSSL does not support the EDDSA curve: please upgrade OpenSSL or rerun with --disable-ed25519])], [AC_INCLUDES_DEFAULT
+#include <openssl/evp.h>
+      ])
+      AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
+      ;;
+    *|no) dnl default
+      ;;
+esac
+
 AC_ARG_ENABLE(dane, AC_HELP_STRING([--disable-dane], [Disable DANE support]))
 case "$enable_dane" in
     no)
index 9927f15363c769109842b5cf83e95b69f8fa76ef..2f1db653a622560e7787a8fe5d22daebd59be1aa 100644 (file)
--- a/dnssec.c
+++ b/dnssec.c
@@ -1707,6 +1707,7 @@ ldns_rdf *
 ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
                                                  const long sig_len)
 {
+#ifdef USE_DSA
        ldns_rdf *sigdata_rdf;
        DSA_SIG *dsasig;
        unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig);
@@ -1750,12 +1751,17 @@ ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
        DSA_SIG_free(dsasig);
 
        return sigdata_rdf;
+#else
+       (void)sig; (void)sig_len;
+       return NULL;
+#endif
 }
 
 ldns_status
 ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
                                                  const ldns_rdf *sig_rdf)
 {
+#ifdef USE_DSA
        /* the EVP api wants the DER encoding of the signature... */
        BIGNUM *R, *S;
        DSA_SIG *dsasig;
@@ -1801,6 +1807,10 @@ ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
        free(raw_sig);
 
        return ldns_buffer_status(target_buffer);
+#else
+       (void)target_buffer; (void)sig_rdf;
+       return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
+#endif
 }
 
 #ifdef USE_ECDSA
@@ -1810,14 +1820,21 @@ ldns_convert_ecdsa_rrsig_asn1len2rdf(const ldns_buffer *sig,
        const long sig_len, int num_bytes)
 {
         ECDSA_SIG* ecdsa_sig;
+       BIGNUM *r, *s;
        unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
         ldns_rdf* rdf;
        ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len);
         if(!ecdsa_sig) return NULL;
 
+#ifdef HAVE_ECDSA_SIG_GET0
+       ECDSA_SIG_get0(&r, &s, ecdsa_sig);
+#else
+       r = ecdsa_sig->r;
+       s = ecdsa_sig->s;
+#endif
         /* "r | s". */
-        if(BN_num_bytes(ecdsa_sig->r) > num_bytes ||
-               BN_num_bytes(ecdsa_sig->s) > num_bytes) {
+        if(BN_num_bytes(r) > num_bytes ||
+               BN_num_bytes(s) > num_bytes) {
                 ECDSA_SIG_free(ecdsa_sig);
                return NULL; /* numbers too big for passed curve size */
        }
@@ -1829,8 +1846,8 @@ ldns_convert_ecdsa_rrsig_asn1len2rdf(const ldns_buffer *sig,
        /* write the bignums (in big-endian) a little offset if the BN code
         * wants to write a shorter number of bytes, with zeroes prefixed */
        memset(data, 0, num_bytes*2);
-        BN_bn2bin(ecdsa_sig->r, data+num_bytes-BN_num_bytes(ecdsa_sig->r));
-        BN_bn2bin(ecdsa_sig->s, data+num_bytes*2-BN_num_bytes(ecdsa_sig->s));
+        BN_bn2bin(r, data+num_bytes-BN_num_bytes(r));
+        BN_bn2bin(s, data+num_bytes*2-BN_num_bytes(s));
        rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(num_bytes*2), data);
         ECDSA_SIG_free(ecdsa_sig);
         return rdf;
@@ -1840,35 +1857,48 @@ ldns_status
 ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
         const ldns_rdf *sig_rdf)
 {
-        ECDSA_SIG* sig;
-       int raw_sig_len;
+        /* convert from two BIGNUMs in the rdata buffer, to ASN notation.
+        * ASN preable:  30440220 <R 32bytefor256> 0220 <S 32bytefor256>
+        * the '20' is the length of that field (=bnsize).
+        * 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;
         long bnsize = (long)ldns_rdf_size(sig_rdf) / 2;
+        uint8_t* d = ldns_rdf_data(sig_rdf);
         /* if too short, or not even length, do not bother */
         if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf))
                 return LDNS_STATUS_ERR;
-        
-        /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
-        sig = ECDSA_SIG_new();
-        if(!sig) return LDNS_STATUS_MEM_ERR;
-        sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf),
-                bnsize, sig->r);
-        sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize,
-                bnsize, sig->s);
-        if(!sig->r || !sig->s) {
-                ECDSA_SIG_free(sig);
-                return LDNS_STATUS_MEM_ERR;
+        /* 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;
+        if(ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
+                ldns_buffer_write_u8(target_buffer, pre[0]);
+                ldns_buffer_write_u8(target_buffer, raw_sig_len-2);
+                ldns_buffer_write_u8(target_buffer, pre[2]);
+                ldns_buffer_write_u8(target_buffer, bnsize + r_high - r_rem);
+                if(r_high)
+                        ldns_buffer_write_u8(target_buffer, 0);
+                ldns_buffer_write(target_buffer, d+r_rem, bnsize-r_rem);
+                ldns_buffer_write(target_buffer, mid, mid_len-1);
+                ldns_buffer_write_u8(target_buffer, bnsize + s_high - s_rem);
+                if(s_high)
+                        ldns_buffer_write_u8(target_buffer, 0);
+                ldns_buffer_write(target_buffer, d+bnsize+s_rem, bnsize-s_rem);
         }
-
-       raw_sig_len = i2d_ECDSA_SIG(sig, NULL);
-       if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
-                unsigned char* pp = (unsigned char*)
-                       ldns_buffer_current(target_buffer);
-               raw_sig_len = i2d_ECDSA_SIG(sig, &pp);
-                ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len);
-       }
-        ECDSA_SIG_free(sig);
-
-       return ldns_buffer_status(target_buffer);
+        return ldns_buffer_status(target_buffer);
 }
 
 #endif /* S_SPLINT_S */
index c9c6c7a82f067848c9600e7b44017029b799a1ae..4c8068cc6b7c3751dcb13ef9d82a51d706f125e3 100644 (file)
@@ -122,6 +122,7 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
        ldns_rdf *b64rdf = NULL;
 
        switch(ldns_key_algorithm(current_key)) {
+#ifdef USE_DSA
        case LDNS_SIGN_DSA:
        case LDNS_SIGN_DSA_NSEC3:
                b64rdf = ldns_sign_public_evp(
@@ -129,6 +130,7 @@ ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
                                   ldns_key_evp_key(current_key),
                                   EVP_dss1());
                break;
+#endif /* USE_DSA */
        case LDNS_SIGN_RSASHA1:
        case LDNS_SIGN_RSASHA1_NSEC3:
                b64rdf = ldns_sign_public_evp(
@@ -308,6 +310,7 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
 ldns_rdf *
 ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
 {
+#ifdef USE_DSA
        unsigned char *sha1_hash;
        ldns_rdf *sigdata_rdf;
        ldns_buffer *b64sig;
@@ -363,6 +366,10 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
         DSA_SIG_free(sig);
 
        return sigdata_rdf;
+#else
+       (void)to_sign; (void)key;
+       return NULL;
+#endif
 }
 
 #ifdef USE_ECDSA
@@ -373,7 +380,7 @@ ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
 {
         EC_KEY* ec;
         const EC_GROUP* g;
-        if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
+        if(EVP_PKEY_base_id(pkey) != EVP_PKEY_EC)
                 return 0;
         ec = EVP_PKEY_get1_EC_KEY(pkey);
         g = EC_KEY_get0_group(ec);
@@ -404,7 +411,7 @@ ldns_sign_public_evp(ldns_buffer *to_sign,
        unsigned int siglen;
        ldns_rdf *sigdata_rdf;
        ldns_buffer *b64sig;
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *ctx;
        const EVP_MD *md_type;
        int r;
 
@@ -422,46 +429,61 @@ ldns_sign_public_evp(ldns_buffer *to_sign,
                return NULL;
        }
 
-       EVP_MD_CTX_init(&ctx);
-       r = EVP_SignInit(&ctx, md_type);
+       ctx = EVP_MD_CTX_new();
+       if(!ctx) {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+       r = EVP_SignInit(ctx, md_type);
        if(r == 1) {
-               r = EVP_SignUpdate(&ctx, (unsigned char*)
+               r = EVP_SignUpdate(ctx, (unsigned char*)
                                            ldns_buffer_begin(to_sign),
                                            ldns_buffer_position(to_sign));
        } else {
                ldns_buffer_free(b64sig);
+               EVP_MD_CTX_destroy(ctx);
                return NULL;
        }
        if(r == 1) {
-               r = EVP_SignFinal(&ctx, (unsigned char*)
+               r = EVP_SignFinal(ctx, (unsigned char*)
                                           ldns_buffer_begin(b64sig), &siglen, key);
        } else {
                ldns_buffer_free(b64sig);
+               EVP_MD_CTX_destroy(ctx);
                return NULL;
        }
        if(r != 1) {
                ldns_buffer_free(b64sig);
+               EVP_MD_CTX_destroy(ctx);
                return NULL;
        }
 
        /* unfortunately, OpenSSL output is differenct from DNS DSA format */
 #ifndef S_SPLINT_S
+#ifdef USE_DSA
        if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
                sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
+       }
+#endif
+#if defined(USE_DSA) && defined(USE_ECDSA)
+       else
+#endif
 #ifdef USE_ECDSA
-        } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
+        if(EVP_PKEY_base_id(key) == EVP_PKEY_EC &&
                 ldns_pkey_is_ecdsa(key)) {
                 sigdata_rdf = ldns_convert_ecdsa_rrsig_asn1len2rdf(
                        b64sig, siglen, ldns_pkey_is_ecdsa(key));
+       }
 #endif
-       else {
+       else {
                /* ok output for other types is the same */
                sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
                                                                         ldns_buffer_begin(b64sig));
        }
 #endif /* splint */
        ldns_buffer_free(b64sig);
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_MD_CTX_destroy(ctx);
        return sigdata_rdf;
 }
 
index a03435bbb3a64f3a43048c7b3bbcd4f098b1fa21..a523ab645be31dd901e7e055d7aca3865896e2d4 100644 (file)
@@ -1935,6 +1935,7 @@ ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
 {
        /* check for right key */
        switch(algo) {
+#ifdef USE_DSA
        case LDNS_DSA:
        case LDNS_DSA_NSEC3:
                return ldns_verify_rrsig_dsa_raw(sig,
@@ -1943,6 +1944,7 @@ ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
                                                                   key,
                                                                   keylen);
                break;
+#endif
        case LDNS_RSASHA1:
        case LDNS_RSASHA1_NSEC3:
                return ldns_verify_rrsig_rsasha1_raw(sig,
@@ -2088,6 +2090,7 @@ ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, const ldns_rr* rrsig)
                        return LDNS_STATUS_MEM_ERR;
                }
                break;
+#ifdef USE_DSA
        case LDNS_DSA:
        case LDNS_DSA_NSEC3:
                /* EVP takes rfc2459 format, which is a tad longer than dns format */
@@ -2104,6 +2107,7 @@ ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, const ldns_rr* rrsig)
                        return LDNS_STATUS_MEM_ERR;
                }
                break;
+#endif
 #ifdef USE_ECDSA
         case LDNS_ECDSAP256SHA256:
         case LDNS_ECDSAP384SHA384:
@@ -2485,18 +2489,20 @@ ldns_status
 ldns_verify_rrsig_evp_raw(const unsigned char *sig, size_t siglen, 
                                         const ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
 {
-       EVP_MD_CTX ctx;
+       EVP_MD_CTX *ctx;
        int res;
 
-       EVP_MD_CTX_init(&ctx);
+       ctx = EVP_MD_CTX_new();
+       if(!ctx)
+               return LDNS_STATUS_MEM_ERR;
        
-       EVP_VerifyInit(&ctx, digest_type);
-       EVP_VerifyUpdate(&ctx,
+       EVP_VerifyInit(ctx, digest_type);
+       EVP_VerifyUpdate(ctx,
                                  ldns_buffer_begin(rrset),
                                  ldns_buffer_position(rrset));
-       res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
+       res = EVP_VerifyFinal(ctx, sig, (unsigned int) siglen, key);
        
-       EVP_MD_CTX_cleanup(&ctx);
+       EVP_MD_CTX_destroy(ctx);
        
        if (res == 1) {
                return LDNS_STATUS_OK;
@@ -2545,6 +2551,7 @@ ldns_status
 ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
                                         ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
+#ifdef USE_DSA
        EVP_PKEY *evp_key;
        ldns_status result;
 
@@ -2560,7 +2567,10 @@ ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
        }
        EVP_PKEY_free(evp_key);
        return result;
-
+#else
+       (void)sig; (void)siglen; (void)rrset; (void)key; (void)keylen;
+       return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
+#endif
 }
 
 ldns_status
index 2bd57e075707529902920813d04430a8bee5b3a8..a9e7e8a435fc2250b6a661c7baa37754f86d4e6b 100644 (file)
@@ -1016,7 +1016,6 @@ main(int argc, char *argv[])
        xfree(tsig_algorithm);
 
 #ifdef HAVE_SSL
-       ERR_remove_state(0);
        CRYPTO_cleanup_all_ex_data();
        ERR_free_strings();
        EVP_cleanup();
index b44a8cd908695543cc6526b89629a2e72c6a4246..20a89ee66625aa8abfc1c4ba18ad2630d4899b45 100644 (file)
@@ -1678,9 +1678,10 @@ main(int argc, char* const* argv)
                if (! cert) {
                        ssl_err("could not SSL_get_certificate");
                }
-#ifndef S_SPLINT_S
-               extra_certs = ctx->extra_certs;
-#endif
+               if(!SSL_CTX_get_extra_chain_certs(ctx, &extra_certs)) {
+                       ssl_err("could not SSL_CTX_get_extra_chain_certs");
+               }
+               /* I don't know if we have to stack-free the extra_certs */
 
                switch (mode) {
                case CREATE: dane_create(tlsas, tlsa_owner, certificate_usage,
index 5d693660ded6c4ac13aa76b40be762730643416f..c77f2e76b8dfe3a54703f31d77951359b40a5dfb 100644 (file)
@@ -377,8 +377,6 @@ main(int argc, char *argv[])
        
        keys = ldns_key_list_new();
 
-       OPENSSL_config(NULL);
-
        while ((c = getopt(argc, argv, "a:bde:f:i:k:no:ps:t:vAUE:K:")) != -1) {
                switch (c) {
                case 'a':
diff --git a/keys.c b/keys.c
index 2af69a3ce693dd0d2382a9c675de7b0165601006..fcf29883f281b6eaec3c6ba3dfec5cdb59b6a71a 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -35,8 +35,10 @@ ldns_lookup_table ldns_signing_algorithms[] = {
         { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" },
         { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" },
 #endif
+#ifdef USE_DSA
         { LDNS_SIGN_DSA, "DSA" },
         { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" },
+#endif
         { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" },
         { LDNS_SIGN_HMACSHA1, "hmac-sha1" },
         { LDNS_SIGN_HMACSHA256, "hmac-sha256" },
@@ -296,7 +298,9 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
        ldns_rr *key_rr;
 #ifdef HAVE_SSL
        RSA *rsa;
+#ifdef USE_DSA
        DSA *dsa;
+#endif
        unsigned char *hmac;
        size_t hmac_size;
 #endif /* HAVE_SSL */
@@ -349,7 +353,14 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                alg = (ldns_signing_algorithm)LDNS_DH;
        }
        if (strncmp(d, "3 DSA", 2) == 0) {
+#ifdef USE_DSA
                alg = LDNS_SIGN_DSA;
+#else
+# ifdef STDERR_MSGS
+               fprintf(stderr, "Warning: DSA not compiled into this ");
+               fprintf(stderr, "version of ldns\n");
+# endif
+#endif
        }
        if (strncmp(d, "4 ECC", 2) == 0) {
                alg = (ldns_signing_algorithm)LDNS_ECC;
@@ -358,7 +369,14 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                alg = LDNS_SIGN_RSASHA1;
        }
        if (strncmp(d, "6 DSA", 2) == 0) {
+#ifdef USE_DSA
                alg = LDNS_SIGN_DSA_NSEC3;
+#else
+# ifdef STDERR_MSGS
+               fprintf(stderr, "Warning: DSA not compiled into this ");
+               fprintf(stderr, "version of ldns\n");
+# endif
+#endif
        }
        if (strncmp(d, "7 RSASHA1", 2) == 0) {
                alg = LDNS_SIGN_RSASHA1_NSEC3;
@@ -444,6 +462,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                        ldns_key_assign_rsa_key(k, rsa);
 #endif /* HAVE_SSL */
                        break;
+#ifdef USE_DSA
                case LDNS_SIGN_DSA:
                case LDNS_SIGN_DSA_NSEC3:
                        ldns_key_set_algorithm(k, alg);
@@ -456,6 +475,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
                        ldns_key_assign_dsa_key(k, dsa);
 #endif /* HAVE_SSL */
                        break;
+#endif /* USE_DSA */
                case LDNS_SIGN_HMACMD5:
                case LDNS_SIGN_HMACSHA1:
                case LDNS_SIGN_HMACSHA256:
@@ -820,11 +840,17 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
 {
        ldns_key *k;
 #ifdef HAVE_SSL
+#ifdef USE_DSA
        DSA *d;
-       RSA *r;
+#endif /* USE_DSA */
 #  ifdef USE_ECDSA
         EC_KEY *ec = NULL;
 #  endif
+#  ifdef HAVE_EVP_PKEY_KEYGEN
+       EVP_PKEY_CTX *ctx;
+#  else
+       RSA *r;
+#  endif
 #else
        int i;
        uint16_t offset = 0;
@@ -842,6 +868,29 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                case LDNS_SIGN_RSASHA256:
                case LDNS_SIGN_RSASHA512:
 #ifdef HAVE_SSL
+#ifdef HAVE_EVP_PKEY_KEYGEN
+                       ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
+                       if(!ctx) {
+                               ldns_key_free(k);
+                               return NULL;
+                       }
+                       if(EVP_PKEY_keygen_init(ctx) <= 0) {
+                               ldns_key_free(k);
+                               EVP_PKEY_CTX_free(ctx);
+                               return NULL;
+                       }
+                       if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, size) <= 0) {
+                               ldns_key_free(k);
+                               EVP_PKEY_CTX_free(ctx);
+                               return NULL;
+                       }
+                       if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) {
+                               ldns_key_free(k);
+                               EVP_PKEY_CTX_free(ctx);
+                               return NULL;
+                       }
+                       EVP_PKEY_CTX_free(ctx);
+#else /* HAVE_EVP_PKEY_KEYGEN */
                        r = RSA_generate_key((int)size, RSA_F4, NULL, NULL);
                         if(!r) {
                                ldns_key_free(k);
@@ -853,10 +902,12 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                        }
                        ldns_key_set_rsa_key(k, r);
                        RSA_free(r);
+#endif /* HAVE_EVP_PKEY_KEYGEN */
 #endif /* HAVE_SSL */
                        break;
                case LDNS_SIGN_DSA:
                case LDNS_SIGN_DSA_NSEC3:
+#ifdef USE_DSA
 #ifdef HAVE_SSL
                        d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL);
                        if (!d) {
@@ -870,6 +921,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
                        ldns_key_set_dsa_key(k, d);
                        DSA_free(d);
 #endif /* HAVE_SSL */
+#endif /* USE_DSA */
                        break;
                case LDNS_SIGN_HMACMD5:
                case LDNS_SIGN_HMACSHA1:
@@ -1005,9 +1057,13 @@ ldns_key_set_rsa_key(ldns_key *k, RSA *r)
 void
 ldns_key_set_dsa_key(ldns_key *k, DSA *d)
 {
+#ifdef USE_DSA
        EVP_PKEY *key = EVP_PKEY_new();
        EVP_PKEY_set1_DSA(key, d);
        k->_key.key  = key;
+#else
+       (void)k; (void)d;
+#endif
 }
 
 void
@@ -1021,9 +1077,13 @@ ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
 void
 ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
 {
+#ifdef USE_DSA
        EVP_PKEY *key = EVP_PKEY_new();
        EVP_PKEY_assign_DSA(key, d);
        k->_key.key  = key;
+#else
+       (void)k; (void)d;
+#endif
 }
 #endif /* splint */
 #endif /* HAVE_SSL */
@@ -1137,11 +1197,16 @@ ldns_key_rsa_key(const ldns_key *k)
 DSA *
 ldns_key_dsa_key(const ldns_key *k)
 {
+#ifdef USE_DSA
        if (k->_key.key) {
                return EVP_PKEY_get1_DSA(k->_key.key);
        } else {
                return NULL;
        }
+#else
+       (void)k;
+       return NULL;
+#endif
 }
 #endif /* splint */
 #endif /* HAVE_SSL */
@@ -1311,6 +1376,7 @@ ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size)
        return true;
 }
 
+#ifdef USE_DSA
 /* data pointer must be large enough (LDNS_MAX_KEYLEN) */
 static bool
 ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
@@ -1343,6 +1409,7 @@ ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
        *size = 21 + *size * 3;
        return true;
 }
+#endif /* USE_DSA */
 
 #ifdef USE_GOST
 static bool
@@ -1352,13 +1419,13 @@ ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size)
        unsigned char* pp = NULL;
        if(i2d_PUBKEY(k, &pp) != 37 + 64) {
                /* expect 37 byte(ASN header) and 64 byte(X and Y) */
-               CRYPTO_free(pp);
+               free(pp);
                return false;
        }
        /* omit ASN header */
        for(i=0; i<64; i++)
                data[i] = pp[i+37];
-       CRYPTO_free(pp);
+       free(pp);
        *size = 64;
        return true;
 }
@@ -1380,7 +1447,9 @@ ldns_key2rr(const ldns_key *k)
        uint16_t size = 0;
 #ifdef HAVE_SSL
        RSA *rsa = NULL;
+#ifdef USE_DSA
        DSA *dsa = NULL;
+#endif /* USE_DSA */
 #endif /* HAVE_SSL */
 #ifdef USE_ECDSA
         EC_KEY* ec;
@@ -1445,6 +1514,7 @@ ldns_key2rr(const ldns_key *k)
                case LDNS_SIGN_DSA:
                        ldns_rr_push_rdf(pubkey,
                                        ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA));
+#ifdef USE_DSA
 #ifdef HAVE_SSL
                        dsa = ldns_key_dsa_key(k);
                        if (dsa) {
@@ -1462,10 +1532,12 @@ ldns_key2rr(const ldns_key *k)
                                internal_data = 1;
                        }
 #endif /* HAVE_SSL */
+#endif /* USE_DSA */
                        break;
                case LDNS_SIGN_DSA_NSEC3:
                        ldns_rr_push_rdf(pubkey,
                                        ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3));
+#ifdef USE_DSA
 #ifdef HAVE_SSL
                        dsa = ldns_key_dsa_key(k);
                        if (dsa) {
@@ -1483,6 +1555,7 @@ ldns_key2rr(const ldns_key *k)
                                internal_data = 1;
                        }
 #endif /* HAVE_SSL */
+#endif /* USE_DSA */
                        break;
                case LDNS_SIGN_ECC_GOST:
                        ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
@@ -1691,7 +1764,9 @@ ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
                 {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"},
                 {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"},
                 /* old ldns usage, now RFC names */
+#ifdef USE_DSA
                 {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" },
+#endif
                 {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" },
 #ifdef USE_GOST
                 {LDNS_SIGN_ECC_GOST, "GOST"},