diff --git a/ChangeLog b/ChangeLog index eb46064c..1ebc847d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ * Bugfix #286 reschedule reused listening addresses * Bugfix #166 Allow parallel builds and unit-tests * NSAP-PTR, EID and NIMLOC, TALINK, AVC support - * bugfix of TA RR type + * Bugfix of TA RR type * OPENPGPKEY and SMIMEA support * Bugfix TAG rdata type presentation format for CAA RR type * Bugfix Zero sized gateways with IPSECKEY gateway_type 0 diff --git a/configure.ac b/configure.ac index dd190c55..6281e573 100644 --- a/configure.ac +++ b/configure.ac @@ -297,7 +297,7 @@ fi AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 SSL_CTX_set_min_proto_version]) +AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version]) 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 @@ -500,6 +500,24 @@ case "$enable_dsa" in ;; esac +AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support])) +use_ed25519="no" +case "$enable_ed25519" in + no) + ;; + *) + if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then + AC_CHECK_DECLS([NID_ED25519], [ + AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.]) + use_ed25519="yes" + ], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.]) + fi ], [AC_INCLUDES_DEFAULT +#include + ]) + fi + ;; +esac + AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [Enables the draft mdns client support])) case "$enable_all_drafts" in yes) diff --git a/src/gldns/keyraw.c b/src/gldns/keyraw.c index 9e6adcb2..3f6f1a20 100644 --- a/src/gldns/keyraw.c +++ b/src/gldns/keyraw.c @@ -388,6 +388,27 @@ gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) } #endif /* USE_ECDSA */ +#ifdef USE_ED25519 +EVP_PKEY* +gldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) +{ + /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */ + uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, + 0x70, 0x03, 0x21, 0x00}; + int pre_len = 12; + uint8_t buf[256]; + EVP_PKEY *evp_key; + /* pp gets modified by d2i() */ + const unsigned char* pp = (unsigned char*)buf; + if(keylen != 32 || keylen + pre_len > sizeof(buf)) + return NULL; /* wrong length */ + memmove(buf, pre, pre_len); + memmove(buf+pre_len, key, keylen); + evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); + return evp_key; +} +#endif /* USE_ED25519 */ + int gldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, const EVP_MD* md) diff --git a/src/gldns/keyraw.h b/src/gldns/keyraw.h index c0d33e60..60e2bfde 100644 --- a/src/gldns/keyraw.h +++ b/src/gldns/keyraw.h @@ -92,6 +92,15 @@ EVP_PKEY* gldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); */ RSA *gldns_key_buf2rsa_raw(unsigned char* key, size_t len); +/** + * Converts a holding buffer with key material to EVP PKEY in openssl. + * Only available if ldns was compiled with ED25519. + * \param[in] key the uncompressed wireformat of the key. + * \param[in] len length of key data + * \return the key or NULL on error. + */ +EVP_PKEY* gldns_ed255192pkey_raw(const unsigned char* key, size_t len); + /** * Utility function to calculate hash using generic EVP_MD pointer. * \param[in] data the data to hash. diff --git a/src/gldns/rrdef.c b/src/gldns/rrdef.c index 60b57c31..91739232 100644 --- a/src/gldns/rrdef.c +++ b/src/gldns/rrdef.c @@ -606,7 +606,7 @@ static gldns_rr_descriptor rdata_field_descriptors[] = { {GLDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, #ifdef DRAFT_RRTYPES /* 258 */ - {GLDNS_RR_TYPE_TXT, "AVC", 1, 0, NULL, GLDNS_RDF_TYPE_STR, GLDNS_RR_NO_COMPRESS, 0 }, + {GLDNS_RR_TYPE_AVC, "AVC", 1, 0, NULL, GLDNS_RDF_TYPE_STR, GLDNS_RR_NO_COMPRESS, 0 }, #else {GLDNS_RR_TYPE_NULL, "TYPE258", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, #endif diff --git a/src/gldns/str2wire.c b/src/gldns/str2wire.c index 57cbd4d1..2762aa38 100644 --- a/src/gldns/str2wire.c +++ b/src/gldns/str2wire.c @@ -869,6 +869,8 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, /* we can have the situation, where we've read ok, but still got * no bytes to play with, in this case size is 0 */ if(size == 0) { + if(*len > 0) + rr[0] = 0; *len = 0; *dname_len = 0; return GLDNS_WIREPARSE_ERR_OK; @@ -876,6 +878,7 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { int s; + strlcpy((char*)rr, line, *len); *len = 0; *dname_len = 0; if(!parse_state) return GLDNS_WIREPARSE_ERR_OK; @@ -886,12 +889,19 @@ int gldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, return s; } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { const char* end = NULL; + strlcpy((char*)rr, line, *len); *len = 0; *dname_len = 0; if(!parse_state) return GLDNS_WIREPARSE_ERR_OK; parse_state->default_ttl = gldns_str2period( gldns_strip_ws(line+5), &end); } else if (strncmp(line, "$INCLUDE", 8) == 0) { + strlcpy((char*)rr, line, *len); + *len = 0; + *dname_len = 0; + return GLDNS_WIREPARSE_ERR_INCLUDE; + } else if (strncmp(line, "$", 1) == 0) { + strlcpy((char*)rr, line, *len); *len = 0; *dname_len = 0; return GLDNS_WIREPARSE_ERR_INCLUDE; diff --git a/src/gldns/str2wire.h b/src/gldns/str2wire.h index 23094b6c..1b7777bd 100644 --- a/src/gldns/str2wire.h +++ b/src/gldns/str2wire.h @@ -237,6 +237,8 @@ struct gldns_file_parse_state { * @param rr: this is malloced by the user and the result is stored here, * if an RR is read. If no RR is read this is signalled with the * return len set to 0 (for ORIGIN, TTL directives). + * The read line is available in the rr_buf (zero terminated), for + * $DIRECTIVE style elements. * @param len: on input, the length of the rr buffer. on output the rr len. * Buffer size of 64k should be enough. * @param dname_len: returns the length of the dname initial part of the rr. diff --git a/src/util/orig-headers/lruhash.h b/src/util/orig-headers/lruhash.h index af06b622..4759b500 100644 --- a/src/util/orig-headers/lruhash.h +++ b/src/util/orig-headers/lruhash.h @@ -326,7 +326,7 @@ void lru_demote(struct lruhash* table, struct lruhash_entry* entry); * @param hash: hash value. User calculates the hash. * @param entry: identifies the entry. * @param data: the data. - * @param cb_override: if not null overrides the cb_arg for the deletefunc. + * @param cb_arg: if not null overrides the cb_arg for the deletefunc. * @return: pointer to the existing entry if the key was already present, * or to the entry argument if it was not. */ diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index be88ff43..88d23472 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -228,6 +228,9 @@ dnskey_algo_id_is_supported(int id) case LDNS_ECDSAP256SHA256: case LDNS_ECDSAP384SHA384: #endif +#ifdef USE_ED25519 + case LDNS_ED25519: +#endif #if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) return 1; #endif @@ -555,6 +558,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, #endif break; #endif /* USE_ECDSA */ +#ifdef USE_ED25519 + case LDNS_ED25519: + *evp_key = sldns_ed255192pkey_raw(key, keylen); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "sldns_ed255192pkey_raw failed"); + return 0; + } + *digest_type = NULL; + break; +#endif /* USE_ED25519 */ default: verbose(VERB_QUERY, "verify: unknown algorithm %d", algo); @@ -644,18 +658,29 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, else if(docrypto_free) OPENSSL_free(sigblock); return sec_status_unchecked; } - if(EVP_VerifyInit(ctx, digest_type) == 0) { - verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); +#ifndef HAVE_EVP_DIGESTVERIFY + if(EVP_DigestInit(ctx, digest_type) == 0) { + verbose(VERB_QUERY, "verify: EVP_DigestInit failed"); +#ifdef HAVE_EVP_MD_CTX_NEW EVP_MD_CTX_destroy(ctx); +#else + EVP_MD_CTX_cleanup(ctx); + free(ctx); +#endif EVP_PKEY_free(evp_key); if(dofree) free(sigblock); else if(docrypto_free) OPENSSL_free(sigblock); return sec_status_unchecked; } - if(EVP_VerifyUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf), + if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf), (unsigned int)sldns_buffer_limit(buf)) == 0) { - verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); + verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed"); +#ifdef HAVE_EVP_MD_CTX_NEW EVP_MD_CTX_destroy(ctx); +#else + EVP_MD_CTX_cleanup(ctx); + free(ctx); +#endif EVP_PKEY_free(evp_key); if(dofree) free(sigblock); else if(docrypto_free) OPENSSL_free(sigblock); @@ -663,6 +688,24 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, } res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); +#else /* HAVE_EVP_DIGESTVERIFY */ + if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) { + verbose(VERB_QUERY, "verify: EVP_DigestVerifyInit failed"); +#ifdef HAVE_EVP_MD_CTX_NEW + EVP_MD_CTX_destroy(ctx); +#else + EVP_MD_CTX_cleanup(ctx); + free(ctx); +#endif + EVP_PKEY_free(evp_key); + if(dofree) free(sigblock); + else if(docrypto_free) OPENSSL_free(sigblock); + return sec_status_unchecked; + } + res = EVP_DigestVerify(ctx, sigblock, sigblock_len, + (unsigned char*)sldns_buffer_begin(buf), + sldns_buffer_limit(buf)); +#endif #ifdef HAVE_EVP_MD_CTX_NEW EVP_MD_CTX_destroy(ctx); #else