return 0;
}
+/** return number of rrs in an rrset */
+static size_t
+rrset_get_count(struct ub_packed_rrset_key* rrset)
+{
+ struct packed_rrset_data* d = (struct packed_rrset_data*)
+ rrset->entry.data;
+ if(!d) return 0;
+ return d->count;
+}
+
+/** setup sig alg list from dnskey */
+static void
+setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
+{
+ uint8_t a[ALGO_NEEDS_MAX];
+ size_t i, n = 0;
+ memset(a, 0, sizeof(a));
+ for(i=0; i<rrset_get_count(dnskey); i++) {
+ uint8_t algo = dnskey_get_algo(dnskey, i);
+ if(a[algo] == 0) {
+ a[algo] = 1;
+ sigalg[n++] = algo;
+ }
+ }
+ sigalg[n] = 0;
+}
+
/** verify and test one rrset against the key rrset */
static void
verifytest_rrset(struct module_env* env, struct val_env* ve,
{
enum sec_status sec;
char* reason = NULL;
+ uint8_t sigalg[ALGO_NEEDS_MAX+1];
if(vsig) {
log_nametypeclass(VERB_QUERY, "verify of rrset",
rrset->rk.dname, ntohs(rrset->rk.type),
ntohs(rrset->rk.rrset_class));
}
- sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, 1, &reason);
+ setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
+ sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason);
if(vsig) {
printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
reason?reason:"");
s += packed_rrset_sizeof(kd->rrset_data);
if(kd->reason)
s += strlen(kd->reason)+1;
+ if(kd->algo)
+ s += strlen((char*)kd->algo)+1;
return s;
}
struct key_entry_data* kd = (struct key_entry_data*)data;
free(kd->reason);
free(kd->rrset_data);
+ free(kd->algo);
free(kd);
}
if(!newd->reason)
return NULL;
}
+ if(d->algo) {
+ newd->algo = (uint8_t*)regional_strdup(region,
+ (char*)d->algo);
+ if(!newd->algo)
+ return NULL;
+ }
newk->entry.data = newd;
}
return newk;
return NULL;
}
}
+ if(d->algo) {
+ newd->algo = (uint8_t*)strdup((char*)d->algo);
+ if(!newd->algo) {
+ free(newd->rrset_data);
+ free(newd->reason);
+ free(newd);
+ free(newk->name);
+ free(newk);
+ return NULL;
+ }
+ }
newk->entry.data = newd;
}
return newk;
d->reason = NULL;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
+ d->algo = NULL;
return k;
}
struct key_entry_key*
key_entry_create_rrset(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass,
- struct ub_packed_rrset_key* rrset, uint32_t now)
+ struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now)
{
struct key_entry_key* k;
struct key_entry_data* d;
rd, packed_rrset_sizeof(rd));
if(!d->rrset_data)
return NULL;
+ if(sigalg) {
+ d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
+ if(!d->algo)
+ return NULL;
+ } else d->algo = NULL;
packed_rrset_ptr_fixup(d->rrset_data);
return k;
}
d->reason = NULL;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
+ d->algo = NULL;
return k;
}
struct packed_rrset_data* rrset_data;
/** not NULL sometimes to give reason why bogus */
char* reason;
+ /** list of algorithms signalled, ends with 0, or NULL */
+ uint8_t* algo;
/** DNS RR type of the rrset data (host order) */
uint16_t rrset_type;
/** if the key is bad: Bogus or malformed */
* @param namelen: length of name
* @param dclass: class of key entry. (host order);
* @param rrset: data for key entry. This is copied to the region.
+ * @param sigalg: signalled algorithm list (or NULL).
* @param now: current time (added to ttl of rrset)
* @return new key entry or NULL on alloc failure
*/
struct key_entry_key* key_entry_create_rrset(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass,
- struct ub_packed_rrset_key* rrset, uint32_t now);
+ struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now);
/**
* Create a bad entry, in the given region.
n->num = total;
}
+void algo_needs_init_dnskey_add(struct algo_needs* n,
+ struct ub_packed_rrset_key* dnskey, uint8_t* sigalg)
+{
+ uint8_t algo;
+ size_t i, total = n->num;
+ size_t num = rrset_get_count(dnskey);
+
+ for(i=0; i<num; i++) {
+ algo = (uint8_t)dnskey_get_algo(dnskey, i);
+ if(!dnskey_algo_id_is_supported((int)algo))
+ continue;
+ if(n->needs[algo] == 0) {
+ n->needs[algo] = 1;
+ sigalg[total] = algo;
+ total++;
+ }
+ }
+ sigalg[total] = 0;
+ n->num = total;
+}
+
+void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg)
+{
+ uint8_t algo;
+ size_t total = 0;
+
+ memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX);
+ while( (algo=*sigalg) != 0) {
+ log_assert(dnskey_algo_id_is_supported((int)algo));
+ log_assert(n->needs[algo] == 0);
+ n->needs[algo] = 1;
+ total++;
+ sigalg++;
+ }
+ n->num = total;
+}
+
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
- int fav_ds_algo)
+ int fav_ds_algo, uint8_t* sigalg)
{
uint8_t algo;
size_t i, total = 0;
algo = (uint8_t)ds_get_key_algo(ds, i);
if(!dnskey_algo_id_is_supported((int)algo))
continue;
+ log_assert(algo != 0); /* we do not support 0 and is EOS */
if(n->needs[algo] == 0) {
n->needs[algo] = 1;
+ sigalg[total] = algo;
total++;
}
}
+ sigalg[total] = 0;
n->num = total;
}
enum sec_status
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
- int downprot, char** reason)
+ uint8_t* sigalg, char** reason)
{
enum sec_status sec;
size_t i, num;
return sec_status_bogus;
}
- algo_needs_init_dnskey(&needs, dnskey);
- if(algo_needs_num_missing(&needs) == 0) {
- verbose(VERB_QUERY, "DNSKEY has no known algorithms");
- *reason = "DNSKEY has no known algorithms";
- return sec_status_insecure;
+ if(sigalg) {
+ algo_needs_init_list(&needs, sigalg);
+ if(algo_needs_num_missing(&needs) == 0) {
+ verbose(VERB_QUERY, "zone has no known algorithms");
+ *reason = "zone has no known algorithms";
+ return sec_status_insecure;
+ }
}
for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
dnskey, i, &sortree, reason);
/* see which algorithm has been fixed up */
if(sec == sec_status_secure) {
- if(!downprot)
+ if(!sigalg)
return sec; /* done! */
else if(algo_needs_set_secure(&needs,
(uint8_t)rrset_get_sig_algo(rrset, i)))
return sec; /* done! */
- } else if(downprot && sec == sec_status_bogus) {
+ } else if(sigalg && sec == sec_status_bogus) {
algo_needs_set_bogus(&needs,
(uint8_t)rrset_get_sig_algo(rrset, i));
}
}
verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for "
"%d algorithms", (int)algo_needs_num_missing(&needs));
- if(downprot && (alg=algo_needs_missing(&needs)) != 0) {
+ if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
algo_needs_reason(env, alg, reason, "no signatures");
}
return sec_status_bogus;
/** number of entries in algorithm needs array */
#define ALGO_NEEDS_MAX 256
+
/**
* Storage for algorithm needs. DNSKEY algorithms.
*/
void algo_needs_init_dnskey(struct algo_needs* n,
struct ub_packed_rrset_key* dnskey);
+/**
+ * Initialize algo needs structure, set algos from rrset as needed.
+ * Results are added to an existing need structure.
+ * @param n: struct with storage.
+ * @param dnskey: algos from this struct set as necessary. DNSKEY set.
+ * @param sigalg: adds to signalled algorithm list too.
+ */
+void algo_needs_init_dnskey_add(struct algo_needs* n,
+ struct ub_packed_rrset_key* dnskey, uint8_t* sigalg);
+
+/**
+ * Initialize algo needs structure from a signalled algo list.
+ * @param n: struct with storage.
+ * @param sigalg: signalled algorithm list, numbers ends with 0.
+ */
+void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg);
+
/**
* Initialize algo needs structure, set algos from rrset as needed.
* @param n: struct with storage.
* @param ds: algos from this struct set as necessary. DS set.
* @param fav_ds_algo: filter to use only this DS algo.
+ * @param sigalg: list of signalled algos, constructed as output,
+ * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero.
*/
void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds,
- int fav_ds_algo);
+ int fav_ds_algo, uint8_t* sigalg);
/**
* Mark this algorithm as a success, sec_secure, and see if we are done.
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset to try.
- * @param downprot: if true provide downgrade protection otherwise one
+ * @param sigalg: if nonNULL provide downgrade protection otherwise one
* algorithm is enough.
* @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @return SECURE if one key in the set verifies one rrsig.
*/
enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
- struct ub_packed_rrset_key* dnskey, int downprot, char** reason);
+ struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason);
/**
* verify rrset against one specific dnskey (from rrset)
enum sec_status
val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
- int downprot, char** reason)
+ uint8_t* sigalg, char** reason)
{
enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
}
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
- sec = dnskeyset_verify_rrset(env, ve, rrset, keys, downprot, reason);
+ sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch);
dnskey.rk.dname_len = kkey->namelen;
dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data;
- sec = val_verify_rrset(env, ve, rrset, &dnskey, 1, reason);
+ sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason);
return sec;
}
enum sec_status
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason)
+ struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason)
{
/* as long as this is false, we can consider this DS rrset to be
* equivalent to no DS rrset. */
}
digest_algo = val_favorite_ds_algo(ds_rrset);
- if(downprot)
- algo_needs_init_ds(&needs, ds_rrset, digest_algo);
+ if(sigalg)
+ algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg);
num = rrset_get_count(ds_rrset);
for(i=0; i<num; i++) {
/* Check to see if we can understand this DS.
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
ds_rrset, i, reason);
if(sec == sec_status_secure) {
- if(!downprot || algo_needs_set_secure(&needs,
+ if(!sigalg || algo_needs_set_secure(&needs,
(uint8_t)ds_get_key_algo(ds_rrset, i))) {
verbose(VERB_ALGO, "DS matched DNSKEY.");
return sec_status_secure;
}
- } else if(downprot && sec == sec_status_bogus) {
+ } else if(sigalg && sec == sec_status_bogus) {
algo_needs_set_bogus(&needs,
(uint8_t)ds_get_key_algo(ds_rrset, i));
}
}
/* If any were understandable, then it is bad. */
verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
- if(downprot && (alg=algo_needs_missing(&needs)) != 0) {
+ if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
algo_needs_reason(env, alg, reason, "missing verification of "
"DNSKEY signature");
}
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason)
{
+ uint8_t sigalg[ALGO_NEEDS_MAX+1];
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
- dnskey_rrset, ds_rrset, downprot, reason);
+ dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
ds_rrset->rk.dname, ds_rrset->rk.dname_len,
ntohs(ds_rrset->rk.rrset_class), dnskey_rrset,
- *env->now);
+ downprot?sigalg:NULL, *env->now);
} else if(sec == sec_status_insecure) {
return key_entry_create_null(region, ds_rrset->rk.dname,
ds_rrset->rk.dname_len,
BOGUS_KEY_TTL, *env->now);
}
+enum sec_status
+val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
+ struct ub_packed_rrset_key* dnskey_rrset,
+ struct ub_packed_rrset_key* ta_ds,
+ struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason)
+{
+ /* as long as this is false, we can consider this DS rrset to be
+ * equivalent to no DS rrset. */
+ int has_useful_ta = 0, digest_algo = 0, alg;
+ struct algo_needs needs;
+ size_t i, num;
+ enum sec_status sec;
+
+ if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len ||
+ query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname)
+ != 0)) {
+ verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
+ "by name");
+ *reason = "DNSKEY RRset did not match DS RRset by name";
+ return sec_status_bogus;
+ }
+ if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
+ || query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname)
+ != 0)) {
+ verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
+ "by name");
+ *reason = "DNSKEY RRset did not match anchor RRset by name";
+ return sec_status_bogus;
+ }
+
+ if(ta_ds)
+ digest_algo = val_favorite_ds_algo(ta_ds);
+ if(sigalg) {
+ if(ta_ds)
+ algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg);
+ else memset(&needs, 0, sizeof(needs));
+ if(ta_dnskey)
+ algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg);
+ }
+ if(ta_ds) {
+ num = rrset_get_count(ta_ds);
+ 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(ta_ds, i) ||
+ !ds_key_algo_is_supported(ta_ds, i) ||
+ ds_get_digest_algo(ta_ds, i) != digest_algo) {
+ continue;
+ }
+
+ /* Once we see a single DS with a known digestID and
+ * algorithm, we cannot return INSECURE (with a
+ * "null" KeyEntry). */
+ has_useful_ta = true;
+
+ sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
+ ta_ds, i, reason);
+ if(sec == sec_status_secure) {
+ if(!sigalg || algo_needs_set_secure(&needs,
+ (uint8_t)ds_get_key_algo(ta_ds, i))) {
+ verbose(VERB_ALGO, "DS matched DNSKEY.");
+ return sec_status_secure;
+ }
+ } else if(sigalg && sec == sec_status_bogus) {
+ algo_needs_set_bogus(&needs,
+ (uint8_t)ds_get_key_algo(ta_ds, i));
+ }
+ }
+ }
+
+ /* None of the DS's worked out: check the DNSKEYs. */
+ if(ta_dnskey) {
+ num = rrset_get_count(ta_dnskey);
+ for(i=0; i<num; i++) {
+ /* Check to see if we can understand this DNSKEY */
+ if(!dnskey_algo_is_supported(ta_dnskey, i)) {
+ continue;
+ }
+
+ /* we saw a useful TA */
+ has_useful_ta = true;
+
+ sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
+ ta_dnskey, i, reason);
+ if(sec == sec_status_secure) {
+ if(!sigalg || algo_needs_set_secure(&needs,
+ (uint8_t)dnskey_get_algo(ta_dnskey, i))) {
+ verbose(VERB_ALGO, "DS matched DNSKEY.");
+ return sec_status_secure;
+ }
+ } else if(sigalg && sec == sec_status_bogus) {
+ algo_needs_set_bogus(&needs,
+ (uint8_t)dnskey_get_algo(ta_dnskey, i));
+ }
+ }
+ }
+
+
+ /* If no DSs were understandable, then this is OK. */
+ if(!has_useful_ta) {
+ verbose(VERB_ALGO, "No usable trust anchors were found -- "
+ "treating as insecure.");
+ return sec_status_insecure;
+ }
+ /* If any were understandable, then it is bad. */
+ verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
+ if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
+ algo_needs_reason(env, alg, reason, "missing verification of "
+ "DNSKEY signature");
+ }
+ return sec_status_bogus;
+}
+
+struct key_entry_key*
+val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
+ struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
+ struct ub_packed_rrset_key* ta_ds_rrset,
+ struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
+ char** reason)
+{
+ uint8_t sigalg[ALGO_NEEDS_MAX+1];
+ enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
+ dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
+ downprot?sigalg:NULL, reason);
+
+ if(sec == sec_status_secure) {
+ return key_entry_create_rrset(region,
+ dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
+ ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
+ downprot?sigalg:NULL, *env->now);
+ } else if(sec == sec_status_insecure) {
+ return key_entry_create_null(region, dnskey_rrset->rk.dname,
+ dnskey_rrset->rk.dname_len,
+ ntohs(dnskey_rrset->rk.rrset_class),
+ rrset_get_ttl(dnskey_rrset), *env->now);
+ }
+ return key_entry_create_bad(region, dnskey_rrset->rk.dname,
+ dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class),
+ BOGUS_KEY_TTL, *env->now);
+}
+
int
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
{
* @param ve: validator environment (verification settings)
* @param rrset: what to verify
* @param keys: dnskey rrset to verify with.
- * @param downprot: if true provide downgrade protection otherwise one
- * algorithm is enough.
+ * @param sigalg: if nonNULL provide downgrade protection otherwise one
+ * algorithm is enough. Algo list is constructed in here.
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @return security status of verification.
*/
enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
- int downprot, char** reason);
+ uint8_t* sigalg, char** reason);
/**
* Verify RRset with keys from a keyset.
* @param ve: validator environment (verification settings)
* @param dnskey_rrset: DNSKEY rrset to verify
* @param ds_rrset: DS rrset to verify with.
- * @param downprot: if true provide downgrade protection otherwise one
- * algorithm is enough.
+ * @param sigalg: if nonNULL provide downgrade protection otherwise one
+ * algorithm is enough. The list of signalled algorithms is returned,
+ * must have enough space for ALGO_NEEDS_MAX+1.
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
*/
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason);
+ struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason);
/**
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
* generally only occur in a private algorithm scenario: normally
* this sort of thing is checked before fetching the matching DNSKEY
* rrset.
+ * if downprot is set, a key entry with an algo list is made.
*/
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason);
+
+/**
+ * Verify rrset with trust anchor: DS and DNSKEY rrset.
+ *
+ * @param region: where to allocate key entry result.
+ * @param env: module environment (scratch buffer)
+ * @param ve: validator environment (verification settings)
+ * @param dnskey_rrset: DNSKEY rrset to verify
+ * @param ta_ds_rrset: DS rrset to verify with.
+ * @param ta_dnskey_rrset: the DNSKEY rrset to verify with.
+ * @param downprot: if true provide downgrade protection otherwise one
+ * algorithm is enough.
+ * @param reason: reason of failure. Fixed string or alloced in scratch.
+ * @return a KeyEntry. This will either contain the now trusted
+ * dnskey_rrset, a "null" key entry indicating that this DS
+ * rrset/DNSKEY pair indicate an secure end to the island of trust
+ * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey
+ * rrset fails to verify. Note that the "null" response should
+ * generally only occur in a private algorithm scenario: normally
+ * this sort of thing is checked before fetching the matching DNSKEY
+ * rrset.
+ * if downprot is set, a key entry with an algo list is made.
+ */
+struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
+ struct module_env* env, struct val_env* ve,
+ struct ub_packed_rrset_key* dnskey_rrset,
+ struct ub_packed_rrset_key* ta_ds_rrset,
+ struct ub_packed_rrset_key* ta_dnskey_rrset,
+ int downprot, char** reason);
+
/**
* Determine if DS rrset is usable for validator or not.
* Returns true if the algorithms for key and DShash are supported,
#include "validator/val_nsec.h"
#include "validator/val_nsec3.h"
#include "validator/val_neg.h"
+#include "validator/val_sigcrypt.h"
#include "validator/autotrust.h"
#include "services/cache/dns.h"
#include "util/data/dname.h"
return kkey;
}
/* attempt to verify with trust anchor DS and DNSKEY */
- if(ta->ds_rrset) {
- kkey = val_verify_new_DNSKEYs(qstate->region, qstate->env, ve,
- dnskey_rrset, ta->ds_rrset, 0, &reason);
- if(!kkey) {
- log_err("out of memory: verifying prime DS");
- return NULL;
- }
- if(key_entry_isgood(kkey))
- sec = sec_status_secure;
- else
- sec = sec_status_bogus;
- verbose(VERB_DETAIL, "validate keys with anchor(DS): %s",
- sec_status_to_string(sec));
- }
- if(sec != sec_status_secure && ta->dnskey_rrset) {
- sec = val_verify_rrset(qstate->env, ve, dnskey_rrset,
- ta->dnskey_rrset, 0, &reason);
- verbose(VERB_DETAIL, "validate keys with anchor(DNSKEY): %s",
- sec_status_to_string(sec));
- if(sec == sec_status_secure) {
- kkey = key_entry_create_rrset(qstate->region,
- ta->name, ta->namelen, ta->dclass,
- dnskey_rrset, *qstate->env->now);
- if(!kkey) {
- log_err("out of memory: allocate primed key");
- return NULL;
- }
- }
+ kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve,
+ dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, 0, &reason);
+ if(!kkey) {
+ log_err("out of memory: verifying prime TA");
+ return NULL;
}
+ if(key_entry_isgood(kkey))
+ sec = sec_status_secure;
+ else
+ sec = sec_status_bogus;
+ verbose(VERB_DETAIL, "validate keys with anchor(DS): %s",
+ sec_status_to_string(sec));
if(sec != sec_status_secure) {
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
log_query_info(VERB_DETAIL, "validated DS", qinfo);
*ke = key_entry_create_rrset(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds,
- *qstate->env->now);
+ NULL, *qstate->env->now);
return (*ke) != NULL;
} else if(subtype == VAL_CLASS_NODATA ||
subtype == VAL_CLASS_NAMEERROR) {