Skip to content
SwornMail docs

Reference

Verification and results

Verification is stateless and O(1) per connection, with no verifier-initiated fetch to attacker-named endpoints beyond DNS.

Result values

ResultCause
passAll verification checks passed.
noneNo v=SWORN1 policy or key record, NXDOMAIN, an unimplemented k=, or — in Mode 1 — no confirming operator found.
failSignature failure, off-prefix, expired, or not yet valid.
permerrorMalformed token or record, unauthorised token prefix, policy and token unit mismatch, bad headers, non-canonical or out-of-range prefix, ineligible source, bad unit, bad validity (exp <= iat), lifetime over cap, bad role, non-conforming kid or operator domain, missing required key, duplicate key, crit present, or untagged COSE.
temperrorDNS timeout or SERVFAIL, or — in Mode 1 — the discovery query budget exhausted.

An operator publishing t=y whose checks would all pass is reported as none, with policy.testing=y and policy.wouldbe=pass. See testing mode.

Reporting the result

Results are reported with the sworn method in an Authentication-Results field. Every pass, and every t=y observe-only result, carries two prefixes:

Authentication-Results: mx.example.net;
    sworn=pass policy.op=mailer.example.com
    policy.unit="2001:db8:f00:1200::/56"
    policy.observed="2001:db8:f00:1234::/64" policy.mode=dns

The two are equal at the default u=64. Values containing : or / are quoted. policy.mode is dns for Mode 1 and token for Mode 2.

Reputation semantics

These are the rules that make the protocol safe to deploy. They are the part most likely to be got wrong by an implementer optimising for the obvious.

On pass

Key reputation on the tuple (operator domain, observed unit), where the observed unit is the connecting address masked to /64.

A pass does not prove the operator controls the whole prefix. It proves the connection came from somewhere inside the signed prefix. A shared-hosting tenant can publish a policy covering its provider’s entire aggregate. So unless you hold independent evidence of control over the whole attested prefix — a reverse-DNS delegation rooted at that boundary, a provider authorisation, or applicable authenticated routing evidence — scope both credit and blame to the claimant domain and the observed /64, or finer. Do not let the claim reach the provider’s domain, neighbouring /64s, or the aggregate as an IP-only identity.

With that evidence, you may use the declared unit up to the boundary you verified, and abuse may then affect the operator domain across its attested prefixes. A signed broad claim on its own is never that evidence: a claimant’s u cannot widen the observed unit.

Where several valid attestations cover the same source, the most specific one decides which applies. A token’s role is a self-assertion; never grant more favourable treatment on role alone.

On t=y results

An operator in testing mode has not accepted accountability. Apply no reputation consequences in either direction, and never read the result as a pass: key on sworn=pass, not on the presence of policy.op.

On fail, temperror and permerror

A failed verification identifies no accountable party. Receivers and reputation services must not attribute a failed result to the operator domain named in the token. Anyone can put any domain in a token they made up; treating a failure as evidence against that domain would make SwornMail a weapon against the operators it exists to serve.

None of these results may be treated as worse than none for reputation or delivery. Absence of attestation must not worsen treatment relative to the receiver’s existing unattested-IPv6 policy. This is design goal 1 — fail-open — and it is what makes deploying SwornMail safe for a sender and for a receiver to enable.

Why temperror is not none

A DNS timeout means the question was not answered, not that the answer was “no attestation”. Collapsing the two would let anyone who can disrupt DNS erase an operator’s standing. Implementations must keep them distinct, and reputation services must not record a temporary failure as an absence.

The trust boundary

An inbound sworn= result is trivially spoofable — it is just a header field. Per RFC 8601 §5, an ADMD border MTA must delete or rename any pre-existing Authentication-Results field claiming its own authserv-id. A result must not survive the trust boundary unexamined.

The reference Postfix milter strips inbound AR fields at the boundary for exactly this reason.

Trust in DNS

DNS is SwornMail’s root of trust. Policy authorisation stops a stolen signing key from attesting space the operator never published, but it cannot protect an unsigned lookup: an active attacker who can replace both the policy and the key answers can impersonate the operator.

DNSSEC is recommended. A verifier that can obtain a validated status should expose it to local policy, and security-sensitive deployments should require validated answers. Without it, SwornMail carries the same DNS-rooted residual risk as DKIM. Every link in a delegated CNAME chain is part of this trust path.

Verifiers are also DNS query generators. Syntax checks run before any query, cheap checks run first, Mode 1 has a fixed budget, and negative caching and per-source rate limits bound the load an attacker can aim at a domain of their choosing.

Mode 1: DNS-only discovery

The receiver has a connecting address and needs to find who, if anyone, is accountable for it.

  1. Look for a reverse-tree pointer naming an operator domain. Failing that, take the connecting host’s forward-confirmed PTR.
  2. Fetch that operator’s policy record.
  3. Confirm the connecting address falls inside one of the prefixes the operator actually attested. This containment check is the whole anti-squatting mechanism — a claim is worth nothing without it.

Discovery runs under a hard budget of 10 DNS queries per connection. Exhausting it yields temperror, never none — an attacker must not be able to convert “expensive to answer” into “not attested”.

Mode 1 is experimental in this revision. It binds a prefix to an operator with weaker source authenticity than Mode 2 — a BGP hijack of the prefix defeats it — so give it low reputation weight until operational experience accrues, and weight Mode 2 above it. RPKI Route Origin Authorizations covering the attested prefixes bound the impact of a hijack.

Mode 2: signed token

A compact COSE_Sign1 token presented with the SWORN SMTP command before MAIL FROM, verified statelessly at connection time. The checks run in three stages, and the order is part of the protocol:

  1. Local checks, before any DNS. A tagged COSE_Sign1 with the required protected headers; a well-formed payload; a canonical, in-range prefix; an eligible source address; a validity window inside the 24-hour cap, allowing at most 300 seconds of clock skew; a legal unit; and the connecting address inside the signed prefix.
  2. Policy authorisation. Fetch _prefixes._sworn.<operator domain>. The token’s prefix must equal or sit inside one of the policy’s first 64 prefixes, and the token’s unit must equal the policy’s u. This runs before the key is fetched, so an unauthorised token never triggers a key query.
  3. Key and signature. Fetch <kid>._sworn.<operator domain> and verify with the algorithm the record’s k= names.

No policy record yields none. A malformed policy, an unauthorised prefix or a unit mismatch yields permerror.

A stolen key alone buys little. It can sign only for prefixes the operator’s separately published policy already authorises, and every token must still be presented from inside the prefix it names — replayed from anywhere else it produces sworn=fail. Replay from inside the signed prefix stays possible for the token’s lifetime, so senders should keep lifetimes to an hour or less; 24 hours is a hard cap, not a target.

The algorithm comes from the key record’s k= tag, not from the token: a verifier must take the expected algorithm from the record and reject a token that disagrees, rather than letting the token choose how it is checked.

For k=ed25519 a token may label its algorithm either way: the polymorphic EdDSA (-8), which the reference signer emits, or the fully-specified Ed25519 (-19) from RFC 9864, which IANA now recommends. Both name the same algorithm, so a verifier accepts both. Any other label is a permerror.

A token longer than 3072 octets is malformed and is rejected before it is decoded; the longest SWORN line carries at most 3066 octets of token. Verification is strict. A public key or signature R of small order is a signature failure: under the identity key, one fixed signature verifies for every message, so a domain that publishes such a key has in effect published its private key.