aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/validator
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/validator')
-rw-r--r--external/unbound/validator/autotrust.c14
-rw-r--r--external/unbound/validator/autotrust.h8
-rw-r--r--external/unbound/validator/val_anchor.c59
-rw-r--r--external/unbound/validator/val_anchor.h19
-rw-r--r--external/unbound/validator/val_neg.c32
-rw-r--r--external/unbound/validator/val_neg.h10
-rw-r--r--external/unbound/validator/val_nsec.c2
-rw-r--r--external/unbound/validator/val_nsec3.c28
-rw-r--r--external/unbound/validator/val_nsec3.h4
-rw-r--r--external/unbound/validator/val_secalgo.c316
-rw-r--r--external/unbound/validator/val_secalgo.h8
-rw-r--r--external/unbound/validator/val_sigcrypt.c44
-rw-r--r--external/unbound/validator/val_sigcrypt.h6
-rw-r--r--external/unbound/validator/val_utils.c64
-rw-r--r--external/unbound/validator/validator.c22
-rw-r--r--external/unbound/validator/validator.h2
16 files changed, 482 insertions, 156 deletions
diff --git a/external/unbound/validator/autotrust.c b/external/unbound/validator/autotrust.c
index f8c9c8c63..a533733c7 100644
--- a/external/unbound/validator/autotrust.c
+++ b/external/unbound/validator/autotrust.c
@@ -430,6 +430,8 @@ find_add_tp(struct val_anchors* anchors, uint8_t* rr, size_t rr_len,
}
tp = autr_tp_create(anchors, rr, dname_len, sldns_wirerr_get_class(rr,
rr_len, dname_len));
+ if(!tp)
+ return NULL;
lock_basic_lock(&tp->lock);
return tp;
}
@@ -1062,7 +1064,7 @@ int autr_read_file(struct val_anchors* anchors, const char* nm)
/** string for a trustanchor state */
static const char*
-trustanchor_state2str(autr_state_t s)
+trustanchor_state2str(autr_state_type s)
{
switch (s) {
case AUTR_STATE_START: return " START ";
@@ -1201,7 +1203,7 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp)
if(fsync(fileno(out)) != 0)
log_err("could not fsync(%s): %s", fname, strerror(errno));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
if(fclose(out) != 0) {
fatal_exit("could not complete write: %s: %s",
@@ -1677,7 +1679,7 @@ reset_holddown(struct module_env* env, struct autr_ta* ta, int* changed)
/** Set the state for this trust anchor */
static void
set_trustanchor_state(struct module_env* env, struct autr_ta* ta, int* changed,
- autr_state_t s)
+ autr_state_type s)
{
verbose_key(ta, VERB_ALGO, "update: %s to %s",
trustanchor_state2str(ta->s), trustanchor_state2str(s));
@@ -1987,7 +1989,7 @@ calc_next_probe(struct module_env* env, time_t wait)
static time_t
wait_probe_time(struct val_anchors* anchors)
{
- rbnode_t* t = rbtree_first(&anchors->autr->probe);
+ rbnode_type* t = rbtree_first(&anchors->autr->probe);
if(t != RBTREE_NULL)
return ((struct trust_anchor*)t->key)->autr->next_probe_time;
return 0;
@@ -2326,6 +2328,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
qinfo.qname_len = tp->namelen;
qinfo.qtype = LDNS_RR_TYPE_DNSKEY;
qinfo.qclass = tp->dclass;
+ qinfo.local_alias = NULL;
log_query_info(VERB_ALGO, "autotrust probe", &qinfo);
verbose(VERB_ALGO, "retry probe set in %d seconds",
(int)tp->autr->next_probe_time - (int)*env->now);
@@ -2333,6 +2336,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
edns.ext_rcode = 0;
edns.edns_version = 0;
edns.bits = EDNS_DO;
+ edns.opt_list = NULL;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
@@ -2359,7 +2363,7 @@ static struct trust_anchor*
todo_probe(struct module_env* env, time_t* next)
{
struct trust_anchor* tp;
- rbnode_t* el;
+ rbnode_type* el;
/* get first one */
lock_basic_lock(&env->anchors->lock);
if( (el=rbtree_first(&env->anchors->autr->probe)) == RBTREE_NULL) {
diff --git a/external/unbound/validator/autotrust.h b/external/unbound/validator/autotrust.h
index ae61f8a87..dbaf5126a 100644
--- a/external/unbound/validator/autotrust.h
+++ b/external/unbound/validator/autotrust.h
@@ -58,7 +58,7 @@ typedef enum {
AUTR_STATE_MISSING = 3,
AUTR_STATE_REVOKED = 4,
AUTR_STATE_REMOVED = 5
-} autr_state_t;
+} autr_state_type;
/**
* Autotrust metadata for one trust anchor key.
@@ -73,7 +73,7 @@ struct autr_ta {
/** last update of key state (new pending count keeps date the same) */
time_t last_change;
/** 5011 state */
- autr_state_t s;
+ autr_state_type s;
/** pending count */
uint8_t pending_count;
/** fresh TA was seen */
@@ -90,7 +90,7 @@ struct autr_point_data {
/** file to store the trust point in. chrootdir already applied. */
char* file;
/** rbtree node for probe sort, key is struct trust_anchor */
- rbnode_t pnode;
+ rbnode_type pnode;
/** the keys */
struct autr_ta* keys;
@@ -126,7 +126,7 @@ struct autr_point_data {
struct autr_global_data {
/** rbtree of autotrust anchors sorted by next probe time.
* When time is equal, sorted by anchor class, name. */
- rbtree_t probe;
+ rbtree_type probe;
};
/**
diff --git a/external/unbound/validator/val_anchor.c b/external/unbound/validator/val_anchor.c
index 845b54a2e..6c6322447 100644
--- a/external/unbound/validator/val_anchor.c
+++ b/external/unbound/validator/val_anchor.c
@@ -48,6 +48,7 @@
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
+#include "util/as112.h"
#include "sldns/sbuffer.h"
#include "sldns/rrdef.h"
#include "sldns/str2wire.h"
@@ -112,7 +113,7 @@ assembled_rrset_delete(struct ub_packed_rrset_key* pkey)
/** destroy locks in tree and delete autotrust anchors */
static void
-anchors_delfunc(rbnode_t* elem, void* ATTR_UNUSED(arg))
+anchors_delfunc(rbnode_type* elem, void* ATTR_UNUSED(arg))
{
struct trust_anchor* ta = (struct trust_anchor*)elem;
if(!ta) return;
@@ -197,7 +198,7 @@ anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs,
size_t namelen, uint16_t dclass)
{
struct trust_anchor key;
- rbnode_t* n;
+ rbnode_type* n;
if(!name) return NULL;
key.node.key = &key;
key.name = name;
@@ -221,7 +222,7 @@ anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs,
size_t namelen, uint16_t dclass, int lockit)
{
#ifdef UNBOUND_DEBUG
- rbnode_t* r;
+ rbnode_type* r;
#endif
struct trust_anchor* ta = (struct trust_anchor*)malloc(
sizeof(struct trust_anchor));
@@ -989,7 +990,7 @@ anchors_assemble_rrsets(struct val_anchors* anchors)
size_t nods, nokey;
lock_basic_lock(&anchors->lock);
ta=(struct trust_anchor*)rbtree_first(anchors->tree);
- while((rbnode_t*)ta != RBTREE_NULL) {
+ while((rbnode_type*)ta != RBTREE_NULL) {
next = (struct trust_anchor*)rbtree_next(&ta->node);
lock_basic_lock(&ta->lock);
if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) {
@@ -1029,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;
@@ -1044,8 +1047,18 @@ int
anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
{
struct config_strlist* f;
+ const char** zstr;
char* nm;
sldns_buffer* parsebuf = sldns_buffer_new(65535);
+ if(cfg->insecure_lan_zones) {
+ for(zstr = as112_zones; *zstr; zstr++) {
+ if(!anchor_insert_insecure(anchors, *zstr)) {
+ log_err("error in insecure-lan-zones: %s", *zstr);
+ sldns_buffer_free(parsebuf);
+ return 0;
+ }
+ }
+ }
for(f = cfg->domain_insecure; f; f = f->next) {
if(!f->str || f->str[0] == 0) /* empty "" */
continue;
@@ -1151,7 +1164,7 @@ anchors_lookup(struct val_anchors* anchors,
{
struct trust_anchor key;
struct trust_anchor* result;
- rbnode_t* res = NULL;
+ rbnode_type* res = NULL;
key.node.key = &key;
key.name = qname;
key.namelabs = dname_count_labels(qname);
@@ -1260,3 +1273,39 @@ anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
anchors_delfunc(&ta->node, NULL);
}
+/** compare two keytags, return -1, 0 or 1 */
+static int
+keytag_compare(const void* x, const void* y)
+{
+ if(*(uint16_t*)x == *(uint16_t*)y)
+ return 0;
+ if(*(uint16_t*)x > *(uint16_t*)y)
+ return 1;
+ return -1;
+}
+
+size_t
+anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num)
+{
+ size_t i, ret = 0;
+ if(ta->numDS == 0 && ta->numDNSKEY == 0)
+ return 0; /* insecure point */
+ if(ta->numDS != 0 && ta->ds_rrset) {
+ struct packed_rrset_data* d=(struct packed_rrset_data*)
+ ta->ds_rrset->entry.data;
+ for(i=0; i<d->count; i++) {
+ if(ret == num) continue;
+ list[ret++] = ds_get_keytag(ta->ds_rrset, i);
+ }
+ }
+ if(ta->numDNSKEY != 0 && ta->dnskey_rrset) {
+ struct packed_rrset_data* d=(struct packed_rrset_data*)
+ ta->dnskey_rrset->entry.data;
+ for(i=0; i<d->count; i++) {
+ if(ret == num) continue;
+ list[ret++] = dnskey_calc_keytag(ta->dnskey_rrset, i);
+ }
+ }
+ qsort(list, ret, sizeof(*list), keytag_compare);
+ return ret;
+}
diff --git a/external/unbound/validator/val_anchor.h b/external/unbound/validator/val_anchor.h
index 4951b9996..318a2b227 100644
--- a/external/unbound/validator/val_anchor.h
+++ b/external/unbound/validator/val_anchor.h
@@ -59,14 +59,14 @@ struct sldns_buffer;
*/
struct val_anchors {
/** lock on trees */
- lock_basic_t lock;
+ lock_basic_type lock;
/**
* Anchors are store in this tree. Sort order is chosen, so that
* dnames are in nsec-like order. A lookup on class, name will return
* an exact match of the closest match, with the ancestor needed.
* contents of type trust_anchor.
*/
- rbtree_t* tree;
+ rbtree_type* tree;
/** The DLV trust anchor (if one is configured, else NULL) */
struct trust_anchor* dlv_anchor;
/** Autotrust global data, anchors sorted by next probe time */
@@ -93,9 +93,9 @@ struct ta_key {
*/
struct trust_anchor {
/** rbtree node, key is this structure */
- rbnode_t node;
+ rbnode_type node;
/** lock on the entire anchor and its keys; for autotrust changes */
- lock_basic_t lock;
+ lock_basic_type lock;
/** name of this trust anchor */
uint8_t* name;
/** length of name */
@@ -216,4 +216,15 @@ int anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm);
void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
uint8_t* nm);
+/**
+ * Get a list of keytags for the trust anchor. Zero tags for insecure points.
+ * @param ta: trust anchor (locked by caller).
+ * @param list: array of uint16_t.
+ * @param num: length of array.
+ * @return number of keytags filled into array. If total number of keytags is
+ * bigger than the array, it is truncated at num. On errors, less keytags
+ * are filled in. The array is sorted.
+ */
+size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num);
+
#endif /* VALIDATOR_VAL_ANCHOR_H */
diff --git a/external/unbound/validator/val_neg.c b/external/unbound/validator/val_neg.c
index ab31f483e..fe57ac2c4 100644
--- a/external/unbound/validator/val_neg.c
+++ b/external/unbound/validator/val_neg.c
@@ -111,7 +111,7 @@ size_t val_neg_get_mem(struct val_neg_cache* neg)
/** clear datas on cache deletion */
static void
-neg_clear_datas(rbnode_t* n, void* ATTR_UNUSED(arg))
+neg_clear_datas(rbnode_type* n, void* ATTR_UNUSED(arg))
{
struct val_neg_data* d = (struct val_neg_data*)n;
free(d->name);
@@ -120,7 +120,7 @@ neg_clear_datas(rbnode_t* n, void* ATTR_UNUSED(arg))
/** clear zones on cache deletion */
static void
-neg_clear_zones(rbnode_t* n, void* ATTR_UNUSED(arg))
+neg_clear_zones(rbnode_type* n, void* ATTR_UNUSED(arg))
{
struct val_neg_zone* z = (struct val_neg_zone*)n;
/* delete all the rrset entries in the tree */
@@ -371,7 +371,7 @@ static struct val_neg_zone* neg_closest_zone_parent(struct val_neg_cache* neg,
{
struct val_neg_zone key;
struct val_neg_zone* result;
- rbnode_t* res = NULL;
+ rbnode_type* res = NULL;
key.node.key = &key;
key.name = nm;
key.len = nm_len;
@@ -411,7 +411,7 @@ static struct val_neg_data* neg_closest_data_parent(
{
struct val_neg_data key;
struct val_neg_data* result;
- rbnode_t* res = NULL;
+ rbnode_type* res = NULL;
key.node.key = &key;
key.name = nm;
key.len = nm_len;
@@ -677,7 +677,7 @@ static void wipeout(struct val_neg_cache* neg, struct val_neg_zone* zone,
uint8_t* end;
size_t end_len;
int end_labs, m;
- rbnode_t* walk, *next;
+ rbnode_type* walk, *next;
struct val_neg_data* cur;
uint8_t buf[257];
/* get endpoint */
@@ -823,13 +823,22 @@ void neg_insert_data(struct val_neg_cache* neg,
(h != zone->nsec3_hash || it != zone->nsec3_iter ||
slen != zone->nsec3_saltlen ||
memcmp(zone->nsec3_salt, s, slen) != 0)) {
- uint8_t* sa = memdup(s, slen);
- if(sa) {
+
+ if(slen > 0) {
+ uint8_t* sa = memdup(s, slen);
+ if(sa) {
+ free(zone->nsec3_salt);
+ zone->nsec3_salt = sa;
+ zone->nsec3_saltlen = slen;
+ zone->nsec3_iter = it;
+ zone->nsec3_hash = h;
+ }
+ } else {
free(zone->nsec3_salt);
- zone->nsec3_salt = sa;
- zone->nsec3_saltlen = slen;
- zone->nsec3_hash = h;
+ zone->nsec3_salt = NULL;
+ zone->nsec3_saltlen = 0;
zone->nsec3_iter = it;
+ zone->nsec3_hash = h;
}
}
}
@@ -902,7 +911,7 @@ static int neg_closest_data(struct val_neg_zone* zone,
uint8_t* qname, size_t len, int labs, struct val_neg_data** data)
{
struct val_neg_data key;
- rbnode_t* r;
+ rbnode_type* r;
key.node.key = &key;
key.name = qname;
key.len = len;
@@ -998,6 +1007,7 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
qinfo.qname = qname;
qinfo.qtype = LDNS_RR_TYPE_DLV;
qinfo.qclass = qclass;
+ qinfo.local_alias = NULL;
if(!nsec_proves_nodata(nsec, &qinfo, &wc) &&
!val_nsec_proves_name_error(nsec, qname)) {
/* the NSEC is not a denial for the DLV */
diff --git a/external/unbound/validator/val_neg.h b/external/unbound/validator/val_neg.h
index bf3a2471c..6ae71306c 100644
--- a/external/unbound/validator/val_neg.h
+++ b/external/unbound/validator/val_neg.h
@@ -67,9 +67,9 @@ struct ub_packed_rrset_key;
struct val_neg_cache {
/** the big lock on the negative cache. Because we use a rbtree
* for the data (quick lookup), we need a big lock */
- lock_basic_t lock;
+ lock_basic_type lock;
/** The zone rbtree. contents sorted canonical, type val_neg_zone */
- rbtree_t tree;
+ rbtree_type tree;
/** the first in linked list of LRU of val_neg_data */
struct val_neg_data* first;
/** last in lru (least recently used element) */
@@ -87,7 +87,7 @@ struct val_neg_cache {
*/
struct val_neg_zone {
/** rbtree node element, key is this struct: the name, class */
- rbnode_t node;
+ rbnode_type node;
/** name; the key */
uint8_t* name;
/** length of name */
@@ -114,7 +114,7 @@ struct val_neg_zone {
/** tree of NSEC data for this zone, sorted canonical
* by NSEC owner name */
- rbtree_t tree;
+ rbtree_type tree;
/** class of node; host order */
uint16_t dclass;
@@ -135,7 +135,7 @@ struct val_neg_zone {
*/
struct val_neg_data {
/** rbtree node element, key is this struct: the name */
- rbnode_t node;
+ rbnode_type node;
/** name; the key */
uint8_t* name;
/** length of name */
diff --git a/external/unbound/validator/val_nsec.c b/external/unbound/validator/val_nsec.c
index f104a347c..1e4f440ff 100644
--- a/external/unbound/validator/val_nsec.c
+++ b/external/unbound/validator/val_nsec.c
@@ -343,7 +343,7 @@ int nsec_proves_nodata(struct ub_packed_rrset_key* nsec,
} else {
/* See if the next owner name covers a wildcard
* empty non-terminal. */
- while (dname_strict_subdomain_c(nm, nsec->rk.dname)) {
+ while (dname_canonical_compare(nsec->rk.dname, nm) < 0) {
/* wildcard does not apply if qname below
* the name that exists under the '*' */
if (dname_subdomain_c(qinfo->qname, nm))
diff --git a/external/unbound/validator/val_nsec3.c b/external/unbound/validator/val_nsec3.c
index 22867d170..4d978372a 100644
--- a/external/unbound/validator/val_nsec3.c
+++ b/external/unbound/validator/val_nsec3.c
@@ -623,14 +623,14 @@ nsec3_calc_b32(struct regional* region, sldns_buffer* buf,
}
int
-nsec3_hash_name(rbtree_t* table, struct regional* region, sldns_buffer* buf,
+nsec3_hash_name(rbtree_type* table, struct regional* region, sldns_buffer* buf,
struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname,
size_t dname_len, struct nsec3_cached_hash** hash)
{
struct nsec3_cached_hash* c;
struct nsec3_cached_hash looki;
#ifdef UNBOUND_DEBUG
- rbnode_t* n;
+ rbnode_type* n;
#endif
int r;
looki.node.key = &looki;
@@ -730,7 +730,7 @@ nsec3_hash_matches_owner(struct nsec3_filter* flt,
*/
static int
find_matching_nsec3(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, uint8_t* nm, size_t nmlen,
+ rbtree_type* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr)
{
size_t i_rs;
@@ -823,7 +823,7 @@ nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash,
*/
static int
find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, uint8_t* nm, size_t nmlen,
+ rbtree_type* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr)
{
size_t i_rs;
@@ -869,7 +869,7 @@ find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt,
*/
static int
nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, struct query_info* qinfo, struct ce_response* ce)
+ rbtree_type* ct, struct query_info* qinfo, struct ce_response* ce)
{
uint8_t* nm = qinfo->qname;
size_t nmlen = qinfo->qname_len;
@@ -936,7 +936,7 @@ next_closer(uint8_t* qname, size_t qnamelen, uint8_t* ce,
*/
static enum sec_status
nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, struct query_info* qinfo, int prove_does_not_exist,
+ rbtree_type* ct, struct query_info* qinfo, int prove_does_not_exist,
struct ce_response* ce)
{
uint8_t* nc;
@@ -1016,7 +1016,7 @@ nsec3_ce_wildcard(struct regional* region, uint8_t* ce, size_t celen,
/** Do the name error proof */
static enum sec_status
nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, struct query_info* qinfo)
+ rbtree_type* ct, struct query_info* qinfo)
{
struct ce_response ce;
uint8_t* wc;
@@ -1062,7 +1062,7 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey)
{
- rbtree_t ct;
+ rbtree_type ct;
struct nsec3_filter flt;
if(!list || num == 0 || !kkey || !key_entry_isgood(kkey))
@@ -1086,7 +1086,7 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
/** Do the nodata proof */
static enum sec_status
nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
- rbtree_t* ct, struct query_info* qinfo)
+ rbtree_type* ct, struct query_info* qinfo)
{
struct ce_response ce;
uint8_t* wc;
@@ -1180,7 +1180,7 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) &&
!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) {
verbose(VERB_ALGO, "nsec3 nodata proof: matching "
- "wilcard is a delegation, bogus");
+ "wildcard is a delegation, bogus");
return sec_status_bogus;
}
/* everything is peachy keen, except for optout spans */
@@ -1221,7 +1221,7 @@ nsec3_prove_nodata(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey)
{
- rbtree_t ct;
+ rbtree_type ct;
struct nsec3_filter flt;
if(!list || num == 0 || !kkey || !key_entry_isgood(kkey))
@@ -1240,7 +1240,7 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc)
{
- rbtree_t ct;
+ rbtree_type ct;
struct nsec3_filter flt;
struct ce_response ce;
uint8_t* nc;
@@ -1314,7 +1314,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, char** reason)
{
- rbtree_t ct;
+ rbtree_type ct;
struct nsec3_filter flt;
struct ce_response ce;
struct ub_packed_rrset_key* rrset;
@@ -1403,7 +1403,7 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
struct query_info* qinfo, struct key_entry_key* kkey, int* nodata)
{
enum sec_status sec, secnx;
- rbtree_t ct;
+ rbtree_type ct;
struct nsec3_filter flt;
*nodata = 0;
diff --git a/external/unbound/validator/val_nsec3.h b/external/unbound/validator/val_nsec3.h
index 69ba78d83..27e9f9eac 100644
--- a/external/unbound/validator/val_nsec3.h
+++ b/external/unbound/validator/val_nsec3.h
@@ -224,7 +224,7 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
*/
struct nsec3_cached_hash {
/** rbtree node, key is this structure */
- rbnode_t node;
+ rbnode_type node;
/** where are the parameters for conversion, in this rrset data */
struct ub_packed_rrset_key* nsec3;
/** where are the parameters for conversion, this RR number in data */
@@ -271,7 +271,7 @@ int nsec3_hash_cmp(const void* c1, const void* c2);
* 0 on a malloc failure.
* -1 if the NSEC3 rr was badly formatted (i.e. formerr).
*/
-int nsec3_hash_name(rbtree_t* table, struct regional* region,
+int nsec3_hash_name(rbtree_type* table, struct regional* region,
struct sldns_buffer* buf, struct ub_packed_rrset_key* nsec3, int rr,
uint8_t* dname, size_t dname_len, struct nsec3_cached_hash** hash);
diff --git a/external/unbound/validator/val_secalgo.c b/external/unbound/validator/val_secalgo.c
index b55d4a62c..be88ff438 100644
--- a/external/unbound/validator/val_secalgo.c
+++ b/external/unbound/validator/val_secalgo.c
@@ -72,6 +72,11 @@
#include <openssl/engine.h>
#endif
+/** fake DSA support for unit tests */
+int fake_dsa = 0;
+/** fake SHA1 support for unit tests */
+int fake_sha1 = 0;
+
/* return size of digest if supported, or 0 otherwise */
size_t
nsec3_hash_algo_size_supported(int id)
@@ -98,6 +103,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ (void)SHA256(buf, len, res);
+}
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@@ -107,9 +118,12 @@ size_t
ds_digest_size_supported(int algo)
{
switch(algo) {
-#ifdef HAVE_EVP_SHA1
case LDNS_SHA1:
+#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
return SHA_DIGEST_LENGTH;
+#else
+ if(fake_sha1) return 20;
+ return 0;
#endif
#ifdef HAVE_EVP_SHA256
case LDNS_SHA256:
@@ -117,6 +131,8 @@ ds_digest_size_supported(int algo)
#endif
#ifdef USE_GOST
case LDNS_HASH_GOST:
+ /* we support GOST if it can be loaded */
+ (void)sldns_key_EVP_load_gost_id();
if(EVP_get_digestbyname("md_gost94"))
return 32;
else return 0;
@@ -147,7 +163,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res)
{
switch(algo) {
-#ifdef HAVE_EVP_SHA1
+#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
case LDNS_SHA1:
(void)SHA1(buf, len, res);
return 1;
@@ -186,8 +202,22 @@ dnskey_algo_id_is_supported(int id)
return 0;
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#if defined(USE_DSA) && defined(USE_SHA1)
+ return 1;
+#else
+ if(fake_dsa || fake_sha1) return 1;
+ return 0;
+#endif
+
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA1
+ return 1;
+#else
+ if(fake_sha1) return 1;
+ return 0;
+#endif
+
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256:
#endif
@@ -198,7 +228,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
#endif
+#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
return 1;
+#endif
+
#ifdef USE_GOST
case LDNS_ECC_GOST:
/* we support GOST if it can be loaded */
@@ -225,6 +258,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).
@@ -253,8 +287,12 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
dsasig = DSA_SIG_new();
if(!dsasig) return 0;
+#ifdef HAVE_DSA_SIG_SET0
+ if(!DSA_SIG_set0(dsasig, R, S)) return 0;
+#else
dsasig->r = R;
dsasig->s = S;
+#endif
*sig = NULL;
newlen = i2d_DSA_SIG(dsasig, sig);
if(newlen < 0) {
@@ -266,6 +304,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
DSA_SIG_free(dsasig);
return 1;
}
+#endif /* USE_DSA */
#ifdef USE_ECDSA
/**
@@ -279,36 +318,82 @@ 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 <R 32bytefor256> 0220 <S 32bytefor256>
+ * 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 */
+#ifdef USE_ECDSA_EVP_WORKAROUND
+static EVP_MD ecdsa_evp_256_md;
+static EVP_MD ecdsa_evp_384_md;
+void ecdsa_evp_workaround_init(void)
+{
+ /* openssl before 1.0.0 fixes RSA with the SHA256
+ * hash in EVP. We create one for ecdsa_sha256 */
+ ecdsa_evp_256_md = *EVP_sha256();
+ ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
+
+ ecdsa_evp_384_md = *EVP_sha384();
+ ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
+}
+#endif /* USE_ECDSA_EVP_WORKAROUND */
+
/**
* Setup key and digest for verification. Adjust sig if necessary.
*
@@ -323,10 +408,13 @@ static int
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen)
{
+#if defined(USE_DSA) && defined(USE_SHA1)
DSA* dsa;
+#endif
RSA* rsa;
switch(algo) {
+#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*evp_key = EVP_PKEY_new();
@@ -352,8 +440,13 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
#endif
break;
+#endif /* USE_DSA && USE_SHA1 */
+
+#if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
+#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
+#endif
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256:
#endif
@@ -388,9 +481,14 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = EVP_sha512();
else
#endif
+#ifdef USE_SHA1
*digest_type = EVP_sha1();
-
+#else
+ { verbose(VERB_QUERY, "no digest available"); return 0; }
+#endif
break;
+#endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
+
case LDNS_RSAMD5:
*evp_key = EVP_PKEY_new();
if(!*evp_key) {
@@ -437,20 +535,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA256
- * hash in EVP. We create one for ecdsa_sha256 */
- {
- static int md_ecdsa_256_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_256_done) {
- EVP_MD m = *EVP_sha256();
- md_ecdsa_256_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_256_md;
#else
*digest_type = EVP_sha256();
#endif
@@ -464,20 +549,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA384
- * hash in EVP. We create one for ecdsa_sha384 */
- {
- static int md_ecdsa_384_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_384_done) {
- EVP_MD m = *EVP_sha384();
- md_ecdsa_384_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_384_md;
#else
*digest_type = EVP_sha384();
#endif
@@ -510,9 +582,18 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
char** reason)
{
const EVP_MD *digest_type;
- EVP_MD_CTX ctx;
- int res, dofree = 0;
+ EVP_MD_CTX* ctx;
+ int res, dofree = 0, docrypto_free = 0;
EVP_PKEY *evp_key = NULL;
+
+#ifndef USE_DSA
+ if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
+ return sec_status_secure;
+#endif
+#ifndef USE_SHA1
+ if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
+ return sec_status_secure;
+#endif
if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
verbose(VERB_QUERY, "verify: failed to setup key");
@@ -520,6 +601,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,10 +611,14 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
- dofree = 1;
+ docrypto_free = 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");
@@ -545,32 +631,48 @@ 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_DigestInit(&ctx, digest_type) == 0) {
- verbose(VERB_QUERY, "verify: EVP_DigestInit 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);
+ else if(docrypto_free) OPENSSL_free(sigblock);
return sec_status_unchecked;
}
- if(EVP_DigestUpdate(&ctx, (unsigned char*)sldns_buffer_begin(buf),
- (unsigned int)sldns_buffer_limit(buf)) == 0) {
- verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed");
+ 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);
+ else if(docrypto_free) OPENSSL_free(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");
+ 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_MD_CTX_destroy(ctx);
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
return sec_status_unchecked;
}
+
+ res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
+#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);
+ if(dofree) free(sigblock);
+ else if(docrypto_free) OPENSSL_free(sigblock);
if(res == 1) {
return sec_status_secure;
@@ -622,13 +724,21 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
+}
+
size_t
ds_digest_size_supported(int algo)
{
/* uses libNSS */
switch(algo) {
+#ifdef USE_SHA1
case LDNS_SHA1:
return SHA1_LENGTH;
+#endif
#ifdef USE_SHA2
case LDNS_SHA256:
return SHA256_LENGTH;
@@ -650,9 +760,11 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
{
/* uses libNSS */
switch(algo) {
+#ifdef USE_SHA1
case LDNS_SHA1:
return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
== SECSuccess;
+#endif
#if defined(USE_SHA2)
case LDNS_SHA256:
return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
@@ -680,10 +792,15 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
+#if defined(USE_SHA1) || defined(USE_SHA2)
+#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#endif
+#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
+#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
#endif
@@ -691,6 +808,8 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSASHA512:
#endif
return 1;
+#endif /* SHA1 or SHA2 */
+
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384:
@@ -922,6 +1041,9 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*/
switch(algo) {
+
+#if defined(USE_SHA1) || defined(USE_SHA2)
+#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*pubkey = nss_buf2dsa(key, keylen);
@@ -932,8 +1054,11 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*htype = HASH_AlgSHA1;
/* no prefix for DSA verification */
break;
+#endif
+#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
+#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
#endif
@@ -960,13 +1085,22 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*prefixlen = sizeof(p_sha512);
} else
#endif
+#ifdef USE_SHA1
{
*htype = HASH_AlgSHA1;
*prefix = p_sha1;
*prefixlen = sizeof(p_sha1);
}
+#else
+ {
+ verbose(VERB_QUERY, "verify: no digest algo");
+ return 0;
+ }
+#endif
break;
+#endif /* SHA1 or SHA2 */
+
case LDNS_RSAMD5:
*pubkey = nss_buf2rsa(key, keylen);
if(!*pubkey) {
@@ -1048,6 +1182,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
}
+#if defined(USE_DSA) && defined(USE_SHA1)
/* need to convert DSA, ECDSA signatures? */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
if(sigblock_len == 1+2*SHA1_LENGTH) {
@@ -1070,6 +1205,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 */
@@ -1133,6 +1269,9 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#include "macros.h"
#include "rsa.h"
#include "dsa.h"
+#ifdef HAVE_NETTLE_DSA_COMPAT_H
+#include "dsa-compat.h"
+#endif
#include "asn1.h"
#ifdef USE_ECDSA
#include "ecdsa.h"
@@ -1208,6 +1347,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
+void
+secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
+{
+ _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
+}
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@@ -1218,7 +1363,12 @@ ds_digest_size_supported(int algo)
{
switch(algo) {
case LDNS_SHA1:
+#ifdef USE_SHA1
return SHA1_DIGEST_SIZE;
+#else
+ if(fake_sha1) return 20;
+ return 0;
+#endif
#ifdef USE_SHA2
case LDNS_SHA256:
return SHA256_DIGEST_SIZE;
@@ -1240,8 +1390,10 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res)
{
switch(algo) {
+#ifdef USE_SHA1
case LDNS_SHA1:
return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
+#endif
#if defined(USE_SHA2)
case LDNS_SHA256:
return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
@@ -1265,10 +1417,14 @@ dnskey_algo_id_is_supported(int id)
{
/* uses libnettle */
switch(id) {
+#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
+#endif
+#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
+#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
case LDNS_RSASHA512:
@@ -1285,12 +1441,13 @@ dnskey_algo_id_is_supported(int id)
}
}
+#if defined(USE_DSA) && defined(USE_SHA1)
static char *
_verify_nettle_dsa(sldns_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;
+ uint8_t key_t_value;
int res = 0;
size_t offset;
struct dsa_public_key pubkey;
@@ -1329,8 +1486,8 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
}
/* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
- key_t = key[0];
- if (key_t > 8) {
+ key_t_value = key[0];
+ if (key_t_value > 8) {
return "invalid T value in DSA pubkey";
}
@@ -1341,9 +1498,9 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
expected_len = 1 + /* T */
20 + /* Q */
- (64 + key_t*8) + /* P */
- (64 + key_t*8) + /* G */
- (64 + key_t*8); /* Y */
+ (64 + key_t_value*8) + /* P */
+ (64 + key_t_value*8) + /* G */
+ (64 + key_t_value*8); /* Y */
if (keylen != expected_len ) {
return "invalid DSA pubkey length";
}
@@ -1353,11 +1510,11 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
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);
+ nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset);
+ offset += (64 + key_t_value*8);
+ nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset);
+ offset += (64 + key_t_value*8);
+ nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset);
/* Digest content of "buf" and verify its DSA signature in "sigblock"*/
res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
@@ -1372,6 +1529,7 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
else
return NULL;
}
+#endif /* USE_DSA */
static char *
_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
@@ -1543,6 +1701,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
}
switch(algo) {
+#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
@@ -1550,10 +1709,13 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
else
return sec_status_secure;
+#endif /* USE_DSA */
+#ifdef USE_SHA1
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
+#endif
#ifdef USE_SHA2
case LDNS_RSASHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
diff --git a/external/unbound/validator/val_secalgo.h b/external/unbound/validator/val_secalgo.h
index 589f1f11d..52aaeb9f6 100644
--- a/external/unbound/validator/val_secalgo.h
+++ b/external/unbound/validator/val_secalgo.h
@@ -60,6 +60,14 @@ int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/**
+ * Calculate the sha256 hash for the data buffer into the result.
+ * @param buf: buffer to digest.
+ * @param len: length of the buffer to digest.
+ * @param res: result is stored here (space 256/8 bytes).
+ */
+void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
+
+/**
* 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.
diff --git a/external/unbound/validator/val_sigcrypt.c b/external/unbound/validator/val_sigcrypt.c
index 1dd07b420..25278a8f3 100644
--- a/external/unbound/validator/val_sigcrypt.c
+++ b/external/unbound/validator/val_sigcrypt.c
@@ -51,6 +51,7 @@
#include "util/module.h"
#include "util/net_help.h"
#include "util/regional.h"
+#include "util/config_file.h"
#include "sldns/keyraw.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
@@ -318,12 +319,17 @@ int ds_digest_match_dnskey(struct module_env* env,
size_t dslen;
uint8_t* digest; /* generated digest */
size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx);
-
+
if(digestlen == 0) {
verbose(VERB_QUERY, "DS fail: not supported, or DS RR "
"format error");
return 0; /* not supported, or DS RR format error */
}
+#ifndef USE_SHA1
+ if(fake_sha1 && ds_get_digest_algo(ds_rrset, ds_idx)==LDNS_SHA1)
+ return 1;
+#endif
+
/* check digest length in DS with length from hash function */
ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen);
if(!ds || dslen != digestlen) {
@@ -483,7 +489,7 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
{
enum sec_status sec;
size_t i, num;
- rbtree_t* sortree = NULL;
+ rbtree_type* sortree = NULL;
/* make sure that for all DNSKEY algorithms there are valid sigs */
struct algo_needs needs;
int alg;
@@ -551,7 +557,7 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
{
enum sec_status sec;
size_t i, num, numchecked = 0;
- rbtree_t* sortree = NULL;
+ rbtree_type* sortree = NULL;
int buf_canon = 0;
uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx);
int algo = dnskey_get_algo(dnskey, dnskey_idx);
@@ -585,7 +591,7 @@ enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
- struct rbtree_t** sortree, char** reason)
+ struct rbtree_type** sortree, char** reason)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
@@ -627,7 +633,7 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
*/
struct canon_rr {
/** rbtree node, key is this structure */
- rbnode_t node;
+ rbnode_type node;
/** rrset the RR is in */
struct ub_packed_rrset_key* rrset;
/** which RR in the rrset */
@@ -885,7 +891,7 @@ canonical_tree_compare(const void* k1, const void* k2)
*/
static void
canonical_sort(struct ub_packed_rrset_key* rrset, struct packed_rrset_data* d,
- rbtree_t* sortree, struct canon_rr* rrs)
+ rbtree_type* sortree, struct canon_rr* rrs)
{
size_t i;
/* insert into rbtree to sort and detect duplicates */
@@ -1043,7 +1049,7 @@ canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
int rrset_canonical_equal(struct regional* region,
struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2)
{
- struct rbtree_t sortree1, sortree2;
+ struct rbtree_type sortree1, sortree2;
struct canon_rr *rrs1, *rrs2, *p1, *p2;
struct packed_rrset_data* d1=(struct packed_rrset_data*)k1->entry.data;
struct packed_rrset_data* d2=(struct packed_rrset_data*)k2->entry.data;
@@ -1120,7 +1126,7 @@ int rrset_canonical_equal(struct regional* region,
static int
rrset_canonical(struct regional* region, sldns_buffer* buf,
struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen,
- struct rbtree_t** sortree)
+ struct rbtree_type** sortree)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
uint8_t* can_owner = NULL;
@@ -1129,8 +1135,8 @@ rrset_canonical(struct regional* region, sldns_buffer* buf,
struct canon_rr* rrs;
if(!*sortree) {
- *sortree = (struct rbtree_t*)regional_alloc(region,
- sizeof(rbtree_t));
+ *sortree = (struct rbtree_type*)regional_alloc(region,
+ sizeof(rbtree_type));
if(!*sortree)
return 0;
if(d->count > RR_COUNT_MAX)
@@ -1283,15 +1289,23 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
/* so now:
* d->ttl: rrset ttl read from message or cache. May be reduced
* origttl: original TTL from signature, authoritative TTL max.
+ * MIN_TTL: minimum TTL from config.
* expittl: TTL until the signature expires.
*
- * Use the smallest of these.
+ * Use the smallest of these, but don't let origttl set the TTL
+ * below the minimum.
*/
- if(d->ttl > (time_t)origttl) {
- verbose(VERB_QUERY, "rrset TTL larger than original TTL,"
- " adjusting TTL downwards");
+ if(MIN_TTL > (time_t)origttl && d->ttl > MIN_TTL) {
+ verbose(VERB_QUERY, "rrset TTL larger than original and minimum"
+ " TTL, adjusting TTL downwards to minimum ttl");
+ d->ttl = MIN_TTL;
+ }
+ else if(MIN_TTL <= origttl && d->ttl > (time_t)origttl) {
+ verbose(VERB_QUERY, "rrset TTL larger than original TTL, "
+ "adjusting TTL downwards to original ttl");
d->ttl = origttl;
}
+
if(expittl > 0 && d->ttl > (time_t)expittl) {
verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl,"
" adjusting TTL downwards");
@@ -1304,7 +1318,7 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
- struct rbtree_t** sortree, int* buf_canon, char** reason)
+ struct rbtree_type** sortree, int* buf_canon, char** reason)
{
enum sec_status sec;
uint8_t* sig; /* RRSIG rdata */
diff --git a/external/unbound/validator/val_sigcrypt.h b/external/unbound/validator/val_sigcrypt.h
index 68aa9a445..5a975acff 100644
--- a/external/unbound/validator/val_sigcrypt.h
+++ b/external/unbound/validator/val_sigcrypt.h
@@ -47,7 +47,7 @@
struct val_env;
struct module_env;
struct ub_packed_rrset_key;
-struct rbtree_t;
+struct rbtree_type;
struct regional;
struct sldns_buffer;
@@ -277,7 +277,7 @@ enum sec_status dnskey_verify_rrset(struct module_env* env,
enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
struct val_env* ve, time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
- struct rbtree_t** sortree, char** reason);
+ struct rbtree_type** sortree, char** reason);
/**
* verify rrset, with specific dnskey(from set), for a specific rrsig
@@ -302,7 +302,7 @@ enum sec_status dnskey_verify_rrset_sig(struct regional* region,
struct sldns_buffer* buf, struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
- struct rbtree_t** sortree, int* buf_canon, char** reason);
+ struct rbtree_type** sortree, int* buf_canon, char** reason);
/**
* canonical compare for two tree entries
diff --git a/external/unbound/validator/val_utils.c b/external/unbound/validator/val_utils.c
index 475b0c905..e3677e1d9 100644
--- a/external/unbound/validator/val_utils.c
+++ b/external/unbound/validator/val_utils.c
@@ -54,6 +54,8 @@
#include "util/net_help.h"
#include "util/module.h"
#include "util/regional.h"
+#include "sldns/wire2str.h"
+#include "sldns/parseutil.h"
enum val_classification
val_classify_response(uint16_t query_flags, struct query_info* origqinf,
@@ -217,7 +219,7 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
{
size_t i;
- if(subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY) {
+ if(subtype == VAL_CLASS_POSITIVE) {
/* check for the answer rrset */
for(i=skip; i<rep->an_numrrsets; i++) {
if(query_dname_compare(qinf->qname,
@@ -269,6 +271,29 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
signer_name, signer_len, &matchcount);
}
}
+ } else if(subtype == VAL_CLASS_ANY) {
+ /* check for one of the answer rrset that has signatures,
+ * or potentially a DNAME is in use with a different qname */
+ for(i=skip; i<rep->an_numrrsets; i++) {
+ if(query_dname_compare(qinf->qname,
+ rep->rrsets[i]->rk.dname) == 0) {
+ val_find_rrset_signer(rep->rrsets[i],
+ signer_name, signer_len);
+ if(*signer_name)
+ return;
+ }
+ }
+ /* no answer RRSIGs with qname, try a DNAME */
+ if(skip < rep->an_numrrsets &&
+ ntohs(rep->rrsets[skip]->rk.type) ==
+ LDNS_RR_TYPE_DNAME) {
+ val_find_rrset_signer(rep->rrsets[skip],
+ signer_name, signer_len);
+ if(*signer_name)
+ return;
+ }
+ *signer_name = NULL;
+ *signer_len = 0;
} else if(subtype == VAL_CLASS_REFERRAL) {
/* find keys for the item at skip */
if(skip < rep->rrset_count) {
@@ -470,16 +495,21 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
return sec_status_bogus;
}
- digest_algo = val_favorite_ds_algo(ds_rrset);
- if(sigalg)
+ if(sigalg) {
+ /* harden against algo downgrade is enabled */
+ digest_algo = val_favorite_ds_algo(ds_rrset);
algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg);
+ } else {
+ /* accept any key algo, any digest algo */
+ digest_algo = -1;
+ }
num = rrset_get_count(ds_rrset);
for(i=0; i<num; i++) {
/* Check to see if we can understand this DS.
* And check it is the strongest digest */
if(!ds_digest_algo_is_supported(ds_rrset, i) ||
!ds_key_algo_is_supported(ds_rrset, i) ||
- ds_get_digest_algo(ds_rrset, i) != digest_algo) {
+ (sigalg && (ds_get_digest_algo(ds_rrset, i) != digest_algo))) {
continue;
}
@@ -691,6 +721,31 @@ val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
ds_key_algo_is_supported(ds_rrset, i))
return 1;
}
+ if(verbosity < VERB_ALGO)
+ return 0;
+ if(rrset_get_count(ds_rrset) == 0)
+ verbose(VERB_ALGO, "DS is not usable");
+ else {
+ /* report usability for the first DS RR */
+ sldns_lookup_table *lt;
+ char herr[64], aerr[64];
+ lt = sldns_lookup_by_id(sldns_hashes,
+ (int)ds_get_digest_algo(ds_rrset, i));
+ if(lt) snprintf(herr, sizeof(herr), "%s", lt->name);
+ else snprintf(herr, sizeof(herr), "%d",
+ (int)ds_get_digest_algo(ds_rrset, i));
+ lt = sldns_lookup_by_id(sldns_algorithms,
+ (int)ds_get_key_algo(ds_rrset, i));
+ if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name);
+ else snprintf(aerr, sizeof(aerr), "%d",
+ (int)ds_get_key_algo(ds_rrset, i));
+ verbose(VERB_ALGO, "DS unsupported, hash %s %s, "
+ "key algorithm %s %s", herr,
+ (ds_digest_algo_is_supported(ds_rrset, 0)?
+ "(supported)":"(unsupported)"), aerr,
+ (ds_key_algo_is_supported(ds_rrset, 0)?
+ "(supported)":"(unsupported)"));
+ }
return 0;
}
@@ -1088,6 +1143,7 @@ val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c,
qinfo.qname_len = nmlen;
qinfo.qtype = LDNS_RR_TYPE_DS;
qinfo.qclass = c;
+ qinfo.local_alias = NULL;
/* do not add SOA to reply message, it is going to be used internal */
msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache,
env->scratch_buffer, *env->now, 0, topname);
diff --git a/external/unbound/validator/validator.c b/external/unbound/validator/validator.c
index db4383bed..81ba5fa17 100644
--- a/external/unbound/validator/validator.c
+++ b/external/unbound/validator/validator.c
@@ -156,6 +156,9 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
return 1;
}
+#ifdef USE_ECDSA_EVP_WORKAROUND
+void ecdsa_evp_workaround_init(void);
+#endif
int
val_init(struct module_env* env, int id)
{
@@ -171,10 +174,14 @@ val_init(struct module_env* env, int id)
lock_basic_init(&val_env->bogus_lock);
lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus,
sizeof(val_env->num_rrset_bogus));
+#ifdef USE_ECDSA_EVP_WORKAROUND
+ ecdsa_evp_workaround_init();
+#endif
if(!val_apply_cfg(env, val_env, env->cfg)) {
log_err("validator: could not apply configuration settings.");
return 0;
}
+
return 1;
}
@@ -371,6 +378,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
ask.qname_len = namelen;
ask.qtype = qtype;
ask.qclass = qclass;
+ ask.local_alias = NULL;
log_query_info(VERB_ALGO, "generate request", &ask);
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
/* enable valrec flag to avoid recursion to the same validation
@@ -2084,15 +2092,17 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
if(qstate->query_flags&BIT_RD) {
/* if secure, this will override cache anyway, no need
* to check if from parentNS */
- if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
- vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
- qstate->query_flags)) {
- log_err("out of memory caching validator results");
+ if(!qstate->no_cache_store) {
+ if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
+ vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
+ qstate->query_flags)) {
+ log_err("out of memory caching validator results");
+ }
}
} else {
/* for a referral, store the verified RRsets */
/* and this does not get prefetched, so no leeway */
- if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
+ if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
vq->orig_msg->rep, 1, 0, 0, NULL,
qstate->query_flags)) {
log_err("out of memory caching validator results");
@@ -2274,6 +2284,7 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
(void)outbound;
if(event == module_event_new ||
(event == module_event_pass && vq == NULL)) {
+
/* pass request to next module, to get it */
verbose(VERB_ALGO, "validator: pass to next module");
qstate->ext_state[id] = module_wait_module;
@@ -2282,6 +2293,7 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
if(event == module_event_moddone) {
/* check if validation is needed */
verbose(VERB_ALGO, "validator: nextmodule returned");
+
if(!needs_validation(qstate, qstate->return_rcode,
qstate->return_msg)) {
/* no need to validate this */
diff --git a/external/unbound/validator/validator.h b/external/unbound/validator/validator.h
index 20f806ada..23d307242 100644
--- a/external/unbound/validator/validator.h
+++ b/external/unbound/validator/validator.h
@@ -126,7 +126,7 @@ struct val_env {
size_t* nsec3_maxiter;
/** lock on bogus counter */
- lock_basic_t bogus_lock;
+ lock_basic_type bogus_lock;
/** number of times rrsets marked bogus */
size_t num_rrset_bogus;
};