Documentation
¶
Overview ¶
Package dnssec implements pure DNSSEC verification primitives: RRSIG/DS validation, NSEC and NSEC3 denial-of-existence proofs, and the EDE-coded sentinel errors they return. None of the functions here hold resolver state; they take the records they need to validate as inputs and return a pass/fail result. The recursive resolver wraps them with the chain-of-trust orchestration (DS lookups, key fetches, trust-anchor management).
Index ¶
- Variables
- func DNSKEYMissingForZone(zone string) *util.EDEError
- func IsSupportedDNSKEYAlgorithm(alg uint8) bool
- func IsSupportedDS(ds *dns.DS) bool
- func IsSupportedDSDigest(t uint8) bool
- func SignatureExpiredForRRset(rrtype, zone string) *util.EDEError
- func ValidateSigner(signer, qname string) error
- func VerifyDS(keyMap map[uint16][]*dns.DNSKEY, parentDSSet []dns.RR) (bool, error)
- func VerifyDelegation(delegation string, nsec []dns.RR) error
- func VerifyDelegationNSEC(delegation string, nsecSet []dns.RR) error
- func VerifyNODATA(msg *dns.Msg, nsec []dns.RR) error
- func VerifyNODATANSEC(msg *dns.Msg, nsecSet []dns.RR) error
- func VerifyNSEC(q dns.Question, nsecSet []dns.RR) (typeMatch bool)
- func VerifyNameError(msg *dns.Msg, nsec []dns.RR) error
- func VerifyNameErrorNSEC(msg *dns.Msg, nsecSet []dns.RR) error
- func VerifyRRSIG(signer string, keys map[uint16][]*dns.DNSKEY, msg *dns.Msg) (bool, error)
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoDNSKEY = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSKEYMissing, Message: "No DNSKEY records found in response", } ErrMissingKSK = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSKEYMissing, Message: "No KSK DNSKEY matches DS records from parent", } ErrFailedToConvertKSK = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "Unable to validate DNSKEY against parent DS record", } ErrMismatchingDS = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "DNSKEY does not match DS record from parent zone", } ErrNoSignatures = &util.EDEError{ Code: dns.ExtendedErrorCodeRRSIGsMissing, Message: "Response is missing required RRSIG records", } ErrMissingDNSKEY = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSKEYMissing, Message: "No DNSKEY found to validate RRSIG", } ErrInvalidSignaturePeriod = &util.EDEError{ Code: dns.ExtendedErrorCodeSignatureExpired, Message: "RRSIG validity period check failed", } ErrMissingSigned = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "RRsets covered by RRSIG are missing", } ErrDSRecords = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "Parent has DS records but zone appears unsigned", } Code: dns.ExtendedErrorCodeOther, Message: "Trust anchors unavailable — refusing to validate", } )
DNSKEY-side validation errors.
var ( ErrNSECTypeExists = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "NSEC record indicates queried type exists", } ErrNSECMissingCoverage = &util.EDEError{ Code: dns.ExtendedErrorCodeNSECMissing, Message: "Incomplete NSEC proof for name non-existence", } ErrNSECBadDelegation = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "Invalid NSEC type bitmap for delegation", } ErrNSECNSMissing = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "NSEC missing NS bit at delegation point", } ErrNSECOptOut = &util.EDEError{ Code: dns.ExtendedErrorCodeDNSBogus, Message: "NSEC3 opt-out validation failed", } )
NSEC / NSEC3 denial-of-existence errors.
Functions ¶
func DNSKEYMissingForZone ¶
DNSKEYMissingForZone returns a DNSKEY-missing error tagged with zone.
func IsSupportedDNSKEYAlgorithm ¶
IsSupportedDNSKEYAlgorithm reports whether miekg/dns' RRSIG.Verify can process signatures of the given algorithm without returning ErrAlg. DS records advertising unsupported DNSKEY algorithms are unusable — DNSKEY.ToDS will still hash them, but later RRSIG verification would fail. Per RFC 6840 §5.2 such DS entries must be disregarded so an unsupported-only DS RRset is treated as insecure rather than bogus.
The list intentionally matches miekg/dns' switch in RRSIG.Verify exactly. RSAMD5 (deprecated by RFC 8624) is *not* accepted there, so classifying it as supported would let an RSAMD5 DS RRset appear usable and then bogus out on verification instead of downgrading to insecure.
func IsSupportedDS ¶
IsSupportedDS reports whether a DS record is usable for validation: both its digest type and the DNSKEY algorithm it advertises must be something this validator can verify.
func IsSupportedDSDigest ¶
IsSupportedDSDigest reports whether the given DS digest type is implemented locally. RFC 6840 §5.2 requires validators to ignore DS records that use unknown or unimplemented digest algorithms. Only the three digest types miekg/dns' DNSKEY.ToDS actually computes are treated as supported here — anything else (GOST94, future digest types, unknown values) is skipped.
func SignatureExpiredForRRset ¶
SignatureExpiredForRRset returns a signature-expired error tagged with the RR type and zone.
func ValidateSigner ¶
ValidateSigner checks that the signer claimed by an RRSIG is a plausible zone apex for qname — either qname itself or a proper ancestor. The check must run before the DS-chain lookup because RRSIG.SignerName is unauthenticated RDATA until a key verifies the signature: without it, an on-path attacker can rewrite SignerName to an unsigned sibling or descendant, then rely on findDS() returning an empty set to silently skip verifyDNSSEC() and downgrade a signed response to "insecure" instead of bogus.
func VerifyDS ¶
VerifyDS looks for a DS record in parentDSSet that authenticates one of the KSKs in keyMap. It returns (unsupportedOnly, err):
- (false, nil) — at least one supported DS matched a KSK.
- (false, err) — at least one supported DS was present but none matched; the zone is bogus (not "insecure").
- (true, err) — every DS in the RRset uses an unsupported digest type. Per RFC 6840 §5.2 validators MUST ignore such records, and if none remain the caller must treat the zone as insecure.
keyMap groups DNSKEYs by key tag because RFC 4034 Appendix B.1 does not guarantee key-tag uniqueness: a colliding tag could otherwise mask the KSK that actually authenticates the DS.
func VerifyDelegation ¶
VerifyDelegation verifies an insecure-delegation claim using NSEC3. The delegation is authenticated either by an exact-match NSEC3 with NS set (and DS / SOA cleared) or, for opt-out spans, by an NSEC3 covering the next closer name with the Opt-Out bit set.
func VerifyDelegationNSEC ¶
VerifyDelegationNSEC verifies an insecure-delegation claim using NSEC records (RFC 4035 §5.2). It must find an NSEC whose owner equals the delegation name and whose type bitmap contains NS but neither DS nor SOA. Anything looser would let a malicious parent strip the DS from a signed child and have the resolver treat the child as insecure.
func VerifyNODATA ¶
VerifyNODATA verifies a NODATA proof using NSEC3 records (RFC 5155 §8.5–§8.7), including the DS-specific opt-out branch.
func VerifyNODATANSEC ¶
VerifyNODATANSEC verifies NODATA using NSEC records (RFC 4035 §3.1.3.1).
func VerifyNSEC ¶
VerifyNSEC reports whether any NSEC in nsecSet has q.Qtype set in its type bitmap. This is a cheap structural check used as a pre-filter before the full denial-of-existence proofs in VerifyNODATANSEC / VerifyNameErrorNSEC. A true result alone does not authenticate anything.
func VerifyNameError ¶
VerifyNameError verifies an NXDOMAIN proof using NSEC3 records (RFC 5155 §8.4): closest encloser exists, an NSEC3 covers the next closer name, and an NSEC3 covers the wildcard at the closest encloser.
func VerifyNameErrorNSEC ¶
VerifyNameErrorNSEC verifies NXDOMAIN using NSEC records (RFC 4035 §3.1.3.2). The proof requires two NSEC records: one that covers QNAME (proving QNAME does not exist) and one that covers the wildcard at the closest encloser of QNAME (proving no wildcard match could synthesize the answer). Accepting wildcard coverage from an arbitrary ancestor lets a mismatched proof pass, so the wildcard is derived from the covering NSEC's owner/next labels, not from any ancestor of QNAME.
func VerifyRRSIG ¶
VerifyRRSIG validates that every in-zone RRset in msg is covered by at least one RRSIG that successfully verifies against the supplied DNSKEYs.
The signer zone is supplied by the caller (verifyDNSSEC / verifyRootKeys) and represents the zone whose keys should authenticate this response. RRsets whose owner name is not in that zone — for example, target records appended via DNAME synthesis — are validated by their own recursion and are skipped here. An unsigned RRset inside the zone is rejected; a signature that fails (missing key, bad exponent, verify error, expired) only causes the RRset to fail if no sibling signature succeeds.
Types ¶
This section is empty.