From e4955d69ef3e0d236457ff981cbaa95f9307af8a Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 24 Mar 2016 11:14:14 +0100 Subject: [PATCH 1/3] Updates from unbound --- src/gldns/rrdef.c | 12 +- src/gldns/rrdef.h | 4 + src/gldns/str2wire.c | 4 +- src/util/import.sh | 1 + src/util/rbtree.c | 2 +- src/util/val_secalgo.c | 647 ++++++++++++++++++++++++++++++++++++++--- src/util/val_secalgo.h | 15 + 7 files changed, 644 insertions(+), 41 deletions(-) diff --git a/src/gldns/rrdef.c b/src/gldns/rrdef.c index fe409e4a..3d5a5961 100644 --- a/src/gldns/rrdef.c +++ b/src/gldns/rrdef.c @@ -144,6 +144,12 @@ static const gldns_rdf_type type_dhcid_wireformat[] = { static const gldns_rdf_type type_talink_wireformat[] = { GLDNS_RDF_TYPE_DNAME, GLDNS_RDF_TYPE_DNAME }; +static const gldns_rdf_type type_openpgpkey_wireformat[] = { + GLDNS_RDF_TYPE_B64 +}; +static const gldns_rdf_type type_csync_wireformat[] = { + GLDNS_RDF_TYPE_INT32, GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_NSEC +}; /* nsec3 is some vars, followed by same type of data of nsec */ static const gldns_rdf_type type_nsec3_wireformat[] = { /* GLDNS_RDF_TYPE_NSEC3_VARS, GLDNS_RDF_TYPE_NSEC3_NEXT_OWNER, GLDNS_RDF_TYPE_NSEC*/ @@ -361,8 +367,10 @@ static gldns_rr_descriptor rdata_field_descriptors[] = { {GLDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, /* 60 */ {GLDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, -{GLDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, -{GLDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, + /* 61 */ +{GLDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, + /* 62 */ + {GLDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index 55803cb6..703ee31e 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -182,6 +182,8 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ GLDNS_RR_TYPE_NSEC3PARAMS = 51, GLDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */ + GLDNS_RR_TYPE_SMIMEA = 53, /* draft-ietf-dane-smime, TLSA-like but may + be extended */ GLDNS_RR_TYPE_HIP = 55, /* RFC 5205 */ @@ -193,6 +195,8 @@ enum gldns_enum_rr_type GLDNS_RR_TYPE_TALINK = 58, GLDNS_RR_TYPE_CDS = 59, /** RFC 7344 */ GLDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ + GLDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */ + GLDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ GLDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ diff --git a/src/gldns/str2wire.c b/src/gldns/str2wire.c index d662636f..2ac0e23a 100644 --- a/src/gldns/str2wire.c +++ b/src/gldns/str2wire.c @@ -204,7 +204,7 @@ rrinternal_get_owner(gldns_buffer* strbuf, uint8_t* rr, size_t* len, return RET_ERR(GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, gldns_buffer_position(strbuf)); memmove(rr, tocopy, *dname_len); - } else if(strlen(token) == 0) { + } else if(*token == '\0') { /* no ownername was given, try prev, if that fails * origin, else default to root */ uint8_t* tocopy; @@ -1091,7 +1091,7 @@ int gldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) uint8_t prefix; size_t i; - if(strlen(my_str) == 0) { + if(*my_str == '\0') { /* empty APL element, no data, no string */ *len = 0; return GLDNS_WIREPARSE_ERR_OK; diff --git a/src/util/import.sh b/src/util/import.sh index 08cad0af..ee903681 100755 --- a/src/util/import.sh +++ b/src/util/import.sh @@ -39,6 +39,7 @@ do -e '/^#include "util\/data\/packed_rrset.h"$/d' \ -e 's/^#include "validator/#include "util/g' \ -e 's/^#include "gldns\/sbuffer/#include "gldns\/gbuffer/g' \ + -e 's/^#include "util\/val_nsec3.h"/#define NSEC3_HASH_SHA1 0x01/g' \ -e 's/ds_digest_size_supported/_getdns_ds_digest_size_supported/g' \ -e 's/secalgo_ds_digest/_getdns_secalgo_ds_digest/g' \ -e 's/dnskey_algo_id_is_supported/_getdns_dnskey_algo_id_is_supported/g' \ diff --git a/src/util/rbtree.c b/src/util/rbtree.c index 468011f4..c52be727 100644 --- a/src/util/rbtree.c +++ b/src/util/rbtree.c @@ -68,7 +68,7 @@ static void _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* child, _getdns_rbnode_t* child_parent); /* - * Creates a new red black tree, intializes and returns a pointer to it. + * Creates a new red black tree, initializes and returns a pointer to it. * * Return NULL on failure. * diff --git a/src/util/val_secalgo.c b/src/util/val_secalgo.c index 99b0d8c5..b04400cc 100644 --- a/src/util/val_secalgo.c +++ b/src/util/val_secalgo.c @@ -42,12 +42,13 @@ */ #include "config.h" #include "util/val_secalgo.h" +#define NSEC3_HASH_SHA1 0x01 #include "util/log.h" #include "gldns/rrdef.h" #include "gldns/keyraw.h" #include "gldns/gbuffer.h" -#if !defined(HAVE_SSL) && !defined(HAVE_NSS) +#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE) #error "Need crypto library to do digital signature cryptography" #endif @@ -69,10 +70,36 @@ #include #endif +/* return size of digest if supported, or 0 otherwise */ +size_t +nsec3_hash_algo_size_supported(int id) +{ + switch(id) { + case NSEC3_HASH_SHA1: + return SHA_DIGEST_LENGTH; + default: + return 0; + } +} + +/* perform nsec3 hash. return false on failure */ +int +secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, + unsigned char* res) +{ + switch(algo) { + case NSEC3_HASH_SHA1: + (void)SHA1(buf, len, res); + return 1; + default: + return 0; + } +} + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. - * @return size in bytes of digest, or 0 if not supported. + * @return size in bytes of digest, or 0 if not supported. */ size_t _getdns_ds_digest_size_supported(int algo) @@ -88,7 +115,8 @@ _getdns_ds_digest_size_supported(int algo) #endif #ifdef USE_GOST case GLDNS_HASH_GOST: - (void) gldns_key_EVP_load_gost_id(); + /* we support GOST if it can be loaded */ + (void)gldns_key_EVP_load_gost_id(); if(EVP_get_digestbyname("md_gost94")) return 32; else return 0; @@ -156,8 +184,10 @@ _getdns_dnskey_algo_id_is_supported(int id) case GLDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ return 0; +#ifdef USE_DSA case GLDNS_DSA: case GLDNS_DSA_NSEC3: +#endif case GLDNS_RSASHA1: case GLDNS_RSASHA1_NSEC3: #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) @@ -197,6 +227,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). @@ -238,6 +269,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len) DSA_SIG_free(dsasig); return 1; } +#endif /* USE_DSA */ #ifdef USE_ECDSA /** @@ -251,32 +283,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; + uint8_t* 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((size_t)raw_sig_len); + if(!*sig) return 0; + p = (uint8_t*)*sig; + p[0] = pre[0]; + p[1] = (uint8_t)(raw_sig_len-2); + p[2] = pre[2]; + p[3] = (uint8_t)(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, (size_t)bnsize-r_rem); + p += bnsize-r_rem; + memmove(p, mid, (size_t)mid_len-1); + p += mid_len-1; + *p = (uint8_t)(bnsize + s_high - s_rem); + p += 1; + if(s_high) { + *p = 0; + p += 1; + } + memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem); + *len = (unsigned int)raw_sig_len; return 1; } #endif /* USE_ECDSA */ @@ -295,10 +356,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 GLDNS_DSA: case GLDNS_DSA_NSEC3: *evp_key = EVP_PKEY_new(); @@ -320,6 +384,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, *digest_type = EVP_dss1(); break; +#endif /* USE_DSA */ case GLDNS_RSASHA1: case GLDNS_RSASHA1_NSEC3: #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) @@ -478,7 +543,7 @@ _getdns_verify_canonrrset(gldns_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; @@ -488,6 +553,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); return 0; } +#ifdef USE_DSA /* if it is a DSA signature in bind format, convert to DER format */ if((algo == GLDNS_DSA || algo == GLDNS_DSA_NSEC3) && sigblock_len == 1+2*SHA_DIGEST_LENGTH) { @@ -499,8 +565,12 @@ _getdns_verify_canonrrset(gldns_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 == GLDNS_ECDSAP256SHA256 || algo == GLDNS_ECDSAP384SHA384) { + if(algo == GLDNS_ECDSAP256SHA256 || algo == GLDNS_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"); @@ -513,28 +583,36 @@ _getdns_verify_canonrrset(gldns_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) { - verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); +#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 0; } - if(EVP_VerifyUpdate(&ctx, (unsigned char*)gldns_buffer_begin(buf), + if(EVP_VerifyInit(ctx, digest_type) == 0) { + verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); + EVP_MD_CTX_destroy(ctx); + EVP_PKEY_free(evp_key); + if(dofree) free(sigblock); + return 0; + } + if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), (unsigned int)gldns_buffer_limit(buf)) == 0) { verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); + EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); return 0; } - 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 0; - } + res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); + EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) @@ -564,6 +642,32 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, /* nspr4 */ #include "prerror.h" +/* return size of digest if supported, or 0 otherwise */ +size_t +nsec3_hash_algo_size_supported(int id) +{ + switch(id) { + case NSEC3_HASH_SHA1: + return SHA1_LENGTH; + default: + return 0; + } +} + +/* perform nsec3 hash. return false on failure */ +int +secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, + unsigned char* res) +{ + switch(algo) { + case NSEC3_HASH_SHA1: + (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len); + return 1; + default: + return 0; + } +} + size_t _getdns_ds_digest_size_supported(int algo) { @@ -622,8 +726,10 @@ _getdns_dnskey_algo_id_is_supported(int id) case GLDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ return 0; +#ifdef USE_DSA case GLDNS_DSA: case GLDNS_DSA_NSEC3: +#endif case GLDNS_RSASHA1: case GLDNS_RSASHA1_NSEC3: #ifdef USE_SHA2 @@ -864,6 +970,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, */ switch(algo) { +#ifdef USE_DSA case GLDNS_DSA: case GLDNS_DSA_NSEC3: *pubkey = nss_buf2dsa(key, keylen); @@ -874,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 GLDNS_RSASHA1: case GLDNS_RSASHA1_NSEC3: #ifdef USE_SHA2 @@ -990,6 +1098,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, return 0; } +#ifdef USE_DSA /* need to convert DSA, ECDSA signatures? */ if((algo == GLDNS_DSA || algo == GLDNS_DSA_NSEC3)) { if(sigblock_len == 1+2*SHA1_LENGTH) { @@ -1012,6 +1121,7 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, SECITEM_FreeItem(p, PR_TRUE); } } +#endif /* USE_DSA */ /* do the signature cryptography work */ /* hash the data */ @@ -1068,5 +1178,470 @@ _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, return 0; } +#elif defined(HAVE_NETTLE) -#endif /* HAVE_SSL or HAVE_NSS */ +#include "sha.h" +#include "bignum.h" +#include "macros.h" +#include "rsa.h" +#include "dsa.h" +#include "asn1.h" +#ifdef USE_ECDSA +#include "ecdsa.h" +#include "ecc-curve.h" +#endif + +static int +_digest_nettle(int algo, uint8_t* buf, size_t len, + unsigned char* res) +{ + switch(algo) { + case SHA1_DIGEST_SIZE: + { + struct sha1_ctx ctx; + sha1_init(&ctx); + sha1_update(&ctx, len, buf); + sha1_digest(&ctx, SHA1_DIGEST_SIZE, res); + return 1; + } + case SHA256_DIGEST_SIZE: + { + struct sha256_ctx ctx; + sha256_init(&ctx); + sha256_update(&ctx, len, buf); + sha256_digest(&ctx, SHA256_DIGEST_SIZE, res); + return 1; + } + case SHA384_DIGEST_SIZE: + { + struct sha384_ctx ctx; + sha384_init(&ctx); + sha384_update(&ctx, len, buf); + sha384_digest(&ctx, SHA384_DIGEST_SIZE, res); + return 1; + } + case SHA512_DIGEST_SIZE: + { + struct sha512_ctx ctx; + sha512_init(&ctx); + sha512_update(&ctx, len, buf); + sha512_digest(&ctx, SHA512_DIGEST_SIZE, res); + return 1; + } + default: + break; + } + return 0; +} + +/* return size of digest if supported, or 0 otherwise */ +size_t +nsec3_hash_algo_size_supported(int id) +{ + switch(id) { + case NSEC3_HASH_SHA1: + return SHA1_DIGEST_SIZE; + default: + return 0; + } +} + +/* perform nsec3 hash. return false on failure */ +int +secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, + unsigned char* res) +{ + switch(algo) { + case NSEC3_HASH_SHA1: + return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len, + res); + default: + return 0; + } +} + +/** + * Return size of DS digest according to its hash algorithm. + * @param algo: DS digest algo. + * @return size in bytes of digest, or 0 if not supported. + */ +size_t +_getdns_ds_digest_size_supported(int algo) +{ + switch(algo) { + case GLDNS_SHA1: + return SHA1_DIGEST_SIZE; +#ifdef USE_SHA2 + case GLDNS_SHA256: + return SHA256_DIGEST_SIZE; +#endif +#ifdef USE_ECDSA + case GLDNS_SHA384: + return SHA384_DIGEST_SIZE; +#endif + /* GOST not supported */ + case GLDNS_HASH_GOST: + default: + break; + } + return 0; +} + +int +_getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len, + unsigned char* res) +{ + switch(algo) { + case GLDNS_SHA1: + return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res); +#if defined(USE_SHA2) + case GLDNS_SHA256: + return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res); +#endif +#ifdef USE_ECDSA + case GLDNS_SHA384: + return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res); + +#endif + case GLDNS_HASH_GOST: + default: + verbose(VERB_QUERY, "unknown DS digest algorithm %d", + algo); + break; + } + return 0; +} + +int +_getdns_dnskey_algo_id_is_supported(int id) +{ + /* uses libnettle */ + switch(id) { +#ifdef USE_DSA + case GLDNS_DSA: + case GLDNS_DSA_NSEC3: +#endif + case GLDNS_RSASHA1: + case GLDNS_RSASHA1_NSEC3: +#ifdef USE_SHA2 + case GLDNS_RSASHA256: + case GLDNS_RSASHA512: +#endif +#ifdef USE_ECDSA + case GLDNS_ECDSAP256SHA256: + case GLDNS_ECDSAP384SHA384: +#endif + return 1; + case GLDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ + case GLDNS_ECC_GOST: + default: + return 0; + } +} + +static char * +_verify_nettle_dsa(gldns_buffer* buf, unsigned char* sigblock, + unsigned int sigblock_len, unsigned char* key, unsigned int keylen) +{ + uint8_t digest[SHA1_DIGEST_SIZE]; + uint8_t key_t; + int res = 0; + size_t offset; + struct dsa_public_key pubkey; + struct dsa_signature signature; + unsigned int expected_len; + + /* Extract DSA signature from the record */ + nettle_dsa_signature_init(&signature); + /* Signature length: 41 bytes - RFC 2536 sec. 3 */ + if(sigblock_len == 41) { + if(key[0] != sigblock[0]) + return "invalid T value in DSA signature or pubkey"; + nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1); + nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20); + } else { + /* DER encoded, decode the ASN1 notated R and S bignums */ + /* SEQUENCE { r INTEGER, s INTEGER } */ + struct asn1_der_iterator i, seq; + if(asn1_der_iterator_first(&i, sigblock_len, + (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED + || i.type != ASN1_SEQUENCE) + return "malformed DER encoded DSA signature"; + /* decode this element of i using the seq iterator */ + if(asn1_der_decode_constructed(&i, &seq) != + ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) + return "malformed DER encoded DSA signature"; + if(!asn1_der_get_bignum(&seq, signature.r, 20*8)) + return "malformed DER encoded DSA signature"; + if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE + || seq.type != ASN1_INTEGER) + return "malformed DER encoded DSA signature"; + if(!asn1_der_get_bignum(&seq, signature.s, 20*8)) + return "malformed DER encoded DSA signature"; + if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) + return "malformed DER encoded DSA signature"; + } + + /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */ + key_t = key[0]; + if (key_t > 8) { + return "invalid T value in DSA pubkey"; + } + + /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */ + if (keylen < 21) { + return "DSA pubkey too short"; + } + + expected_len = 1 + /* T */ + 20 + /* Q */ + (64 + key_t*8) + /* P */ + (64 + key_t*8) + /* G */ + (64 + key_t*8); /* Y */ + if (keylen != expected_len ) { + return "invalid DSA pubkey length"; + } + + /* Extract DSA pubkey from the record */ + nettle_dsa_public_key_init(&pubkey); + offset = 1; + nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset); + offset += 20; + nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset); + offset += (64 + key_t*8); + nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset); + offset += (64 + key_t*8); + nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset); + + /* Digest content of "buf" and verify its DSA signature in "sigblock"*/ + res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= dsa_sha1_verify_digest(&pubkey, digest, &signature); + + /* Clear and return */ + nettle_dsa_signature_clear(&signature); + nettle_dsa_public_key_clear(&pubkey); + if (!res) + return "DSA signature verification failed"; + else + return NULL; +} + +static char * +_verify_nettle_rsa(gldns_buffer* buf, unsigned int digest_size, char* sigblock, + unsigned int sigblock_len, uint8_t* key, unsigned int keylen) +{ + uint16_t exp_len = 0; + size_t exp_offset = 0, mod_offset = 0; + struct rsa_public_key pubkey; + mpz_t signature; + int res = 0; + + /* RSA pubkey parsing as per RFC 3110 sec. 2 */ + if( keylen <= 1) { + return "null RSA key"; + } + if (key[0] != 0) { + /* 1-byte length */ + exp_len = key[0]; + exp_offset = 1; + } else { + /* 1-byte NUL + 2-bytes exponent length */ + if (keylen < 3) { + return "incorrect RSA key length"; + } + exp_len = READ_UINT16(key+1); + if (exp_len == 0) + return "null RSA exponent length"; + exp_offset = 3; + } + /* Check that we are not over-running input length */ + if (keylen < exp_offset + exp_len + 1) { + return "RSA key content shorter than expected"; + } + mod_offset = exp_offset + exp_len; + nettle_rsa_public_key_init(&pubkey); + pubkey.size = keylen - mod_offset; + nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]); + nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]); + + /* Digest content of "buf" and verify its RSA signature in "sigblock"*/ + nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock); + switch (digest_size) { + case SHA1_DIGEST_SIZE: + { + uint8_t digest[SHA1_DIGEST_SIZE]; + res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= rsa_sha1_verify_digest(&pubkey, digest, signature); + break; + } + case SHA256_DIGEST_SIZE: + { + uint8_t digest[SHA256_DIGEST_SIZE]; + res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= rsa_sha256_verify_digest(&pubkey, digest, signature); + break; + } + case SHA512_DIGEST_SIZE: + { + uint8_t digest[SHA512_DIGEST_SIZE]; + res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= rsa_sha512_verify_digest(&pubkey, digest, signature); + break; + } + default: + break; + } + + /* Clear and return */ + nettle_rsa_public_key_clear(&pubkey); + mpz_clear(signature); + if (!res) { + return "RSA signature verification failed"; + } else { + return NULL; + } +} + +#ifdef USE_ECDSA +static char * +_verify_nettle_ecdsa(gldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock, + unsigned int sigblock_len, unsigned char* key, unsigned int keylen) +{ + int res = 0; + struct ecc_point pubkey; + struct dsa_signature signature; + + /* Always matched strength, as per RFC 6605 sec. 1 */ + if (sigblock_len != 2*digest_size || keylen != 2*digest_size) { + return "wrong ECDSA signature length"; + } + + /* Parse ECDSA signature as per RFC 6605 sec. 4 */ + nettle_dsa_signature_init(&signature); + switch (digest_size) { + case SHA256_DIGEST_SIZE: + { + uint8_t digest[SHA256_DIGEST_SIZE]; + mpz_t x, y; + nettle_ecc_point_init(&pubkey, &nettle_secp_256r1); + nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key); + nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE); + nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock); + nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE); + res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= nettle_ecc_point_set(&pubkey, x, y); + res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature); + mpz_clear(x); + mpz_clear(y); + break; + } + case SHA384_DIGEST_SIZE: + { + uint8_t digest[SHA384_DIGEST_SIZE]; + mpz_t x, y; + nettle_ecc_point_init(&pubkey, &nettle_secp_384r1); + nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key); + nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE); + nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock); + nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE); + res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)gldns_buffer_begin(buf), + (unsigned int)gldns_buffer_limit(buf), (unsigned char*)digest); + res &= nettle_ecc_point_set(&pubkey, x, y); + res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature); + mpz_clear(x); + mpz_clear(y); + nettle_ecc_point_clear(&pubkey); + break; + } + default: + return "unknown ECDSA algorithm"; + } + + /* Clear and return */ + nettle_dsa_signature_clear(&signature); + if (!res) + return "ECDSA signature verification failed"; + else + return NULL; +} +#endif + +/** + * Check a canonical sig+rrset and signature against a dnskey + * @param buf: buffer with data to verify, the first rrsig part and the + * canonicalized rrset. + * @param algo: DNSKEY algorithm. + * @param sigblock: signature rdata field from RRSIG + * @param sigblock_len: length of sigblock data. + * @param key: public key data from DNSKEY RR. + * @param keylen: length of keydata. + * @param reason: bogus reason in more detail. + * @return secure if verification succeeded, bogus on crypto failure, + * unchecked on format errors and alloc failures. + */ +int +_getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, + unsigned int sigblock_len, unsigned char* key, unsigned int keylen, + char** reason) +{ + unsigned int digest_size = 0; + + if (sigblock_len == 0 || keylen == 0) { + *reason = "null signature"; + return 0; + } + + switch(algo) { +#ifdef USE_DSA + case GLDNS_DSA: + case GLDNS_DSA_NSEC3: + *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); + if (*reason != NULL) + return 0; + else + return 1; +#endif /* USE_DSA */ + + case GLDNS_RSASHA1: + case GLDNS_RSASHA1_NSEC3: + digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE); +#ifdef USE_SHA2 + case GLDNS_RSASHA256: + digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); + case GLDNS_RSASHA512: + digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE); + +#endif + *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock, + sigblock_len, key, keylen); + if (*reason != NULL) + return 0; + else + return 1; + +#ifdef USE_ECDSA + case GLDNS_ECDSAP256SHA256: + digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); + case GLDNS_ECDSAP384SHA384: + digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE); + *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock, + sigblock_len, key, keylen); + if (*reason != NULL) + return 0; + else + return 1; +#endif + case GLDNS_RSAMD5: + case GLDNS_ECC_GOST: + default: + *reason = "unable to verify signature, unknown algorithm"; + return 0; + } +} + +#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */ diff --git a/src/util/val_secalgo.h b/src/util/val_secalgo.h index 924217a0..917ebc00 100644 --- a/src/util/val_secalgo.h +++ b/src/util/val_secalgo.h @@ -44,6 +44,21 @@ #define VALIDATOR_VAL_SECALGO_H struct gldns_buffer; +/** Return size of nsec3 hash algorithm, 0 if not supported */ +size_t nsec3_hash_algo_size_supported(int id); + +/** + * Hash a single hash call of an NSEC3 hash algorithm. + * Iterations and salt are done by the caller. + * @param algo: nsec3 hash algorithm. + * @param buf: the buffer to digest + * @param len: length of buffer to digest. + * @param res: result stored here (must have sufficient space). + * @return false on failure. +*/ +int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, + unsigned char* res); + /** * Return size of DS digest according to its hash algorithm. * @param algo: DS digest algo. From e10e774d325938dbbaa78b9543b4305e3fa70b7d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 24 Mar 2016 11:46:42 +0100 Subject: [PATCH 2/3] Reversed IPv6 lookup can take a while --- src/test/Makefile.in | 8 ++++---- src/test/check_getdns_hostname.h | 2 +- src/test/check_getdns_hostname_sync.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 8afada13..03e1cce1 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -154,10 +154,10 @@ nolibcheck: test: $(NOLIBCHECK) all (cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}') rm -f fails - CK_LOG_FILE_NAME="$(CHECK_GETDNS).log" ./$(CHECK_GETDNS) || echo "$(CHECK_GETDNS) failed" >> fails - if test $(have_libevent) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_EVENT_PROG).log" ./$(CHECK_EVENT_PROG) || echo "$(CHECK_EVENT_PROG) failed" >> fails; fi - if test $(have_libev) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_EV_PROG).log" ./$(CHECK_EV_PROG) || echo "$(CHECK_EV_PROG) failed" >> fails; fi - if test $(have_libuv) = 1 ; then CK_LOG_FILE_NAME="$(CHECK_UV_PROG).log" ./$(CHECK_UV_PROG) || echo "$(CHECK_UV_PROG) failed" >> fails; fi + CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_GETDNS).log" ./$(CHECK_GETDNS) || echo "$(CHECK_GETDNS) failed" >> fails + if test $(have_libevent) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_EVENT_PROG).log" ./$(CHECK_EVENT_PROG) || echo "$(CHECK_EVENT_PROG) failed" >> fails; fi + if test $(have_libev) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_EV_PROG).log" ./$(CHECK_EV_PROG) || echo "$(CHECK_EV_PROG) failed" >> fails; fi + if test $(have_libuv) = 1 ; then CK_TIMEOUT_MULTIPLIER=2 CK_LOG_FILE_NAME="$(CHECK_UV_PROG).log" ./$(CHECK_UV_PROG) || echo "$(CHECK_UV_PROG) failed" >> fails; fi test ! -e fails @echo "All tests OK" diff --git a/src/test/check_getdns_hostname.h b/src/test/check_getdns_hostname.h index 8403ea14..461ad373 100644 --- a/src/test/check_getdns_hostname.h +++ b/src/test/check_getdns_hostname.h @@ -401,7 +401,7 @@ struct getdns_context *context = NULL; struct getdns_dict *address = NULL; struct getdns_bindata address_type = { 5, (void *)"IPv6" }; - struct getdns_bindata address_data = { 16, (void *)"\x2a\x04\xb9\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x37" }; + struct getdns_bindata address_data = { 16, (void *)"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88" }; void* eventloop = NULL; getdns_transaction_t transaction_id = 0; diff --git a/src/test/check_getdns_hostname_sync.h b/src/test/check_getdns_hostname_sync.h index e4053509..260a0f19 100644 --- a/src/test/check_getdns_hostname_sync.h +++ b/src/test/check_getdns_hostname_sync.h @@ -338,7 +338,7 @@ struct getdns_context *context = NULL; struct getdns_dict *address = NULL; struct getdns_bindata address_type = { 5, (void *)"IPv6" }; - struct getdns_bindata address_data = { 16, (void *)"\x2a\x04\xb9\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x37" }; + struct getdns_bindata address_data = { 16, (void *)"\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88" }; struct getdns_dict *response = NULL; CONTEXT_CREATE(TRUE); From fdd3992f655006994c442680f628ae066bc8f4be Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 24 Mar 2016 14:02:18 +0100 Subject: [PATCH 3/3] openssl 1.1 support --- configure.ac | 14 +++++++++++++- m4/acx_openssl.m4 | 26 +++++++++++++------------- src/context.c | 27 +++++++++++++++++++++------ src/pubkey-pinning.c | 7 +------ src/request-internal.c | 30 ++++++++++++++++++++---------- src/sync.c | 2 ++ 6 files changed, 70 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index 5fb0a23c..633ffcdf 100644 --- a/configure.ac +++ b/configure.ac @@ -223,7 +223,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_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode]) +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]) 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 @@ -404,6 +404,18 @@ 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(draft-dnssec-roadblock-avoidance, AC_HELP_STRING([--enable-draft-dnssec-roadblock-avoidance], [Enable experimental dnssec roadblock avoidance])) AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies])) diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index 485f6599..fc3b4dde 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -47,16 +47,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [ ACX_RUNTIME_PATH_ADD([$ssldir/lib]) fi - AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) + AC_MSG_CHECKING([for HMAC_Update in -lcrypto]) LIBS="-lssl -lcrypto $LIBS" LIBSSL_LIBS="-lssl -lcrypto $LIBSSL_LIBS" AC_TRY_LINK(, [ - int HMAC_CTX_init(void); - (void)HMAC_CTX_init(); + int HMAC_Update(void); + (void)HMAC_Update(); ], [ + AC_DEFINE([HAVE_HMAC_UPDATE], 1, + [If you have HMAC_Update]) AC_MSG_RESULT(yes) - AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, - [If you have HMAC_CTX_init]) ], [ AC_MSG_RESULT(no) # check if -lwsock32 or -lgdi32 are needed. @@ -66,11 +66,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [ LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" AC_MSG_CHECKING([if -lcrypto needs -lgdi32]) AC_TRY_LINK([], [ - int HMAC_CTX_init(void); - (void)HMAC_CTX_init(); + int HMAC_Update(void); + (void)HMAC_Update(); ],[ - AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, - [If you have HMAC_CTX_init]) + AC_DEFINE([HAVE_HMAC_UPDATE], 1, + [If you have HMAC_Update]) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) @@ -80,11 +80,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [ LIBSSL_LIBS="$LIBSSL_LIBS -ldl" AC_MSG_CHECKING([if -lcrypto needs -ldl]) AC_TRY_LINK([], [ - int HMAC_CTX_init(void); - (void)HMAC_CTX_init(); + int HMAC_Update(void); + (void)HMAC_Update(); ],[ - AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, - [If you have HMAC_CTX_init]) + AC_DEFINE([HAVE_HMAC_UPDATE], 1, + [If you have HMAC_Update]) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) diff --git a/src/context.c b/src/context.c index ba2096f9..53cad3f3 100644 --- a/src/context.c +++ b/src/context.c @@ -1232,7 +1232,7 @@ getdns_context_create_with_extended_memory_functions( result->edns_do_bit = 0; result->edns_client_subnet_private = 0; result->tls_query_padding_blocksize = 1; /* default is to not try to pad */ - result-> tls_ctx = NULL; + result->tls_ctx = NULL; result->extension = &result->default_eventloop.loop; _getdns_default_eventloop_init(&result->default_eventloop); @@ -1926,17 +1926,19 @@ getdns_return_t getdns_context_set_dns_root_servers( getdns_context *context, getdns_list *addresses) { -#if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB) +#ifdef HAVE_LIBUNBOUND +# ifndef HAVE_UB_CTX_SET_STUB char tmpfn[FILENAME_MAX] = P_tmpdir "/getdns-root-dns-servers-XXXXXX"; FILE *fh; int fd; size_t dst_len; -#endif +# endif size_t i; getdns_dict *rr_dict; getdns_return_t r; getdns_bindata *addr_bd; char dst[2048]; +#endif getdns_list *newlist; if (!context) @@ -2893,9 +2895,22 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, if (context->tls_ctx == NULL) { #ifdef HAVE_TLS_v1_2 /* Create client context, use TLS v1.2 only for now */ +# ifdef HAVE_TLS_CLIENT_METHOD + context->tls_ctx = SSL_CTX_new(TLS_client_method()); +# else context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); +# endif if(context->tls_ctx == NULL) return GETDNS_RETURN_BAD_CONTEXT; + +# ifdef HAVE_TLS_CLIENT_METHOD + if (!SSL_CTX_set_min_proto_version( + context->tls_ctx, TLS1_2_VERSION)) { + SSL_CTX_free(context->tls_ctx); + context->tls_ctx = NULL; + return GETDNS_RETURN_BAD_CONTEXT; + } +# endif /* Be strict and only use the cipher suites recommended in RFC7525 Unless we later fallback to opportunistic. */ const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM"; @@ -2903,11 +2918,11 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, return GETDNS_RETURN_BAD_CONTEXT; /* For strict authentication, we must have local root certs available Set up is done only when the tls_ctx is created (per getdns_context)*/ -#ifndef USE_WINSOCK +# ifndef USE_WINSOCK if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) { -#else +# else if (!add_WIN_cacerts_to_openssl_store(context->tls_ctx)) { -#endif /* USE_WINSOCK */ +# endif /* USE_WINSOCK */ if (context->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) return GETDNS_RETURN_BAD_CONTEXT; } diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 427c965d..5263882b 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -393,18 +393,13 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, } x = sk_X509_value(store->untrusted, i); - if (x->cert_info == NULL) - continue; #if defined(STUB_DEBUG) && STUB_DEBUG DEBUG_STUB("%s %-35s: Name of cert: %d ", STUB_DEBUG_SETUP_TLS, __FUNCTION__, i); if (x->cert_info->subject != NULL) - X509_NAME_print_ex_fp(stderr, x->cert_info->subject, 1, XN_FLAG_ONELINE); + X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE); fprintf(stderr, "\n"); #endif - if (x->cert_info->key == NULL) - continue; - /* digest the cert with sha256 */ len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); if (len > sizeof(raw)) { diff --git a/src/request-internal.c b/src/request-internal.c index 69a6718c..429e6b2f 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -459,7 +459,10 @@ _getdns_network_validate_tsig(getdns_network_req *req) unsigned int result_mac_len = EVP_MAX_MD_SIZE; uint16_t original_id; const EVP_MD *digester; - HMAC_CTX ctx; + HMAC_CTX *ctx; +#ifndef HAVE_HMAC_CTX_NEW + HMAC_CTX ctx_space; +#endif DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNCTION__); for ( rr = _getdns_rr_iter_init(&rr_spc, req->query, @@ -587,14 +590,18 @@ _getdns_network_validate_tsig(getdns_network_req *req) #endif default : return; } - - HMAC_CTX_init(&ctx); - (void) HMAC_Init_ex(&ctx, req->upstream->tsig_key, +#ifdef HAVE_HMAC_CTX_NEW + ctx = HMAC_CTX_new(); +#else + ctx = &ctx_space; + HMAC_CTX_init(ctx); +#endif + (void) HMAC_Init_ex(ctx, req->upstream->tsig_key, req->upstream->tsig_size, digester, NULL); - (void) HMAC_Update(&ctx, request_mac - 2, request_mac_len + 2); - (void) HMAC_Update(&ctx, req->response, rr->pos - req->response); - (void) HMAC_Update(&ctx, tsig_vars, gldns_buffer_position(&gbuf)); - HMAC_Final(&ctx, result_mac, &result_mac_len); + (void) HMAC_Update(ctx, request_mac - 2, request_mac_len + 2); + (void) HMAC_Update(ctx, req->response, rr->pos - req->response); + (void) HMAC_Update(ctx, tsig_vars, gldns_buffer_position(&gbuf)); + HMAC_Final(ctx, result_mac, &result_mac_len); DEBUG_STUB("%s %-35s: Result MAC length: %d\n", STUB_DEBUG_TSIG, __FUNCTION__, (int)(result_mac_len)); @@ -602,8 +609,11 @@ _getdns_network_validate_tsig(getdns_network_req *req) memcmp(result_mac, response_mac, result_mac_len) == 0) req->tsig_status = GETDNS_DNSSEC_SECURE; - HMAC_CTX_cleanup(&ctx); - +#ifdef HAVE_HMAC_CTX_FREE + HMAC_CTX_free(ctx); +#else + HMAC_CTX_cleanup(ctx); +#endif gldns_write_uint16(req->response, gldns_read_uint16(req->query)); gldns_write_uint16(req->response + 10, gldns_read_uint16(req->response + 10) + 1); diff --git a/src/sync.c b/src/sync.c index a75ce081..508492a6 100644 --- a/src/sync.c +++ b/src/sync.c @@ -57,7 +57,9 @@ typedef struct getdns_sync_data { static getdns_return_t getdns_sync_data_init(getdns_context *context, getdns_sync_data *data) { +#ifdef HAVE_LIBUNBOUND getdns_eventloop *ext = &context->sync_eventloop.loop; +#endif data->context = context; data->to_run = 1;