DNSSEC08

Status: Final

Purpose

  • Verify that DNSKEY RRset signatures are present, time-valid, algorithm-supported, and cryptographically match DNSKEY records at child nameservers.

Preconditions And Inputs

  • Preconditions:
    • A zone.Zone object is available.
  • Required inputs:
  • Profile/config knobs that affect behavior:
    • net.ipv4 and net.ipv6: disabled transports are skipped with transport debug tags.
    • resolver.defaults.parallel: parallel DNSKEY-query execution fanout.

Algorithm And Decision Flow

  1. Emit TEST_CASE_START.
  2. Build nameserver set from the union of GlueNameservers and ApexNameservers (deduplicated by ns.String()), then deduplicate by IP.
  3. For each unique nameserver IP (parallelized):
    • If transport is disabled, emit IPV4_DISABLED or IPV6_DISABLED for rrtype DNSKEY and skip.
    • Query child apex DNSKEY with DNSSEC enabled.
    • Require response message, RCODE=NOERROR, and AA=true; otherwise skip nameserver.
    • Require at least one apex DNSKEY answer record; otherwise skip nameserver.
    • If no RRSIG answer records, mark nameserver in DNSKEY without RRSIG.
    • Else evaluate each answer-section RRSIG record:
      • If inception is in future, mark DNSKEY RRSIG not yet valid by keytag.
      • Else if expiration is in past, mark DNSKEY RRSIG expired by keytag.
      • Else if signature algorithm is unsupported, mark Algo Not Supported By ZM by keytag+algo.
      • Else find matching DNSKEYs by keytag:
        • If none found, mark No matching DNSKEY.
        • Else verify signature against matching DNSKEY candidates:
          • If verification reports unsupported algorithm (dns.ErrAlg), mark Algo Not Supported By ZM.
          • Else if no candidate validates, mark RRSIG not valid by DNSKEY.
  4. Emit accumulated findings:
    • DS08_MISSING_RRSIG_IN_RESPONSE
    • DS08_DNSKEY_RRSIG_NOT_YET_VALID
    • DS08_DNSKEY_RRSIG_EXPIRED
    • DS08_NO_MATCHING_DNSKEY
    • DS08_RRSIG_NOT_VALID_BY_DNSKEY
    • DS08_ALGO_NOT_SUPPORTED_BY_ZM
  5. Collect nameserver IPs that had RRSIGs and emitted no DS08 failure; if non-empty emit DS08_DNSKEY_RRSIG_VALID.
  6. Emit TEST_CASE_END.

Per-NS DNSKEY RRSIG Verification (steps 2-6)

child set = GlueNameservers ++ ApexNameservers; dedupe by IP

For each unique child NS IP (parallel; fan-out = resolver.defaults.parallel):

   transport disabled for DNSKEY -> IPV4_DISABLED / IPV6_DISABLED, skip
   query DNSKEY at z.Name, DNSSEC=on
    +- resp.Msg == nil / RCODE != NOERROR / !AA  -> skip
    +- no apex DNSKEY in answer                  -> skip
    +- no RRSIG records in answer                -> missingRRSIG[ns]
    +- otherwise, for each RRSIG (per-sig keyed by sig.KeyTag):
         sig.Inception > packet now
                                                 -> rrsigNotYetValid[keytag][ns]
         sig.Expiration < packet now
                                                 -> rrsigExpired[keytag][ns]
         algorithm not supported in advance
                                                 -> algoNotSupportedByZM[keytag][algo][ns]
         no DNSKEY with that keytag in answer
                                                 -> noMatchingDNSKEY[keytag][ns]
         verify against matching DNSKEYs:
            err == ErrAlg
                                                 -> algoNotSupportedByZM[keytag][algo][ns]
            no candidate validates
                                                 -> rrsigNotValidByDNSKEY[keytag][ns]
            success
                                                 -> mark ns as having at least one valid RRSIG

Emit per category:
  missingRRSIG IPs                     -> DS08_MISSING_RRSIG_IN_RESPONSE  (addresses)
  per keytag rrsigNotYetValid          -> DS08_DNSKEY_RRSIG_NOT_YET_VALID (keytag, addresses)
  per keytag rrsigExpired              -> DS08_DNSKEY_RRSIG_EXPIRED       (keytag, addresses)
  per keytag noMatchingDNSKEY          -> DS08_NO_MATCHING_DNSKEY         (keytag, addresses)
  per keytag rrsigNotValidByDNSKEY     -> DS08_RRSIG_NOT_VALID_BY_DNSKEY  (keytag, addresses)
  per (keytag, algo) algoNotSupportedByZM
                                       -> DS08_ALGO_NOT_SUPPORTED_BY_ZM  (keytag, algo_num,
                                                                          algo_mnemo, addresses)

  IPs that had any RRSIG AND no DS08 failure
                                       -> DS08_DNSKEY_RRSIG_VALID         (addresses)

emit TEST_CASE_END

Emitted Tags (Possible Set)

TagEmitted when
DS08_ALGO_NOT_SUPPORTED_BY_ZMRRSIG verification requires an unsupported DNSSEC algorithm.
DS08_DNSKEY_RRSIG_VALIDAt least one nameserver returned DNSKEY with RRSIG and all RRSIG checks passed.
DS08_DNSKEY_RRSIG_EXPIREDDNSKEY-related RRSIG expiration is before packet test time.
DS08_DNSKEY_RRSIG_NOT_YET_VALIDDNSKEY-related RRSIG inception is after packet test time.
DS08_MISSING_RRSIG_IN_RESPONSEDNSKEY answer exists but contains no RRSIG records.
DS08_NO_MATCHING_DNSKEYRRSIG keytag has no matching DNSKEY in DNSKEY RRset.
DS08_RRSIG_NOT_VALID_BY_DNSKEYMatching DNSKEY candidates exist but none validate the RRSIG.
IPV4_DISABLEDIPv4 transport is disabled for a queried nameserver (DNSKEY).
IPV6_DISABLEDIPv6 transport is disabled for a queried nameserver (DNSKEY).
TEST_CASE_ENDTestcase completion marker is emitted.
TEST_CASE_STARTTestcase start marker is emitted.

Tag Arguments

TagArgument keyTypeMeaning
DS08_ALGO_NOT_SUPPORTED_BY_ZMkeytagintRRSIG keytag associated with unsupported algorithm.
DS08_ALGO_NOT_SUPPORTED_BY_ZMalgo_numintUnsupported DNSSEC algorithm number.
DS08_ALGO_NOT_SUPPORTED_BY_ZMalgo_mnemostringUnsupported DNSSEC algorithm mnemonic.
DS08_ALGO_NOT_SUPPORTED_BY_ZMaddressesarray<string>Structured child nameserver IP list.
DS08_DNSKEY_RRSIG_EXPIREDkeytagintRRSIG keytag with expired validity window.
DS08_DNSKEY_RRSIG_EXPIREDaddressesarray<string>Structured child nameserver IP list.
DS08_DNSKEY_RRSIG_NOT_YET_VALIDkeytagintRRSIG keytag with not-yet-valid validity window.
DS08_DNSKEY_RRSIG_NOT_YET_VALIDaddressesarray<string>Structured child nameserver IP list.
DS08_DNSKEY_RRSIG_VALIDaddressesarray<string>Structured child nameserver IP list where all DNSKEY RRSIG checks passed.
DS08_MISSING_RRSIG_IN_RESPONSEaddressesarray<string>Structured child nameserver IP list lacking RRSIG in DNSKEY response.
DS08_NO_MATCHING_DNSKEYkeytagintRRSIG keytag with no matching DNSKEY keytag in DNSKEY RRset.
DS08_NO_MATCHING_DNSKEYaddressesarray<string>Structured child nameserver IP list.
DS08_RRSIG_NOT_VALID_BY_DNSKEYkeytagintRRSIG keytag that failed DNSKEY verification.
DS08_RRSIG_NOT_VALID_BY_DNSKEYaddressesarray<string>Structured child nameserver IP list.
IPV4_DISABLEDnsstringNameserver identity (ns name only; use address for IP) skipped on IPv4.
IPV4_DISABLEDaddressstringNameserver IP address for the same endpoint.
IPV4_DISABLEDrrtypestringrrtype skipped (DNSKEY).
IPV6_DISABLEDnsstringNameserver identity (ns name only; use address for IP) skipped on IPv6.
IPV6_DISABLEDaddressstringNameserver IP address for the same endpoint.
IPV6_DISABLEDrrtypestringrrtype skipped (DNSKEY).
TEST_CASE_ENDtestcasestringTestcase display name (DNSSEC08).
TEST_CASE_STARTtestcasestringTestcase display name (DNSSEC08).

Severity Levels Per Tag

TagLevelNotes
DS08_ALGO_NOT_SUPPORTED_BY_ZMNOTICEDefault from share/profile.json (test_levels.DNSSEC).
DS08_DNSKEY_RRSIG_EXPIREDERRORDefault from share/profile.json (test_levels.DNSSEC).
DS08_DNSKEY_RRSIG_NOT_YET_VALIDERRORDefault from share/profile.json (test_levels.DNSSEC).
DS08_DNSKEY_RRSIG_VALIDINFODefault from share/profile.json (test_levels.DNSSEC).
DS08_MISSING_RRSIG_IN_RESPONSEERRORDefault from share/profile.json (test_levels.DNSSEC).
DS08_NO_MATCHING_DNSKEYERRORDefault from share/profile.json (test_levels.DNSSEC).
DS08_RRSIG_NOT_VALID_BY_DNSKEYERRORDefault from share/profile.json (test_levels.DNSSEC).
IPV4_DISABLEDDEBUGDefault from share/profile.json (test_levels.DNSSEC).
IPV6_DISABLEDDEBUGDefault from share/profile.json (test_levels.DNSSEC).
TEST_CASE_ENDDEBUGDefault from share/profile.json (test_levels.DNSSEC).
TEST_CASE_STARTDEBUGDefault from share/profile.json (test_levels.DNSSEC).

Differences From Upstream

  • Differences (Upstream vs Gonemaster):
    • Upstream: procedure text describes evaluation of DNSKEY RRSIG records (covering the DNSKEY RRset). Gonemaster: evaluates all answer-section RRSIG records and does not explicitly filter on TypeCovered == DNSKEY before classification.
    • Upstream: does not explicitly specify testcase boundary and per-query transport debug emissions in this testcase summary. Gonemaster: emits TEST_CASE_START, TEST_CASE_END, IPV4_DISABLED, and IPV6_DISABLED.
  • Potential upstream report:
    • no

Edge Cases And Limitations

  • Nameserver evaluation is deduplicated by IP; repeated names on one IP share one query outcome.
  • Responses failing shape checks (Msg, NOERROR, AA, apex DNSKEY presence) are silently skipped for DS08 findings.
  • Unsupported algorithm can be detected either before verification (dnssecAlgorithmSupported) or during verification (dns.ErrAlg).