]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- algorithm compromise protection using the algorithms signalled in
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 21 Dec 2010 14:19:55 +0000 (14:19 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 21 Dec 2010 14:19:55 +0000 (14:19 +0000)
         the DS record.  Also, trust anchors, DLV, and RFC5011 receive this,
         and thus, if you have multiple algorithms in your trust-anchor-file
         then it will now behave different than before.  Also, 5011 rollover
         for algorithms needs to be double-signature until the old algorithm
         is revoked.

git-svn-id: file:///svn/unbound/trunk@2358 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
validator/autotrust.c
validator/val_utils.c
validator/val_utils.h
validator/validator.c

index a4f02e33de121c776b3c834dd5201e1c7927ca3a..9ba77404d70e16af2b49ddaa60dbdd942eee69b2 100644 (file)
@@ -1,3 +1,12 @@
+21 December 2010: Wouter
+       - algorithm compromise protection using the algorithms signalled in
+         the DS record.  Also, trust anchors, DLV, and RFC5011 receive this,
+         and thus, if you have multiple algorithms in your trust-anchor-file
+         then it will now behave different than before.  Also, 5011 rollover
+         for algorithms needs to be double-signature until the old algorithm
+         is revoked.
+         It is not an option, because I see no use to turn the security off.
+
 17 December 2010: Wouter
        - squelch 'tcp connect: bla' in logfile, (set verbosity 2 to see them).
        - fix validation in this case: CNAME to nodata for co-hosted opt-in
index e43d94166a84a8be4874fc52be7f0fe3b09e25c6..943f57b545298611fa8ed9502ce81f50d1bfb6d7 100644 (file)
@@ -972,27 +972,17 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
         struct trust_anchor* tp, struct ub_packed_rrset_key* rrset)
 {
        char* reason = NULL;
-       if(tp->ds_rrset) {
-               /* verify with ds, any will do to prime autotrust */
-               enum sec_status sec = val_verify_DNSKEY_with_DS(
-                       env, ve, rrset, tp->ds_rrset, 0, &reason);
-               verbose(VERB_ALGO, "autotrust: validate DNSKEY with DS: %s",
-                       sec_status_to_string(sec));
-               if(sec == sec_status_secure) {
-                       return 1;
-               }
-       }
-       if(tp->dnskey_rrset) {
-               /* verify with keys */
-               enum sec_status sec = val_verify_rrset(env, ve, rrset,
-                       tp->dnskey_rrset, 0, &reason);
-               verbose(VERB_ALGO, "autotrust: validate DNSKEY with keys: %s",
-                       sec_status_to_string(sec));
-               if(sec == sec_status_secure) {
-                       return 1;
-               }
-       }
-       return 0;
+       uint8_t sigalg[ALGO_NEEDS_MAX+1];
+       int downprot = 1;
+       enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
+               tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason);
+       /* sigalg is ignored, it returns algorithms signalled to exist, but
+        * in 5011 there are no other rrsets to check.  if downprot is
+        * enabled, then it checks that the DNSKEY is signed with all
+        * algorithms available in the trust store. */
+       verbose(VERB_ALGO, "autotrust: validate DNSKEY with anchor: %s",
+               sec_status_to_string(sec));
+       return sec == sec_status_secure;
 }
 
 /** Find minimum expiration interval from signatures */
@@ -1024,6 +1014,8 @@ rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve,
        char* reason = NULL;
        verbose(VERB_ALGO, "seen REVOKE flag, check self-signed, rr %d",
                (int)i);
+       /* no algorithm downgrade protection necessary, if it is selfsigned
+        * revoked it can be removed. */
        sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i, 
                &reason);
        return (sec == sec_status_secure);
index 928af2b2a4240481d1b1b7278851a297280437ae..b0475d8031c4b6978a3274742308322e73bb8db2 100644 (file)
@@ -551,8 +551,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
        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. */
+       /* as long as this is false, we can consider this anchor to be
+        * equivalent to no anchor. */
        int has_useful_ta = 0, digest_algo = 0, alg;
        struct algo_needs needs;
        size_t i, num;
@@ -591,9 +591,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                 * 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) {
+                       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 
@@ -620,9 +619,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
            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)) {
+               if(!dnskey_algo_is_supported(ta_dnskey, i))
                        continue;
-               }
 
                /* we saw a useful TA */
                has_useful_ta = true;
@@ -632,7 +630,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
                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.");
+                               verbose(VERB_ALGO, "anchor matched DNSKEY.");
                                return sec_status_secure;
                        }
                } else if(sigalg && sec == sec_status_bogus) {
@@ -642,7 +640,6 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
            }
        }
 
-
        /* If no DSs were understandable, then this is OK. */
        if(!has_useful_ta) {
                verbose(VERB_ALGO, "No usable trust anchors were found -- "
@@ -659,7 +656,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
 }
 
 struct key_entry_key* 
-val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env, 
+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,
index c38b82ce9518470acc102a33cf3afd03a83daf9f..f0afc3756e9f1e105bb7c5734e5d1aa611e30b9f 100644 (file)
@@ -158,6 +158,27 @@ 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, uint8_t* sigalg, char** reason);
 
+/**
+ * Verify DNSKEYs with DS and DNSKEY rrset.  Like val_verify_DNSKEY_with_DS
+ * but for a trust anchor.
+ * @param env: module environment (scratch buffer)
+ * @param ve: validator environment (verification settings)
+ * @param dnskey_rrset: DNSKEY rrset to verify
+ * @param ta_ds: DS rrset to verify with.
+ * @param ta_dnskey: DNSKEY rrset to verify with.
+ * @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).
+ *     sec_status_bogus if it fails.
+ */
+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);
+
 /**
  * Verify new DNSKEYs with DS rrset. The DS contains hash values that should
  * match the DNSKEY keys.
index c907574d94c079f0c9c6e818c0ed224b56ee06ea..c765567441eaf76a1d2385251cc74f3cfdeb7715 100644 (file)
@@ -2241,6 +2241,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
        struct key_entry_key* kkey = NULL;
        enum sec_status sec = sec_status_unchecked;
        char* reason = NULL;
+       int downprot = 1;
 
        if(!dnskey_rrset) {
                log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
@@ -2262,7 +2263,8 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
        }
        /* attempt to verify with trust anchor DS and DNSKEY */
        kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, 
-               dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, 0, &reason);
+               dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot,
+               &reason);
        if(!kkey) {
                log_err("out of memory: verifying prime TA");
                return NULL;