a positive test proves Ze does what the requirement demands and a negative one proves it refuses what the requirement forbids
RFC 7296 - Internet Key Exchange Protocol Version 2 (IKEv2)
Every requirement this repository extracted from RFC 7296, the tests bound to it, and what a reader has verified about them. This summary is enrolled and gated by ./le rfc check.
Overview
Positive
what Ze has
the requirement admits no counter-case, so one polarity plus a recorded reason is the whole proof available for it
one direction is tested, the other is neither tested nor excused, and nothing states which
scoped tests exist; the remaining obligation is unmet or unproven, with zero whole-requirement credit
no test carries the requirement id, whether or not a gap states why
a red was observed once under a recorded procedure, and the unit, the claim and the producer it rested on still hash to what was recorded. The break is not re-run. A test pair is not a proof until one has been observed
Neutral
measures that are neither good news nor bad
MUST-level requirements the gate HOLDS. A population, not a result: the shares beside it are what says how Ze stands
an obligation that does not bind Ze. A {not-applicable} annotation says it never bound; a {feature-declined} annotation says its condition is an optional feature Ze does not offer, and quotes the RFC sentence that makes it optional. Scope, not coverage: it stays in the denominator every share on this page is taken over
a {not-applicable} annotation says the obligation does not bind Ze, so no test is owed for it. It stays in the denominator every share here is taken over
a {lower-layer} annotation says a layer under Ze performs the behavior, on state Ze installs into that layer, and names the producer that installs it. The obligation binds Ze and is met; Ze proves none of it, because its own boundary carries no value the behavior reads
a {feature-declined} annotation says the obligation is conditional on a feature the RFC makes optional and Ze does not offer, and it quotes the sentence that makes it optional. The condition is false, so nothing is owed and nothing is missing. It stays in the denominator every share here is taken over
Negative
what Ze owes
1 weak, wrong or unimplemented, 0 no longer current. Each is named below under its own requirement id
The 8 shares marked as a part above are the whole of the 223 gated MUSTs: they add to 100%. Proven by a recorded break is a share of TAGGED UNITS, a different population, so it is not one of them.
How to read the colors
A color names what the measure MEANS, not how well Ze scores on it. Green is a good outcome at any value, red is a bad one, and neither a population nor a scope count is an outcome, so both take no color. The number under the label is what says how far Ze has got.
| Card | Tone here | Why that color |
|---|---|---|
| Gated MUSTs | neutral | no color: a population is a scale, and a larger one is neither good news nor bad. It is the accounting total |
| Out of scope | neutral | no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim |
| Tested both ways | ok | green at every value: a test pair is the outcome this gate exists to produce, and the share under the label is what says how far Ze has got |
| One polarity plus reason | ok | green at every value: where no counter-case exists, one polarity IS the complete answer, and a recorded reason is what the gate demands beside it |
| One polarity, unexcused | ok | green at zero, RED above it: half a proof with no reason for the other half |
| Partial proof; remaining gap | ok | green at zero, RED above it: a tested clause cannot prove the whole requirement |
| No test at all | ok | green at zero, RED above it: a binding obligation nothing exercises is a claim with nothing behind it, whether or not a reason is stated |
| Not applicable | neutral | no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim |
| Met below Ze | neutral | no color: an obligation met below Ze is neither a test Ze wrote nor work Ze owes, and the two green shares above are what says how much Ze proves itself |
| Optional feature declined | neutral | no color: an obligation whose condition Ze never meets is neither an achievement nor a failure. The absent FEATURE is disclosed on the RFC's own status row, as an implementation gap a later scope decision can revisit |
| Proven by a recorded break | ok | green at every value: an observed break is the outcome the discrimination gate exists to produce. The denominator is TAGGED UNITS, not obligations, so this share is not one of the parts above |
| Audit verdicts | bad | RED on the first weak, wrong or unimplemented verdict, amber while a verdict is no longer current or a gated MUST is unjudged, green when every one is judged sound and current |
At a glance
| Field | Value |
|---|---|
| Public status | Partial |
| Enrolment | Enrolled |
| Requirements | 232 |
| Gated MUST-level | 223 |
| Not applicable, so out of scope | 0 |
| Declared gaps | 1 |
| Declared gaps a test demonstrates | 0 |
| Gated with no test | 0 |
| Nightly-only evidence | 0 |
| Test tags | 696 |
| Tagged units | 693 |
| Recorded audit verdicts | 92 |
| Discrimination records | 227 |
| Summary | rfc/short/rfc7296.md |
| Requirement shard | rfc/requirements/rfc7296.md |
| RFC text | rfc/full/rfc7296.txt |
Enrolment
Enrolled: Internet Key Exchange Protocol Version 2 / IKEv2 (RFC 7296): Enrolled with every gated row carrying a positive and a negative `RFC requirement:` tag or an annotation saying why not; `./le rfc check` prints the current row, tag and annotation counts. A tag is its author's claim, not a proof: the independent verdicts in rfc/audit/rfc7296.json say which rows are judged enforced, and the rows judged weak or unimplemented there are open findings, so this enrolment does not claim every row is met. The 2026-08 pilot grew the summary from 23 rows and implemented what was absent: COOKIE (engine/cookie.go), the authenticated and out-of-SA error notifications (engine/notify_error.go), traffic-selector narrowing (engine/ts_narrow.go), per-SPI Child SA Delete (engine/delete.go), Message ID exhaustion (engine/msgid.go), and dual ESP form reception (dataplane/espform_linux.go). Two obligation sets are extracted and stay gated in their destination specs instead of here: the Configuration payload / IRAC role (11 rows, plan/immediate/spec-ipsec-remote-access.md; ze takes no IRAC role, which Section 4 permits) and IPComp (4 rows, plan/spec-ipsec-ipcomp.md). The Section 3.2 extraction walk added the two Critical-bit SENDER obligations the summary never carried, RFC7296-3.2-5 (zero asks the recipient to skip an unrecognized payload) and RFC7296-3.2-6 (one asks it to reject the whole message). The same walk added two more the summary never carried, RFC7296-1.3.3-2 (a CREATE_CHILD_SA that replaces an ESP or AH SA carries the REKEY_SA notification) and RFC7296-4-5 (the four-message IKE_SA_INIT and IKE_AUTH exchange establishes two SAs). rfc/extraction/rfc7296.json is signed off (2026-08-02): 261 sites in 104 sections, all classified, so the bound is a recorded walk of the source rather than the 222 extracted rows alone. 12 sites are relocated-to-spec, carrying obligations owner ruling D-1 moved to plan/immediate/spec-ipsec-remote-access.md and plan/spec-ipsec-ipcomp.md, and 26 requirements are unsourced-ids read from indicative prose that carries no keyword
What the public ledger says
Status: Partial
What the ledger says is covered
- Wire codec, cryptographic primitives, initiator and responder FSM, IKE_SA_INIT, IKE_AUTH, CREATE_CHILD_SA, INFORMATIONAL, rekey, DPD. Section 1.4 authenticated Delete on operator
clear(graceful bounce) - Section 2.4 state synchronization: the responder accepts a fresh IKE_SA_INIT in parallel with an established SA and supersedes it only once the new SA authenticates (never on the unauthenticated init)
- INITIAL_CONTACT emitted on the first IKE_AUTH request and honored on receipt. Section 1.4 liveness probes carry the Encrypted payload and authenticate under the negotiated keys. Section 2.4 refuses a verdict about the peer from an unauthenticated message, because an established SA is served by one handler that decrypts first. Section 2.5 accepts an IKE_AUTH whose payloads arrive in any order, on both the initiator and the responder path. Section 3.6 reads the first CERT payload as the peer certificate. It reads every later one as a chain intermediate. Ze sends its configured intermediate after the device certificate. Section 2.2 Message ID exhaustion: both counters stop at the 32-bit ceiling instead of wrapping. The SA rekeys itself in the headroom below the ceiling. The owner loop closes it at the ceiling (engine/msgid.go, engine/established.go). Section 2.3 window: Ze declares a window of one and accepts exactly one request id. It reads a peer SET_WINDOW_SIZE during IKE_AUTH, refuses a body that is not 4 octets, and reports the value as
peer-window-sizeinshow vpn ipsec sa. A peer request that crosses one of ours is accepted and answered, and a request outside the window is never acknowledged. Section 2.3 INVALID_MESSAGE_ID: an out-of-window request that authenticates draws the notification. Ze sends it as a NEW INFORMATIONAL request. That request carries the four-octet invalid Message ID. Ze never sends it as a response. Three bounds apply. Ze decrypts the request first, so an unauthenticated datagram draws nothing at all. Ze sends the notification only when its one request window is free. The notification therefore never displaces a liveness probe, a Delete or a rekey. A token bucket on the SA rate limits it. That bucket satisfies the MUST of Section 2.3 (engine/notify_invalid_msgid.go). Section 2.25: a rekey the peer answers with TEMPORARY_FAILURE waits 60 seconds before it is retried, per rekey kind. Sections 2.21.2, 2.21.3 and 2.21.4 error notifications: a request that fails on an authenticated IKE SA draws an encrypted error notify instead of silence. A refused Child SA rekey draws NO_PROPOSAL_CHOSEN, a malformed request draws INVALID_SYNTAX, and an unrecognized critical payload draws UNSUPPORTED_CRITICAL_PAYLOAD with the one-octet payload type. A datagram that matches no IKE SA draws an unprotected INVALID_IKE_SPI that copies the SPIs, Exchange Type and Message ID. That answer is rate limited. It is never sent in reply to a message marked as a response. It is never sent for an IKE_SA_INIT. An unprotected datagram at a CACHED message id draws no cached response and changes no SA state. This holds on the established path and on the mid-EAP responder path alike (engine/notify_error.go, engine/responder.go replayCachedResponse). The claim is bounded to that message id on purpose. An undecryptable datagram at a message id the responder is still expecting is a different path, and it does change SA state (engine/responder_eap.go handleResponderEAP). Section 3.10.1: an unrecognized error notify in a response fails the request it answers, and an unrecognized status notify is ignored and logged. Section 3.10.1 sender side: Ze adds one status notify of its own, the private-use ZE_PATH_PROBE_PADDING (65280), to the INFORMATIONAL request of the padded path probe thatshow mturuns over a live SA - its Notification Data pads the datagram to a requested size, and a peer that does not recognize it ignores it and answers an empty response (engine/probe.go, wire/payload_notify.go). Section 3.14 is why SK padding is not that carrier: the Pad Length is one octet, so SK padding cannot pass 255 octets, and an AEAD suite pads nothing (RFC 5282)
- under CBC the padding rule fixes the encrypted span to the block size, so the probe reaches sizes on a 16-octet grid and refuses the rest by name. Section 2.1: the probe is an ordinary request
- its retransmission is the same bytes from the IKE header on with only the IP header's DF bit changed, and a probe unanswered through the full budget deems the SA failed exactly as an unanswered Delete does (engine/established.go serviceRequestWindow, unchanged). Sections 1.2 and 2.6 corrected retry: an initiator that guesses the wrong Diffie-Hellman group retries the IKE_SA_INIT under the group the responder names, and refuses a group it never proposed, so a forged unauthenticated notify cannot steer it. The retry re-offers the whole configured suite set and re-anchors the signed IKE_SA_INIT octets. Section 2.6 COOKIE: the responder answers an inbound IKE_SA_INIT with a COOKIE challenge before it commits a half-open slot, and the initiator echoes the cookie as the first payload of a retry that changes nothing else. The cookie is an HMAC over the nonce, the source address and the initiator SPI under a rotating secret, is bounded to 1..64 octets on both the mint and the echo path, and a cookie that does not match is ignored rather than rejected.
cookie-thresholdsets how many half-open IKE SAs are tolerated before challenging, and defaults to 0 (challenge every initiation). Section 2.6.1: a second challenge replaces the first without failing, and the retry budget is bounded (engine/cookie.go, engine/sa_init_retry.go). Section 3.15.1 Configuration payload codec: the attribute type is 15 bits. Ze masks the Reserved bit on the read path and on the write path. A peer that sets that bit still has its INTERNAL_IP4_ADDRESS recognized (wire/payload_cp.go). Sections 2.19, 2.20 and 3.15.1: Ze builds no Configuration payload. It takes no IRAC role, which Section 4 permits. It ignores CFG_SET, which Section 3.15.1 permits. It sends no CFG_REQUEST, no CFG_REPLY and no CFG_ACK, and it gives out no version string. Section 3.4 key exchange pairing: the initiator refuses an IKE_SA_INIT or IKE-rekey response whose KE payload names a Diffie-Hellman group that no proposal of the same message specifies, and refuses a KE payload at all when no proposal specifies a group. A Transform ID of NONE names no group for both rules (wire/payload_sa.go, engine/fsm.go). Section 3.3.6: an IKE SA negotiation never selects the group NONE, and the one exchange that does select it, a Child SA rekey without PFS, ignores any KE payload the peer sends and omits one from the response (engine/rekey.go). Section 2.4: INITIAL_CONTACT is withheld by an identity that may be replicated. An EAP credential names a user rather than a device, so an EAP peer sends none - a pre-shared secret or X.509 device identity still sends it (engine/auth.go). Section 2.8: an IKE SA whose negotiated lifetime has expired is refused for use at the point every protected message is built, not merely scheduled for teardown, and hard expiry is no longer deferred by an in-flight rekey. The rekey trigger is placed a full retransmit budget before the hard time so the replacement exchange still has room (engine/sa.go, engine/auth.go, engine/established.go, engine/rekey.go). Section 4: a rekey the peer refuses with NO_ADDITIONAL_SAS is answered by deleting the old SA and creating a new one through the initial exchanges, instead of retrying an exchange that peer will never accept (engine/rekey.go, engine/inbound.go). Section 3.6 certificate count:
certificate-countbounds the chain Ze sends and the chain it accepts, and it defaults to the four the section names. A peer that sends more is refused, never truncated (engine/cert_payload.go). Section 3.6 Hash and URL:hash-and-urlturns on both encodings. Ze sends encoding 12 for one certificate and encoding 13 for a bundle, and it advertises HTTP_CERT_LOOKUP_SUPPORTED. It resolves a payload a peer sends through a bounded http fetch. That fetch permits the http scheme only. It caps the body at 64 KiB and times out after 5 seconds. It follows no redirect. It denies loopback, private, link-local and metadata addresses. It verifies the SHA-1 before any parser reads the bytes. The leaf defaults to false, so no fetch is reachable until an operator asks for one (engine/certurl.go, engine/certbundle.go). Section 2.9 traffic-selector narrowing: the responder narrows the initiator's proposed TSi/TSr to a subset its configuredtraffic-selectorlist allows, leads that subset with the initiator's first choices, and answers TS_UNACCEPTABLE when nothing is acceptable. A peer with no configured selectors accepts whatever it is offered, which is the behavior of every configuration written before the list existed. The selectors Ze puts on the wire are the selectors it programs: a proposal it cannot program exactly is narrowed further, never rounded outward (engine/ts_narrow.go, ipsec/traffic_selector.go). Section 2.9.2: a rekey is never narrowed below the scope currently in use (engine/rekey.go). Sections 1.3.1 and 2.23.1 transport mode:mode transportsends USE_TRANSPORT_MODE with the Child SA request and pins TSi and TSr to the IKE SA's own OBSERVED address pair, one address each. A responder accepts the request only when its own configuration asks for transport mode, and echoes the notification when it does. A peer that declines leaves a tunnel-mode Child SA, andtransport-requiredmakes that decline delete the SA instead (engine/transport_mode.go, engine/child.go). Section 2.23.1 address substitution: with a NAT on the path, both roles replace the transport-mode selector addresses before those selectors are used for anything except storing the originals. The responder substitutes the TSi address with the observed remote address when the peer is behind a NAT, and the TSr address with its own local address when it is, before the policy lookup that is Ze's SPD lookup. The initiator substitutes the mirror pair before the answer is checked against what it proposed and before the SAD entry is created. The substituted address is always one this node observed, never one the peer asserted, so the narrowing guard still refuses an answer outside the proposal. The SA records which SIDE each translation is on, separately from whether a NAT is present, and stores the pre-substitution addresses the section requires be kept. Tunnel mode and a NAT-free path are unchanged. Proven against strongSwan across a netfilter box that really rewrites both addresses, in test/interop-ipsec/scenarios/real-nat-transport-ze-initiator, real-nat-transport-ze-responder and real-nat-tunnel-control (engine/ts_nat_substitute.go, engine/ts_narrow.go, engine/sa.go). Section 3.13.1 port selectors: a selector carries all ports (0/65535) or one port under a protocol that defines ports (ipsec/traffic_selector.go). Section 4 conformance set: Ze accepts PKIX certificates signed by RSA keys of 1024 and 2048 bits. The identity passed can be ID_FQDN, ID_RFC822_ADDR or ID_DER_ASN1_DN, which binds against the certificate subject exactly.remote-id-type key-idlets an operator accept ID_KEY_ID, which corresponds to no certificate field. The same leaf pins one identity type per peer (engine/remote_id.go). Section 3.3 transform alternatives: one proposal CAN carry several transforms of the same Transform Type. Ze reads every one of them as an alternative, and it does not keep only the last. A peer CAN offer two Diffie-Hellman groups, two key lengths, two PRFs or two integrity algorithms in one proposal. Ze considers all of them, in the order the peer listed them. Ze selects the peer's first choice that it supports. The number of combinations one proposal expands to is bounded, so an unauthenticated peer cannot turn a cross product into unbounded work (engine/initiator.go). Section 1.4.1 Delete: an inbound Child SA Delete is resolved to the pair the peer named by SPI and that pair is closed, and the response carries a Delete payload naming the paired SA going in the other direction. A Delete that crosses one Ze already sent for the same pair is answered without a Delete payload, and the two halves of the pair go at the two points the section names. An IKE SA Delete still draws an empty response (engine/delete.go). Section 1.5: the out-of-SA notification emitter is a fixed point, so its own output fed back to it produces nothing and two nodes cannot trade messages forever (engine/notify_error.go). Section 2.12: closing an IKE SA erases SK_d and the rest of SK_*, the Diffie-Hellman private value and the EAP MSK, and releases the nonces, on every path that ends an SA including an abandoned half-open handshake. The two holders that live on the peer SESSION rather than on the SA are released on the same exit: the Diffie-Hellman private value of a rekey that never got its answer, and a whole IKE SA built while answering the peer's rekey and never confirmed by the peer's Delete. The session outlives the SA, so either one left behind would carry key material into the next reconnect cycle (engine/sa.go, engine/established.go, engine/fsm.go). Section 2.16: the EAP shared key generates the AUTH payloads that follow EAP Success, and the responder sends Success on a completed method and Failure on a refused one (eap/eap.go, engine/eap_auth.go). Section 2.24 ECN: no config leaf and no negotiated parameter can reach an ECN knob, and the netlink state Ze fills carries no flags field, so XFRM_STATE_NOECN is unreachable and the kernel's ECN propagation stands (dataplane/xfrm_linux.go). Section 3.1: a liveness probe sets the I bit from the ORIGINAL initiator role rather than hardcoding it (engine/dpd.go). Section 3.5: an ID_FQDN or ID_RFC822_ADDR carrying a terminator octet is refused, on the receive path against a peer's asserted identity and at commit against local-id and remote-id (engine/remote_id.go, ipsec/validate.go). Section 3.3 ESP alternatives: every transform of a type in one ESP proposal is read as an alternative, and a key length is only ever compared beside the id of the transform that carried it (engine/responder.go). Section 2.7 Extended Sequence Numbers: Ze keys a 32-bit ESP sequence space, so it offers and answers Transform Type 5 value 0 and selects that value from a proposal that offers both. A proposal offering value 1 alone is refused with NO_PROPOSAL_CHOSEN rather than answered with a transform the peer never proposed, and an answer selecting value 1 ends the exchange on the initiator side (engine/responder.go, engine/initiator.go). Proven against strongSwan in test/interop-ipsec/scenarios/esn-extended-only-refused and esn-both-offered. Section 2.23 NAT-T: one Child SA receives BOTH ESP forms, and the form Ze SENDS follows the NAT verdict alone. Reception and transmission are two decisions. The inbound XFRM state carries the encapsulation template when a NAT was detected or the IKE SA runs on port 4500, so the kernel serves that form on its fast path. The other form is served beside the kernel: a raw IPPROTO_ESP reader takes the bare datagram XFRM refused and re-presents it through port 4500, which carries UDP_ENCAP, so the kernel hands XFRM the encapsulation type the template wants. Ze encapsulates on transmission only when it detected a NAT, which RFC 7296 Section 2.23 makes mandatory there and leaves free otherwise. Reading the port as a transmission signal broke interop against a strongSwan that floats to port 4500 for MOBIKE with no NAT present and then sends bare ESP (engine/child.go, dataplane/espform.go, dataplane/espform_linux.go, transport/encap_linux.go). Section 2.2 two counters: each end keeps its own next Message ID. A responder-role SA raises its first request at the id a conforming peer expects. It took the peer's id before this fix, so it raised no DPD, no Delete and no rekey (engine/responder.go, engine/msgid.go). Section 2.9 narrowing orientation: the responder narrows against the orientation of the exchange in hand. The IKE SA role is a different question. A Child SA rekey the peer starts on a tunnel Ze initiated is answered rather than refused with TS_UNACCEPTABLE (engine/ts_narrow.go). Section 2.8 rekey on the XFRM dataplane: the replacement Child SA inherits the retired pair's selectors and their orientation. The make-before-break window holds one policy, and retiring the superseded pair removes no selector the live pair still needs.test/ipsec/ipsec-child-rekey-xfrm.cimeasures it on the real backend with the two roles crossed (engine/rekey.go, engine/child.go). Section 2.21.2 childless IKE SA: an IKE_AUTH whose AUTH verifies keeps the IKE SA when its Child SA is refused, in both roles. The responder answers IDr, CERT and AUTH with the error notify and no SAr2, and the initiator establishes from that answer and sends no Delete. The IKE SA initiator then asks for its Child SA with a CREATE_CHILD_SA new-child request (Section 1.3.1), with KEi when pfs is on, retried on a doubling schedule from 30 to 300 seconds - either role answers a peer's new-child request on a childless IKE SA, and answers NO_ADDITIONAL_SAS while it holds one (engine/responder.go, engine/fsm.go, engine/create_child.go, engine/inbound.go).
What the ledger says remains
No MUST gap remains gated in rfc/short/rfc7296.md. The Delete-payload echo that RFC7296-1.4-1 recorded is implemented: an inbound Child SA Delete now closes the pair the peer designated by SPI and the response names the paired SA going the other way (engine/delete.go). Two platform limits are gated and disclosed, and neither is left as a gap. Section 3.13.1 OPAQUE ports: Ze implements the 65535/0 encoding and proves it. Ze refuses OPAQUE at commit and at negotiation. The kernel policy selector derives its port mask from the port value, so an exact match on port 0 would install as any-port. That is wider than the selector negotiated. Section 2.23 ESP forms: the platform limit is LIFTED. One established Child SA now receives both UDP-encapsulated and bare ESP, so a peer that changes form on that SA is served. TestEncapOneStateAcceptsBothForms measures it against a real kernel: ONE state on ONE SPI, the encapsulated form on the kernel fast path and the bare form read off a raw IPPROTO_ESP socket and re-presented, both reaching the crypto check (dataplane/encap_hybrid_integration_linux_test.go). That test re-presents the datagram by hand, so it measures the kernel mechanism and not the shipped path. TestEncapEstablishedSAServesAPeerFormChange measures the shipped path: the SA is installed through the production backend, a live SA carries one form, the peer switches to the other, then back, and the kernel's state table shows ONE state with an unchanged add time throughout (dataplane/encap_formchange_integration_linux_test.go). The claim is also proven against strongSwan, over a real interface, in test/interop-ipsec/scenarios/esp-form-change: a live Child SA whose peer sends the form Ze's kernel state refuses carries traffic in both directions and is neither rekeyed nor deleted. That scenario is what caught the one defect that made this claim false in a real deployment. Linux runs xfrm4_policy_check before it queues a packet to a raw socket, and Ze's own inbound Child SA policy rejected the datagrams the receiver exists to recover, so the kernel dropped every one of them. The reader now carries a per-socket inbound bypass, scoped to that socket alone (dataplane/espform_linux.go). No loopback test can see that defect, because a loopback dst entry carries DST_NOPOLICY and the check is skipped. One Linux XFRM state still binds one form, which TestEncapKernelBindsOneESPFormPerState records, so the second form is served beside the kernel rather than through it (dataplane/encap_integration_linux_test.go). Two states on one SPI do NOT help, and that is now MEASURED rather than reasoned. The kernel refuses to install the second state with file exists, both with identical addresses and with a differing source, because the uniqueness key and the lookup key are the same tuple. The earlier text said the lookup returns the first match and the encapsulation check then drops the packet.
That mechanism is wrong: the second state never exists (dataplane/encap_dualform_integration_linux_test.go). One combination stays unreachable and is bounded by the RFC rather than by Ze: a template-free inbound state cannot receive the encapsulated form, because the port-4500 socket carries UDP_ENCAP and the kernel consumes that datagram before any userspace reader sees it (TestEncapEncapsulatedESPHiddenFromUserspaceWhenSocketDecapsulates). No conforming peer produces it. RFC 3948 Section 2.1 requires the ESP-in-UDP ports to equal the IKE ports, and RFC 7296 Section 2.23 forbids encapsulation on port 500, so a peer that encapsulates ESP runs its IKE on port 4500 and Ze templates that SA.
Coverage
| Bucket | Count | What it counts |
|---|---|---|
| Positive and negative tests | 223 | one part of the gated population |
| Annotated (including scoped evidence) | 0 | one part of the gated population |
| One polarity only | 0 | one part of the gated population |
| No test and no annotation | 0 | one part of the gated population |
| Partial proof; remaining gap (subset of annotated; zero whole-requirement credit) | 0 | an overlay: each of these is also counted by the part it falls in |
| Evidence that runs nightly only | 0 | an overlay: each of these is also counted by the part it falls in |
| Derived from other rows | 0 | outside the gated population: each asserts nothing and derives its state from the rows it names, which the parts above already count |
| Gated MUST-level requirements | 223 | every gated MUST falls in exactly one bucket above |
Positive and negative tests (223): RFC7296-1.2-1, RFC7296-2.6-1, RFC7296-2.7-1, RFC7296-3.3-1, RFC7296-3.3-2, RFC7296-3.3.2-1, RFC7296-1.3.3-1, RFC7296-1.3.3-2, RFC7296-1.3.3-3, RFC7296-1.3.3-4, RFC7296-2.9-1, RFC7296-2.9-2, RFC7296-2.9.2-1, RFC7296-2.9.2-2, RFC7296-1.3.1-1, RFC7296-1.3.1-2, RFC7296-2.23.1-1, RFC7296-2.23.1-2, RFC7296-2.23.1-3, RFC7296-3.13.1-1, RFC7296-3.13.1-2, RFC7296-3.13.1-3, RFC7296-2.23-1, RFC7296-2.23-2, RFC7296-2.23-3, RFC7296-2.4-1, RFC7296-2.8-2, RFC7296-1-1, RFC7296-1.2-2, RFC7296-1.2-3, RFC7296-1.2-4, RFC7296-1.2-5, RFC7296-1.2-6, RFC7296-2.4-11, RFC7296-2.4-12, RFC7296-2.4-13, RFC7296-2.7-2, RFC7296-2.10-4, RFC7296-2.11-1, RFC7296-2.11-2, RFC7296-2.11-3, RFC7296-2.16-11, RFC7296-2.16-6, RFC7296-2.16-7, RFC7296-2.23-7, RFC7296-2.23-8, RFC7296-2.23-9, RFC7296-2.23-10, RFC7296-2.23-11, RFC7296-2.23-12, RFC7296-3.9-2, RFC7296-1.3-2, RFC7296-2.8.2-1, RFC7296-3.3.6-3, RFC7296-1.4-3, RFC7296-1.4-4, RFC7296-1.4-5, RFC7296-1.4.1-6, RFC7296-1.4.1-7, RFC7296-1.5-1, RFC7296-2.12-1, RFC7296-2.24-1, RFC7296-2.24-2, RFC7296-2.16-12, RFC7296-2.16-13, RFC7296-2.16-14, RFC7296-2.16-15, RFC7296-3.1-13, RFC7296-3.5-5, RFC7296-3.5-6, RFC7296-1.4.1-1, RFC7296-1.4.1-4, RFC7296-1.4.1-5, RFC7296-2.4-9, RFC7296-2.4-10, RFC7296-2.16-5, RFC7296-3.4-1, RFC7296-1.3-1, RFC7296-2.1-3, RFC7296-2.1-4, RFC7296-2.1-5, RFC7296-2.1-6, RFC7296-2.1-7, RFC7296-2.1-8, RFC7296-2.2-1, RFC7296-2.2-2, RFC7296-2.2-3, RFC7296-2.3-2, RFC7296-2.3-4, RFC7296-2.3-5, RFC7296-2.3-7, RFC7296-2.3-8, RFC7296-2.3-9, RFC7296-2.25-1, RFC7296-2.8-5, RFC7296-2.8-6, RFC7296-2.8-7, RFC7296-2.8.1-1, RFC7296-2.18-2, RFC7296-2.18-3, RFC7296-3.16-1, RFC7296-3.16-2, RFC7296-3.16-3, RFC7296-3.16-4, RFC7296-1.7-2, RFC7296-2-1, RFC7296-2.5-1, RFC7296-2.5-2, RFC7296-2.5-6, RFC7296-2.5-7, RFC7296-2.5-8, RFC7296-2.5-9, RFC7296-2.5-11, RFC7296-2.5-13, RFC7296-2.5-14, RFC7296-2.5-15, RFC7296-2.5-16, RFC7296-2.5-17, RFC7296-2.5-18, RFC7296-2.21.2-1, RFC7296-2.21.2-2, RFC7296-2.21.2-3, RFC7296-2.21.3-1, RFC7296-2.21.4-1, RFC7296-2.21.4-2, RFC7296-2.21.4-3, RFC7296-2.21.4-4, RFC7296-2.21.4-5, RFC7296-2.21.4-6, RFC7296-2.21.4-7, RFC7296-3.10.1-1, RFC7296-3.10.1-2, RFC7296-3.10.1-3, RFC7296-2.6-2, RFC7296-2.6-3, RFC7296-2.6-4, RFC7296-2.6-5, RFC7296-2.6.1-1, RFC7296-2.10-2, RFC7296-2.10-3, RFC7296-2.13-1, RFC7296-2.13-3, RFC7296-2.13-4, RFC7296-2.15-1, RFC7296-2.15-2, RFC7296-2.17-1, RFC7296-2.17-2, RFC7296-3.1-1, RFC7296-3.1-2, RFC7296-3.1-3, RFC7296-3.1-4, RFC7296-3.1-5, RFC7296-3.1-6, RFC7296-3.1-7, RFC7296-3.1-8, RFC7296-3.1-9, RFC7296-3.1-11, RFC7296-3.1-12, RFC7296-3.2-2, RFC7296-3.2-3, RFC7296-3.2-4, RFC7296-3.2-5, RFC7296-3.2-6, RFC7296-3.3-3, RFC7296-3.3-4, RFC7296-3.3-5, RFC7296-3.3-6, RFC7296-3.3-7, RFC7296-3.3.1-1, RFC7296-3.3.1-2, RFC7296-3.3.3-1, RFC7296-3.3.4-2, RFC7296-3.3.4-3, RFC7296-3.3.5-1, RFC7296-3.3.5-2, RFC7296-3.3.5-3, RFC7296-3.3.5-4, RFC7296-3.3.5-5, RFC7296-3.3.6-4, RFC7296-3.3.6-5, RFC7296-3.3.6-7, RFC7296-3.9-1, RFC7296-3.10-3, RFC7296-3.10-4, RFC7296-3.10-5, RFC7296-3.11-1, RFC7296-3.11-2, RFC7296-3.12-2, RFC7296-3.12-3, RFC7296-3.12-4, RFC7296-3.14-2, RFC7296-3.14-3, RFC7296-3.14-4, RFC7296-3.14-5, RFC7296-3.14-6, RFC7296-3.14-7, RFC7296-5-2, RFC7296-5-3, RFC7296-2.19-1, RFC7296-2.19-4, RFC7296-2.20-1, RFC7296-3.15.1-2, RFC7296-3.15.1-5, RFC7296-3.15.1-6, RFC7296-3.15.1-7, RFC7296-2.4-3, RFC7296-2.4-4, RFC7296-3.4-2, RFC7296-3.4-3, RFC7296-3.3.6-8, RFC7296-2.4-14, RFC7296-2.8-8, RFC7296-4-1, RFC7296-2.15-3, RFC7296-3.3.4-4, RFC7296-3.5-2, RFC7296-3.5-3, RFC7296-3.5-4, RFC7296-3.6-1, RFC7296-3.6-2, RFC7296-3.6-3, RFC7296-4-4, RFC7296-4-5
Requirements
| Requirement | Level | Section | Tests |
|---|---|---|---|
RFC7296-1.2-1 | The first pair of messages (IKE_SA_INIT) negotiate cryptographic algorithms, exchange nonces, and do a Diffie-Hellman exchange [DH]. The second pair of messages (IKE_AUTH) authenticate the previous messages, exchange identities and certificates, and establish the first Child SA. Parts of these messages are encrypted and integrity protected with keys established through the IKE_SA_INIT exchange, so the identities are hidden from eavesdroppers and all fields in all the messages are authenticated. (§1.2) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-2.6-1 | The initial two eight-octet fields in the header, called the "IKE SPIs", are used as a connection identifier at the beginning of IKE packets. (§2.6) | ||
| MUST | 2.6 | ||
RFC7296-2.7-1 | The responder MUST accept a single proposal or reject them all and return an error. The error is given in a notification of type NO_PROPOSAL_CHOSEN. Each IPsec protocol proposal contains one or more transforms. Each transform contains a Transform Type. The accepted cryptographic suite MUST contain exactly one transform of each type included in the proposal. (§2.7) | ||
| MUST | 2.7 | ||
RFC7296-3.3-1 | If an initiator wants to propose both combined- mode ciphers and normal ciphers, it must include two proposals: one will have all the combined-mode ciphers, and the other will have all the normal ciphers with the integrity algorithms. (§3.3) | ||
| MUST | 3.3 | ||
RFC7296-3.3-2 | Combined-mode ciphers include both integrity and encryption in a single encryption algorithm, and MUST either offer no integrity algorithm or a single integrity algorithm of "NONE" (§3.3) | ||
| MUST | 3.3 | ||
RFC7296-3.3.2-1 | An SA payload proposing the establishment of an SA has the following mandatory and optional Transform Types. A compliant implementation MUST understand all mandatory and optional types for each protocol it supports (though it need not accept proposals with unacceptable suites). A proposal MAY omit the optional types if the only value for them it will accept is NONE. Protocol Mandatory Types Optional Types --------------------------------------------------- IKE ENCR, PRF, INTEG*, D-H (§3.3.3) | ||
| MUST | 3.3.3 | ||
RFC7296-1.3.3-1 | The KEi payload MUST be included. (§1.3.2) | ||
| MUST | 1.3.2 - Rekeying the IKE SA | ||
RFC7296-1.3.3-2 | The REKEY_SA notification MUST be included in a CREATE_CHILD_SA exchange if the purpose of the exchange is to replace an existing ESP or AH SA (§1.3.3) | ||
| MUST | 1.3.3 - Rekeying a Child SA | ||
RFC7296-1.3.3-3 | The initiator sends SA offer(s) in the SA payload, a nonce in the Ni payload, optionally a Diffie-Hellman value in the KEi payload, and the proposed Traffic Selectors for the proposed Child SA in the TSi and TSr payloads. (§1.3.3) | ||
| MUST | 1.3.3 - Rekeying a Child SA | ||
RFC7296-1.3.3-4 | The Traffic Selectors for traffic to be sent on that SA are specified in the TS payloads in the response, which may be a subset of what the initiator of the Child SA proposed. (§1.3.3) | ||
| MUST | 1.3.3 - Rekeying a Child SA | ||
RFC7296-2.9-1 | When the responder chooses a subset of the traffic proposed by the initiator, it narrows the Traffic Selectors to some subset of the initiator's proposal (provided the set does not become the null set). (§2.9) | ||
| MUST | 2.9 | ||
RFC7296-2.9-2 | If the responder's policy allows it to accept the first selector of TSi and TSr, then the responder MUST narrow the Traffic Selectors to a subset that includes the initiator's first choices (§2.9) | ||
| MUST | 2.9 | ||
RFC7296-2.9.2-1 | Thus, the new SA MUST NOT have narrower selectors than the original (§2.9.2) | ||
| MUST NOT | 2.9.2 | ||
RFC7296-2.9.2-2 | The responder MUST NOT narrow down the Traffic Selectors narrower than the scope currently in use (§2.9.2) | ||
| MUST NOT | 2.9.2 | ||
RFC7296-1.3.1-1 | If the request is accepted, the response MUST also include a notification of type USE_TRANSPORT_MODE (§1.3.1) | ||
| MUST | 1.3.1 - Creating a new Child SA | ||
RFC7296-1.3.1-2 | If the responder declines the request, the Child SA will be established in tunnel mode. If this is unacceptable to the initiator, the initiator MUST delete the SA (§1.3.1) | ||
| MUST | 1.3.1 - Creating a new Child SA | ||
RFC7296-2.23.1-1 | For transport mode, it MUST use exactly one IP address in the TSi and TSr payloads (§2.23.1) | ||
| MUST | 2.23.1 | ||
RFC7296-2.23.1-2 | The TSi entries MUST have exactly one IP address, and that MUST match the source address of the IKE SA (§2.23.1) | ||
| MUST | 2.23.1 | ||
RFC7296-2.23.1-3 | The TSr entries MUST have exactly one IP address, and that MUST match the destination address of the IKE SA (§2.23.1) | ||
| MUST | 2.23.1 | ||
RFC7296-3.13.1-1 | For protocols for which port is undefined (including protocol 0), or if all ports are allowed, this field MUST be zero. (§3.13.1) | ||
| MUST | 3.13.1 | ||
RFC7296-3.13.1-2 | For protocols for which port is undefined (including protocol 0), or if all ports are allowed, this field MUST be 65535. (§3.13.1) | ||
| MUST | 3.13.1 | ||
RFC7296-3.13.1-3 | Systems working with [IPSECARCH] that wish to indicate "OPAQUE" ports, but not "ANY" ports, MUST set the start port to 65535 and the end port to 0. (§3.13.1) | ||
| MUST | 3.13.1 | ||
RFC7296-2.23-1 | The IKE initiator MUST check the NAT_DETECTION_SOURCE_IP or NAT_DETECTION_DESTINATION_IP payloads if present (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-2 | However, if a NAT is detected, both devices MUST use UDP encapsulation for ESP. (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-3 | To tunnel IKE packets over UDP port 4500, the IKE header has four octets of zeros prepended and the result immediately follows the UDP header. (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.8-1 | If redundant SAs are created through such a collision, the SA created with the lowest of the four nonces used in the two exchanges SHOULD be closed by the endpoint that created it (§2.8, §2.8.1) | ||
| SHOULD | 2.8 | ||
RFC7296-2.4-1 | To check whether the other side is alive, IKE specifies an empty INFORMATIONAL request that (like all IKE requests) requires an acknowledgement (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-1.4-1 | Normally, the response in the INFORMATIONAL exchange will contain Delete payloads for the paired SAs going in the other direction. (§1.4.1) | ||
| SHOULD | 1.4.1 - Deleting an SA | ||
RFC7296-2.8-2 | A difference between IKEv1 and IKEv2 is that in IKEv1 SA lifetimes were negotiated. In IKEv2, each end of the SA is responsible for enforcing its own lifetime policy on the SA and rekeying the SA when necessary. (§2.8) | ||
| MUST NOT | 2.8 | ||
RFC7296-1-1 | In all cases, all IKE_SA_INIT exchanges MUST complete before any other exchange type, then all IKE_AUTH exchanges MUST complete, and following that, any number of CREATE_CHILD_SA and INFORMATIONAL exchanges may occur in any order (§1) | ||
| MUST | 1 | ||
RFC7296-1.2-2 | If any CERT payloads are included, the first certificate provided MUST contain the public key used to verify the AUTH field (§1.2, §3.6) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-1.2-3 | Both parties in the IKE_AUTH exchange MUST verify that all signatures and Message Authentication Codes (MACs) are computed correctly (§1.2) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-1.2-4 | If either side uses a shared secret for authentication, the names in the ID payload MUST correspond to the key used to generate the AUTH payload (§1.2) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-1.2-5 | If the initiator guesses wrong, the responder will respond with a Notify payload of type INVALID_KE_PAYLOAD indicating the selected group. In this case, the initiator MUST retry the IKE_SA_INIT with the corrected Diffie-Hellman group (§1.2) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-1.2-6 | The initiator MUST again propose its full set of acceptable cryptographic suites because the rejection message was unauthenticated and otherwise an active attacker could trick the endpoints into negotiating a weaker suite than a stronger one that they both prefer (§1.2) | ||
| MUST | 1.2 - The initial exchanges | ||
RFC7296-2.4-11 | An endpoint MUST conclude that the other endpoint has failed only when repeated attempts to contact it have gone unanswered for a timeout period or when a cryptographically protected INITIAL_CONTACT notification is received on a different IKE SA to the same authenticated identity (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.4-12 | Implementations MUST limit the rate at which they take actions based on unprotected messages (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.4-13 | To be a good network citizen, retransmission times MUST increase exponentially to avoid flooding the network and making an existing congestion situation worse (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.7-2 | Each proposal contains one protocol. If a proposal is accepted, the SA response MUST contain the same protocol (§2.7) | ||
| MUST | 2.7 | ||
RFC7296-2.10-4 | Nonces used in IKEv2 MUST be randomly chosen (§2.10) | ||
| MUST | 2.10 | ||
RFC7296-2.11-1 | An implementation MUST accept incoming requests even if the source port is not 500 or 4500 (§2.11, §2.23) | ||
| MUST | 2.11 | ||
RFC7296-2.11-2 | MUST respond to the address and port from which the request was received (§2.11) | ||
| MUST | 2.11 | ||
RFC7296-2.11-3 | It MUST specify the address and port at which the request was received as the source address and port in the response (§2.11) | ||
| MUST | 2.11 | ||
RFC7296-2.16-11 | these protocols are typically used to authenticate the initiator to the responder and MUST be used in conjunction with a public-key-signature-based authentication of the responder to the initiator. (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-6 | Extensible authentication is implemented in IKE as additional IKE_AUTH exchanges that MUST be completed in order to initialize the IKE SA (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-7 | This shared key generated during an IKE exchange MUST NOT be used for any other purpose (§2.16) | ||
| MUST NOT | 2.16 | ||
RFC7296-2.23-7 | Both the IKE initiator and responder MUST include in their IKE_SA_INIT packets Notify payloads of type NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-8 | An IPsec endpoint that discovers a NAT between it and its correspondent (as described below) MUST send all subsequent traffic from port 4500 (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-9 | UDP encapsulation MUST NOT be done on port 500 (§2.23) | ||
| MUST NOT | 2.23 | ||
RFC7296-2.23-10 | If Network Address Translation Traversal (NAT-T) is supported (that is, if NAT_DETECTION_*_IP payloads were exchanged during IKE_SA_INIT), all devices MUST be able to receive and process both UDP-encapsulated ESP and non-UDP-encapsulated ESP packets at any time. (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-11 | Implementations MUST process received UDP-encapsulated ESP packets even when no NAT was detected (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-12 | To tunnel ESP packets over UDP port 4500, the ESP header immediately follows the UDP header. Since the first four octets of the ESP header contain the SPI, and the SPI cannot validly be zero, it is always possible to distinguish ESP and IKE messages. (§2.23) | ||
| MUST | 2.23 | ||
RFC7296-2.23-13 | When such a validated packet is found, a host that does not support other methods of recovery such as IKEv2 Mobility and Multihoming (MOBIKE) [MOBIKE], and that is not behind a NAT, SHOULD send all packets (including retransmission packets) to the IP address and port in the validated packet, and SHOULD store this as the new address and port combination for the SA (that is, they SHOULD dynamically update the address). (§2.23) | ||
| SHOULD | 2.23 | ||
RFC7296-3.9-2 | Nonce values MUST NOT be reused (§3.9) | ||
| MUST NOT | 3.9 | ||
RFC7296-1.3-2 | If the responder selects a proposal using a different Diffie-Hellman group (other than NONE), the responder MUST reject the request and indicate its preferred Diffie-Hellman group in the INVALID_KE_PAYLOAD Notify payload (§1.3, §3.4) | ||
| MUST | 1.3 - The CREATE_CHILD_SA exchange | ||
RFC7296-2.8.2-1 | The new IKE SA containing the lowest nonce SHOULD be deleted by the node that created it, and the other surviving new IKE SA MUST inherit all the Child SAs (§2.8.2) | ||
| MUST | 2.8.2 | ||
RFC7296-3.3.6-3 | The initiator of an exchange MUST check that the accepted offer is consistent with one of its proposals, and if not MUST terminate the exchange (§3.3.6) | ||
| MUST | 3.3.6 | ||
RFC7296-1.4-3 | Control messages that pertain to an IKE SA MUST be sent under that IKE SA. Control messages that pertain to Child SAs MUST be sent under the protection of the IKE SA that generated them (§1.4) | ||
| MUST | 1.4 - The INFORMATIONAL exchange | ||
RFC7296-1.4-4 | The recipient of an INFORMATIONAL exchange request MUST send some response; otherwise, the sender will assume the message was lost in the network and will retransmit it (§1.4, §4) | ||
| MUST | 1.4 - The INFORMATIONAL exchange | ||
RFC7296-1.4-5 | INFORMATIONAL exchanges MUST ONLY occur after the initial exchanges and are cryptographically protected with the negotiated keys (§1.4) | ||
| MUST | 1.4 - The INFORMATIONAL exchange | ||
RFC7296-1.4.1-6 | To delete an SA, an INFORMATIONAL exchange with one or more Delete payloads is sent listing the SPIs (as they would be expected in the headers of inbound packets) of the SAs to be deleted. The recipient MUST close the designated SAs (§1.4.1) | ||
| MUST | 1.4.1 - Deleting an SA | ||
RFC7296-1.4.1-7 | If a node receives a delete request for SAs for which it has already issued a delete request, it MUST delete the outgoing SAs while processing the request and the incoming SAs while processing the response (§1.4.1) | ||
| MUST | 1.4.1 - Deleting an SA | ||
RFC7296-1.5-1 | This message is not part of an INFORMATIONAL exchange, and the receiving node MUST NOT respond to it because doing so could cause a message loop (§1.5) | ||
| MUST NOT | 1.5 - Informational messages outside an IKE SA | ||
RFC7296-2.12-1 | Achieving perfect forward secrecy requires that when a connection is closed, each endpoint MUST forget not only the keys used by the connection but also any information that could be used to recompute those keys (§2.12) | ||
| MUST | 2.12 | ||
RFC7296-2.24-1 | tunnel encapsulators and decapsulators for all tunnel mode SAs created by IKEv2 MUST support the ECN full-functionality option for tunnels specified in [ECN] (§2.24) | ||
| MUST | 2.24 | ||
RFC7296-2.24-2 | MUST implement the tunnel encapsulation and decapsulation processing specified in [IPSECARCH] to prevent discarding of ECN congestion indications. (§2.24) | ||
| MUST | 2.24 | ||
RFC7296-2.16-12 | For EAP methods that create a shared key as a side effect of authentication, that shared key MUST be used by both the initiator and responder to generate AUTH payloads in messages 7 and 8 using the syntax for shared secrets specified in Section 2.15 (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-13 | Following such an extended exchange, the EAP AUTH payloads MUST be included in the two messages following the one containing the EAP Success message (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-14 | Once the protocol exchange defined by the chosen EAP authentication method has successfully terminated, the responder MUST send an EAP payload containing the Success message (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-15 | Similarly, if the authentication method has failed, the responder MUST send an EAP payload containing the Failure message (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-3.1-13 | * I (Initiator) - This bit MUST be set in messages sent by the original initiator of the IKE SA and MUST be cleared in messages sent by the original responder. (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.5-5 | A fully-qualified domain name string. An example of an ID_FQDN is "example.com". The string MUST NOT contain any terminators (e.g., NULL, CR, etc.). (§3.5) | ||
| MUST NOT | 3.5 | ||
RFC7296-3.5-6 | A fully-qualified RFC 822 email address string. An example of a ID_RFC822_ADDR is "jsmith@example.com". The string MUST NOT contain any terminators. (§3.5) | ||
| MUST NOT | 3.5 | ||
RFC7296-1.4.1-1 | When an SA is closed, both members of the pair MUST be closed (that is, deleted). Each endpoint MUST close its incoming SAs and allow the other endpoint to close the other SA in each pair (§1.4.1) | ||
| MUST | 1.4.1 - Deleting an SA | ||
RFC7296-1.4.1-4 | In that case, the responses MUST NOT include Delete payloads for the deleted SAs, since that would result in duplicate deletion and could in theory delete the wrong SA. (§1.4.1) | ||
| MUST NOT | 1.4.1 - Deleting an SA | ||
RFC7296-1.4.1-5 | A node MAY refuse to accept incoming data on half-closed connections but MUST NOT unilaterally close them and reuse the SPIs (§1.4.1) | ||
| MUST NOT | 1.4.1 - Deleting an SA | ||
RFC7296-2.4-9 | If a system creates Child SAs that can fail independently from one another without the associated IKE SA being able to send a delete message, then the system MUST negotiate such Child SAs using separate IKE SAs (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.4-10 | If an IKE endpoint chooses to delete Child SAs, it MUST send Delete payloads to the other end notifying it of the deletion (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.16-5 | If EAP methods that do not generate a shared key are used, the AUTH payloads in messages 7 and 8 MUST be generated using SK_pi and SK_pr, respectively (§2.16) | ||
| MUST | 2.16 | ||
RFC7296-2.16-16 | EAP methods that do not establish a shared key SHOULD NOT be used, as they are subject to a number of man-in-the-middle attacks [EAPMITM] if these EAP methods are used in other protocols that do not use a server-authenticated tunnel. (§2.16) | ||
| SHOULD NOT | 2.16 | ||
RFC7296-3.4-1 | The length of the Diffie-Hellman public value for MODP groups MUST be equal to the length of the prime modulus over which the exponentiation was performed, prepending zero bits to the value if necessary (§3.4) | ||
| MUST | 3.4 | ||
RFC7296-1.3-1 | If a CREATE_CHILD_SA exchange includes a KEi payload, at least one of the SA offers MUST include the Diffie-Hellman group of the KEi (§1.3) | ||
| MUST | 1.3 - The CREATE_CHILD_SA exchange | ||
RFC7296-2.1-3 | The responder MUST never retransmit a response unless it receives a retransmission of the request (§2.1) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.1-4 | In that event, the responder MUST ignore the retransmitted request except insofar as it causes a retransmission of the response (§2.1) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.1-5 | The initiator MUST remember each request until it receives the corresponding response. The responder MUST remember each response until it receives a request whose sequence number is larger than or equal to the sequence number in the response plus its window size (§2.1, §2.3) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.1-6 | If the responder receives a retransmitted request for which it has already forgotten the response, it MUST ignore the request (and not, for example, attempt constructing a new response) (§2.1) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.1-7 | IKE is a reliable protocol: the initiator MUST retransmit a request until it either receives a corresponding response or deems the IKE SA to have failed (§2.1) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.1-8 | A retransmission from the initiator MUST be bitwise identical to the original request (§2.1) | ||
| MUST | 2.1 - Retransmission timers | ||
RFC7296-2.2-1 | Retransmission of a message MUST use the same Message ID as the original message (§2.2) | ||
| MUST | 2.2 - Message ID sequence numbers | ||
RFC7296-2.2-2 | In the unlikely event that Message IDs grow too large to fit in 32 bits, the IKE SA MUST be closed or rekeyed (§2.2) | ||
| MUST | 2.2 - Message ID sequence numbers | ||
RFC7296-2.2-3 | Each endpoint in the IKE Security Association maintains two "current" Message IDs: the next one to be used for a request it initiates and the next one it expects to see in a request from the other end. (§2.2) | ||
| MUST | 2.2 - Message ID sequence numbers | ||
RFC7296-2.3-2 | An IKE endpoint MUST wait for a response to each of its messages before sending a subsequent message unless it has received a SET_WINDOW_SIZE Notify message from its peer (§2.3) | ||
| MUST | 2.3 - Window size for overlapping requests | ||
RFC7296-2.3-4 | An IKE endpoint MUST NOT exceed the peer's stated window size for transmitted IKE requests (§2.3) | ||
| MUST NOT | 2.3 - Window size for overlapping requests | ||
RFC7296-2.3-5 | This Notify message MUST NOT be sent in a response; the invalid request MUST NOT be acknowledged (§2.3) | ||
| MUST NOT | 2.3 - Window size for overlapping requests | ||
RFC7296-2.3-7 | The data associated with a SET_WINDOW_SIZE notification MUST be 4 octets long and contain the big endian representation of the number of messages the sender promises to keep (§2.3) | ||
| MUST | 2.3 - Window size for overlapping requests | ||
RFC7296-2.3-8 | An IKE endpoint MUST be prepared to accept and process a request while it has a request outstanding in order to avoid a deadlock in this situation (§2.3) | ||
| MUST | 2.3 - Window size for overlapping requests | ||
RFC7296-2.3-9 | Sending this notification is OPTIONAL, and notifications of this type MUST be rate limited (§2.3) | ||
| MUST | 2.3 - Window size for overlapping requests | ||
RFC7296-2.25-1 | When a peer receives a TEMPORARY_FAILURE notification, it MUST NOT immediately retry the operation; it MUST wait so that the sender may complete whatever operation caused the temporary condition (§2.25) | ||
| MUST NOT | 2.25 | ||
RFC7296-2.8-5 | If an SA has expired or is about to expire and rekeying attempts using the mechanisms described here fail, an implementation MUST close the IKE SA and any associated Child SAs and then MAY start new ones (§2.8) | ||
| MUST | 2.8 | ||
RFC7296-2.8-6 | After the new equivalent IKE SA is created, the initiator deletes the old IKE SA, and the Delete payload to delete itself MUST be the last request sent over the old IKE SA (§2.8) | ||
| MUST | 2.8 | ||
RFC7296-2.8-7 | The responder to a CREATE_CHILD_SA MUST be prepared to accept messages on an SA before sending its response to the creation request, so there is no ambiguity for the initiator (§2.8) | ||
| MUST | 2.8 | ||
RFC7296-2.8.1-1 | When there are two SAs eligible to receive packets, a node MUST accept incoming packets through either SA (§2.8.1) | ||
| MUST | 2.8.1 | ||
RFC7296-2.18-2 | The new IKE SA MUST reset its message counters to 0 (§2.18) | ||
| MUST | 2.18 | ||
RFC7296-2.18-3 | implementations MUST perform a new Diffie-Hellman exchange when rekeying the IKE SA. In other words, an initiator MUST NOT propose the value "NONE" for the Diffie-Hellman transform, and a responder MUST NOT accept such a proposal. (§2.18) | ||
| MUST NOT | 2.18 | ||
RFC7296-3.16-1 | Identifier (1 octet) - Used in PPP to distinguish replayed messages from repeated ones. Since in IKE, EAP runs over a reliable protocol, the Identifier serves no function here. In a response message, this octet MUST be set to match the identifier in the corresponding request. (§3.16) | ||
| MUST | 3.16 - The EAP payload and the EAP message format | ||
RFC7296-3.16-2 | Length (2 octets, unsigned integer) - The length of the EAP message. MUST be four less than the Payload Length of the encapsulating payload. (§3.16) | ||
| MUST | 3.16 - The EAP payload and the EAP message format | ||
RFC7296-3.16-3 | For other codes, the EAP message length MUST be four octets and the Type and Type_Data fields MUST NOT be present. (§3.16) | ||
| MUST | 3.16 - The EAP payload and the EAP message format | ||
RFC7296-3.16-4 | In a Response (2) message, Type MUST either be Nak or match the type of the data requested (§3.16) | ||
| MUST | 3.16 - The EAP payload and the EAP message format | ||
RFC7296-1.7-2 | This document adds the restriction in Section 2.13 that all pseudorandom functions (PRFs) used with IKEv2 MUST take variable- sized keys. (§1.7) | ||
| MUST | 1.7 - The change list against RFC 4306 | ||
RFC7296-2-1 | All IKEv2 implementations MUST be able to send, receive, and process IKE messages that are up to 1280 octets long (§2) | ||
| MUST | 2 - IKE protocol details and variations | ||
RFC7296-2.5-1 | The minor version number indicates new capabilities, and MUST be ignored by a node with a smaller minor version number, but used for informational purposes by the node with the larger minor version number (§2.5, §3.1) | ||
| MUST | 2.5 | ||
RFC7296-2.5-2 | If an endpoint receives a message with a higher major version number, it MUST drop the message (§2.5, §3.1) | ||
| MUST | 2.5 | ||
RFC7296-2.5-6 | Also, for forward compatibility, all fields marked RESERVED MUST be set to zero by an implementation running version 2.0 (§2.5, §3.2, §3.3.1, §3.3.2, §3.5, §3.8, §3.13, §3.15, §3.15.1) | ||
| MUST | 2.5 | ||
RFC7296-2.5-7 | Also, for forward compatibility, all fields marked RESERVED MUST be set to zero by an implementation running version 2.0, and their content MUST be ignored by an implementation running version 2.0 (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-8 | Similarly, payload types that are not defined are reserved for future use; implementations of a version where they are undefined MUST skip over those payloads and ignore their contents. (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-9 | If the critical flag is set and the payload type is unrecognized, the message MUST be rejected (§2.5, §4) | ||
| MUST | 2.5 | ||
RFC7296-2.5-11 | If the critical flag is not set and the payload type is unsupported, that payload MUST be ignored (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-13 | implementations MUST NOT reject as invalid a message with those payloads in any other order. (§2.5) | ||
| MUST NOT | 2.5 | ||
RFC7296-2.5-14 | If an endpoint supports major version n, and major version m, it MUST support all versions between n and m (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-15 | If it receives a message with a major version that it supports, it MUST respond with that version number (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-16 | If they mistakenly (perhaps through an active attacker sending error messages) negotiate to version n, then both will notice that the other side can support a higher version number, and they MUST break the connection and reconnect using version n+1 (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.5-17 | Payloads sent in IKE response messages MUST NOT have the critical flag set (§2.5) | ||
| MUST NOT | 2.5 | ||
RFC7296-2.5-18 | the response to the IKE request containing that payload MUST include a Notify payload UNSUPPORTED_CRITICAL_PAYLOAD, indicating an unsupported critical payload was included. In that Notify payload, the Notification Data contains the one-octet payload type. (§2.5) | ||
| MUST | 2.5 | ||
RFC7296-2.21.2-1 | Note, however, that request messages that contain an unsupported critical payload, or where the whole message is malformed (rather than just bad payload contents), MUST be rejected in their entirety, and MUST only lead to an UNSUPPORTED_CRITICAL_PAYLOAD or INVALID_SYNTAX Notification sent as a response. (§2.21.2) | ||
| MUST | 2.21.2 | ||
RFC7296-2.21.2-2 | Specifically, a responder may include all the payloads associated with authentication (IDr, CERT, and AUTH) while sending error notifications for the piggybacked exchanges (FAILED_CP_REQUIRED, NO_PROPOSAL_CHOSEN, and so on), and the initiator MUST NOT fail the authentication because of this. (§2.21.2) | ||
| MUST NOT | 2.21.2 | ||
RFC7296-2.21.2-3 | Extension documents may define new error notifications with these semantics, but MUST NOT use them unless the peer has been shown to understand them, such as by using the Vendor ID payload (§2.21.2) | ||
| MUST NOT | 2.21.2 | ||
RFC7296-2.21.3-1 | After the IKE SA is authenticated, all requests having errors MUST result in a response notifying the other end of the error (§2.21.3) | ||
| MUST | 2.21.3 | ||
RFC7296-2.21.4-1 | If the message is marked as a response, the node can audit the suspicious event but MUST NOT respond (§2.21.4) | ||
| MUST NOT | 2.21.4 | ||
RFC7296-2.21.4-2 | If a response is sent, the response MUST be sent to the IP address and port from where it came with the same IKE SPIs and the Message ID copied. (§2.21.4) | ||
| MUST | 2.21.4 | ||
RFC7296-2.21.4-3 | The response MUST NOT be cryptographically protected (§2.21.4) | ||
| MUST NOT | 2.21.4 | ||
RFC7296-2.21.4-4 | The response MUST NOT be cryptographically protected and MUST contain an INVALID_IKE_SPI Notify payload. (§2.21.4) | ||
| MUST | 2.21.4 | ||
RFC7296-2.21.4-5 | A peer receiving such an unprotected Notify payload MUST NOT respond (§2.21.4) | ||
| MUST NOT | 2.21.4 | ||
RFC7296-2.21.4-6 | A peer receiving such an unprotected Notify payload MUST NOT respond and MUST NOT change the state of any existing SAs. (§2.21.4) | ||
| MUST NOT | 2.21.4 | ||
RFC7296-2.21.4-7 | The recipient MUST NOT change the state of any SAs as a result, but may wish to audit the event to aid in diagnosing malfunctions. (§2.21.4) | ||
| MUST NOT | 2.21.4 | ||
RFC7296-2.21.4-8 | A node receiving a suspicious message from an IP address (and port, if NAT traversal is used) with which it has an IKE SA SHOULD send an IKE Notify payload in an IKE INFORMATIONAL exchange over that SA. (§2.21.4) | ||
| SHOULD | 2.21.4 | positive
no testno positive testnegative
no testno negative test{gap}: Ze sends no protected Notify over an existing IKE SA when a suspicious message arrives from that peer's address. An unprotected message at a cached Message ID is dropped and counted (inbound.go, countErrorNotifySuppressed "unprotected-retransmit"), and an unprotected INVALID_IKE_SPI changes nothing, but neither path starts an INFORMATIONAL exchange over the SA |
|
RFC7296-3.10.1-1 | Types in the range 0 - 16383 are intended for reporting errors. An implementation receiving a Notify payload with one of these types that it does not recognize in a response MUST assume that the corresponding request has failed entirely. (§3.10.1) | ||
| MUST | 3.10.1 | ||
RFC7296-3.10.1-2 | Unrecognized error types in a request and status types in a request or response MUST be ignored, and they should be logged (§3.10.1) | ||
| MUST | 3.10.1 | ||
RFC7296-3.10.1-3 | To avoid leaking information to someone probing a node, this status MUST be sent in response to any error not covered by one of the other status types. (§3.10.1) | ||
| MUST | 3.10.1 | ||
RFC7296-3.10.1-4 | Notify payloads with status types MAY be added to any message and MUST be ignored if not recognized (§3.10.1) | ||
| MAY | 3.10.1 | positive
no testno positive testnegative
no testno negative test |
|
RFC7296-2.6-2 | Each endpoint chooses one of the two SPIs and MUST choose them so as to be unique identifiers of an IKE SA (§2.6) | ||
| MUST | 2.6 | ||
RFC7296-2.6-3 | The data associated with this notification MUST be between 1 and 64 octets in length (inclusive) (§2.6) | ||
| MUST | 2.6 | ||
RFC7296-2.6-4 | If the IKE_SA_INIT response includes the COOKIE notification, the initiator MUST then retry the IKE_SA_INIT request, and include the COOKIE notification containing the received data as the first payload, and all other payloads unchanged (§2.6) | ||
| MUST | 2.6 | ||
RFC7296-2.6-5 | When one party receives an IKE_SA_INIT request containing a cookie whose contents do not match the value expected, that party MUST ignore the cookie and process the message as if no cookie had been included; usually this means sending a response containing a new cookie (§2.6) | ||
| MUST | 2.6 | ||
RFC7296-2.6.1-1 | Implementations SHOULD support this shorter exchange, but MUST NOT fail if other implementations do not support this shorter exchange (§2.6.1) | ||
| MUST NOT | 2.6.1 | ||
RFC7296-2.10-2 | Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits in size (§2.10) | ||
| MUST | 2.10 | ||
RFC7296-2.10-3 | Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits in size, and MUST be at least half the key size of the negotiated pseudorandom function (PRF). (§2.10) | ||
| MUST | 2.10 | ||
RFC7296-2.13-1 | For algorithms that accept a variable-length key, a fixed key size MUST be specified as part of the cryptographic transform negotiated (§2.13) | ||
| MUST | 2.13 | ||
RFC7296-2.13-3 | The preferred key size MUST be used as the length of SK_d, SK_pi, and SK_pr (§2.13, §2.14) | ||
| MUST | 2.13 | ||
RFC7296-2.13-4 | Other types of PRFs MUST specify their preferred key size (§2.13) | ||
| MUST | 2.13 | ||
RFC7296-2.15-1 | The management interface by which the shared secret is provided MUST accept ASCII strings of at least 64 octets (§2.15) | ||
| MUST | 2.15 | ||
RFC7296-2.15-2 | MUST NOT add a null terminator before using them as shared secrets (§2.15) | ||
| MUST NOT | 2.15 | ||
RFC7296-2.17-1 | keying material for each Child SA MUST be taken from the expanded KEYMAT using the following rules: o All keys for SAs carrying data from the initiator to the responder are taken before SAs going from the responder to the initiator. (§2.17) | ||
| MUST | 2.17 | ||
RFC7296-2.17-2 | For ESP and AH, [IPSECARCH] defines the order, namely: the encryption key (if any) MUST be taken from the first bits and the integrity key (if any) MUST be taken from the remaining bits. (§2.17) | ||
| MUST | 2.17 | ||
RFC7296-3.1-1 | An Encrypted payload MUST be the last payload in a packet (§3.1, §3.14) | ||
| MUST | 3.1 | ||
RFC7296-3.1-2 | an Encrypted payload MUST NOT contain another Encrypted payload (§3.1) | ||
| MUST NOT | 3.1 | ||
RFC7296-3.1-3 | Initiator's SPI (8 octets) - A value chosen by the initiator to identify a unique IKE Security Association. This value MUST NOT be zero. (§3.1) | ||
| MUST NOT | 3.1 | ||
RFC7296-3.1-4 | Responder's SPI (8 octets) - A value chosen by the responder to identify a unique IKE Security Association. This value MUST be zero in the first message of an IKE initial exchange (including repeats of that message including a cookie). (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-5 | Implementations based on this version of IKE MUST set the major version to 2 (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-6 | Implementations based on this version of IKE MUST set the minor version to 0 (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-7 | 'X' bits MUST be cleared when sending (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-8 | 'X' bits MUST be cleared when sending and MUST be ignored on receipt. (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-9 | R (Response) - This bit indicates that this message is a response to a message containing the same Message ID. This bit MUST be cleared in all request messages and MUST be set in all responses. (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-11 | V (Version) - This bit indicates that the transmitter is capable of speaking a higher major version number of the protocol than the one indicated in the major version number field. Implementations of IKEv2 MUST clear this bit when sending and MUST ignore it in incoming messages. (§3.1) | ||
| MUST | 3.1 | ||
RFC7296-3.1-12 | An IKE endpoint MUST NOT generate a response to a message that is marked as being a response (with one exception; see Section 2.21.2) (§3.1) | ||
| MUST NOT | 3.1 | ||
RFC7296-3.2-2 | Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. MUST be ignored by the recipient if the recipient understands the payload type code. (§3.2) | ||
| MUST | 3.2 | ||
RFC7296-3.2-3 | all implementations MUST understand all payload types defined in this document (§3.2) | ||
| MUST | 3.2 | ||
RFC7296-3.2-4 | Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. MUST be ignored by the recipient if the recipient understands the payload type code. MUST be set to zero for payload types defined in this document. (§3.2) | ||
| MUST | 3.2 | ||
RFC7296-3.2-5 | o Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. (§3.2) | ||
| MUST | 3.2 | ||
RFC7296-3.2-6 | Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. (§3.2) | ||
| MUST | 3.2 | ||
RFC7296-3.3-3 | An SA payload MAY contain multiple proposals. If there is more than one, they MUST be ordered from most preferred to least preferred (§3.3) | ||
| MUST | 3.3 | ||
RFC7296-3.3-4 | When parsing an SA, an implementation MUST check that the total Payload Length is consistent with the payload's internal lengths and counts (§3.3) | ||
| MUST | 3.3 | ||
RFC7296-3.3-5 | Each structure MUST have a proposal number one (1) greater than the previous structure. The first Proposal in the initiator's SA payload MUST have a Proposal Num of one (1) (§3.3, §3.3.1) | ||
| MUST | 3.3 | ||
RFC7296-3.3-6 | A transform MUST NOT have multiple attributes of the same type (§3.3) | ||
| MUST NOT | 3.3 | ||
RFC7296-3.3-7 | To propose alternate values for an attribute (for example, multiple key sizes for the AES encryption algorithm), an implementation MUST include multiple transforms with the same Transform Type each with a single Attribute. (§3.3) | ||
| MUST | 3.3 | ||
RFC7296-3.3.1-1 | When a proposal is accepted, the proposal number in the SA payload MUST match the number on the proposal sent that was accepted (§3.3.1) | ||
| MUST | 3.3.1 | ||
RFC7296-3.3.1-2 | o SPI Size (1 octet) - For an initial IKE SA negotiation, this field MUST be zero; the SPI is obtained from the outer header. (§3.3.1) | ||
| MUST | 3.3.1 | ||
RFC7296-3.3.3-1 | A compliant implementation MUST understand all mandatory and optional types for each protocol it supports (§3.3.3) | ||
| MUST | 3.3.3 | ||
RFC7296-3.3.4-2 | Upon receipt of a payload with a set of Transform IDs, the implementation MUST compare the transmitted Transform IDs against those locally configured via the management controls, to verify that the proposed suite is acceptable based on local policy (§3.3.4) | ||
| MUST | 3.3.4 | ||
RFC7296-3.3.4-3 | The implementation MUST reject SA proposals that are not authorized by these IKE suite controls (§3.3.4) | ||
| MUST | 3.3.4 | ||
RFC7296-3.3.5-1 | Attributes described as fixed length MUST NOT be encoded using the variable-length encoding unless that length exceeds two bytes (§3.3.5) | ||
| MUST NOT | 3.3.5 | ||
RFC7296-3.3.5-2 | Variable-length attributes MUST NOT be encoded as fixed-length even if their value can fit into two octets (§3.3.5) | ||
| MUST NOT | 3.3.5 | ||
RFC7296-3.3.5-3 | The Key Length attribute specifies the key length in bits (MUST use network byte order) (§3.3.5) | ||
| MUST | 3.3.5 | ||
RFC7296-3.3.5-4 | The Key Length attribute MUST NOT be used with transforms that use a fixed-length key (§3.3.5) | ||
| MUST NOT | 3.3.5 | ||
RFC7296-3.3.5-5 | o Some transforms specify that the Key Length attribute MUST be always included (omitting the attribute is not allowed, and proposals not containing it MUST be rejected). (§3.3.5) | ||
| MUST | 3.3.5 | ||
RFC7296-3.3.6-4 | If the responder receives a proposal that contains a Transform Type it does not understand, or a proposal that is missing a mandatory Transform Type, it MUST consider this proposal unacceptable; however, other proposals in the same SA payload are processed as usual (§3.3.6) | ||
| MUST | 3.3.6 | ||
RFC7296-3.3.6-5 | Similarly, if the responder receives a transform that it does not understand, or one that contains a Transform Attribute it does not understand, it MUST consider this transform unacceptable; other transforms with the same Transform Type are processed as usual. (§3.3.6) | ||
| MUST | 3.3.6 | ||
RFC7296-3.3.6-7 | Any attributes of a selected transform MUST be returned unmodified (§3.3.6) | ||
| MUST | 3.3.6 | ||
RFC7296-3.9-1 | The size of the Nonce Data MUST be between 16 and 256 octets, inclusive (§3.9) | ||
| MUST | 3.9 | ||
RFC7296-3.10-3 | For a notification concerning the IKE SA, the SPI Size MUST be zero and the field must be empty. (§3.10) | ||
| MUST | 3.10 | ||
RFC7296-3.10-4 | For notifications concerning Child SAs, this field MUST contain either (2) to indicate AH or (3) to indicate ESP. (§3.10) | ||
| MUST | 3.10 | ||
RFC7296-3.10-5 | If the SPI field is empty, this field MUST be sent as zero and MUST be ignored on receipt. (§3.10) | ||
| MUST | 3.10 | ||
RFC7296-3.11-1 | each SPI MUST be for the same protocol. Mixing of protocol identifiers MUST NOT be performed in the Delete payload. (§3.11) | ||
| MUST NOT | 3.11 | ||
RFC7296-3.11-2 | SPI Size (1 octet) - Length in octets of the SPI as defined by the protocol ID. It MUST be zero for IKE (SPI is in message header) or four for AH and ESP. (§3.11) | ||
| MUST | 3.11 | ||
RFC7296-3.12-2 | Unfamiliar Vendor IDs MUST be ignored (§3.12) | ||
| MUST | 3.12 | ||
RFC7296-3.12-3 | Writers of documents who wish to extend this protocol MUST define a Vendor ID payload to announce the ability to implement the extension in the document (§3.12) | ||
| MUST | 3.12 | ||
RFC7296-3.12-4 | A Vendor ID payload MUST NOT change the interpretation of any information defined in this specification (i.e., the critical bit MUST be set to 0) (§3.12) | ||
| MUST NOT | 3.12 | ||
RFC7296-3.14-2 | Senders MUST select a new unpredictable IV for every message (§3.14) | ||
| MUST | 3.14 | ||
RFC7296-3.14-3 | Initialization Vector - For CBC mode ciphers, the length of the initialization vector (IV) is equal to the block length of the underlying encryption algorithm. Senders MUST select a new unpredictable IV for every message; recipients MUST accept any value. (§3.14) | ||
| MUST | 3.14 | ||
RFC7296-3.14-4 | Padding MAY contain any value chosen by the sender, and MUST have a length that makes the combination of the payloads, the Padding, and the Pad Length to be a multiple of the encryption block size (§3.14) | ||
| MUST | 3.14 | ||
RFC7296-3.14-5 | the recipient MUST accept any length that results in proper alignment (§3.14) | ||
| MUST | 3.14 | ||
RFC7296-3.14-6 | The checksum MUST be computed over the encrypted message (§3.14) | ||
| MUST | 3.14 | ||
RFC7296-3.14-7 | Peers MUST NOT negotiate transforms for which no such specification exists (§3.14) | ||
| MUST NOT | 3.14 | ||
RFC7296-5-2 | Though the security of negotiated Child SAs does not depend on the strength of the encryption and integrity protection negotiated in the IKE SA, implementations MUST NOT negotiate NONE as the IKE integrity protection algorithm or ENCR_NULL as the IKE encryption algorithm. (§5) | ||
| MUST NOT | 5 - Security considerations | ||
RFC7296-5-3 | For this reason, a PRF whose output is less than 128 bits (e.g., 3DES-CBC) MUST NOT be used with this protocol. (§5) | ||
| MUST NOT | 5 - Security considerations | ||
RFC7296-2.19-1 | Since the IKE_AUTH exchange creates an IKE SA and a Child SA, the IRAC MUST request the IRAS-controlled address (and optionally other information concerning the protected network) in the IKE_AUTH exchange (§2.19, §4) | ||
| MUST | 2.19 | ||
RFC7296-2.19-4 | CP(CFG_REQUEST) MUST contain at least an INTERNAL_ADDRESS attribute (either IPv4 or IPv6) but MAY contain any number of additional attributes the initiator wants returned in the response (§2.19) | ||
| MUST | 2.19 | ||
RFC7296-2.20-1 | An IKE implementation MAY decline to give out version information prior to authentication or even after authentication in case some implementation is known to have some security weakness. In that case, it MUST either return an empty string or no CP payload if CP is not supported. (§2.20) | ||
| MUST | 2.20 | ||
RFC7296-3.15.1-2 | An empty INTERNAL_IP4_NETMASK attribute can be included in a CFG_REQUEST to request this information (although the gateway can send the information even when not requested). Non-empty values for this attribute in a CFG_REQUEST do not make sense and thus MUST NOT be included. (§3.15.1) | ||
| MUST NOT | 3.15.1 | ||
RFC7296-3.15.1-5 | The responder MUST return a Configuration payload if it accepted any of the configuration data, and the Configuration payload MUST contain the attributes that the responder accepted with zero-length data (§3.15.1) | ||
| MUST | 3.15.1 | ||
RFC7296-3.15.1-6 | Those attributes that it did not accept MUST NOT be in the CFG_ACK Configuration payload (§3.15.1) | ||
| MUST NOT | 3.15.1 | ||
RFC7296-3.15.1-7 | If no attributes were accepted, the responder MUST return either an empty CFG_ACK payload or a response message without a CFG_ACK payload (§3.15.1) | ||
| MUST | 3.15.1 | ||
RFC7296-2.1-2 | they SHOULD be able to send, receive, and process messages that are up to 3000 octets long. (§2) | ||
| SHOULD | 2 - IKE protocol details and variations | positive
no testno positive testnegative
no testno negative test |
|
RFC7296-2.4-2 | If there has only been outgoing traffic on all of the SAs associated with an IKE SA, it is essential to confirm liveness of the other endpoint to avoid black holes. If no cryptographically protected messages have been received on an IKE SA or any of its Child SAs recently, the system needs to perform a liveness check in order to prevent sending messages to a dead peer. (§2.4) | ||
| SHOULD | 2.4 | ||
RFC7296-2.4-3 | Since IKE is designed to operate in spite of DoS attacks from the network, an endpoint MUST NOT conclude that the other endpoint has failed based on any routing information (e.g., ICMP messages) or IKE messages that arrive without cryptographic protection (e.g., Notify messages complaining about unknown SPIs). (§2.4) | ||
| MUST NOT | 2.4 | ||
RFC7296-2.4-4 | The INITIAL_CONTACT notification, if sent, MUST be in the first IKE_AUTH request or response, not as a separate exchange afterwards (§2.4) | ||
| MUST | 2.4 | ||
RFC7296-2.8-3 | To reduce the probability of this happening, the timing of rekeying requests SHOULD be jittered (delayed by a random amount of time after the need for rekeying is noticed). (§2.8.1) | ||
| SHOULD | 2.8.1 | positive
no testno positive testnegative
no testno negative test |
|
RFC7296-3.4-2 | This Diffie-Hellman Group Num MUST match a Diffie-Hellman group specified in a proposal in the SA payload that is sent in the same message (§3.4) | ||
| MUST | 3.4 | ||
RFC7296-3.4-3 | If none of the proposals in that SA payload specifies a Diffie-Hellman group, the KE payload MUST NOT be present (§3.4) | ||
| MUST NOT | 3.4 | ||
RFC7296-3.3.6-8 | If one of the proposals offered is for the Diffie-Hellman group of NONE, and the responder selects that Diffie-Hellman group, then it MUST ignore the initiator's KE payload and omit the KE payload from the response (§3.3.6) | ||
| MUST | 3.3.6 | ||
RFC7296-2.4-14 | This notification MUST NOT be sent by an entity that may be replicated (§2.4) | ||
| MUST NOT | 2.4 | ||
RFC7296-2.8-8 | When the lifetime of a Security Association expires, the Security Association MUST NOT be used (§2.8) | ||
| MUST NOT | 2.8 | ||
RFC7296-4-1 | If the responder rejects the CREATE_CHILD_SA request with a NO_ADDITIONAL_SAS notification, the implementation MUST be capable of instead deleting the old SA and creating a new one (§4) | ||
| MUST | 4 - Conformance requirements | ||
RFC7296-2.15-3 | It MUST also accept a hex encoding of the shared secret (§2.15) | ||
| MUST | 2.15 | ||
RFC7296-3.3.4-4 | All implementations of IKEv2 MUST include a management facility that enables a user or system administrator to specify the suites that are acceptable for use with IKE (§3.3.4) | ||
| MUST | 3.3.4 | ||
RFC7296-3.5-2 | To assure maximum interoperability, implementations MUST be configurable to send at least one of ID_IPV4_ADDR, ID_FQDN, ID_RFC822_ADDR, or ID_KEY_ID (§3.5) | ||
| MUST | 3.5 | ||
RFC7296-3.5-3 | To assure maximum interoperability, implementations MUST be configurable to send at least one of ID_IPV4_ADDR, ID_FQDN, ID_RFC822_ADDR, or ID_KEY_ID, and MUST be configurable to accept all of these four types. (§3.5) | ||
| MUST | 3.5 | ||
RFC7296-3.5-4 | IPv6-capable implementations MUST additionally be configurable to accept ID_IPV6_ADDR (§3.5) | ||
| MUST | 3.5 | ||
RFC7296-3.6-1 | Implementations MUST be capable of being configured to send and accept up to four X.509 certificates in support of authentication (§3.6) | ||
| MUST | 3.6 | ||
RFC7296-3.6-2 | and also MUST be capable of being configured to send and accept the two Hash and URL formats (with HTTP URLs). (§3.6) | ||
| MUST | 3.6 | ||
RFC7296-3.6-3 | Implementations MUST support the "http:" scheme for hash-and-URL lookup (§3.6, §1.7) | ||
| MUST | 3.6 | ||
RFC7296-4-4 | For an implementation to be called conforming to this specification, it MUST be possible to configure it to accept the following: o Public Key Infrastructure using X.509 (PKIX) Certificates containing and signed by RSA keys of size 1024 or 2048 bits, where the ID passed is any of ID_KEY_ID, ID_FQDN, ID_RFC822_ADDR, or ID_DER_ASN1_DN. o Shared key authentication where the ID passed is any of ID_KEY_ID, ID_FQDN, or ID_RFC822_ADDR. (§4) | ||
| MUST | 4 - Conformance requirements | ||
RFC7296-4-5 | Every implementation MUST be capable of doing four-message IKE_SA_INIT and IKE_AUTH exchanges establishing two SAs (one for IKE, one for ESP or AH) (§4) | ||
| MUST | 4 - Conformance requirements | ||
Gaps and untested MUSTs
| Requirement | State | Reason |
|---|---|---|
RFC7296-2.21.4-8 A node receiving a suspicious message from an IP address (and port, if NAT traversal is used) with which it has an IKE SA SHOULD send an IKE Notify payload in an IKE INFORMATIONAL exchange over that SA. (§2.21.4) |
{gap} | Ze sends no protected Notify over an existing IKE SA when a suspicious message arrives from that peer's address. An unprotected message at a cached Message ID is dropped and counted (inbound.go, countErrorNotifySuppressed "unprotected-retransmit"), and an unprotected INVALID_IKE_SPI changes nothing, but neither path starts an INFORMATIONAL exchange over the SA |
Proof state
A tagged unit reads unproven where no discrimination record exists for it: nothing in this tree has been observed to break it, so the claim its tag makes is unproven.
RFC7296-1.2-1
The first pair of messages (IKE_SA_INIT) negotiate cryptographic algorithms, exchange nonces, and do a Diffie-Hellman exchange [DH]. The second pair of messages (IKE_AUTH) authenticate the previous messages, exchange identities and certificates, and establish the first Child SA. Parts of these messages are encrypted and integrity protected with keys established through the IKE_SA_INIT exchange, so the identities are hidden from eavesdroppers and all fields in all the messages are authenticated. (§1.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30. Descriptive row kept MUST under D-3. Positive TestRFC7296InitialExchangesCarryWhatSection12Names runs production handleSAInitRequest/handleAuthRequest/handleAuthResponse in X.509 mode over all four captured messages: IKE_SA_INIT req/resp carry SA+KE+Nonce, the single accepted proposal is one offered and both SAs hold it; Ni/Nr held crosswise and distinct; both KE name the negotiated group, each side holds the other's public value, equal SK_d; IKE_AUTH req IDi+CERT+AUTH+ESP SA+TSi+TSr, resp IDr+CERT+AUTH+one ESP proposal+TSi+TSr; identities recorded, both Established, initiator holds negotiated TS. Negative TestRFC7296TamperedIKESAInitFailsIKEAuth ('authenticate the previous messages'): one flipped octet in the stored IKE_SA_INIT copy on either side (PSK and X.509) keeps that side off Established while an untouched control establishes; genuine, it fails if AUTH stopped covering the IKE_SA_INIT octets. Encryption clause: TestInitialExchangeEncryptionBoundary +/-. The negotiation, nonce and DH clauses are positive-only here; their refusals are held by their own rows (3.3.6, 2.10, 1.2 KE/3.4). Records: handleSAInitRequest +, verifyRemoteAuth -, observed red.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296TamperedIKESAInitFailsIKEAuth |
unit/verify | revert, verified |
| negative | TestInitialExchangeEncryptionBoundary |
unit/verify | revert, verified |
| positive | TestRFC7296InitialExchangesCarryWhatSection12Names |
unit/verify | revert, verified |
| positive | TestInitialExchangeEncryptionBoundary |
unit/verify | revert, verified |
RFC7296-2.6-1
The initial two eight-octet fields in the header, called the "IKE SPIs", are used as a connection identifier at the beginning of IKE packets. (§2.6)
Audit verdict: enforced (the tests do what the requirement demands), fresh. The earlier residual is closed. New TestRFC7296MismatchedResponderSPIReachesNoSAThroughTheReceiveLoops runs the real receive loops over loopback UDP, dispatchInbound (port 500) and dispatchNATTInbound (non-ESP marker): a datagram with the established SA's initiator SPI and a different non-zero responder SPI, sent first, is never delivered to the SA's session (the first delivered datagram must carry the SA's own responder SPI, and no second one arrives); the datagram with the full pair is delivered. Ordering on loopback and the single dispatch goroutine make 'not delivered' distinguishable from 'delayed'. Kept: lookupInbound units TestRFC7296IKESPIPairIdentifiesTheIKESA / TestRFC7296UnknownIKESPIPairMapsToNoSA (full-pair map, zero-rSPI exceptions) and wire header round-trip/short-header tags. Records: dispatchInbound, dispatchNATTInbound, lookupInbound reverts observed red.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296MismatchedResponderSPIReachesNoSAThroughTheReceiveLoops |
unit/verify | revert, verified |
| negative | TestRFC7296UnknownIKESPIPairMapsToNoSA |
unit/verify | revert, verified |
| negative | TestDecodeTruncatedHeader |
unit/verify | revert, verified |
| positive | TestRFC7296MismatchedResponderSPIReachesNoSAThroughTheReceiveLoops |
unit/verify | revert, verified |
| positive | TestRFC7296IKESPIPairIdentifiesTheIKESA |
unit/verify | revert, verified |
| positive | TestHeaderRoundtrip |
unit/verify | revert, verified |
RFC7296-2.7-1
The responder MUST accept a single proposal or reject them all and return an error. The error is given in a notification of type NO_PROPOSAL_CHOSEN. Each IPsec protocol proposal contains one or more transforms. Each transform contains a Transform Type. The accepted cryptographic suite MUST contain exactly one transform of each type included in the proposal. (§2.7)
Audit verdict: enforced (the tests do what the requirement demands), fresh. RFC 7296 Section 2.7 (rfc/full/rfc7296.txt): "The responder MUST accept a single proposal or reject them all and return an error. The error is given in a notification of type NO_PROPOSAL_CHOSEN." and "The accepted cryptographic suite MUST contain exactly one transform of each type included in the proposal." NegotiateIKE picks one proposal or returns ErrNoProposalChosen (TestProposalNegotiationFirstMatch/NoMatch); TestEsnResponderAnswersOnlyAValueTheOfferCarried asserts SAr2 carries one proposal with exactly one ESN transform of a value the offer carried and maps refusal to NO_PROPOSAL_CHOSEN. Interop: checkESNExtendedOnlyRefused isolates the ESN type (aes256gcm16-esn alone) and asserts ze reached NO_PROPOSAL_CHOSEN (logged by buildChildlessAuthResponse as it builds the refusal notify) with no CHILD_SA on strongSwan and zero XFRM states on both ends, recorded red with the espProposalMatches ESN comparison reverted; checkESNBothOffered asserts both ends keyed, strongSwan's state carries no esn, and traffic crosses, so both ends selected the same single ESN value. Limitation, not a defect: the interop negative reads ze's log, not strongSwan's receipt of the notify; the wire mapping is held by the engine unit test. Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit, and the helpers they call (waitLog, listSAs, checkXFRMCount, establish, waitXFRM, xfrmState, verifyTunnelTraffic), is byte-identical between 35c3b0b699 and HEAD; the diff touches the scenarioCheckers registry shape (both ESN scenarios still map to these checkers) and the childless-IKE-SA checkers, and the producer change adds only a fix field to the refusal log line, so the verdict stands.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestProposalNegotiationNoMatch |
unit/verify | unproven |
| negative | TestEsnResponderAnswersOnlyAValueTheOfferCarried |
unit/verify | unproven |
| negative | checkESNExtendedOnlyRefused |
interop/nightly | unproven |
| positive | TestProposalNegotiationFirstMatch |
unit/verify | unproven |
| positive | TestEsnResponderAnswersOnlyAValueTheOfferCarried |
unit/verify | unproven |
| positive | checkESNBothOffered |
interop/nightly | unproven |
RFC7296-3.3-1
If an initiator wants to propose both combined- mode ciphers and normal ciphers, it must include two proposals: one will have all the combined-mode ciphers, and the other will have all the normal ciphers with the integrity algorithms. (§3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 after R30 D-8 (lookups return errors). The sentence (Section 3.3, rfc/full/rfc7296.txt:4308) obliges an initiator offering both classes to use two proposals. Send side: TestESPProposalsNeverMixAEADClass builds a group holding an AEAD and a non-AEAD proposal through the offer builder (now wireESPOffer via the test-only one-value wrapper) and asserts two proposals, AEAD with one ENCR and no INTEG, non-AEAD with one ENCR and one INTEG; a merge or an INTEG beside the AEAD cipher goes red. ipsec.ESPProposal holds one cipher, so the send-side negative is inexpressible (single-polarity positive on that side). Receive side: TestAeadMixInOneProposalIsRefused (negative) feeds espProposalMatches one proposal with the AEAD cipher plus a real INTEG and asserts refusal; TestAeadAloneInItsOwnProposalIsAccepted (positive, absent INTEG and explicit NONE) rules out a comparison that refuses every AEAD proposal. The edit to the negative is mechanical: lookupIntegrity now returns (T, error) and the test fails on the error; assertions and fixture unchanged. Records: negative revert on responder.go::espProposalMatches, observed red. The two positives carry no record (tags predate the record ratchet).
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAeadMixInOneProposalIsRefused |
unit/verify | revert, verified |
| positive | TestAeadAloneInItsOwnProposalIsAccepted |
unit/verify | unproven |
| positive | TestESPProposalsNeverMixAEADClass |
unit/verify | unproven |
RFC7296-3.3-2
Combined-mode ciphers include both integrity and encryption in a single encryption algorithm, and MUST either offer no integrity algorithm or a single integrity algorithm of "NONE" (§3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. AEAD ESP proposal built with no INTEG transform, non-AEAD keeps it (TestESPWireProposalAEADIntegNone)
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestESPWireProposalAEADIntegNone |
unit/verify | unproven |
| positive | TestESPWireProposalAEADIntegNone |
unit/verify | unproven |
RFC7296-3.3.2-1
An SA payload proposing the establishment of an SA has the following mandatory and optional Transform Types. A compliant implementation MUST understand all mandatory and optional types for each protocol it supports (though it need not accept proposals with unacceptable suites). A proposal MAY omit the optional types if the only value for them it will accept is NONE. Protocol Mandatory Types Optional Types --------------------------------------------------- IKE ENCR, PRF, INTEG*, D-H (§3.3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Row quotes the Section 3.3.3 span: the understand-all-types sentence and the IKE line (ENCR, PRF, INTEG*, D-H). IKE line through the responder's selection (wireProposalsToIKE + crypto.NegotiateIKE): a complete proposal is chosen and an AES-GCM proposal without INTEG is chosen with integrity NONE (TestRFC7296PeerIKEProposalWithTheMandatoryTypesIsAccepted); proposals missing ENCR or INTEG draw ErrProposalIncomplete and one missing D-H draws ErrDHGroupNone (TestRFC7296PeerIKEProposalMissingAMandatoryTypeIsRefused); missing PRF draws ErrNoProposalChosen (TestIKEWireProposalHasAllTransforms). TestResponderRequiresKEForDH proves the KE payload, a neighbour. Re-judged 2026-09-30 (leftovers): the weak finding (understand-every-type clause unproven under this id) is closed by tagging TestTftUnknownTransformTypeMakesProposalUnacceptable: positive, a wire IKE proposal of ENCR, PRF, INTEG and D-H is converted and accepted, so every IKE-line type is understood (an ununderstood one would mark the proposal unacceptable); negative, the same proposal plus an unassigned type 6 or an ESN transform is refused with ErrNoProposalChosen, which shows the understood predicate is what admits the four. The negative is the table-bound side (shared with RFC7296-3.3.3-1 and 3.3.6-4); the missing-type negatives above remain this row's direct violations. Records: TransformTypeUnderstoodIKE panic revert observed red both polarities. Judge ran the unit: PASS.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296PeerIKEProposalMissingAMandatoryTypeIsRefused |
unit/verify | revert, verified |
| negative | TestIKEWireProposalHasAllTransforms |
unit/verify | revert, verified |
| negative | TestResponderRequiresKEForDH |
unit/verify | revert, verified |
| negative | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | revert, verified |
| positive | TestRFC7296PeerIKEProposalWithTheMandatoryTypesIsAccepted |
unit/verify | revert, verified |
| positive | TestIKEWireProposalHasAllTransforms |
unit/verify | revert, verified |
| positive | TestResponderRequiresKEForDH |
unit/verify | revert, verified |
| positive | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | revert, verified |
RFC7296-1.3.3-1
The KEi payload MUST be included. (§1.3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor). SHIFTED by 6e063fb498 (tests: give ten assert-nothing tests a real assertion), whose hunks sit in untagged sibling tests and the import block. The tagged unit is byte-identical (gate-verified) and no helper it calls changed. Verdict stands. initiateIKERekey emits KEi (TestRespondIKERekey) and respondIKERekey refuses a rekey without KE naming KEi; test comment still cites Section 1.3.3 where the sentence is 1.3.2
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRespondIKERekeyRejectsMissingKE |
unit/verify | unproven |
| positive | TestRespondIKERekey |
unit/verify | unproven |
RFC7296-1.3.3-2
The REKEY_SA notification MUST be included in a CREATE_CHILD_SA exchange if the purpose of the exchange is to replace an existing ESP or AH SA (§1.3.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRksaChildRekeyCarriesTheRekeySANotify |
unit/verify | unproven |
| positive | TestRksaChildRekeyCarriesTheRekeySANotify |
unit/verify | unproven |
RFC7296-1.3.3-3
The initiator sends SA offer(s) in the SA payload, a nonce in the Ni payload, optionally a Diffie-Hellman value in the KEi payload, and the proposed Traffic Selectors for the proposed Child SA in the TSi and TSr payloads. (§1.3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Positive: TestRFC7296ChildRekeyRequestCarriesTheOfferNonceAndSelectors decrypts ze's initiateChildRekey request at the peer: exactly one SA, one Ni, one TSi and one TSr with selectors, KEi present with pfs enable and absent with pfs disable (the optional clause both ways). Negative (receive side): TestRFC7296ChildRekeyRequestMissingAPayloadIsRefused removes SA, Ni, TSi or TSr one at a time from a peer request: each refused with errMalformedRequest and INVALID_SYNTAX, nothing installed; the complete request is answered. TestRekeyWithoutTrafficSelectorsIsRefused (moved from 2.9-1) adds the no-TS request refusal and its answered twin.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRekeyWithoutTrafficSelectorsIsRefused |
unit/verify | revert, verified |
| negative | TestRFC7296ChildRekeyRequestMissingAPayloadIsRefused |
unit/verify | revert, verified |
| positive | TestRekeyWithoutTrafficSelectorsIsRefused |
unit/verify | revert, verified |
| positive | TestRFC7296ChildRekeyRequestCarriesTheOfferNonceAndSelectors |
unit/verify | revert, verified |
RFC7296-1.3.3-4
The Traffic Selectors for traffic to be sent on that SA are specified in the TS payloads in the response, which may be a subset of what the initiator of the Child SA proposed. (§1.3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. TestRFC7296ChildRekeyResponseCarriesTheSelectorsAndMayNarrow: ze's respondChildRekey response announces TSi/TSr equal to the installed scope, and ze as rekey initiator installs an answer narrowed to 10.1.0.0/25 from a /24 proposal (the may-be-a-subset clause). TestChildRekeyAnswerWithoutTrafficSelectorsIsRefused (moved from 2.9-1): a response without TS payloads is refused and installs nothing, the same fixture with both payloads installs their scope.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildRekeyAnswerWithoutTrafficSelectorsIsRefused |
unit/verify | revert, verified |
| positive | TestChildRekeyAnswerWithoutTrafficSelectorsIsRefused |
unit/verify | revert, verified |
| positive | TestRFC7296ChildRekeyResponseCarriesTheSelectorsAndMayNarrow |
unit/verify | revert, verified |
RFC7296-2.9-1
When the responder chooses a subset of the traffic proposed by the initiator, it narrows the Traffic Selectors to some subset of the initiator's proposal (provided the set does not become the null set). (§2.9)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-10 (independent judge) against RFC 7296 Section 2.9: "When the responder chooses a subset of the traffic proposed by the initiator, it narrows the Traffic Selectors to some subset of the initiator's proposal (provided the set does not become the null set)." The upgrade path named in the earlier weak verdict is now met by TestResponderNarrowsBothSelectorsToPolicy, which drives narrowChildSelectors, the producer every responder path calls (responder.go buildAuthResponse, responder_eap.go, create_child.go, rekey.go). Positive: a 10.0.0.0/8 proposal on BOTH TSi and TSr against policy 10.10.0.0/16 (initiator side) and 10.20.0.0/16 (responder side) must yield NegotiatedTSi 10.10.0.0/16 and NegotiatedTSr 10.20.0.0/16 exactly, and the IKE_AUTH response payloads from buildChildSAResponsePayloads must carry exactly one selector each spanning those prefixes. Negative (control, a responder MUST has no violating input): a proposal already inside policy (10.10.1.0/24, 10.20.2.0/24) must come back unchanged on both halves. Mutants judged: echoing the proposal, taking the wider prefix in intersectNet, or narrowing one side only reds the positive; answering with the policy prefixes reds the negative on both halves, so the earlier hole (intersectPair answering policy on TSr) is closed. The null-set proviso stays with TestTSUnacceptableIsSentWhenNothingIsAcceptable (disjoint proposal draws TS_UNACCEPTABLE, no pairs recorded). TestChildRekeyInitiatorInstallsTheAnsweredSelectors remains tagged but is Ze as initiator refusing a widened answer, supporting evidence only. Isolation: no floor, tunnel mode, no NAT state, so neither the Section 2.9.2 floor check nor transport single-address narrowing nor NAT substitution can decide the result. Limit: the unit drives the producer, not a whole IKE_AUTH exchange; the recorded discrimination breaks (panic in intersectPair / intersectNet) prove the path is reached, not the narrowing, which the exact-value assertions above carry.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildRekeyInitiatorInstallsTheAnsweredSelectors |
unit/verify | unproven |
| negative | TestResponderNarrowsBothSelectorsToPolicy |
unit/verify | revert, verified |
| negative | TestTSUnacceptableIsSentWhenNothingIsAcceptable |
unit/verify | unproven |
| positive | TestChildRekeyInitiatorInstallsTheAnsweredSelectors |
unit/verify | unproven |
| positive | TestResponderNarrowsBothSelectorsToPolicy |
unit/verify | revert, verified |
| positive | TestTSUnacceptableIsSentWhenNothingIsAcceptable |
unit/verify | unproven |
RFC7296-2.9-2
If the responder's policy allows it to accept the first selector of TSi and TSr, then the responder MUST narrow the Traffic Selectors to a subset that includes the initiator's first choices (§2.9)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNarrowingIncludesFirstChoice |
unit/verify | unproven |
| positive | TestPeerInitiatedRekeyIsNarrowedInTheExchangeOrientation |
unit/verify | unproven |
| positive | TestAuthResponsePayloadsCarryTheNarrowedSelectors |
unit/verify | unproven |
| positive | TestNarrowingIncludesFirstChoice |
unit/verify | unproven |
RFC7296-2.9.2-1
Thus, the new SA MUST NOT have narrower selectors than the original (§2.9.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildRekeyAnswerBelowTheScopeInUseIsRefused |
unit/verify | unproven |
| negative | TestRekeyFloorIsNotNarrowed |
unit/verify | unproven |
| positive | TestChildRekeyAnswerBelowTheScopeInUseIsRefused |
unit/verify | unproven |
| positive | TestRekeyAnswerMatchesTheInstalledSelectors |
unit/verify | unproven |
| positive | TestRekeyFloorIsNotNarrowed |
unit/verify | unproven |
RFC7296-2.9.2-2
The responder MUST NOT narrow down the Traffic Selectors narrower than the scope currently in use (§2.9.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildRekeyAnswerBelowTheScopeInUseIsRefused |
unit/verify | unproven |
| negative | TestRekeyProposalBelowTheFloorIsRefused |
unit/verify | unproven |
| negative | TestRekeyFloorIsNotNarrowed |
unit/verify | unproven |
| positive | TestChildRekeyAnswerBelowTheScopeInUseIsRefused |
unit/verify | unproven |
| positive | TestRekeyProposalBelowTheFloorIsRefused |
unit/verify | unproven |
| positive | TestRekeyFloorIsNotNarrowed |
unit/verify | unproven |
RFC7296-1.3.1-1
If the request is accepted, the response MUST also include a notification of type USE_TRANSPORT_MODE (§1.3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestUseTransportModeNotifyIsEchoedOnlyWhenAccepted |
unit/verify | unproven |
| positive | TestUseTransportModeNotifyIsEchoedOnlyWhenAccepted |
unit/verify | unproven |
RFC7296-1.3.1-2
If the responder declines the request, the Child SA will be established in tunnel mode. If this is unacceptable to the initiator, the initiator MUST delete the SA (§1.3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestTransportRequiredDeletesTheSAOnDecline |
unit/verify | unproven |
| positive | TestChildlessInitiatorDeletesDeclinedTransportChildSA |
unit/verify | revert, verified |
| positive | TestTransportRequiredDeletesTheSAOnDecline |
unit/verify | unproven |
RFC7296-2.23.1-1
For transport mode, it MUST use exactly one IP address in the TSi and TSr payloads (§2.23.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResponderAnswersTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| negative | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
| positive | TestResponderAnswersTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| positive | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
RFC7296-2.23.1-2
The TSi entries MUST have exactly one IP address, and that MUST match the source address of the IKE SA (§2.23.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestTransportSelectorsMatchTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| negative | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
| positive | TestTransportSelectorsMatchTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| positive | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
RFC7296-2.23.1-3
The TSr entries MUST have exactly one IP address, and that MUST match the destination address of the IKE SA (§2.23.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestTransportSelectorsMatchTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| negative | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
| positive | TestTransportSelectorsMatchTheIKESAAddressesBehindANAT |
unit/verify | revert, verified |
| positive | TestTransportModeUsesExactlyOneAddress |
unit/verify | unproven |
RFC7296-3.13.1-1
For protocols for which port is undefined (including protocol 0), or if all ports are allowed, this field MUST be zero. (§3.13.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. selectorsToWire encodes protocol-0 all-ports Start Port 0; single-port selector proves the encoder can emit non-zero
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
| positive | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
RFC7296-3.13.1-2
For protocols for which port is undefined (including protocol 0), or if all ports are allowed, this field MUST be 65535. (§3.13.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. all-ports End Port 65535; single-port 443 discriminator
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
| positive | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
RFC7296-3.13.1-3
Systems working with [IPSECARCH] that wish to indicate "OPAQUE" ports, but not "ANY" ports, MUST set the start port to 65535 and the end port to 0. (§3.13.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. PortOpaque encodes 65535/0 and ANY is not emitted in that form
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
| positive | TestPortEncodingFollowsSection3131 |
unit/verify | unproven |
RFC7296-2.23-1
The IKE initiator MUST check the NAT_DETECTION_SOURCE_IP or NAT_DETECTION_DESTINATION_IP payloads if present (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-09-30 (ike-eap judge). TestRFC7296InitiatorChecksEachNATDetectionPayload drives handleSAInitResponse over a real encoded IKE_SA_INIT response: a SOURCE_IP mismatch alone sets NATDetected+PeerBehindNAT and floats to 4500, a DESTINATION_IP mismatch alone sets NATDetected+BehindNAT and floats, so ignoring either payload goes red. TestRFC7296InitiatorCheckFindsNoNATOnMatchingPayloads (both present, both matching: no NAT, not floated) goes red if presence alone were taken as a NAT, i.e. if the payloads were not checked. Both carry observed-red records on fsm.go handleSAInitResponse. HEAD tags on transport TestNATDetectionPresent/Absent (DetectNAT in isolation) are supplementary and hold no record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296InitiatorCheckFindsNoNATOnMatchingPayloads |
unit/verify | revert, verified |
| negative | TestNATDetectionAbsent |
unit/verify | revert, verified |
| positive | TestRFC7296InitiatorChecksEachNATDetectionPayload |
unit/verify | revert, verified |
| positive | TestNATDetectionPresent |
unit/verify | revert, verified |
RFC7296-2.23-2
However, if a NAT is detected, both devices MUST use UDP encapsulation for ESP. (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-15 after b457ba88cf rewrote TestChildSANATTEncapPorts. RFC 7296 Section 2.23: 'However, if a NAT is detected, both devices MUST use UDP encapsulation for ESP.' With NATDetected and the IKE SA floated to its NAT-T socket, the test runs createFirstChildSA and requires exactly two installed states, inbound and outbound, each with UDPEncap true, so a NAT-detected Child SA installed without UDP encapsulation on either direction fails. The rewrite added port assertions (the IKE SA's ports, both fixtures off 4500) that serve RFC 3948 Section 2.1 and do not weaken the UDPEncap assertion. No receive-side refusal is legitimate (RFC7296-2.23-10 requires plain ESP to stay accepted), so TestChildSANoNATNoEncap stays a supplementary no-NAT guard. Rekey still carries NATDetected and UDPEncap from the old child (rekey.go newRekeyedChild), asserted by the untagged TestRekeyKeepsBothESPFormAcceptance outside this fingerprint.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildSANoNATNoEncap |
unit/verify | revert, verified |
| positive | TestChildSANATTEncapPorts |
unit/verify | revert, verified |
RFC7296-2.23-3
To tunnel IKE packets over UDP port 4500, the IKE header has four octets of zeros prepended and the result immediately follows the UDP header. (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-09-30 (ike-eap judge). TestRFC7296IKEOnPort4500CarriesTheZeroMarker sends through sendRaw (the shared post-establishment send path) on an SA floated to 4500 and reads the raw UDP payload at the peer: exactly 00000000 followed by the IKE message byte for byte, so a missing marker or anything between the UDP header and the marker goes red. TestRFC7296IKEOnPort500CarriesNoMarker shows the same send on port 500 carries the message unchanged, so the zeros are conditional on 4500. Both carry observed-red records on established.go sendRaw. HEAD tags on transport TestNonESPMarker/TestNonESPMarkerESPPacket (helpers in isolation) are supplementary and hold no record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296IKEOnPort500CarriesNoMarker |
unit/verify | revert, verified |
| negative | TestNonESPMarkerESPPacket |
unit/verify | revert, verified |
| positive | TestRFC7296IKEOnPort4500CarriesTheZeroMarker |
unit/verify | revert, verified |
| positive | TestNonESPMarker |
unit/verify | revert, verified |
RFC7296-2.8-1
If redundant SAs are created through such a collision, the SA created with the lowest of the four nonces used in the two exchanges SHOULD be closed by the endpoint that created it (§2.8, §2.8.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRekeyCollision |
unit/verify | unproven |
| negative | TestRekeyCollisionIKEBranchLowestNonceAbandons |
unit/verify | unproven |
| negative | TestRekeyCollisionLowestNonceAbandons |
unit/verify | unproven |
| positive | TestRekeyCollision |
unit/verify | unproven |
| positive | TestRekeyCollisionIKEBranchLowestNonceAbandons |
unit/verify | unproven |
| positive | TestRekeyCollisionLowestNonceAbandons |
unit/verify | unproven |
RFC7296-2.4-1
To check whether the other side is alive, IKE specifies an empty INFORMATIONAL request that (like all IKE requests) requires an acknowledgement (§2.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. empty INFORMATIONAL request answered by an encrypted INFORMATIONAL response with zero inner payloads echoing the message ID; a response is not answered
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDPDEmptyInformationalGetsEmptyResponse |
unit/verify | unproven |
| positive | TestDPDEmptyInformationalGetsEmptyResponse |
unit/verify | unproven |
RFC7296-1.4-1
Normally, the response in the INFORMATIONAL exchange will contain Delete payloads for the paired SAs going in the other direction. (§1.4.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after the owner moved the level from MUST to SHOULD (970ea021d8); quote unchanged. RFC 7296 1.4.1: 'Normally, the response in the INFORMATIONAL exchange will contain Delete payloads for the paired SAs going in the other direction.' TestDelResponseCarriesThePairedDelete sends a Child SA Delete naming ze's outbound SPI and requires the response to carry one ESP Delete naming the paired inbound SPI and not the deleted one, so an empty or echoing response fails; that is the recommended behavior at either level. TestDelIKEDeleteDrawsAnEmptyResponse (IKE SA Delete draws an empty response, per the same paragraph) is a scoping control rather than a violating input, and the crossing-Delete exception is proven under RFC7296-1.4.1-4 and -7. The lower level asks less, so the proof still covers it. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDelIKEDeleteDrawsAnEmptyResponse |
unit/verify | unproven |
| positive | TestDelResponseCarriesThePairedDelete |
unit/verify | unproven |
RFC7296-2.8-2
A difference between IKEv1 and IKEv2 is that in IKEv1 SA lifetimes were negotiated. In IKEv2, each end of the SA is responsible for enforcing its own lifetime policy on the SA and rekeying the SA when necessary. (§2.8)
Audit verdict: enforced (the tests do what the requirement demands), fresh. no lifetime transform or attribute reaches the wire (TestLifetimesNotNegotiatedOnWire); lifetime state derives from the local value (TestSALifetimeTime)
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLifetimesNotNegotiatedOnWire |
unit/verify | unproven |
| positive | TestSALifetimeTime |
unit/verify | unproven |
RFC7296-1-1
In all cases, all IKE_SA_INIT exchanges MUST complete before any other exchange type, then all IKE_AUTH exchanges MUST complete, and following that, any number of CREATE_CHILD_SA and INFORMATIONAL exchanges may occur in any order (§1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutExchangesRunInRFCOrder |
unit/verify | unproven |
| positive | TestAutExchangesRunInRFCOrder |
unit/verify | unproven |
RFC7296-1.2-2
If any CERT payloads are included, the first certificate provided MUST contain the public key used to verify the AUTH field (§1.2, §3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutFirstCertificateCarriesTheAuthKey |
unit/verify | unproven |
| negative | TestRccTwoLevelChainAuthenticates |
unit/verify | unproven |
| positive | TestAutFirstCertificateCarriesTheAuthKey |
unit/verify | unproven |
| positive | TestRccTwoLevelChainAuthenticates |
unit/verify | unproven |
RFC7296-1.2-3
Both parties in the IKE_AUTH exchange MUST verify that all signatures and Message Authentication Codes (MACs) are computed correctly (§1.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutIKEAuthVerifiesEveryMAC |
unit/verify | unproven |
| negative | TestAutIKEAuthVerifiesSignatures |
unit/verify | unproven |
| positive | TestAutIKEAuthVerifiesEveryMAC |
unit/verify | unproven |
| positive | TestAutIKEAuthVerifiesSignatures |
unit/verify | unproven |
RFC7296-1.2-4
If either side uses a shared secret for authentication, the names in the ID payload MUST correspond to the key used to generate the AUTH payload (§1.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutSharedSecretAuthBindsTheIDName |
unit/verify | unproven |
| positive | TestAutSharedSecretAuthBindsTheIDName |
unit/verify | unproven |
RFC7296-1.2-5
If the initiator guesses wrong, the responder will respond with a Notify payload of type INVALID_KE_PAYLOAD indicating the selected group. In this case, the initiator MUST retry the IKE_SA_INIT with the corrected Diffie-Hellman group (§1.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestKegInitiatorRefusesUnofferedGroup |
unit/verify | unproven |
| positive | TestKegInitiatorRetriesOnInvalidKEPayload |
unit/verify | unproven |
RFC7296-1.2-6
The initiator MUST again propose its full set of acceptable cryptographic suites because the rejection message was unauthenticated and otherwise an active attacker could trick the endpoints into negotiating a weaker suite than a stronger one that they both prefer (§1.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestKegRetryOfferIsNotNarrowedByTheNotify |
unit/verify | unproven |
| positive | TestKegRetryReproposesEveryConfiguredSuite |
unit/verify | unproven |
RFC7296-2.4-11
An endpoint MUST conclude that the other endpoint has failed only when repeated attempts to contact it have gone unanswered for a timeout period or when a cryptographically protected INITIAL_CONTACT notification is received on a different IKE SA to the same authenticated identity (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDPDNoTransportTakesNoWindow |
unit/verify | unproven |
| negative | TestDPDVerdictNeedsARepeatedAttempt |
unit/verify | unproven |
| negative | TestSesPeerFailedOnlyAfterRepeatedSilence |
unit/verify | unproven |
| positive | TestDPDVerdictEndsAProbeThatCannotBeRepeated |
unit/verify | unproven |
| positive | TestDPDVerdictNeedsARepeatedAttempt |
unit/verify | unproven |
| positive | TestSesPeerFailedOnlyAfterRepeatedSilence |
unit/verify | unproven |
RFC7296-2.4-12
Implementations MUST limit the rate at which they take actions based on unprotected messages (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrResponderWindowDoesNotReflectToObservedSource |
unit/verify | unproven |
| negative | TestErrUnprotectedMessageDrawsNoCachedResponse |
unit/verify | unproven |
| negative | TestSesLimitsWorkOnUnprotectedMessages |
unit/verify | unproven |
| positive | TestErrResponderWindowDoesNotReflectToObservedSource |
unit/verify | unproven |
| positive | TestErrUnprotectedMessageDrawsNoCachedResponse |
unit/verify | unproven |
| positive | TestSesLimitsWorkOnUnprotectedMessages |
unit/verify | unproven |
RFC7296-2.4-13
To be a good network citizen, retransmission times MUST increase exponentially to avoid flooding the network and making an existing congestion situation worse (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesRetransmitWaitIncreasesExponentially |
unit/verify | unproven |
| positive | TestSesRetransmitWaitIncreasesExponentially |
unit/verify | unproven |
RFC7296-2.7-2
Each proposal contains one protocol. If a proposal is accepted, the SA response MUST contain the same protocol (§2.7)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesAcceptedProposalKeepsItsProtocol |
unit/verify | unproven |
| positive | TestSesAcceptedProposalKeepsItsProtocol |
unit/verify | unproven |
RFC7296-2.10-4
Nonces used in IKEv2 MUST be randomly chosen (§2.10)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesNoncesAreRandomlyChosenAndNeverReused |
unit/verify | unproven |
| positive | TestSesNoncesAreRandomlyChosenAndNeverReused |
unit/verify | unproven |
RFC7296-2.11-1
An implementation MUST accept incoming requests even if the source port is not 500 or 4500 (§2.11, §2.23)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesAcceptsRequestFromAnySourcePort |
unit/verify | unproven |
| negative | TestPrtAcceptsDatagramFromAnySourcePort |
unit/verify | unproven |
| positive | TestSesAcceptsRequestFromAnySourcePort |
unit/verify | unproven |
| positive | TestPrtAcceptsDatagramFromAnySourcePort |
unit/verify | unproven |
RFC7296-2.11-2
MUST respond to the address and port from which the request was received (§2.11)
Audit verdict: enforced (the tests do what the requirement demands), fresh. TestRFC7296ReplyLandsOnTheRequestSourcePort reads the reply datagram on the socket bound to the request's odd source port (response flag, request Message ID, decrypts under the IKE SA). The negative is now TestRFC7296ReplyDoesNotGoToTheConfiguredEndpoint alone: the configured remote, the violating destination, receives nothing. The NAT-T unauthenticated-packet unit moved to RFC7296-2.23-13, the row it proves. The older natt positive asserts only the stored endpoint and is supplementary.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ReplyDoesNotGoToTheConfiguredEndpoint |
unit/verify | revert, verified |
| positive | TestNattRepliesToTheObservedSourcePort |
unit/verify | revert, verified |
| positive | TestRFC7296ReplyLandsOnTheRequestSourcePort |
unit/verify | revert, verified |
RFC7296-2.11-3
It MUST specify the address and port at which the request was received as the source address and port in the response (§2.11)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNattReplyRefusesWithoutADestination |
unit/verify | unproven |
| positive | TestNattReplyLeavesFromTheArrivalSocket |
unit/verify | unproven |
RFC7296-2.16-11
these protocols are typically used to authenticate the initiator to the responder and MUST be used in conjunction with a public-key-signature-based authentication of the responder to the initiator. (§2.16)
Audit verdict: enforced (the tests do what the requirement demands), fresh. EAP responder AUTH is an RFC 7427 signature verified under the cert key; no-cert EAP refused at setup and config; initiator refuses PSK AUTH from EAP responder; PSK peers unaffected
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapAuthConfigRejectsEAPWithoutCertificate |
unit/verify | unproven |
| negative | TestEapAuthInitiatorRefusesPreSharedKeyResponder |
unit/verify | unproven |
| negative | TestEapAuthResponderRefusesWithoutCertificate |
unit/verify | unproven |
| positive | TestEapAuthConfigAcceptsPreSharedKeyPeer |
unit/verify | unproven |
| positive | TestEapAuthNonEAPPreSharedKeyStillAuthenticates |
unit/verify | unproven |
| positive | TestEapAuthResponderSignsWithPublicKey |
unit/verify | unproven |
RFC7296-2.16-6
Extensible authentication is implemented in IKE as additional IKE_AUTH exchanges that MUST be completed in order to initialize the IKE SA (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutEAPRunsAsExtraIKEAuthExchanges |
unit/verify | unproven |
| positive | TestAutEAPRunsAsExtraIKEAuthExchanges |
unit/verify | unproven |
RFC7296-2.16-7
This shared key generated during an IKE exchange MUST NOT be used for any other purpose (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAutEAPSharedKeyServesAuthAlone |
unit/verify | unproven |
| positive | TestAutEAPSharedKeyServesAuthAlone |
unit/verify | unproven |
RFC7296-2.23-7
Both the IKE initiator and responder MUST include in their IKE_SA_INIT packets Notify payloads of type NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP (§2.23)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesBothEndsSendNATDetectionNotifies |
unit/verify | unproven |
| positive | TestSesBothEndsSendNATDetectionNotifies |
unit/verify | unproven |
RFC7296-2.23-8
An IPsec endpoint that discovers a NAT between it and its correspondent (as described below) MUST send all subsequent traffic from port 4500 (§2.23)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNattFloatedSAWithoutNATTSocketSendsNothing |
unit/verify | revert, verified |
| negative | TestNattNoFloatWithoutNAT |
unit/verify | revert, verified |
| positive | TestNattFloatsEverySenderToPort4500 |
unit/verify | revert, verified |
| positive | TestNattRekeyedChildKeepsUDPEncap |
unit/verify | unproven |
RFC7296-2.23-9
UDP encapsulation MUST NOT be done on port 500 (§2.23)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEncapPortsAreExpressible |
unit/verify | unproven |
| positive | TestEncapNeverRequestedOnPort500 |
unit/verify | revert, verified |
RFC7296-2.23-10
If Network Address Translation Traversal (NAT-T) is supported (that is, if NAT_DETECTION_*_IP payloads were exchanged during IKE_SA_INIT), all devices MUST be able to receive and process both UDP-encapsulated ESP and non-UDP-encapsulated ESP packets at any time. (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. every Child SA accepts both ESP forms inbound (AcceptBothESPForms) and both forms are programmable; kernel behavior measured by the cited QEMU tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBfmBothESPFormsReceivedOnOneChildSA |
unit/verify | unproven |
| positive | TestBfmBothESPFormsAreReachable |
unit/verify | unproven |
RFC7296-2.23-11
Implementations MUST process received UDP-encapsulated ESP packets even when no NAT was detected (§2.23)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBfmBareESPKeptForUnfloatedSA |
unit/verify | unproven |
| positive | TestBfmEncapsulatedESPAcceptedWithoutNAT |
unit/verify | revert, verified |
| positive | TestBfmEncapsulatedESPSentWhenNATDetected |
unit/verify | revert, verified |
RFC7296-2.23-12
To tunnel ESP packets over UDP port 4500, the ESP header immediately follows the UDP header. Since the first four octets of the ESP header contain the SPI, and the SPI cannot validly be zero, it is always possible to distinguish ESP and IKE messages. (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-09-30 (ike-eap judge). Sentence 1: Linux performs ESP-in-UDP, so the proof is the state Ze installs: TestRFC7296ESPInUDPStateHasESPRightAfterUDP asserts xfrmStateFromParams builds an encapsulated 4500/4500 SA with Encap.Type XFRM_ENCAP_ESPINUDP (the RFC 3948 form, ESP header right after UDP, not ESPINUDP_NON_IKE) and the SA's SPI. Sentence 2: TestRFC7296ESPInUDPStateRefusesSPIZero forces SPI 0 on an encapsulated SA and requires a refusal with no state; judge mutation (SPI==0 check disabled in xfrmStateFromParams) turned it red, so it is not vacuous. Both carry records. Receive-side distinction stays on transport TestNonESPMarker/TestNonESPMarkerESPPacket (recorded). No netns wire capture (needs root); the template Ze installs is the boundary Ze owns.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ESPInUDPStateRefusesSPIZero |
unit/verify | revert, verified |
| negative | TestNonESPMarkerESPPacket |
unit/verify | revert, verified |
| positive | TestRFC7296ESPInUDPStateHasESPRightAfterUDP |
unit/verify | revert, verified |
| positive | TestNonESPMarker |
unit/verify | revert, verified |
RFC7296-2.23-13
When such a validated packet is found, a host that does not support other methods of recovery such as IKEv2 Mobility and Multihoming (MOBIKE) [MOBIKE], and that is not behind a NAT, SHOULD send all packets (including retransmission packets) to the IP address and port in the validated packet, and SHOULD store this as the new address and port combination for the SA (that is, they SHOULD dynamically update the address). (§2.23)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Row is verbatim §2.23. Positive TestRFC7296ValidatedPacketFromANewEndpointMovesTheSA: responder not behind a NAT and without MOBIKE; a second validated request from a new port moves peerEndpoint and remoteUDPAddr (what every send and retransmission reads), and the response is read on the new socket. Negatives each violate one bound of the sentence against adoptAuthenticatedEndpoint: behind a NAT (§2.23 'A host behind a NAT SHOULD NOT do this type of dynamic address update') and MOBIKE keep the stored endpoint (TestRFC7296ValidatedPacketDoesNotMoveTheSAOutsideTheRow); a packet with an in-window Message ID whose integrity check fails, from a new endpoint, moves nothing (TestNattUnauthenticatedPacketDoesNotMoveTheEndpoint). Each guard in the producer has a case that reddens without it. The 'new packet' replay bound is a separate lowercase-should sentence, not this row.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ValidatedPacketDoesNotMoveTheSAOutsideTheRow |
unit/verify | revert, verified |
| negative | TestNattUnauthenticatedPacketDoesNotMoveTheEndpoint |
unit/verify | revert, verified |
| positive | TestRFC7296ValidatedPacketFromANewEndpointMovesTheSA |
unit/verify | revert, verified |
RFC7296-3.9-2
Nonce values MUST NOT be reused (§3.9)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSesNoncesAreRandomlyChosenAndNeverReused |
unit/verify | unproven |
| negative | TestSesRekeyDrawsFreshNoncesOnBothSides |
unit/verify | unproven |
| positive | TestSesNoncesAreRandomlyChosenAndNeverReused |
unit/verify | unproven |
| positive | TestSesRekeyDrawsFreshNoncesOnBothSides |
unit/verify | unproven |
RFC7296-1.3-2
If the responder selects a proposal using a different Diffie-Hellman group (other than NONE), the responder MUST reject the request and indicate its preferred Diffie-Hellman group in the INVALID_KE_PAYLOAD Notify payload (§1.3, §3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNegRekeyRejectsMismatchedKEGroup |
unit/verify | unproven |
| positive | TestNegRekeyRejectsMismatchedKEGroup |
unit/verify | unproven |
RFC7296-2.8.2-1
The new IKE SA containing the lowest nonce SHOULD be deleted by the node that created it, and the other surviving new IKE SA MUST inherit all the Child SAs (§2.8.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNegIKERekeyCollisionResolves |
unit/verify | unproven |
| negative | TestNegSurvivingSAInheritsChildren |
unit/verify | unproven |
| positive | TestNegIKERekeyCollisionResolves |
unit/verify | unproven |
| positive | TestNegSurvivingSAInheritsChildren |
unit/verify | unproven |
RFC7296-3.3.6-3
The initiator of an exchange MUST check that the accepted offer is consistent with one of its proposals, and if not MUST terminate the exchange (§3.3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestVerInitiatorRefusesUnsentESPKeyLength |
unit/verify | unproven |
| negative | TestVerInitiatorRefusesUnsentIKEKeyLength |
unit/verify | unproven |
| negative | TestEsnInitiatorRefusesAnESNValueItNeverOffered |
unit/verify | unproven |
| negative | TestKlnInitiatorRefusesLongerAcceptedKey |
unit/verify | unproven |
| negative | TestNegInitiatorRejectsUnproposedOffer |
unit/verify | unproven |
| positive | TestVerInitiatorRefusesUnsentESPKeyLength |
unit/verify | unproven |
| positive | TestVerInitiatorRefusesUnsentIKEKeyLength |
unit/verify | unproven |
| positive | TestEsnInitiatorRefusesAnESNValueItNeverOffered |
unit/verify | unproven |
| positive | TestKlnInitiatorRefusesLongerAcceptedKey |
unit/verify | unproven |
| positive | TestNegInitiatorRejectsUnproposedOffer |
unit/verify | unproven |
RFC7296-1.4-3
Control messages that pertain to an IKE SA MUST be sent under that IKE SA. Control messages that pertain to Child SAs MUST be sent under the protection of the IKE SA that generated them (§1.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyControlMessagesRideTheirOwnIKESA |
unit/verify | unproven |
| positive | TestLcyControlMessagesRideTheirOwnIKESA |
unit/verify | unproven |
RFC7296-1.4-4
The recipient of an INFORMATIONAL exchange request MUST send some response; otherwise, the sender will assume the message was lost in the network and will retransmit it (§1.4, §4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyEveryInformationalRequestDrawsAResponse |
unit/verify | unproven |
| positive | TestLcyEveryInformationalRequestDrawsAResponse |
unit/verify | unproven |
RFC7296-1.4-5
INFORMATIONAL exchanges MUST ONLY occur after the initial exchanges and are cryptographically protected with the negotiated keys (§1.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDpdProbeIsEncrypted |
unit/verify | unproven |
| positive | TestDpdProbeIsEncrypted |
unit/verify | unproven |
RFC7296-1.4.1-6
To delete an SA, an INFORMATIONAL exchange with one or more Delete payloads is sent listing the SPIs (as they would be expected in the headers of inbound packets) of the SAs to be deleted. The recipient MUST close the designated SAs (§1.4.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDelUnknownSPIClosesNothing |
unit/verify | unproven |
| positive | TestDelPeerDeleteClosesTheDesignatedChildSA |
unit/verify | unproven |
RFC7296-1.4.1-7
If a node receives a delete request for SAs for which it has already issued a delete request, it MUST delete the outgoing SAs while processing the request and the incoming SAs while processing the response (§1.4.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDelWithoutOwnDeleteTheSameRequestIsPaired |
unit/verify | unproven |
| positive | TestDelCrossingDeleteAnswersWithoutAPairedDelete |
unit/verify | unproven |
RFC7296-1.5-1
This message is not part of an INFORMATIONAL exchange, and the receiving node MUST NOT respond to it because doing so could cause a message loop (§1.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWp2OutOfSAAnswersARequest |
unit/verify | unproven |
| positive | TestWp2OutOfSAEmitterIsAFixedPoint |
unit/verify | unproven |
RFC7296-2.12-1
Achieving perfect forward secrecy requires that when a connection is closed, each endpoint MUST forget not only the keys used by the connection but also any information that could be used to recompute those keys (§2.12)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWp2OpenSAKeepsItsKeys |
unit/verify | unproven |
| positive | TestRunEstablishedClearsPendingIKESwapOnExit |
unit/verify | unproven |
| positive | TestWp2ForgetKeysErasesEverySecret |
unit/verify | unproven |
RFC7296-2.24-1
tunnel encapsulators and decapsulators for all tunnel mode SAs created by IKEv2 MUST support the ECN full-functionality option for tunnels specified in [ECN] (§2.24)
Audit verdict: enforced (the tests do what the requirement demands), fresh. installed Child SAs are tunnel mode with no ECN-disabling field (engine and XFRM scans); VPP InstallSA sets ENCAP/DECAP_COPY_ECN. Negatives are non-vacuity checks rather than violating inputs
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEcnTheScannedStateIsTheOneZeInstalls |
unit/verify | unproven |
| negative | TestVPPInstallSAECNIsOnTheSAZeInstalls |
unit/verify | unproven |
| negative | TestEcnTheInstalledSAsAreRealAndDirectional |
unit/verify | unproven |
| positive | TestEcnInstalledStateDisablesNothing |
unit/verify | unproven |
| positive | TestVPPInstallSACopiesECN |
unit/verify | unproven |
| positive | TestEcnInstalledChildSAAsksForNoECNChange |
unit/verify | unproven |
RFC7296-2.24-2
MUST implement the tunnel encapsulation and decapsulation processing specified in [IPSECARCH] to prevent discarding of ECN congestion indications. (§2.24)
Audit verdict: enforced (the tests do what the requirement demands), fresh. same units: XFRM state carries no NOECN path, VPP sets DECAP_COPY_ECN; transport mode refused by VPP backend
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEcnTheScannedStateIsTheOneZeInstalls |
unit/verify | unproven |
| negative | TestVPPInstallSAECNIsOnTheSAZeInstalls |
unit/verify | unproven |
| negative | TestEcnTheInstalledSAsAreRealAndDirectional |
unit/verify | unproven |
| positive | TestEcnInstalledStateDisablesNothing |
unit/verify | unproven |
| positive | TestVPPInstallSACopiesECN |
unit/verify | unproven |
| positive | TestEcnInstalledChildSAAsksForNoECNChange |
unit/verify | unproven |
RFC7296-2.16-12
For EAP methods that create a shared key as a side effect of authentication, that shared key MUST be used by both the initiator and responder to generate AUTH payloads in messages 7 and 8 using the syntax for shared secrets specified in Section 2.15 (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapAuthProducerOutputIsRefusedUnderAnotherKey |
unit/verify | unproven |
| positive | TestEapAuthProducerIsKeyedByTheNegotiatedMSK |
unit/verify | unproven |
RFC7296-2.16-13
Following such an extended exchange, the EAP AUTH payloads MUST be included in the two messages following the one containing the EAP Success message (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapAuthFollowsTheSuccessMessage |
unit/verify | unproven |
| positive | TestEapAuthFollowsTheSuccessMessage |
unit/verify | unproven |
RFC7296-2.16-14
Once the protocol exchange defined by the chosen EAP authentication method has successfully terminated, the responder MUST send an EAP payload containing the Success message (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapResultFailureIsSent |
unit/verify | unproven |
| positive | TestEapResultSuccessIsSent |
unit/verify | unproven |
RFC7296-2.16-15
Similarly, if the authentication method has failed, the responder MUST send an EAP payload containing the Failure message (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapResultSuccessIsNotFailure |
unit/verify | unproven |
| positive | TestEapResultFailureIsSent |
unit/verify | unproven |
RFC7296-3.1-13
* I (Initiator) - This bit MUST be set in messages sent by the original initiator of the IKE SA and MUST be cleared in messages sent by the original responder. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Every call site of initiatorFlag is now product-driven for both original roles: IKE_SA_INIT/IKE_AUTH request and response, INFORMATIONAL responses, IKE rekey request, DPD probes (earlier units), and TestRFC7296InitiatorBitAtEveryRemainingCallSite: writeDelete and sendIKESATeardown Delete requests and startMobikeRequest read off the peer socket, respondMobikeError, buildErrorNotifyResponse, initiateChildRekey, respondChildRekey accepted and INVALID_KE, respondIKERekey accepted and INVALID_KE. Each check asserts I == original-initiator and the R flag, so a site deriving I from direction goes red on a response or on the original responder's request, and a hard-coded value goes red for one role. The older unit's test-built Delete remains but no longer carries the Delete claim alone.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWp2DPDProbeIBitDiffersByRole |
unit/verify | revert, verified |
| positive | TestRFC7296InitiatorBitAtEveryRemainingCallSite |
unit/verify | revert, verified |
| positive | TestRFC7296InitiatorBitFollowsTheOriginalRole |
unit/verify | revert, verified |
| positive | TestWp2DPDProbeIBitFollowsRole |
unit/verify | revert, verified |
RFC7296-3.5-5
A fully-qualified domain name string. An example of an ID_FQDN is "example.com". The string MUST NOT contain any terminators (e.g., NULL, CR, etc.). (§3.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Row now quotes the ID_FQDN entry through its ban (verbatim §3.5; the keyword-free ASCII/IDNA sentence the old weak verdict turned on is out of the span). TestWp2IDTerminatorRefused: a peer ID_FQDN holding NUL, CR or LF is refused by refuseIDTerminators, and ze's own local-id/remote-id holding one is refused by ValidateIdentities (config.go:158), the only path to the ID_FQDN ze sends (encodeIKEID). TestWp2IDWithoutTerminatorAccepted: clean FQDN accepted on both paths, NUL ID_KEY_ID left alone, so neither check refuses everything. Both halves call the validators directly; the call sites remote_id.go:393 and config.go:158 are unasserted. Producer comments at remote_id.go:352 and ipsec/validate.go:181 still quote the invented sentence the row dropped.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWp2IDWithoutTerminatorAccepted |
unit/verify | revert, verified |
| positive | TestWp2IDTerminatorRefused |
unit/verify | revert, verified |
RFC7296-3.5-6
A fully-qualified RFC 822 email address string. An example of a ID_RFC822_ADDR is "jsmith@example.com". The string MUST NOT contain any terminators. (§3.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-01 under owner ruling 5 (ruling 2 reading). Ze never sends an ID_RFC822_ADDR: encodeIKEID (auth.go) emits only ID_IPV4_ADDR, ID_IPV6_ADDR or ID_FQDN, and the config path refuses a local-id/remote-id holding a terminator before it can be sent. The handling of the peer's violation is the refusal: TestWp2IDTerminatorRefused feeds refuseIDTerminators an ID_RFC822_ADDR holding a NUL and asserts refusal; TestWp2IDWithoutTerminatorAccepted is the control, a clean mail address accepted, so a check refusing every identity goes red. Tag labels are inverted relative to ruling 2 (refusal tagged positive, acceptance negative) but the pair is complete and isolated (one NUL octet is the only difference). Both units hold observed-red revert records.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWp2IDWithoutTerminatorAccepted |
unit/verify | revert, verified |
| positive | TestWp2IDTerminatorRefused |
unit/verify | revert, verified |
RFC7296-1.4.1-1
When an SA is closed, both members of the pair MUST be closed (that is, deleted). Each endpoint MUST close its incoming SAs and allow the other endpoint to close the other SA in each pair (§1.4.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyClosingAChildSAClosesBothHalvesAndDeletesOurInbound |
unit/verify | unproven |
| positive | TestLcyClosingAChildSAClosesBothHalvesAndDeletesOurInbound |
unit/verify | unproven |
RFC7296-1.4.1-4
In that case, the responses MUST NOT include Delete payloads for the deleted SAs, since that would result in duplicate deletion and could in theory delete the wrong SA. (§1.4.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. TestDelCrossingDeleteAnswersWithoutAPairedDelete runs the production crossing sequence (recordOwnDelete, send, remove) and asserts the response to the peer's crossing Delete carries no Delete payload; reddens when crossOwnDelete stops detecting the crossing. TestDelWithoutOwnDeleteTheSameRequestIsPaired pins the row's own 'In that case' scope: outside the exception the same Delete draws the paired Delete §1.4.1 requires ('Normally, the response ... will contain Delete payloads for the paired SAs'), so a responder that never pairs cannot pass. The tags on TestLcyInformationalResponseCarriesNoDeletePayload are gone and its stale premise rewritten.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDelWithoutOwnDeleteTheSameRequestIsPaired |
unit/verify | revert, verified |
| positive | TestDelCrossingDeleteAnswersWithoutAPairedDelete |
unit/verify | revert, verified |
RFC7296-1.4.1-5
A node MAY refuse to accept incoming data on half-closed connections but MUST NOT unilaterally close them and reuse the SPIs (§1.4.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyRetiredSPIsAreNeverReused |
unit/verify | unproven |
| positive | TestLcyRetiredSPIsAreNeverReused |
unit/verify | unproven |
RFC7296-2.4-9
If a system creates Child SAs that can fail independently from one another without the associated IKE SA being able to send a delete message, then the system MUST negotiate such Child SAs using separate IKE SAs (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyOneChildSALivesUnderOneIKESA |
unit/verify | unproven |
| positive | TestLcyOneChildSALivesUnderOneIKESA |
unit/verify | unproven |
RFC7296-2.4-10
If an IKE endpoint chooses to delete Child SAs, it MUST send Delete payloads to the other end notifying it of the deletion (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLcyRetiringAChildSASendsADeletePayload |
unit/verify | unproven |
| positive | TestLcyRetiringAChildSASendsADeletePayload |
unit/verify | unproven |
RFC7296-2.16-5
If EAP methods that do not generate a shared key are used, the AUTH payloads in messages 7 and 8 MUST be generated using SK_pi and SK_pr, respectively (§2.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEAPAuthOfKeyDerivingMethodStillUsesTheMSK |
unit/verify | revert, verified |
| positive | TestEAPAuthOfNonKeyDerivingMethodUsesSKpiAndSKpr |
unit/verify | revert, verified |
RFC7296-2.16-16
EAP methods that do not establish a shared key SHOULD NOT be used, as they are subject to a number of man-in-the-middle attacks [EAPMITM] if these EAP methods are used in other protocols that do not use a server-authenticated tunnel. (§2.16)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Non-compliant behaviour: an IKEv2 exchange selecting an EAP method that establishes no key when the operator did not name one. Positive: TestRFC3748IKEv2EAPModesSelectAKeyDerivingMethod fails ('auth mode %s selected an EAP method that derives no key') for any EAP mode other than AuthEAPMD5 whose newEAPSession session answers false to DerivesKey. Negative: TestRFC3748IKEv2NoAuthModeSelectsAKeylessMethod sweeps every AuthMode value through newEAPSession and startEAPExchange, and assertKeylessModeIsNamedAndAnnounced goes red when a keyless method is reached by an unnamed value or without the adoption warning. The SHOULD NOT is met as a deviation the operator must name, which the warning makes visible.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC3748IKEv2NoAuthModeSelectsAKeylessMethod |
unit/verify | revert, verified |
| positive | TestRFC3748IKEv2EAPModesSelectAKeyDerivingMethod |
unit/verify | revert, verified |
RFC7296-3.4-1
The length of the Diffie-Hellman public value for MODP groups MUST be equal to the length of the prime modulus over which the exponentiation was performed, prepending zero bits to the value if necessary (§3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296MODPShortPublicValueIsRefusedOnReceipt |
unit/verify | unproven |
| positive | TestRFC7296MODPPublicValueMatchesModulusLength |
unit/verify | unproven |
RFC7296-1.3-1
If a CREATE_CHILD_SA exchange includes a KEi payload, at least one of the SA offers MUST include the Diffie-Hellman group of the KEi (§1.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildRekeyProposesDiffieHellmanWhenPFSIsEnabled |
unit/verify | unproven |
| negative | TestChildRekeyProposesNoDiffieHellmanWhenPFSIsDisabled |
unit/verify | revert, verified |
| negative | TestRkyIKERekeyOffersTheKEiGroup |
unit/verify | unproven |
| positive | TestChildRekeyProposesDiffieHellmanWhenPFSIsEnabled |
unit/verify | revert, verified |
| positive | TestRkyIKERekeyOffersTheKEiGroup |
unit/verify | unproven |
RFC7296-2.1-3
The responder MUST never retransmit a response unless it receives a retransmission of the request (§2.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapRtxMidEAPReplayRefusesUnprotected |
unit/verify | revert, verified |
| negative | TestRtxResponderReplaysCachedResponseOnlyForDuplicate |
unit/verify | revert, verified |
| positive | TestEapRtxResponderReplaysCachedResponseMidEAP |
unit/verify | revert, verified |
| positive | TestRtxResponderReplaysCachedResponseOnlyForDuplicate |
unit/verify | revert, verified |
RFC7296-2.1-4
In that event, the responder MUST ignore the retransmitted request except insofar as it causes a retransmission of the response (§2.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapRtxResponderReplaysCachedResponseMidEAP |
unit/verify | revert, verified |
| negative | TestRtxResponderReplaysCachedResponseOnlyForDuplicate |
unit/verify | revert, verified |
| positive | TestEapRtxResponderReplaysCachedResponseMidEAP |
unit/verify | revert, verified |
| positive | TestRtxResponderReplaysCachedResponseOnlyForDuplicate |
unit/verify | revert, verified |
RFC7296-2.1-5
The initiator MUST remember each request until it receives the corresponding response. The responder MUST remember each response until it receives a request whose sequence number is larger than or equal to the sequence number in the response plus its window size (§2.1, §2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxEachSideRemembersWhatItSent |
unit/verify | unproven |
| negative | TestWinDeleteIsRememberedUntilAnswered |
unit/verify | revert, verified |
| positive | TestRtxEachSideRemembersWhatItSent |
unit/verify | unproven |
| positive | TestWinDeleteIsRememberedUntilAnswered |
unit/verify | revert, verified |
RFC7296-2.1-6
If the responder receives a retransmitted request for which it has already forgotten the response, it MUST ignore the request (and not, for example, attempt constructing a new response) (§2.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxResponderIgnoresRequestWithForgottenResponse |
unit/verify | revert, verified |
| positive | TestRtxResponderIgnoresRequestWithForgottenResponse |
unit/verify | revert, verified |
RFC7296-2.1-7
IKE is a reliable protocol: the initiator MUST retransmit a request until it either receives a corresponding response or deems the IKE SA to have failed (§2.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxInitiatorResendsUnansweredRekeyRequest |
unit/verify | revert, verified |
| negative | TestRtxInitiatorResendsUnansweredSAInit |
unit/verify | unproven |
| negative | TestWinUnansweredRequestFailsTheSA |
unit/verify | revert, verified |
| positive | TestRtxInitiatorResendsUnansweredRekeyRequest |
unit/verify | revert, verified |
| positive | TestRtxInitiatorResendsUnansweredSAInit |
unit/verify | unproven |
| positive | TestWinUnansweredRequestFailsTheSA |
unit/verify | revert, verified |
RFC7296-2.1-8
A retransmission from the initiator MUST be bitwise identical to the original request (§2.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxRetransmissionIsBitwiseIdenticalAndReusesMessageID |
unit/verify | revert, verified |
| positive | TestRtxRetransmissionIsBitwiseIdenticalAndReusesMessageID |
unit/verify | revert, verified |
RFC7296-2.2-1
Retransmission of a message MUST use the same Message ID as the original message (§2.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxRetransmissionIsBitwiseIdenticalAndReusesMessageID |
unit/verify | revert, verified |
| positive | TestRtxRetransmissionIsBitwiseIdenticalAndReusesMessageID |
unit/verify | revert, verified |
RFC7296-2.2-2
In the unlikely event that Message IDs grow too large to fit in 32 bits, the IKE SA MUST be closed or rekeyed (§2.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMidInboundCounterFreezesAtTheCeiling |
unit/verify | unproven |
| negative | TestMidNearExhaustionRekeysTheIKESA |
unit/verify | revert, verified |
| negative | TestMidOutboundCounterFreezesAtTheCeiling |
unit/verify | revert, verified |
| negative | TestMidResponderEstablishDoesNotWrapTheCounter |
unit/verify | unproven |
| positive | TestMidInboundCounterFreezesAtTheCeiling |
unit/verify | unproven |
| positive | TestMidNearExhaustionRekeysTheIKESA |
unit/verify | revert, verified |
| positive | TestMidOutboundCounterFreezesAtTheCeiling |
unit/verify | revert, verified |
| positive | TestMidResponderEstablishDoesNotWrapTheCounter |
unit/verify | unproven |
RFC7296-2.2-3
Each endpoint in the IKE Security Association maintains two "current" Message IDs: the next one to be used for a request it initiates and the next one it expects to see in a request from the other end. (§2.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. finishResponderEstablish advances only the inbound counter; responder's first request id 0 is classified as new by the initiator
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMidResponderEstablishDoesNotWrapTheCounter |
unit/verify | unproven |
| positive | TestResponderFirstRequestMatchesWhatTheInitiatorExpects |
unit/verify | unproven |
RFC7296-2.3-2
An IKE endpoint MUST wait for a response to each of its messages before sending a subsequent message unless it has received a SET_WINDOW_SIZE Notify message from its peer (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDPDNoTransportTakesNoWindow |
unit/verify | unproven |
| negative | TestWinOneRequestPerTick |
unit/verify | revert, verified |
| negative | TestWinTeardownDoesNotHang |
unit/verify | revert, verified |
| positive | TestWinOneRequestPerTick |
unit/verify | revert, verified |
| positive | TestWinTeardownDoesNotHang |
unit/verify | revert, verified |
RFC7296-2.3-4
An IKE endpoint MUST NOT exceed the peer's stated window size for transmitted IKE requests (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestWinResponseReleasesSlot |
unit/verify | revert, verified |
| positive | TestWinResponseReleasesSlot |
unit/verify | revert, verified |
RFC7296-2.3-5
This Notify message MUST NOT be sent in a response; the invalid request MUST NOT be acknowledged (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestOsrOutOfWindowRequestIsNotAcknowledged |
unit/verify | unproven |
| positive | TestImiNotificationCarriesTheFourOctetMessageID |
unit/verify | unproven |
| positive | TestOsrOutOfWindowRequestIsNotAcknowledged |
unit/verify | unproven |
RFC7296-2.3-7
The data associated with a SET_WINDOW_SIZE notification MUST be 4 octets long and contain the big endian representation of the number of messages the sender promises to keep (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSwzMalformedWindowSizeIsRefused |
unit/verify | unproven |
| negative | TestSwzPeerWindowSizeIsRead |
unit/verify | unproven |
| negative | TestNtfySetWindowSizeDataIsFourOctets |
unit/verify | unproven |
| positive | TestSwzPeerWindowSizeIsRead |
unit/verify | unproven |
| positive | TestNtfySetWindowSizeDataIsFourOctets |
unit/verify | unproven |
RFC7296-2.3-8
An IKE endpoint MUST be prepared to accept and process a request while it has a request outstanding in order to avoid a deadlock in this situation (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestImiHeldWindowSuppressesTheNotification |
unit/verify | unproven |
| negative | TestOsrOwnerLoopKeepsAForeignWindowHeld |
unit/verify | unproven |
| negative | TestOsrRequestAcceptedWhileOursIsOutstanding |
unit/verify | unproven |
| negative | TestOsrRetireOnlyFreesItsOwnWindow |
unit/verify | unproven |
| positive | TestOsrOwnerLoopRetiresTheStrandedWindow |
unit/verify | unproven |
| positive | TestOsrRequestAcceptedWhileOursIsOutstanding |
unit/verify | unproven |
RFC7296-2.3-9
Sending this notification is OPTIONAL, and notifications of this type MUST be rate limited (§2.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestImiHeldWindowSuppressesTheNotification |
unit/verify | unproven |
| negative | TestImiUnauthenticatedRequestDrawsNothing |
unit/verify | unproven |
| positive | TestImiNotificationCarriesTheFourOctetMessageID |
unit/verify | unproven |
| positive | TestImiRateLimitCapsTheNotification |
unit/verify | unproven |
RFC7296-2.25-1
When a peer receives a TEMPORARY_FAILURE notification, it MUST NOT immediately retry the operation; it MUST wait so that the sender may complete whatever operation caused the temporary condition (§2.25)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMidTemporaryFailureDefersTheIKERekey |
unit/verify | revert, verified |
| negative | TestMidTemporaryFailureDefersTheRetry |
unit/verify | revert, verified |
| positive | TestMidTemporaryFailureDefersTheIKERekey |
unit/verify | revert, verified |
| positive | TestMidTemporaryFailureDefersTheRetry |
unit/verify | revert, verified |
RFC7296-2.8-5
If an SA has expired or is about to expire and rekeying attempts using the mechanisms described here fail, an implementation MUST close the IKE SA and any associated Child SAs and then MAY start new ones (§2.8)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRkyExhaustedRekeyClosesTheChildSAs |
unit/verify | unproven |
| positive | TestRkyExhaustedRekeyClosesTheChildSAs |
unit/verify | unproven |
RFC7296-2.8-6
After the new equivalent IKE SA is created, the initiator deletes the old IKE SA, and the Delete payload to delete itself MUST be the last request sent over the old IKE SA (§2.8)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRkyIKERekeyDeleteIsTheLastRequestOnTheOldSA |
unit/verify | revert, verified |
| positive | TestRkyIKERekeyDeleteIsTheLastRequestOnTheOldSA |
unit/verify | revert, verified |
RFC7296-2.8-7
The responder to a CREATE_CHILD_SA MUST be prepared to accept messages on an SA before sending its response to the creation request, so there is no ambiguity for the initiator (§2.8)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRkyResponderInstallsTheNewChildBeforeItAnswers |
unit/verify | revert, verified |
| positive | TestRkyResponderInstallsTheNewChildBeforeItAnswers |
unit/verify | revert, verified |
RFC7296-2.8.1-1
When there are two SAs eligible to receive packets, a node MUST accept incoming packets through either SA (§2.8.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRkyOldAndNewChildBothReceiveUntilThePeerDeletes |
unit/verify | unproven |
| positive | TestRkyOldAndNewChildBothReceiveUntilThePeerDeletes |
unit/verify | unproven |
RFC7296-2.18-2
The new IKE SA MUST reset its message counters to 0 (§2.18)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRtxRekeyedIKESAResetsMessageCounters |
unit/verify | unproven |
| positive | TestRtxRekeyedIKESAResetsMessageCounters |
unit/verify | unproven |
RFC7296-2.18-3
implementations MUST perform a new Diffie-Hellman exchange when rekeying the IKE SA. In other words, an initiator MUST NOT propose the value "NONE" for the Diffie-Hellman transform, and a responder MUST NOT accept such a proposal. (§2.18)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Both roles now proven on the rekey path itself. Initiator: TestRFC7296IKERekeyInitiatorNeverProposesDHNone decrypts the real initiateIKERekey request at the peer and asserts every proposal's D-H transform is the configured group 14 and the KE payload is group 14 (a new exchange); forced toward the violation (configured group NONE) initiateIKERekey returns an error, no bytes, and consumes no message ID. Responder: TestRFC7296IKERekeyResponderRefusesDHNone rewrites only the D-H transform of the real rekey request to NONE, sets local policy to NONE too so nothing else can refuse, and asserts errors.Is ErrDHGroupNone with no SA and no response; the unmodified request is accepted with a new SA. Crypto TestPropDHNoneRefusedForIKESA keeps the NegotiateIKE-level pair. Records: initiateIKERekey, respondIKERekey, NewDHExchange, acceptDHGroup reverts observed red; the crypto-level tags carry none.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropDHNoneRefusedForIKESA |
unit/verify | revert, verified |
| negative | TestRFC7296IKERekeyInitiatorNeverProposesDHNone |
unit/verify | revert, verified |
| negative | TestRFC7296IKERekeyResponderRefusesDHNone |
unit/verify | revert, verified |
| positive | TestPropDHNoneRefusedForIKESA |
unit/verify | revert, verified |
| positive | TestRFC7296IKERekeyInitiatorNeverProposesDHNone |
unit/verify | revert, verified |
| positive | TestRFC7296IKERekeyResponderRefusesDHNone |
unit/verify | revert, verified |
RFC7296-3.16-1
Identifier (1 octet) - Used in PPP to distinguish replayed messages from repeated ones. Since in IKE, EAP runs over a reliable protocol, the Identifier serves no function here. In a response message, this octet MUST be set to match the identifier in the corresponding request. (§3.16)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge; row widened to the Identifier item head, obligation 'In a response message, this octet MUST be set to match the identifier in the corresponding request' (RFC 7296 3.16). TestEapfmtResponseIdentifierMatchesRequest drives the EAP peer through Identity, MS-CHAPv2 Challenge and Success with identifiers 200, 7 and 91 and requires each response to echo exactly, so a constant or a counter fails. Peer methods other than MS-CHAPv2 are not sampled. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapfmtResponseIdentifierMatchesRequest |
unit/verify | unproven |
| positive | TestEapfmtResponseIdentifierMatchesRequest |
unit/verify | unproven |
RFC7296-3.16-2
Length (2 octets, unsigned integer) - The length of the EAP message. MUST be four less than the Payload Length of the encapsulating payload. (§3.16)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge; row widened to the Length item head, obligation 'MUST be four less than the Payload Length of the encapsulating payload' (RFC 7296 3.16). TestEapfmtEAPLengthIsFourLessThanPayloadLength reads both lengths off the encoded IKE payload for five body sizes and requires eapLen == payloadLen-4 and eapLen == 4+size, refusing a repeated or copied length; the decoder recovers every data octet. Send side only; no test feeds a received EAP payload whose lengths disagree. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapfmtEAPLengthIsFourLessThanPayloadLength |
unit/verify | unproven |
| positive | TestEapfmtEAPLengthIsFourLessThanPayloadLength |
unit/verify | unproven |
RFC7296-3.16-3
For other codes, the EAP message length MUST be four octets and the Type and Type_Data fields MUST NOT be present. (§3.16)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Success/Failure encode to four octets with no Type; Request keeps Type
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapfmtSuccessAndFailureCarryNoTypeField |
unit/verify | unproven |
| positive | TestEapfmtSuccessAndFailureCarryNoTypeField |
unit/verify | unproven |
RFC7296-3.16-4
In a Response (2) message, Type MUST either be Nak or match the type of the data requested (§3.16)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEapfmtPeerResponseTypeIsNakOrMatchesRequest |
unit/verify | unproven |
| positive | TestEapfmtPeerResponseTypeIsNakOrMatchesRequest |
unit/verify | unproven |
RFC7296-1.7-2
This document adds the restriction in Section 2.13 that all pseudorandom functions (PRFs) used with IKEv2 MUST take variable- sized keys. (§1.7)
Audit verdict: enforced (the tests do what the requirement demands), fresh. HMAC PRFs accept 1..200-octet keys and consume the key
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPRFTakesVariableSizedKeys |
unit/verify | unproven |
| positive | TestPRFTakesVariableSizedKeys |
unit/verify | unproven |
RFC7296-2-1
All IKEv2 implementations MUST be able to send, receive, and process IKE messages that are up to 1280 octets long (§2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMessageHandles1280Octets |
unit/verify | unproven |
| positive | TestMessageHandles1280Octets |
unit/verify | unproven |
RFC7296-2.5-1
The minor version number indicates new capabilities, and MUST be ignored by a node with a smaller minor version number, but used for informational purposes by the node with the larger minor version number (§2.5, §3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMinorVersionIgnoredMajorIsNot |
unit/verify | unproven |
| positive | TestMinorVersionIgnoredMajorIsNot |
unit/verify | unproven |
RFC7296-2.5-2
If an endpoint receives a message with a higher major version number, it MUST drop the message (§2.5, §3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestHigherMajorVersionDropped |
unit/verify | unproven |
| positive | TestHigherMajorVersionDropped |
unit/verify | unproven |
RFC7296-2.5-6
Also, for forward compatibility, all fields marked RESERVED MUST be set to zero by an implementation running version 2.0 (§2.5, §3.2, §3.3.1, §3.3.2, §3.5, §3.8, §3.13, §3.15, §3.15.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestConfigAttributeReservedBitSentAsZero |
unit/verify | unproven |
| negative | TestReservedFieldsSentAsZero |
unit/verify | unproven |
| positive | TestConfigAttributeReservedBitSentAsZero |
unit/verify | unproven |
| positive | TestReservedFieldsSentAsZero |
unit/verify | unproven |
RFC7296-2.5-7
Also, for forward compatibility, all fields marked RESERVED MUST be set to zero by an implementation running version 2.0, and their content MUST be ignored by an implementation running version 2.0 (§2.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged under the D-10 corrected row, which now quotes the whole Section 2.5 sentence (set to zero, and content ignored). Receive clause, this row's obligation: TestRFC7296EveryReservedOctetIsIgnoredOnReceipt parses AUTH, KE, ID, TS, CP bodies and Proposal/Transform substructures with every RESERVED octet at 0xff and asserts no error and DeepEqual to the clean decode; TestRFC7296DefinedOctetBesideReservedIsNotIgnored flips the adjacent defined octet and requires a changed decode or a refusal. Set-to-zero clause: the same positive unit asserts the encoder sends each RESERVED octet as zero for those bodies, and the sending obligation is also RFC7296-2.5-6's row. Generic header flags (wire/rfc7296_test.go) and the CP attribute R bit (rfc7296_cp_test.go) keep their tags. Records: payload_auth ReadFrom and payload_ke ReadFrom reverts observed red, re-recorded for the new row text.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestConfigAttributeReservedBitIgnoredOnReceipt |
unit/verify | revert, verified |
| negative | TestRFC7296DefinedOctetBesideReservedIsNotIgnored |
unit/verify | revert, verified |
| negative | TestReservedFieldsIgnoredOnReceipt |
unit/verify | revert, verified |
| positive | TestConfigAttributeReservedBitIgnoredOnReceipt |
unit/verify | revert, verified |
| positive | TestRFC7296EveryReservedOctetIsIgnoredOnReceipt |
unit/verify | revert, verified |
| positive | TestReservedFieldsIgnoredOnReceipt |
unit/verify | revert, verified |
RFC7296-2.5-8
Similarly, payload types that are not defined are reserved for future use; implementations of a version where they are undefined MUST skip over those payloads and ignore their contents. (§2.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. undefined payload type decoded as payloadRaw and the chain continues, outer and inner chain; defined type not demoted
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInnerChainSkipsUndefinedType |
unit/verify | unproven |
| negative | TestUndefinedPayloadTypeSkipped |
unit/verify | unproven |
| positive | TestInnerChainSkipsUndefinedType |
unit/verify | unproven |
| positive | TestUndefinedPayloadTypeSkipped |
unit/verify | unproven |
RFC7296-2.5-9
If the critical flag is set and the payload type is unrecognized, the message MUST be rejected (§2.5, §4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInnerChainRejectsCriticalUnrecognized |
unit/verify | unproven |
| negative | TestCriticalUnrecognizedPayloadRejected |
unit/verify | unproven |
| positive | TestInnerChainRejectsCriticalUnrecognized |
unit/verify | unproven |
| positive | TestCriticalUnrecognizedPayloadRejected |
unit/verify | unproven |
RFC7296-2.5-11
If the critical flag is not set and the payload type is unsupported, that payload MUST be ignored (§2.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInnerChainIgnoresNonCriticalUnsupported |
unit/verify | unproven |
| negative | TestNonCriticalUnsupportedPayloadIgnored |
unit/verify | unproven |
| positive | TestInnerChainIgnoresNonCriticalUnsupported |
unit/verify | unproven |
| positive | TestNonCriticalUnsupportedPayloadIgnored |
unit/verify | unproven |
RFC7296-2.5-13
implementations MUST NOT reject as invalid a message with those payloads in any other order. (§2.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Nonce/KE/SA order parses with all three; engine handleAuthResponse accepts unconventional order
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPodAuthResponseAcceptsAuthBeforeIdentity |
unit/verify | unproven |
| negative | TestPayloadOrderNotRejected |
unit/verify | unproven |
| positive | TestPodAuthResponseAcceptsAuthBeforeIdentity |
unit/verify | unproven |
| positive | TestPayloadOrderNotRejected |
unit/verify | unproven |
RFC7296-2.5-14
If an endpoint supports major version n, and major version m, it MUST support all versions between n and m (§2.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNATTDispatchAppliesTheSameVersionGate |
unit/verify | unproven |
| positive | TestSupportedMajorVersionSetIsSingleton |
unit/verify | unproven |
RFC7296-2.5-15
If it receives a message with a major version that it supports, it MUST respond with that version number (§2.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResponderEchoesTheSupportedMajorVersion |
unit/verify | unproven |
| positive | TestResponderEchoesTheSupportedMajorVersion |
unit/verify | unproven |
RFC7296-2.5-16
If they mistakenly (perhaps through an active attacker sending error messages) negotiate to version n, then both will notice that the other side can support a higher version number, and they MUST break the connection and reconnect using version n+1 (§2.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNATTDispatchAppliesTheSameVersionGate |
unit/verify | unproven |
| positive | TestSupportedMajorVersionSetIsSingleton |
unit/verify | unproven |
RFC7296-2.5-17
Payloads sent in IKE response messages MUST NOT have the critical flag set (§2.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResponsePayloadsAreNeverCritical |
unit/verify | unproven |
| positive | TestResponsePayloadsAreNeverCritical |
unit/verify | unproven |
RFC7296-2.5-18
the response to the IKE request containing that payload MUST include a Notify payload UNSUPPORTED_CRITICAL_PAYLOAD, indicating an unsupported critical payload was included. In that Notify payload, the Notification Data contains the one-octet payload type. (§2.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Response side now proven through the real handler: protected INFORMATIONAL requests with an unrecognized critical inner payload (types 200 and 49) draw a response with exactly one notify, UNSUPPORTED_CRITICAL_PAYLOAD, whose Notification Data is the one octet of that type (so the data follows the payload, not a constant). Negative: the same payload with the critical bit clear is answered with no such notify. Wire tags keep the parse error carrying the type and the non-critical demotion.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296NonCriticalUnknownPayloadDrawsNoUnsupportedCritical |
unit/verify | revert, verified |
| negative | TestCritUnknownCriticalPayloadNamesItsType |
unit/verify | revert, verified |
| positive | TestRFC7296UnsupportedCriticalResponseNamesThePayloadType |
unit/verify | revert, verified |
| positive | TestCritUnknownCriticalPayloadNamesItsType |
unit/verify | revert, verified |
RFC7296-2.21.2-1
Note, however, that request messages that contain an unsupported critical payload, or where the whole message is malformed (rather than just bad payload contents), MUST be rejected in their entirety, and MUST only lead to an UNSUPPORTED_CRITICAL_PAYLOAD or INVALID_SYNTAX Notification sent as a response. (§2.21.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 (independent judge). Both halves asserted. Unsupported critical payload: rfc7296_inner_error_answers_test.go::TestRFC7296UnsupportedCriticalPayloadDrawsOnlyThatNotify sends a protected INFORMATIONAL whose only inner payload is private type 200 with C=1; the request never reaches the exchange handlers (peerAlive false) and the answer, decrypted under the IKE SA, carries exactly one payload, UNSUPPORTED_CRITICAL_PAYLOAD with data {200}. Malformed message: TestErrInnerParseFailureDrawsInvalidSyntaxAndOuterDrawsNothing (truncated inner chain answered with INVALID_SYNTAX only). Negative: TestCritChainReportsTruncationButNotBadContents (bad payload contents are not a malformed message). Revert record observed red on inbound.go::respondInnerParseError. Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit is byte-identical to the judged one (git diff 2d57003d45..HEAD touches only other functions, a const block, and new functions appended to the file), so the verdict stands unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCritChainReportsTruncationButNotBadContents |
unit/verify | revert, verified |
| positive | TestRFC7296UnsupportedCriticalPayloadDrawsOnlyThatNotify |
unit/verify | revert, verified |
| positive | TestErrInnerParseFailureDrawsInvalidSyntaxAndOuterDrawsNothing |
unit/verify | revert, verified |
| positive | TestCritChainReportsTruncationButNotBadContents |
unit/verify | revert, verified |
RFC7296-2.21.2-2
Specifically, a responder may include all the payloads associated with authentication (IDr, CERT, and AUTH) while sending error notifications for the piggybacked exchanges (FAILED_CP_REQUIRED, NO_PROPOSAL_CHOSEN, and so on), and the initiator MUST NOT fail the authentication because of this. (§2.21.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-10 against RFC 7296 S2.21.2 "a responder may include all the payloads associated with authentication (IDr, CERT, and AUTH) while sending error notifications for the piggybacked exchanges (FAILED_CP_REQUIRED, NO_PROPOSAL_CHOSEN, and so on), and the initiator MUST NOT fail the authentication because of this." New unit TestInitiatorKeepsChildlessIKESA takes a real PSK IKE_AUTH response, removes SAr2/TSi/TSr and adds NO_PROPOSAL_CHOSEN with IDr and AUTH untouched: handleAuthResponse must reach StateEstablished, mark the SA childless, log the refusal and send nothing (no Delete). Its negative control flips one AUTH octet in the same response and requires StateDead, so the outcome is decided by AUTH, not by the notify. TestErrInitiatorSurvivesPiggybackedErrorNotify (unchanged) drives NO_PROPOSAL_CHOSEN, FAILED_CP_REQUIRED and TS_UNACCEPTABLE to established and AUTHENTICATION_FAILED to dead. An initiator that failed on the notify or on the missing SAr2 goes red in both. The negatives are controls, since a MUST NOT on the receiver has no violating input. Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit is byte-identical to the judged one (git diff 2d57003d45..HEAD touches only other functions, a const block, and new functions appended to the file), so the verdict stands unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInitiatorKeepsChildlessIKESA |
unit/verify | revert, verified |
| negative | TestErrInitiatorSurvivesPiggybackedErrorNotify |
unit/verify | unproven |
| positive | TestInitiatorKeepsChildlessIKESA |
unit/verify | revert, verified |
| positive | TestErrInitiatorSurvivesPiggybackedErrorNotify |
unit/verify | unproven |
RFC7296-2.21.2-3
Extension documents may define new error notifications with these semantics, but MUST NOT use them unless the peer has been shown to understand them, such as by using the Vendor ID payload (§2.21.2)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestMobikeAuthExtensionErrorsRequirePeerUnderstanding |
unit/verify | revert, verified |
| positive | TestMobikeAuthExtensionErrorsRequirePeerUnderstanding |
unit/verify | revert, verified |
RFC7296-2.21.3-1
After the IKE SA is authenticated, all requests having errors MUST result in a response notifying the other end of the error (§2.21.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrNewChildRequestIsAnswered |
unit/verify | unproven |
| negative | TestErrRefusedChildRekeyIsAnswered |
unit/verify | unproven |
| negative | TestErrRefusedIKERekeyIsAnswered |
unit/verify | unproven |
| positive | TestDelMalformedSPISizeDrawsInvalidSyntax |
unit/verify | unproven |
| positive | TestErrNewChildRequestIsAnswered |
unit/verify | unproven |
| positive | TestErrRefusedChildRekeyIsAnswered |
unit/verify | unproven |
| positive | TestErrRefusedIKERekeyIsAnswered |
unit/verify | unproven |
RFC7296-2.21.4-1
If the message is marked as a response, the node can audit the suspicious event but MUST NOT respond (§2.21.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfOutOfSAIgnoresResponses |
unit/verify | unproven |
| negative | TestNtfOutOfSASkipsSAInitAndRateLimits |
unit/verify | unproven |
| negative | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
| positive | TestNtfOutOfSAIgnoresResponses |
unit/verify | unproven |
| positive | TestNtfOutOfSASkipsSAInitAndRateLimits |
unit/verify | unproven |
| positive | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
RFC7296-2.21.4-2
If a response is sent, the response MUST be sent to the IP address and port from where it came with the same IKE SPIs and the Message ID copied. (§2.21.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-15 after 1ae1c731bd moved the three reject=stderr:pattern= lines of ipsec-error-notify-no-loop.ci under the daemon cmd line; under the new harness a stderr reject is a whole-run log check, so no assertion reads less, and expect=exit and the probe's pass line still bind the fixture. RFC 7296 Section 2.21.4: 'If a response is sent, the response MUST be sent to the IP address and port from where it came with the same IKE SPIs and the Message ID copied.' tunnelIPsecErrorNotify reads the answer on the socket that sent the request and fails unless both SPIs, exchange type 37, the Response flag and Message ID 7 are copied; the ordering marker with a different initiator SPI must draw an answer carrying that SPI and Message ID 11, so the copy is per request. TestNtfOutOfSAAnswersWithInvalidIKESPI and TestNtfOutOfSAAnswerCarriesTheSocketFraming pin the same fields and the arrival socket framing at unit level.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfOutOfSAAnswerCarriesTheSocketFraming |
unit/verify | unproven |
| negative | TestNtfOutOfSAAnswersWithInvalidIKESPI |
unit/verify | unproven |
| negative | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
| positive | TestNtfOutOfSAAnswerCarriesTheSocketFraming |
unit/verify | unproven |
| positive | TestNtfOutOfSAAnswersWithInvalidIKESPI |
unit/verify | unproven |
| positive | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
RFC7296-2.21.4-3
The response MUST NOT be cryptographically protected (§2.21.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfOutOfSAAnswerIsUnprotected |
unit/verify | unproven |
| positive | TestNtfOutOfSAAnswerIsUnprotected |
unit/verify | unproven |
RFC7296-2.21.4-4
The response MUST NOT be cryptographically protected and MUST contain an INVALID_IKE_SPI Notify payload. (§2.21.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-15 after 1ae1c731bd moved the .ci's stderr rejects under the daemon cmd line (whole-run scope, no assertion weakened). RFC 7296 Section 2.21.4: 'The response MUST NOT be cryptographically protected and MUST contain an INVALID_IKE_SPI Notify payload.' TestNtfOutOfSAAnswersWithInvalidIKESPI parses the answer and requires exactly one payload, a Notify of type INVALID_IKE_SPI with an empty SPI and no data, so a wrong type, a missing Notify, an extra payload or an SK payload fails; the fixture behind ipsec-error-notify-no-loop.ci requires the body after the header to be one 4-octet Notify of type 4 (INVALID_IKE_SPI) with next payload 0 through the real UDP path. The negatives (an IKE_SA_INIT to an unknown SPI draws nothing) are controls on the emitter's guard rather than violating inputs. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfOutOfSAAnswersWithInvalidIKESPI |
unit/verify | unproven |
| negative | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
| positive | TestNtfOutOfSAAnswersWithInvalidIKESPI |
unit/verify | unproven |
| positive | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
RFC7296-2.21.4-5
A peer receiving such an unprotected Notify payload MUST NOT respond (§2.21.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfEmitterIsAFixedPoint |
unit/verify | unproven |
| negative | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
| positive | TestNtfEmitterIsAFixedPoint |
unit/verify | unproven |
| positive | ipsec-error-notify-no-loop.ci |
functional/verify | unproven |
RFC7296-2.21.4-6
A peer receiving such an unprotected Notify payload MUST NOT respond and MUST NOT change the state of any existing SAs. (§2.21.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after 87b04ed6cd. RFC 7296 2.21.4: "A peer receiving such an unprotected Notify payload MUST NOT respond and MUST NOT change the state of any existing SAs." This row keeps the state clause (MUST NOT respond is RFC7296-2.21.4-5). The defect the previous verdict named is fixed at the producer: handleAuthResponse and handleEAPResponse (fsm.go) now return on an IKE_AUTH response with no SK payload before touching the SA, where they used to set StateDead. The new TestErrUnprotectedNotifyLeavesHalfOpenSA uses the bytes sendInvalidIKESPI writes (asserted: IKE_AUTH, R bit, one unprotected INVALID_IKE_SPI Notify), delivers them through routeInbound to an initiator SA (newInitiatorSA via testSAWithKeys) in StateAuthSent and in StateEAPInProgress, and asserts no datagram before a sentinel and State, NextMsgID, ExpectedMsgID, RetransmitTime, RetransmitCount and the EAP session unchanged. The mutant record restoring StateDead in the handleAuthResponse drop is observed red; the EAP subtest has no record, but read at the producer handleInbound's StateEAPInProgress arm reaches handleEAPResponse for this input, so a StateDead there fails the State assertion. The handshake arms read no Message ID before the SK check, so the message ID the test picks (sa.NextMsgID) does not weaken it. The established route stays as judged before: TestErrUnprotectedNotifyChangesNoState (positive, unit unchanged) with its SK-protected negative at the same R bit and Message ID, both polarities with mutant records on the inboundInvalid decrypt condition in handleOwnedInbound. Other routes, read at the producer: handleOwnedInbound drops every unprotected message silently (decryptAndParse fails on no SK); handleResponderInbound returns before its state switch on any message with the R bit, which TestNrsResponseNeverDrawsAResponse (tagged RFC7296-3.1-12) pins, untagged here; the initiator StateSAInitSent arm kills the attempt on an IKE_SA_INIT response holding only an error notify, which Section 2.21.1 sanctions ("In an IKE_SA_INIT exchange, any error notification causes the exchange to fail.") and which no keyed SA yet exists for. Residual outside this row: a half-open initiator SA still goes StateDead when an SK payload is present but fails decryption (handleAuthResponse and handleEAPResponse, 'decryption failed'), a forged-SK case, not an unprotected Notify.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrUnprotectedNotifyChangesNoState |
unit/verify | mutant, verified |
| positive | TestErrUnprotectedNotifyChangesNoState |
unit/verify | mutant, verified |
| positive | TestErrUnprotectedNotifyLeavesHalfOpenSA |
unit/verify | mutant, verified |
RFC7296-2.21.4-7
The recipient MUST NOT change the state of any SAs as a result, but may wish to audit the event to aid in diagnosing malfunctions. (§2.21.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 (independent judge) after the row was narrowed to the MUST NOT sentence, verbatim at RFC 7296 Section 2.21.4: "The recipient MUST NOT change the state of any SAs as a result, but may wish to audit the event to aid in diagnosing malfunctions." The SHOULD-send sentence is RFC7296-2.21.4-8 {gap}. TestErrProtectedInformationalNotifyChangesNoState: a protected INFORMATIONAL carrying INVALID_SELECTORS (the kind of notify a node sends after a suspicious ESP packet) is answered, leaves the IKE SA state unchanged and the Child SA in place; control: the same exchange carrying a Delete does change state. Revert records observed red on inbound.go::handleInformationalOwned. Limit: the Child SA check is pointer identity, so an in-place mutation of the Child SA would not be seen; handleInformationalOwned acts on Delete and MOBIKE notifies only. Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit is byte-identical to the judged one (git diff 2d57003d45..HEAD touches only other functions, a const block, and new functions appended to the file), so the verdict stands unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrProtectedInformationalNotifyChangesNoState |
unit/verify | revert, verified |
| positive | TestErrProtectedInformationalNotifyChangesNoState |
unit/verify | revert, verified |
RFC7296-2.21.4-8
A node receiving a suspicious message from an IP address (and port, if NAT traversal is used) with which it has an IKE SA SHOULD send an IKE Notify payload in an IKE INFORMATIONAL exchange over that SA. (§2.21.4)
Audit verdict: unimplemented (no code path enforces the requirement), fresh. Re-judged 2026-10-15 after 4fecbbd82a changed handleOwnedInbound: the only edit calls rebindChildSAs (rebind.go) when an AUTHENTICATED message moves the peer endpoint, migrating Child SAs or owing a rekey; it sends no Notify. RFC 7296 Section 2.21.4: 'A node receiving a suspicious message from an IP address (and port, if NAT traversal is used) with which it has an IKE SA SHOULD send an IKE Notify payload in an IKE INFORMATIONAL exchange over that SA.' handleOwnedInbound still returns after countErrorNotifySuppressed on outer-parse-unauthenticated, unprotected-retransmit, replay-rate-limited and invalid-msgid-unauthenticated without starting a protected exchange, and answerOutOfSA (notify_error.go) still emits only the unprotected INVALID_IKE_SPI response to an unknown SPI with no address-based existing-SA lookup. The SHOULD stays unmet and the {gap} annotation matches the code. No tests tag this row.
No test carries RFC7296-2.21.4-8, so no unit is bound to it.
RFC7296-3.10.1-1
Types in the range 0 - 16383 are intended for reporting errors. An implementation receiving a Notify payload with one of these types that it does not recognize in a response MUST assume that the corresponding request has failed entirely. (§3.10.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. unrecognized error-range notify in an IKE_AUTH response ends the exchange; unrecognized status type ignored and SA establishes Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit is byte-identical to the judged one (git diff 2d57003d45..HEAD touches only other functions, a const block, and new functions appended to the file), so the verdict stands unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrUnrecognizedNotifyHandling |
unit/verify | unproven |
| positive | TestErrUnrecognizedNotifyHandling |
unit/verify | unproven |
RFC7296-3.10.1-2
Unrecognized error types in a request and status types in a request or response MUST be ignored, and they should be logged (§3.10.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrUnrecognizedNotifyHandling |
unit/verify | unproven |
| negative | TestCritNotifyTypeClassification |
unit/verify | unproven |
| positive | TestErrUnrecognizedNotifyHandling |
unit/verify | unproven |
| positive | TestCritNotifyTypeClassification |
unit/verify | unproven |
RFC7296-3.10.1-3
To avoid leaking information to someone probing a node, this status MUST be sent in response to any error not covered by one of the other status types. (§3.10.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 (independent judge). INVALID_SYNTAX for errors no other status type covers, in an authenticated request: truncated inner chain (TestErrInnerParseFailureDrawsInvalidSyntaxAndOuterDrawsNothing) and now Payload Length 0 and 3 (rfc7296_inner_error_answers_test.go::TestRFC7296UncoveredInnerErrorsDrawInvalidSyntax), each answered with exactly one notify, INVALID_SYNTAX, and not dispatched. Every non-critical inner-chain parse error reaches the same single producer, respondInnerParseError, which answers INVALID_SYNTAX unconditionally. An invalid field value (a Delete with the wrong SPI Size) is answered with INVALID_SYNTAX under RFC7296-3.11-2's tests. Negative: an outer parse failure (Message ID and checksum never validated) draws nothing. Revert record observed red on inbound.go::respondInnerParseError. Re-judged 2026-10-10 (independent judge, mode rejudge): every tagged unit is byte-identical to the judged one (git diff 2d57003d45..HEAD touches only other functions, a const block, and new functions appended to the file), so the verdict stands unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestErrInnerParseFailureDrawsInvalidSyntaxAndOuterDrawsNothing |
unit/verify | revert, verified |
| positive | TestRFC7296UncoveredInnerErrorsDrawInvalidSyntax |
unit/verify | revert, verified |
| positive | TestErrInnerParseFailureDrawsInvalidSyntaxAndOuterDrawsNothing |
unit/verify | revert, verified |
RFC7296-2.6-2
Each endpoint chooses one of the two SPIs and MUST choose them so as to be unique identifiers of an IKE SA (§2.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSPIsAreUniqueIdentifiers |
unit/verify | unproven |
| positive | TestSPIsAreUniqueIdentifiers |
unit/verify | unproven |
RFC7296-2.6-3
The data associated with this notification MUST be between 1 and 64 octets in length (inclusive) (§2.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCkeEchoedCookieIsBoundedToo |
unit/verify | unproven |
| positive | TestCkeMintedCookieIsWithinTheLengthBound |
unit/verify | unproven |
RFC7296-2.6-4
If the IKE_SA_INIT response includes the COOKIE notification, the initiator MUST then retry the IKE_SA_INIT request, and include the COOKIE notification containing the received data as the first payload, and all other payloads unchanged (§2.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCkeCookieIsAbsentWithoutAChallenge |
unit/verify | unproven |
| positive | TestCkeRetryCarriesCookieFirstAndNothingElseChanged |
unit/verify | unproven |
RFC7296-2.6-5
When one party receives an IKE_SA_INIT request containing a cookie whose contents do not match the value expected, that party MUST ignore the cookie and process the message as if no cookie had been included; usually this means sending a response containing a new cookie (§2.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCkeValidCookieReachesTheHandshake |
unit/verify | unproven |
| positive | TestCkeMismatchedCookieIsIgnoredNotRejected |
unit/verify | unproven |
RFC7296-2.6.1-1
Implementations SHOULD support this shorter exchange, but MUST NOT fail if other implementations do not support this shorter exchange (§2.6.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCkeCookieAndInvalidKECombineWithoutFailing |
unit/verify | unproven |
| positive | TestCkeSecondCookieReplacesTheFirstWithoutFailing |
unit/verify | unproven |
RFC7296-2.10-2
Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits in size (§2.10)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged under the D-10 corrected row 'Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits in size'. The 128-bit floor, both directions: send, TestRFC7296EmittedNoncesAreAtLeast128Bits checks all six emitted nonces (IKE_SA_INIT Ni/Nr, Child SA rekey Ni/Nr, IKE SA rekey Ni/Nr off the wire) are >= 16 octets; receive, TestNonceLengthBounds accepts 16 and refuses 15 octets with ErrNonceTooShort. The randomness clause the span passes through is the verbatim text of RFC7296-2.10-4, whose own tagged units (engine/rfc7296_session_test.go) carry it; this row's units assert the floor alone, as the correction states. Record: GenerateNonce revert observed red, re-recorded for the new row text.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNonceLengthBounds |
unit/verify | revert, verified |
| positive | TestRFC7296EmittedNoncesAreAtLeast128Bits |
unit/verify | revert, verified |
| positive | TestNonceLengthBounds |
unit/verify | revert, verified |
RFC7296-2.10-3
Nonces used in IKEv2 MUST be randomly chosen, MUST be at least 128 bits in size, and MUST be at least half the key size of the negotiated pseudorandom function (PRF). (§2.10)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 after the row text was widened to the whole verbatim Section 2.10 sentence (D-10, rfc/corrections/rfc7296.md). The gated clause is the half-PRF-key floor; the random choice is gated by RFC7296-2.10-4 and the 128-bit floor by RFC7296-2.10-2, which quote the leading spans of the same sentence, so this row's tests are judged on the final clause alone. Positive TestRFC7296EmittedNoncesMeetHalfOfEveryPRFKey reads every PRF from the registry and asserts all six emission sites (IKE_SA_INIT Ni/Nr, Child SA rekey Ni/Nr, IKE SA rekey Ni/Nr, rekey nonces off the wire); negative TestRFC7296EmittedNoncesMeetTheLargestPRFBound negotiates prf-hmac-sha2-512 on a rekey and checks the wire Ni/Nr meet 32 octets. Records re-recorded (GenerateNonce revert). Judge's own clause probe: GenerateNonce capped at 16 octets via go test -overlay reddens both units (sha384/sha512 halves), so both discriminate the half-PRF clause, not merely call the producer.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296EmittedNoncesMeetTheLargestPRFBound |
unit/verify | revert, verified |
| positive | TestRFC7296EmittedNoncesMeetHalfOfEveryPRFKey |
unit/verify | revert, verified |
RFC7296-2.13-1
For algorithms that accept a variable-length key, a fixed key size MUST be specified as part of the cryptographic transform negotiated (§2.13)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestTransformRegistryStatesKeySizes |
unit/verify | unproven |
| positive | TestTransformRegistryStatesKeySizes |
unit/verify | unproven |
RFC7296-2.13-3
The preferred key size MUST be used as the length of SK_d, SK_pi, and SK_pr (§2.13, §2.14)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKKeyLengthsComeFromTransforms |
unit/verify | unproven |
| positive | TestSKKeyLengthsComeFromTransforms |
unit/verify | unproven |
RFC7296-2.13-4
Other types of PRFs MUST specify their preferred key size (§2.13)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestTransformRegistryStatesKeySizes |
unit/verify | unproven |
| positive | TestTransformRegistryStatesKeySizes |
unit/verify | unproven |
RFC7296-2.15-1
The management interface by which the shared secret is provided MUST accept ASCII strings of at least 64 octets (§2.15)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPSKAcceptsAtLeast64ASCIIOctets |
unit/verify | unproven |
| positive | TestPSKAcceptsAtLeast64ASCIIOctets |
unit/verify | unproven |
RFC7296-2.15-2
MUST NOT add a null terminator before using them as shared secrets (§2.15)
Audit verdict: enforced (the tests do what the requirement demands), fresh. The weak finding (use path unexercised) is closed. Parse side: ipsec TestPSKHasNoNullTerminatorAdded (parseAuthConfig keeps the PSK octets, adds and strips nothing). Use side, new engine/rfc7296_psk_terminator_test.go: positive TestRFC7296PSKIsUsedWithoutANullTerminator compares computePSKAuth's AUTH with an independent stdlib HMAC-SHA2-256 prf(prf(secret,'Key Pad for IKEv2'),SignedOctets) over the secret octets alone (equal) and over secret+0x00 (not equal), and verifyPSKAuth accepts the no-terminator AUTH; negative TestRFC7296PSKWithANullTerminatorAddedIsRefused: verifyPSKAuth refuses the AUTH over secret+0x00 with errAuthFailed, so the receiving side adds no terminator either. Producers read: both pass []byte(sa.PeerCfg.Auth.PSK) to computeAuthFromSharedSecret/verifyAuthFromSharedSecret. Records: computePSKAuth and verifyPSKAuth panic reverts observed red. Judge ran both: PASS. Prose defect, not a proof gap: psktermSecret is 65 octets, while its comment and both claims say 64; the claim wording should be corrected (and the records re-recorded) by the author.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296PSKWithANullTerminatorAddedIsRefused |
unit/verify | revert, verified |
| negative | TestPSKHasNoNullTerminatorAdded |
unit/verify | revert, verified |
| positive | TestRFC7296PSKIsUsedWithoutANullTerminator |
unit/verify | revert, verified |
| positive | TestPSKHasNoNullTerminatorAdded |
unit/verify | revert, verified |
RFC7296-2.17-1
keying material for each Child SA MUST be taken from the expanded KEYMAT using the following rules: o All keys for SAs carrying data from the initiator to the responder are taken before SAs going from the responder to the initiator. (§2.17)
Audit verdict: enforced (the tests do what the requirement demands), fresh. DeriveChildSAKeys slices recomputed prf+ KEYMAT with both initiator keys before responder keys
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildSAKeymatOrder |
unit/verify | unproven |
| positive | TestChildSAKeymatOrder |
unit/verify | unproven |
RFC7296-2.17-2
For ESP and AH, [IPSECARCH] defines the order, namely: the encryption key (if any) MUST be taken from the first bits and the integrity key (if any) MUST be taken from the remaining bits. (§2.17)
Audit verdict: enforced (the tests do what the requirement demands), fresh. encryption key then integrity key per direction, positional, asserted against recomputed KEYMAT
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChildSAKeymatOrder |
unit/verify | unproven |
| positive | TestChildSAKeymatOrder |
unit/verify | unproven |
RFC7296-3.1-1
An Encrypted payload MUST be the last payload in a packet (§3.1, §3.14)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKIsLastAndNeverNested |
unit/verify | unproven |
| positive | TestSKIsLastAndNeverNested |
unit/verify | unproven |
RFC7296-3.1-2
an Encrypted payload MUST NOT contain another Encrypted payload (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. IKE_AUTH request and response inner chains hold no SK payload; negative is a vacuity guard
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKIsLastAndNeverNested |
unit/verify | unproven |
| positive | TestSKIsLastAndNeverNested |
unit/verify | unproven |
RFC7296-3.1-3
Initiator's SPI (8 octets) - A value chosen by the initiator to identify a unique IKE Security Association. This value MUST NOT be zero. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Send: GenerateSPI and new SAs asserted non-zero (TestSPIZeroRules, positive, recorded on GenerateSPI). Receive, both dispatchers: TestRFC7296ZeroInitiatorSPIIsDroppedOnReceipt (port 500, dispatchInbound) and TestRFC7296ZeroInitiatorSPIIsDroppedOnTheNATTSocket (port 4500, dispatchNATTInbound, non-ESP marker) each put an SA with a zero Initiator's SPI in the table, so without the guard the zero-iSPI datagram would reach that SA's owner; the following non-zero datagram is delivered (NAT-T: marker stripped). Records are whole-producer reverts (reach); the isolation comes from the zero-iSPI SA in the table. Closure rejudge 2026-10-02: the negative tag on TestSPIZeroRules was removed, since its body never calls dispatchInbound; the negative polarity rests on the two dedicated recorded units above.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ZeroInitiatorSPIIsDroppedOnTheNATTSocket |
unit/verify | revert, verified |
| negative | TestRFC7296ZeroInitiatorSPIIsDroppedOnReceipt |
unit/verify | revert, verified |
| positive | TestSPIZeroRules |
unit/verify | revert, verified |
RFC7296-3.1-4
Responder's SPI (8 octets) - A value chosen by the responder to identify a unique IKE Security Association. This value MUST be zero in the first message of an IKE initial exchange (including repeats of that message including a cookie). (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. First message: TestSPIZeroRules asserts octets 8..15 zero in Ze's IKE_SA_INIT request, non-zero in the response. Cookie repeat: TestRFC7296ResponderSPIIsZeroInTheFirstMessageAndItsCookieRepeat answers a COOKIE challenge whose Responder's SPI is 0909..09, checks the repeat carries the COOKIE notify and the same Initiator's SPI, and asserts octets 8..15 of the repeat are zero, red on a retry that copies the challenge's SPI. Rejudged 2026-10-02: TestSPIZeroRules changed only by the removal of its RFC7296-3.1-3 negative tag lines; the 3.1-4 assertions are unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSPIZeroRules |
unit/verify | revert, verified |
| positive | TestSPIZeroRules |
unit/verify | revert, verified |
| positive | TestRFC7296ResponderSPIIsZeroInTheFirstMessageAndItsCookieRepeat |
unit/verify | revert, verified |
RFC7296-3.1-5
Implementations based on this version of IKE MUST set the major version to 2 (§3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBuiltMessagesCarryVersion2Point0 |
unit/verify | unproven |
| positive | TestBuiltMessagesCarryVersion2Point0 |
unit/verify | unproven |
RFC7296-3.1-6
Implementations based on this version of IKE MUST set the minor version to 0 (§3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBuiltMessagesCarryVersion2Point0 |
unit/verify | unproven |
| positive | TestBuiltMessagesCarryVersion2Point0 |
unit/verify | unproven |
RFC7296-3.1-7
'X' bits MUST be cleared when sending (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. every engine-built message has X bits clear; I and R observed so the mask is not vacuous
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBuiltMessagesClearXAndVBits |
unit/verify | unproven |
| positive | TestBuiltMessagesClearXAndVBits |
unit/verify | unproven |
RFC7296-3.1-8
'X' bits MUST be cleared when sending and MUST be ignored on receipt. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after e855bc0689. RFC 7296 3.1: "'X' bits MUST be cleared when sending and MUST be ignored on receipt." This row keeps the receive clause (the send clause is RFC7296-3.1-7, correction 2026-10-11). The earlier finding (the fresh request bypassed the dispatch site that reads the flags octet) is fixed: TestXBitsIgnoredOnReceipt now calls tryResponderSAInit, which tests pkt.Data[19] at register.go and then routes through handleInbound into handleResponderInbound (responder.go Flags&FlagResponse) and handleSAInitRequest; a protected INFORMATIONAL request with every X bit set goes through handleOwnedInbound (inbound.go isResponse) and must be answered, advance ExpectedMsgID and credit liveness; an IKE_SA_INIT response with the X bits goes through handleInbound (fsm.go StateSAInitSent arm) and must reach auth-sent. Each outcome is exact and matches the clean message, not 'no error'. Negative: the same fresh request with the R bit (not an X bit) is refused with no SA, so the positive is not passing through a flags-blind path; it is a control for the X-bit scope rather than a violation of this clause, which is the only negative an ignore obligation admits. Discrimination: mutant records at register.go tryResponderSAInit (refuse any bit but I: positive red; never refuse R: negative red). The owned and initiator sites carry no record, but by reading a break there that refuses or reclassifies on an X bit leaves the request unanswered or the initiator in sa-init-sent, both asserted. Residual, not a defect: four receive readers are not driven with X bits (fsm.go AUTH-response and EAP-response arms, the established-SA response arm, the out-of-SA guard in sendInvalidIKESPI); every one tests Flags&wire.FlagResponse alone, so the code complies, and the claim enumerates only the three messages it asserts.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestXBitsIgnoredOnReceipt |
unit/verify | mutant, verified |
| positive | TestXBitsIgnoredOnReceipt |
unit/verify | mutant, verified |
RFC7296-3.1-9
R (Response) - This bit indicates that this message is a response to a message containing the same Message ID. This bit MUST be cleared in all request messages and MUST be set in all responses. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after the row was widened to the R item head. Whole sentence 'This bit MUST be cleared in all request messages and MUST be set in all responses' (RFC 7296 3.1). TestResponseBitMatchesDirection compares the R bit for equality with isResponse on every engine-built message, so a request with R set or a response with R clear fails. TestRFC7296InitiatorIgnoresAResponseWithTheRBitClear feeds handleInbound the responder's real IKE_SA_INIT answer with only the R bit cleared (state stays sa-init-sent), then the untouched answer (advances): isolation by a one-bit difference. Revert records on buildSAInitResponse and handleInbound are reach proofs only.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296InitiatorIgnoresAResponseWithTheRBitClear |
unit/verify | revert, verified |
| positive | TestResponseBitMatchesDirection |
unit/verify | revert, verified |
RFC7296-3.1-11
V (Version) - This bit indicates that the transmitter is capable of speaking a higher major version number of the protocol than the one indicated in the major version number field. Implementations of IKEv2 MUST clear this bit when sending and MUST ignore it in incoming messages. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after 9c536b0e45. RFC 7296 3.1: "Implementations of IKEv2 MUST clear this bit when sending and MUST ignore it in incoming messages." Send clause: the previous gap is closed. A grep of non-test code under internal/component/ike finds exactly five header-flags writers: writeAuthHeaderWithMsgID (auth.go), the IKE_SA_INIT request literal (initiator.go), buildSAInitResponse and sendSAInitNotifyRaw (responder.go), sendInvalidIKESPI (notify_error.go); none copies an incoming flags octet and no non-test code sets wire.FlagVersion. TestBuiltMessagesClearXAndVBits (unit unchanged) samples the first three. The new TestSAInitNotifiesClearXAndVBits drives sendSAInitNotifyRaw through both of its production callers, sendCookieChallenge (COOKIE) and sendSAInitNotify (NO_PROPOSAL_CHOSEN, INVALID_KE_PAYLOAD), and TestInvalidIKESPIClearsXAndVBits drives sendInvalidIKESPI through answerOutOfSA, once with a request carrying V and every X bit so a flags copy would be caught. Each parses the datagram the peer read, pins the notify type (which writer) and the R bit (right octet), and asserts V clear. Mutant records setting wire.FlagVersion in each header literal are observed red. Receive clause unchanged and sound: the V-bit half of TestXBitsIgnoredOnReceipt (negative tag, unit unchanged) drives tryResponderSAInit, handleOwnedInbound and handleInbound with V set and asserts the clean outcome and a major version 2 answer, with a mutant record at tryResponderSAInit. The #2 tag of TestBuiltMessagesClearXAndVBits (the encoder can set V) is an anti-vacuity control, not a second negative. Residual for the reader: the receive readers in the AUTH and EAP response arms mask R alone and are not driven with V set.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestBuiltMessagesClearXAndVBits |
unit/verify | unproven |
| negative | TestXBitsIgnoredOnReceipt |
unit/verify | mutant, verified |
| positive | TestInvalidIKESPIClearsXAndVBits |
unit/verify | mutant, verified |
| positive | TestSAInitNotifiesClearXAndVBits |
unit/verify | mutant, verified |
| positive | TestBuiltMessagesClearXAndVBits |
unit/verify | unproven |
RFC7296-3.1-12
An IKE endpoint MUST NOT generate a response to a message that is marked as being a response (with one exception; see Section 2.21.2) (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. TestNrsResponseNeverDrawsAResponse drives the responder handshake, out-of-SA admission (with a matching source so the flag is the only difference), INFORMATIONAL and CREATE_CHILD_SA paths: a message marked as a response builds and sends nothing, the same message with the flag clear is answered. TestNrsInformationalHandlerRefusesAResponse takes handleInformationalOwned at its own entry point, both ways. TestResponseBitMatchesDirection's moved negative repeats the handshake arm (R-set IKE_SA_INIT leaves the responder idle, the clear one reaches sa-init-received). The Section 2.21.2 exception is not exercised here.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResponseBitMatchesDirection |
unit/verify | revert, verified |
| negative | TestNrsInformationalHandlerRefusesAResponse |
unit/verify | revert, verified |
| negative | TestNrsResponseNeverDrawsAResponse |
unit/verify | revert, verified |
| positive | TestNrsInformationalHandlerRefusesAResponse |
unit/verify | revert, verified |
| positive | TestNrsResponseNeverDrawsAResponse |
unit/verify | revert, verified |
RFC7296-3.2-2
Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. MUST be ignored by the recipient if the recipient understands the payload type code. (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge; row widened to the Critical item head, kept clause 'MUST be ignored by the recipient if the recipient understands the payload type code' (RFC 7296 3.2). TestCriticalBitIgnoredForKnownType (Message.ReadFrom, outer chain) and TestInnerChainIgnoresCriticalOnKnownType (ParsePayloadChain, inner chain) parse a critical Nonce to the same *PayloadNonce and data with no error, so a parser that refused or altered a critical known payload fails. The negatives (critical unknown type refused with ErrUnsupportedCrit) are scoping controls showing the bit is read, not violations of this clause. One known type (Nonce) is sampled; chain.go consults Critical only in the unknown-payload branch. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInnerChainIgnoresCriticalOnKnownType |
unit/verify | unproven |
| negative | TestCriticalBitIgnoredForKnownType |
unit/verify | unproven |
| positive | TestInnerChainIgnoresCriticalOnKnownType |
unit/verify | unproven |
| positive | TestCriticalBitIgnoredForKnownType |
unit/verify | unproven |
RFC7296-3.2-3
all implementations MUST understand all payload types defined in this document (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. decodePayload yields a concrete type for all sixteen types 33-48; type 204 is ErrUnknownPayload
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAllDefinedPayloadTypesUnderstood |
unit/verify | unproven |
| positive | TestAllDefinedPayloadTypesUnderstood |
unit/verify | unproven |
RFC7296-3.2-4
Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. MUST be ignored by the recipient if the recipient understands the payload type code. MUST be set to zero for payload types defined in this document. (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge; row widened to the Critical item head, kept clause 'MUST be set to zero for payload types defined in this document' (RFC 7296 3.2). TestDefinedPayloadTypesAreSentUncritical sweeps the outer and inner chains of every engine-built message and fails on any defined type with Critical set, with a non-vacuity floor; TestEngineSourceNeverSetsTheCriticalField walks the engine source and refuses a literal or assigned Critical, proven against fixtures. The #2 tag (encoder writes 0x80 when asked) is an expressibility control, not a violating input. No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDefinedPayloadTypesAreSentUncritical |
unit/verify | unproven |
| positive | TestDefinedPayloadTypesAreSentUncritical |
unit/verify | unproven |
| positive | TestEngineSourceNeverSetsTheCriticalField |
unit/verify | unproven |
RFC7296-3.2-5
o Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. zero bit on the wire from the encoded bytes; recipient skips as PayloadRaw; set bit refused
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCritSenderZeroBitRequestsSkip |
unit/verify | unproven |
| positive | TestCritSenderZeroBitRequestsSkip |
unit/verify | unproven |
RFC7296-3.2-6
Critical (1 bit) - MUST be set to zero if the sender wants the recipient to skip this payload if it does not understand the payload type code in the Next Payload field of the previous payload. MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type. (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge; row widened to the Critical item head, kept clause 'MUST be set to one if the sender wants the recipient to reject this entire message if it does not understand the payload type' (RFC 7296 3.2). TestCritSenderOneBitRequestsWholeMessageRejection asserts the encoded bit is 0x80 when the sender chose rejection and that ReadFrom then rejects the whole message (ErrUnsupportedCrit, zero payloads, the payload type named); the negative asserts the bit is clear and the message accepted when the sender did not choose it. The obligation is met at the wire encoder; no engine path wants a rejection (RFC7296-3.2-4). No discrimination record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCritSenderOneBitRequestsWholeMessageRejection |
unit/verify | unproven |
| positive | TestCritSenderOneBitRequestsWholeMessageRejection |
unit/verify | unproven |
RFC7296-3.3-3
An SA payload MAY contain multiple proposals. If there is more than one, they MUST be ordered from most preferred to least preferred (§3.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestProposalOrderPreserved |
unit/verify | unproven |
| positive | TestProposalOrderPreserved |
unit/verify | unproven |
RFC7296-3.3-4
When parsing an SA, an implementation MUST check that the total Payload Length is consistent with the payload's internal lengths and counts (§3.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSAInternalLengthConsistency |
unit/verify | unproven |
| positive | TestSAInternalLengthConsistency |
unit/verify | unproven |
RFC7296-3.3-5
Each structure MUST have a proposal number one (1) greater than the previous structure. The first Proposal in the initiator's SA payload MUST have a Proposal Num of one (1) (§3.3, §3.3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropProposalNumbering |
unit/verify | unproven |
| positive | TestPropProposalNumbering |
unit/verify | unproven |
RFC7296-3.3-6
A transform MUST NOT have multiple attributes of the same type (§3.3)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropDuplicateAttributeRejected |
unit/verify | unproven |
| positive | TestPropDuplicateAttributeRejected |
unit/verify | unproven |
RFC7296-3.3-7
To propose alternate values for an attribute (for example, multiple key sizes for the AES encryption algorithm), an implementation MUST include multiple transforms with the same Transform Type each with a single Attribute. (§3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Proposer side now proven: the IKE and ESP offers ze builds (buildWireIKEProposals, buildWireESPProposals) for AES-CBC/GCM at 128 and 256, encoded and decoded off the wire, carry both key lengths, every ENCR transform with exactly one Key Length attribute; packing two key lengths into one transform fails it. Ze places each alternate ENCR transform in its own proposal, which meets the clause: multiple ENCR transforms, each with a single attribute. Receive side (TestPropAlternateKeyLengthsUseSeparateTransforms) refuses one transform with two key lengths: the genuine receiving-side negative (R1a).
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropAlternateKeyLengthsUseSeparateTransforms |
unit/verify | revert, verified |
| positive | TestRFC7296AlternateKeyLengthsAreOfferedAsSeparateTransforms |
unit/verify | revert, verified |
| positive | TestPropAlternateKeyLengthsUseSeparateTransforms |
unit/verify | revert, verified |
RFC7296-3.3.1-1
When a proposal is accepted, the proposal number in the SA payload MUST match the number on the proposal sent that was accepted (§3.3.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropAcceptedProposalNumberMatchesOffer |
unit/verify | unproven |
| positive | TestPropAcceptedProposalNumberMatchesOffer |
unit/verify | unproven |
RFC7296-3.3.1-2
o SPI Size (1 octet) - For an initial IKE SA negotiation, this field MUST be zero; the SPI is obtained from the outer header. (§3.3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Ze's IKE_SA_INIT proposals carry SPI Size 0; responder kills an initial request with SPI Size 8 and answers nothing
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSpzInitialIKESANegotiationNeedsZeroSPISize |
unit/verify | unproven |
| negative | TestPropSPISizeMatchesProtocol |
unit/verify | unproven |
| positive | TestSpzInitialIKESANegotiationNeedsZeroSPISize |
unit/verify | unproven |
| positive | TestPropSPISizeMatchesProtocol |
unit/verify | unproven |
RFC7296-3.3.3-1
A compliant implementation MUST understand all mandatory and optional types for each protocol it supports (§3.3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. transformTypeUnderstood per protocol matches the Section 3.3.3 table; engine refuses ESN in an IKE proposal. Re-judged 2026-09-30 (leftovers): TestTftUnknownTransformTypeMakesProposalUnacceptable changed only by the two added RFC7296-3.3.2-1 tag lines; body identical to HEAD, judge ran it: PASS; verdict unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropTransformTypesUnderstoodPerProtocol |
unit/verify | unproven |
| negative | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | unproven |
| positive | TestPropTransformTypesUnderstoodPerProtocol |
unit/verify | unproven |
| positive | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | unproven |
RFC7296-3.3.4-2
Upon receipt of a payload with a set of Transform IDs, the implementation MUST compare the transmitted Transform IDs against those locally configured via the management controls, to verify that the proposed suite is acceptable based on local policy (§3.3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropTransformIDsComparedAgainstLocalPolicy |
unit/verify | unproven |
| positive | TestPropTransformIDsComparedAgainstLocalPolicy |
unit/verify | unproven |
RFC7296-3.3.4-3
The implementation MUST reject SA proposals that are not authorized by these IKE suite controls (§3.3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropUnauthorizedProposalRejected |
unit/verify | unproven |
| positive | TestPropUnauthorizedProposalRejected |
unit/verify | unproven |
RFC7296-3.3.5-1
Attributes described as fixed length MUST NOT be encoded using the variable-length encoding unless that length exceeds two bytes (§3.3.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropFixedLengthAttributeRejectsTLVEncoding |
unit/verify | unproven |
| positive | TestPropFixedLengthAttributeRejectsTLVEncoding |
unit/verify | unproven |
RFC7296-3.3.5-2
Variable-length attributes MUST NOT be encoded as fixed-length even if their value can fit into two octets (§3.3.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropVariableLengthAttributeRejectsTVEncoding |
unit/verify | unproven |
| positive | TestPropVariableLengthAttributeRejectsTVEncoding |
unit/verify | unproven |
RFC7296-3.3.5-3
The Key Length attribute specifies the key length in bits (MUST use network byte order) (§3.3.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. 256 encodes 01 00; swapped octets read as 1
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropKeyLengthUsesNetworkByteOrder |
unit/verify | unproven |
| positive | TestPropKeyLengthUsesNetworkByteOrder |
unit/verify | unproven |
RFC7296-3.3.5-4
The Key Length attribute MUST NOT be used with transforms that use a fixed-length key (§3.3.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropKeyLengthRejectedOnFixedKeyTransform |
unit/verify | unproven |
| positive | TestPropKeyLengthRejectedOnFixedKeyTransform |
unit/verify | unproven |
RFC7296-3.3.5-5
o Some transforms specify that the Key Length attribute MUST be always included (omitting the attribute is not allowed, and proposals not containing it MUST be rejected). (§3.3.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Whole row proven. Sender clause (MUST be always included): new TestRFC7296OffersAlwaysCarryTheRequiredKeyLength builds the IKE offer (buildWireIKEProposals) and the ESP offer (espProposalToWire) for all 10 configurable AES ciphers (CBC, GCM, CCM 8/12/16 at 128/256) and asserts exactly one Key Length attribute equal to the configured size; an omitted, duplicated or wrong attribute is red (single-polarity by nature: a builder has no violating input). Receiver clause (proposals not containing it MUST be rejected): crypto TestPropKeyLengthRequiredTransformRejectedWithoutIt, AES-CBC/CTR offers without the attribute refused with ErrKeyLengthMissing and accepted with it. Ze builds no AES-CTR offer. Records: encAttrs revert observed red on the sender unit; the crypto receiver tags carry no record.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropKeyLengthRequiredTransformRejectedWithoutIt |
unit/verify | revert, verified |
| positive | TestPropKeyLengthRequiredTransformRejectedWithoutIt |
unit/verify | revert, verified |
| positive | TestRFC7296OffersAlwaysCarryTheRequiredKeyLength |
unit/verify | revert, verified |
RFC7296-3.3.6-4
If the responder receives a proposal that contains a Transform Type it does not understand, or a proposal that is missing a mandatory Transform Type, it MUST consider this proposal unacceptable; however, other proposals in the same SA payload are processed as usual (§3.3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropProposalMissingMandatoryTransformTypeUnacceptable |
unit/verify | unproven |
| negative | TestTftForeignTransformTypeRefusedInESPOffer |
unit/verify | unproven |
| negative | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | unproven |
| positive | TestPropProposalMissingMandatoryTransformTypeUnacceptable |
unit/verify | unproven |
| positive | TestTftForeignTransformTypeRefusedInESPOffer |
unit/verify | unproven |
| positive | TestTftUnknownTransformTypeMakesProposalUnacceptable |
unit/verify | unproven |
RFC7296-3.3.6-5
Similarly, if the responder receives a transform that it does not understand, or one that contains a Transform Attribute it does not understand, it MUST consider this transform unacceptable; other transforms with the same Transform Type are processed as usual. (§3.3.6)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Judged 2026-09-30 at the producers after the D-8 fix: wire Transform.AttrsUnderstood (attrFormats, Key Length only); appendIKECombinations and espProposalMatches drop a transform carrying an unknown attribute and keep its siblings, and refuse the proposal only when an offered type loses every transform (IKEProposal.UnacceptableTransformType -> ErrTransformUnacceptable in ikeProposalComplete; ESP offered!=usable). This matches Section 3.3.6: the transform is unacceptable, other transforms of the same type are processed as usual, and a type with nothing acceptable leaves no complete set to select. Negative TestRFC7296UnacceptableTransformAloneRefusesTheProposal: unknown ENCR id alone, and each IKE type (ENCR/PRF/INTEG/D-H) and ESP type (ENCR/INTEG/ESN) carrying attribute 99 alone is refused, with a per-type control without the attribute accepted, so the attribute is the only difference (isolated); this failed before the fix. Positive TestRFC7296UnacceptableTransformLeavesSiblingsOnOffer: the unknown-id and unknown-attribute transform beside an understood sibling, both orders, IKE accepted with the sibling's ENCR and ESP matched (catches an over-reaction that refuses the type or proposal). ESP response is built from config, so no unacceptable attribute is echoed. HEAD crypto/engine tags remain supplementary. Records: appendIKECombinations +, espProposalMatches -, observed red.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropUnknownTransformIDMakesTransformUnacceptable |
unit/verify | revert, verified |
| negative | TestAltUnusableAlternativesAreStillRefused |
unit/verify | revert, verified |
| negative | TestRFC7296UnacceptableTransformAloneRefusesTheProposal |
unit/verify | revert, verified |
| positive | TestPropUnknownTransformIDMakesTransformUnacceptable |
unit/verify | revert, verified |
| positive | TestAltDHAlternativesAreBothOffered |
unit/verify | revert, verified |
| positive | TestRFC7296UnacceptableTransformLeavesSiblingsOnOffer |
unit/verify | revert, verified |
RFC7296-3.3.6-7
Any attributes of a selected transform MUST be returned unmodified (§3.3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropSelectedTransformAttributesUnmodified |
unit/verify | unproven |
| positive | TestPropSelectedTransformAttributesUnmodified |
unit/verify | unproven |
RFC7296-3.9-1
The size of the Nonce Data MUST be between 16 and 256 octets, inclusive (§3.9)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNonceLengthBounds |
unit/verify | unproven |
| positive | TestNonceLengthBounds |
unit/verify | unproven |
RFC7296-3.10-3
For a notification concerning the IKE SA, the SPI Size MUST be zero and the field must be empty. (§3.10)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Producer side now proven: every notify of the IKE_SA_INIT request ze builds and the UNSUPPORTED_CRITICAL_PAYLOAD error answer ze sends, decoded off the wire, carry SPI Size 0 and no SPI octets (error data exactly one octet). Negative (R1b): an IKE-SA notify struct naming Protocol ID 1 and SPI Size 8 with no SPI octets is still encoded with SPI Size 0 and an empty SPI field. Engine notify producers read: only REKEY_SA (a Child SA notify, rekey.go) sets an SPI. INITIAL_CONTACT is not driven end to end; it uses the same WriteTo. Wire TestNotifyIKESAHasEmptySPI kept.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296IKESANotifyWithAnSPISizeButNoSPIIsSentEmpty |
unit/verify | revert, verified |
| negative | TestNotifyIKESAHasEmptySPI |
unit/verify | revert, verified |
| positive | TestRFC7296IKESANotifiesZeSendsCarryNoSPI |
unit/verify | revert, verified |
| positive | TestNotifyIKESAHasEmptySPI |
unit/verify | revert, verified |
RFC7296-3.10-4
For notifications concerning Child SAs, this field MUST contain either (2) to indicate AH or (3) to indicate ESP. (§3.10)
Audit verdict: enforced (the tests do what the requirement demands), fresh. SPI-bearing notify with AH/ESP round-trips; Protocol ID 0,1,4,255 beside an SPI refused with ErrNotifyProtocolID
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfyChildSAProtocolIDIsAHOrESP |
unit/verify | unproven |
| positive | TestNtfyChildSAProtocolIDIsAHOrESP |
unit/verify | unproven |
RFC7296-3.10-5
If the SPI field is empty, this field MUST be sent as zero and MUST be ignored on receipt. (§3.10)
Audit verdict: enforced (the tests do what the requirement demands), fresh. WriteTo zeroes Protocol ID for an empty SPI; ReadFrom discards it; kept when an SPI is present
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestNtfyEmptySPIProtocolIDIgnoredOnReceipt |
unit/verify | unproven |
| negative | TestNtfyEmptySPISendsProtocolIDZero |
unit/verify | unproven |
| positive | TestNtfyEmptySPIProtocolIDIgnoredOnReceipt |
unit/verify | unproven |
| positive | TestNtfyEmptySPISendsProtocolIDZero |
unit/verify | unproven |
RFC7296-3.11-1
each SPI MUST be for the same protocol. Mixing of protocol identifiers MUST NOT be performed in the Delete payload. (§3.11)
Audit verdict: enforced (the tests do what the requirement demands), fresh. PayloadDelete holds one ProtocolID by construction; two protocols need two payloads
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestDeletePayloadSingleProtocol |
unit/verify | unproven |
| positive | TestDeletePayloadSingleProtocol |
unit/verify | unproven |
RFC7296-3.11-2
SPI Size (1 octet) - Length in octets of the SPI as defined by the protocol ID. It MUST be zero for IKE (SPI is in message header) or four for AH and ESP. (§3.11)
Audit verdict: enforced (the tests do what the requirement demands), fresh. TestRFC7296DeleteWrongSPISizeForItsProtocolIsRefused drives IKE size 4, AH 0 and 8, ESP 0 through handleInformationalOwned: exactly one INVALID_SYNTAX, no Delete, no SA removed, no reestablish. Each case reddens under the break of its own deleteMalformed arm. TestRFC7296DeleteSPISizeFixedForItsProtocolIsAccepted: IKE 0 and AH 4 draw no notify, so the refusal is per-protocol size and not a refusal of IKE/AH Deletes. The older ESP-size-3 units and the wire units carry no discrimination record; the wire negative (truncation) proves a neighbouring rule.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296DeleteWrongSPISizeForItsProtocolIsRefused |
unit/verify | revert, verified |
| negative | TestDelMalformedSPISizeDrawsInvalidSyntax |
unit/verify | revert, verified |
| negative | TestDeleteSPISizeByProtocol |
unit/verify | revert, verified |
| positive | TestRFC7296DeleteSPISizeFixedForItsProtocolIsAccepted |
unit/verify | revert, verified |
| positive | TestDelWellFormedSPISizeIsAccepted |
unit/verify | revert, verified |
| positive | TestDeleteSPISizeByProtocol |
unit/verify | revert, verified |
RFC7296-3.12-2
Unfamiliar Vendor IDs MUST be ignored (§3.12)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestVendorIDIgnoredButPreserved |
unit/verify | unproven |
| positive | TestVendorIDIgnoredButPreserved |
unit/verify | unproven |
RFC7296-3.12-3
Writers of documents who wish to extend this protocol MUST define a Vendor ID payload to announce the ability to implement the extension in the document (§3.12)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestVendorIDIgnoredButPreserved |
unit/verify | unproven |
| positive | TestVendorIDIgnoredButPreserved |
unit/verify | unproven |
RFC7296-3.12-4
A Vendor ID payload MUST NOT change the interpretation of any information defined in this specification (i.e., the critical bit MUST be set to 0) (§3.12)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestVendorIDDoesNotChangeInterpretation |
unit/verify | unproven |
| positive | TestVendorIDDoesNotChangeInterpretation |
unit/verify | unproven |
RFC7296-3.14-2
Senders MUST select a new unpredictable IV for every message (§3.14)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKSelectsFreshIVPerMessage |
unit/verify | unproven |
| positive | TestSKSelectsFreshIVPerMessage |
unit/verify | unproven |
RFC7296-3.14-3
Initialization Vector - For CBC mode ciphers, the length of the initialization vector (IV) is equal to the block length of the underlying encryption algorithm. Senders MUST select a new unpredictable IV for every message; recipients MUST accept any value. (§3.14)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after the fix round (2691e815b1); only the positive's claim comment changed. RFC 7296 3.14: "Senders MUST select a new unpredictable IV for every message; recipients MUST accept any value." This row's tests carry the recipient clause (the sender clause is RFC7296-3.14-2). TestSKAcceptsAnyIVOnReceipt now claims the three IVs it sends (all-zero, all-ones, ascending) and decrypts each to the exact single Delete payload through decryptAndParse; its claim points the repeated IV to TestRFC7296RecipientAcceptsAnIVTheSenderShouldNotHaveChosen, which decrypts a repeated IV and the previous final ciphertext block used as IV, the inputs a policing recipient would refuse. Claim and body now agree; the earlier defect is resolved. Revert records on auth.go::decryptSKPayload for both units.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296RecipientAcceptsAnIVTheSenderShouldNotHaveChosen |
unit/verify | revert, verified |
| positive | TestSKAcceptsAnyIVOnReceipt |
unit/verify | revert, verified |
RFC7296-3.14-4
Padding MAY contain any value chosen by the sender, and MUST have a length that makes the combination of the payloads, the Padding, and the Pad Length to be a multiple of the encryption block size (§3.14)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKPaddingAlignsAndChecksumCoversCiphertext |
unit/verify | unproven |
| positive | TestSKPaddingAlignsAndChecksumCoversCiphertext |
unit/verify | unproven |
RFC7296-3.14-5
the recipient MUST accept any length that results in proper alignment (§3.14)
Audit verdict: enforced (the tests do what the requirement demands), fresh. minimum pad and +16/+32 accepted; over-long Pad Length refused with a valid MAC
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSKAcceptsAnyAligningPadLength |
unit/verify | unproven |
| positive | TestSKAcceptsAnyAligningPadLength |
unit/verify | unproven |
RFC7296-3.14-6
The checksum MUST be computed over the encrypted message (§3.14)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge because the unit TestSKAcceptsAnyIVOnReceipt moved; the move is a claim comment for RFC7296-3.14-3 only, and its RFC7296-3.14-6 negative claim and body are unchanged. RFC 7296 3.14: "The checksum MUST be computed over the encrypted message." The proof rests on the dedicated pair: TestRFC7296ChecksumIsTheHMACOfTheEncryptedMessage recomputes HMAC-SHA2-256-128 under SK_ai outside Ze over header, SK header, IV and ciphertext and requires Ze's ICV to equal it, and TestRFC7296ChecksumOverThePlaintextIsRefused refuses an ICV computed over the plaintext while the same construction over the ciphertext is accepted. TestSKAcceptsAnyIVOnReceipt's negative (a flipped final ICV octet refused) and TestSKPaddingAlignsAndChecksumCoversCiphertext add integrity-refusal floors only; a plaintext-MAC implementation would also refuse a flipped octet, so those units alone would not discriminate the scope, but the pair above does.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ChecksumOverThePlaintextIsRefused |
unit/verify | revert, verified |
| negative | TestSKAcceptsAnyIVOnReceipt |
unit/verify | revert, verified |
| negative | TestSKPaddingAlignsAndChecksumCoversCiphertext |
unit/verify | revert, verified |
| positive | TestRFC7296ChecksumIsTheHMACOfTheEncryptedMessage |
unit/verify | revert, verified |
| positive | TestSKPaddingAlignsAndChecksumCoversCiphertext |
unit/verify | revert, verified |
RFC7296-3.14-7
Peers MUST NOT negotiate transforms for which no such specification exists (§3.14)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPropUnspecifiedTransformRefused |
unit/verify | unproven |
| positive | TestPropUnspecifiedTransformRefused |
unit/verify | unproven |
RFC7296-5-2
Though the security of negotiated Child SAs does not depend on the strength of the encryption and integrity protection negotiated in the IKE SA, implementations MUST NOT negotiate NONE as the IKE integrity protection algorithm or ENCR_NULL as the IKE encryption algorithm. (§5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30. RFC 7296 Section 5: 'implementations MUST NOT negotiate NONE as the IKE integrity protection algorithm or ENCR_NULL as the IKE encryption algorithm.' The earlier residual is closed: the negative in TestRFC7296NegotiationRefusesNullIntegrityAndNullCipher now asserts errors.Is ErrProposalIncomplete for AUTH_NONE beside AES-CBC and ErrTransformUnspecified for ENCR_NULL, on both NegotiateIKE (responder) and VerifyAcceptedIKE (initiator), with policy holding the identical proposal; its positive accepts AES-CBC/HMAC-SHA2-256-128 on both. TestIKENeverNegotiatesNullAlgorithms keeps only its positive tag (the lookups refuse none/null, so ze cannot build a null proposal); its trailing block is now labelled a control, which it is. Three records observed red. Judge's own probe: removing the AUTH_NONE clause of ikeProposalComplete via go test -overlay reddens the negative on both sides.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296NegotiationRefusesNullIntegrityAndNullCipher |
unit/verify | revert, verified |
| positive | TestRFC7296NegotiationRefusesNullIntegrityAndNullCipher |
unit/verify | revert, verified |
| positive | TestIKENeverNegotiatesNullAlgorithms |
unit/verify | revert, verified |
RFC7296-5-3
For this reason, a PRF whose output is less than 128 bits (e.g., 3DES-CBC) MUST NOT be used with this protocol. (§5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. NegotiateIKE refuses a registered 64-bit PRF; prfOutputAcceptable floor at 128; every specified PRF at or above it
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestPrfFloorRefusesOutputBelow128Bits |
unit/verify | unproven |
| negative | TestPropPRFOutputBelow128BitsRefused |
unit/verify | unproven |
| positive | TestPrfFloorRefusesOutputBelow128Bits |
unit/verify | unproven |
| positive | TestPropPRFOutputBelow128BitsRefused |
unit/verify | unproven |
RFC7296-2.19-1
Since the IKE_AUTH exchange creates an IKE SA and a Child SA, the IRAC MUST request the IRAS-controlled address (and optionally other information concerning the protected network) in the IKE_AUTH exchange (§2.19, §4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestZeSendsNoConfigurationRequest |
unit/verify | unproven |
| positive | TestZeSendsNoConfigurationRequest |
unit/verify | unproven |
RFC7296-2.19-4
CP(CFG_REQUEST) MUST contain at least an INTERNAL_ADDRESS attribute (either IPv4 or IPv6) but MAY contain any number of additional attributes the initiator wants returned in the response (§2.19)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestZeSendsNoConfigurationRequest |
unit/verify | unproven |
| positive | TestZeSendsNoConfigurationRequest |
unit/verify | unproven |
RFC7296-2.20-1
An IKE implementation MAY decline to give out version information prior to authentication or even after authentication in case some implementation is known to have some security weakness. In that case, it MUST either return an empty string or no CP payload if CP is not supported. (§2.20)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Section 2.20's method: TestRFC7296InformationalVersionRequestDrawsNoCP sends the product INFORMATIONAL handler (handleInformationalOwned, MOBIKE enabled so mobikeResponsePayloads builds the answer) a post-auth CP(CFG_REQUEST, empty APPLICATION_VERSION) and asserts the response the peer decrypts carries no CP; TestRFC7296InformationalVersionRequestReflectsNoVersionString pushes toward reflection with a non-empty version string and asserts no CP and no non-empty APPLICATION_VERSION. IKE_AUTH path: TestRFC7296ResponderAnswersAVersionRequestWithNoCP. Sweep: TestZeDeclinesApplicationVersion. Ze supports no CP, so the no-CP arm is the one that binds.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestZeDeclinesApplicationVersion |
unit/verify | revert, verified |
| negative | TestRFC7296InformationalVersionRequestReflectsNoVersionString |
unit/verify | revert, verified |
| positive | TestZeDeclinesApplicationVersion |
unit/verify | revert, verified |
| positive | TestRFC7296InformationalVersionRequestDrawsNoCP |
unit/verify | revert, verified |
| positive | TestRFC7296ResponderAnswersAVersionRequestWithNoCP |
unit/verify | revert, verified |
RFC7296-3.15.1-2
An empty INTERNAL_IP4_NETMASK attribute can be included in a CFG_REQUEST to request this information (although the gateway can send the information even when not requested). Non-empty values for this attribute in a CFG_REQUEST do not make sense and thus MUST NOT be included. (§3.15.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-01 under owner ruling 5 (ruling 2 reading). Ze sends no CFG_REQUEST: no production code constructs a wire.PayloadCP (only the parser does), and TestZeSendsNoConfigRequestNetmask sweeps every engine-built chain (IKE_SA_INIT, IKE_AUTH, INFORMATIONAL, delete, IKE rekey; outer and decrypted inner, with a vacuity guard) and asserts no CP(CFG_REQUEST). Negative (handling of a peer's violation): a peer CFG_REQUEST with a non-empty 4-octet netmask is decrypted and parsed, not rejected, with the value preserved (RFC 7296 Section 2.5 tolerance). Both polarities hold observed-red revert records added 2026-09-30 (buildEncryptedMessageEx, decryptAndParse). The positive would miss a future CP builder only on an exchange the sweep does not drive.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestZeSendsNoConfigRequestNetmask |
unit/verify | revert, verified |
| positive | TestZeSendsNoConfigRequestNetmask |
unit/verify | revert, verified |
RFC7296-3.15.1-5
The responder MUST return a Configuration payload if it accepted any of the configuration data, and the Configuration payload MUST contain the attributes that the responder accepted with zero-length data (§3.15.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
| positive | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
RFC7296-3.15.1-6
Those attributes that it did not accept MUST NOT be in the CFG_ACK Configuration payload (§3.15.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
| positive | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
RFC7296-3.15.1-7
If no attributes were accepted, the responder MUST return either an empty CFG_ACK payload or a response message without a CFG_ACK payload (§3.15.1)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
| positive | TestCFGSetIsIgnoredAndDrawsNoCFGACK |
unit/verify | unproven |
RFC7296-2.4-2
If there has only been outgoing traffic on all of the SAs associated with an IKE SA, it is essential to confirm liveness of the other endpoint to avoid black holes. If no cryptographically protected messages have been received on an IKE SA or any of its Child SAs recently, the system needs to perform a liveness check in order to prevent sending messages to a dead peer. (§2.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-18 (independent auditor, after 98975fb2d8; the earlier weak verdict recorded no tagged unit). Section 2.4: "If no cryptographically protected messages have been received on an IKE SA or any of its Child SAs recently, the system needs to perform a liveness check in order to prevent sending messages to a dead peer." Positive TestRFC7296LivenessCheckFollowsTheInterval arms the state newDPDState builds for a 30-second interval (the YANG default when no dead-peer-detection block is configured, ze-ipsec-conf.yang), asserts no probe at 29 s, one probe at 31 s that reaches the peer's socket, and the probe awaited; red if newDPDState arms nothing (recorded revert) or shouldSend ignores the interval. Negative TestRFC7296LivenessCheckWaitsForTheOutstandingProbe asserts shouldSend false at 61 s and 300 s and an unchanged Message ID while the probe is outstanding: that is the single-request rule of Sections 2.1 and 2.3, a neighbouring obligation, so the negative side of this row rests on the 29-second assertion in the positive. Seams: dpdArmedTick restates the two lines of maintainSA (established.go) rather than driving the owner loop, and lastSent is reset only by sendDPD, so ze probes every interval whether or not protected traffic arrived; that over-checks and does not violate this SHOULD.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296LivenessCheckWaitsForTheOutstandingProbe |
unit/verify | mutant, verified |
| positive | TestRFC7296LivenessCheckFollowsTheInterval |
unit/verify | revert, verified |
RFC7296-2.4-3
Since IKE is designed to operate in spite of DoS attacks from the network, an endpoint MUST NOT conclude that the other endpoint has failed based on any routing information (e.g., ICMP messages) or IKE messages that arrive without cryptographic protection (e.g., Notify messages complaining about unknown SPIs). (§2.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor). SHIFTED by 6e063fb498 (tests: give ten assert-nothing tests a real assertion), whose hunks sit in untagged sibling tests and the import block. The tagged unit is byte-identical (gate-verified) and no helper it calls changed. Verdict stands. Re-judged 2026-09-30. Unprotected-message clause unchanged: TestRteUnownedEstablishedSATrustsNothing (cleartext Delete/CREATE_CHILD_SA refused, authenticated Delete still ends the SA) and the two responder IKE_SA_INIT units. Routing-information clause now asserted with real loopback ICMP (linux, unprivileged, ran and passed, not skipped): the IKE socket sets IP_RECVERR and the queued Port Unreachable is consumed by the transport's real error-queue path (records: panic in drainErrorQueue + and deliverQueuedError - observed red, so the ICMP path runs in each unit). Negative TestRFC7296ICMPFromThePeerWhileWaitingFailsNothing: a Port Unreachable from the peer's own address:port while a probe waits, plus a Fragmentation Needed routed into handleSizeRefusal (the engine's only ICMP consumer): SA stays Established, probe stays outstanding with no sa-failed answer, nothing reaches Refusals, later authenticated answer settles it. Positive TestRFC7296ICMPUnreachableDoesNotFailTheSA: after a queued Port Unreachable the SA's next request reaches the peer and the peer's authenticated answer settles the probe as fits. Limit: the assertion covers today's consumers (Refusals channel, handleSizeRefusal); a new ICMP consumer outside them would need its own test.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC7296ICMPFromThePeerWhileWaitingFailsNothing |
unit/verify | revert, verified |
| negative | TestResponderKeepsOldSAOnUnauthenticatedInit |
unit/verify | revert, verified |
| negative | TestRteUnownedEstablishedSATrustsNothing |
unit/verify | revert, verified |
| positive | TestRFC7296ICMPUnreachableDoesNotFailTheSA |
unit/verify | revert, verified |
| positive | TestResponderAcceptsReinitAfterStaleSA |
unit/verify | revert, verified |
| positive | TestRteUnownedEstablishedSATrustsNothing |
unit/verify | revert, verified |
RFC7296-2.4-4
The INITIAL_CONTACT notification, if sent, MUST be in the first IKE_AUTH request or response, not as a separate exchange afterwards (§2.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor). SHIFTED by 6e063fb498 (tests: give ten assert-nothing tests a real assertion), whose hunks sit in untagged sibling tests and the import block. The tagged unit is byte-identical (gate-verified) and no helper it calls changed. Verdict stands. Re-read 2026-09-27. Forbidden: INITIAL_CONTACT sent outside the first IKE_AUTH. TestInitiatorEmitsInitialContact fails if the responder did not parse it from the first IKE_AUTH; TestInitialContactAbsentFromRekey fails if an IKE rekey CREATE_CHILD_SA carries it. buildAuthRequest (auth.go) is the only producer of NotifyInitialContact, so no other exchange can carry it.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestInitialContactAbsentFromRekey |
unit/verify | unproven |
| positive | TestInitiatorEmitsInitialContact |
unit/verify | unproven |
RFC7296-3.4-2
This Diffie-Hellman Group Num MUST match a Diffie-Hellman group specified in a proposal in the SA payload that is sent in the same message (§3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResInitiatorRejectsKEGroupOutsideTheAcceptedOffer |
unit/verify | unproven |
| negative | TestKesaKEGroupNotOfferedIsRejected |
unit/verify | unproven |
| positive | TestKesaKEGroupOfferedIsAccepted |
unit/verify | unproven |
RFC7296-3.4-3
If none of the proposals in that SA payload specifies a Diffie-Hellman group, the KE payload MUST NOT be present (§3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestKesaKEWithoutDHProposalIsRejected |
unit/verify | unproven |
| positive | TestKesaAbsentKEIsAlwaysAllowed |
unit/verify | unproven |
RFC7296-3.3.6-8
If one of the proposals offered is for the Diffie-Hellman group of NONE, and the responder selects that Diffie-Hellman group, then it MUST ignore the initiator's KE payload and omit the KE payload from the response (§3.3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResIKESANeverSelectsDHGroupNone |
unit/verify | unproven |
| positive | TestResSelectedDHGroupNoneOmitsKEFromTheResponse |
unit/verify | unproven |
RFC7296-2.4-14
This notification MUST NOT be sent by an entity that may be replicated (§2.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResInitialContactNotSentByReplicableIdentity |
unit/verify | unproven |
| positive | TestResInitialContactSentByNonReplicableIdentity |
unit/verify | unproven |
RFC7296-2.8-8
When the lifetime of a Security Association expires, the Security Association MUST NOT be used (§2.8)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResExpiredSAIsNotUsed |
unit/verify | unproven |
| positive | TestResRekeyLeadLeavesRoomBeforeHardExpiry |
unit/verify | unproven |
| positive | TestResUnexpiredSAIsUsed |
unit/verify | unproven |
RFC7296-4-1
If the responder rejects the CREATE_CHILD_SA request with a NO_ADDITIONAL_SAS notification, the implementation MUST be capable of instead deleting the old SA and creating a new one (§4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestResOtherRekeyFailuresDoNotReestablish |
unit/verify | unproven |
| positive | TestResNoAdditionalSAsTriggersReestablish |
unit/verify | unproven |
RFC7296-2.15-3
It MUST also accept a hex encoding of the shared secret (§2.15)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestHexEncodingIsExplicitAndNeverGuessed |
unit/verify | unproven |
| positive | TestPSKAcceptsHexEncoding |
unit/verify | unproven |
RFC7296-3.3.4-4
All implementations of IKEv2 MUST include a management facility that enables a user or system administrator to specify the suites that are acceptable for use with IKE (§3.3.4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestIKESuitePolicyRejectsAnUnhonourableSuite |
unit/verify | unproven |
| positive | TestIKESuitePolicyIsOperatorSpecified |
unit/verify | unproven |
RFC7296-3.5-2
To assure maximum interoperability, implementations MUST be configurable to send at least one of ID_IPV4_ADDR, ID_FQDN, ID_RFC822_ADDR, or ID_KEY_ID (§3.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestLocalIDIsOperatorControlledNotDerived |
unit/verify | unproven |
| positive | TestLocalIDTypeFollowsConfiguredIdentity |
unit/verify | unproven |
RFC7296-3.5-3
To assure maximum interoperability, implementations MUST be configurable to send at least one of ID_IPV4_ADDR, ID_FQDN, ID_RFC822_ADDR, or ID_KEY_ID, and MUST be configurable to accept all of these four types. (§3.5)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-11 by an independent judge after the fix round (2691e815b1). RFC 7296 3.5: "implementations MUST be configurable to send at least one of ID_IPV4_ADDR, ID_FQDN, ID_RFC822_ADDR, or ID_KEY_ID, and MUST be configurable to accept all of these four types." The send clause is proven under RFC7296-3.5-2 (buildIDPayload tests); this row's tests carry the accept clause. Positive TestRemoteIDAcceptsEveryMandatoryType (unchanged) requires checkRemoteIdentity to accept all four types under a configured remote-id, each with an anti-vacuity refusal of a wrong value, so refusing any of the four or short-circuiting on an empty remote-id fails. Negative TestRemoteIDRefusesTypesItCannotCompare: its claim now names ID_DER_ASN1_GN only, which is exactly what the body sends, and requires the not-comparable branch ("cannot compare") rather than a value mismatch, so a checker that accepts every type turns red; the earlier defect (claim naming ID_DER_ASN1_DN, which RFC7296-4-4 requires accepted) is resolved. Revert record on remote_id.go::assertedIdentity.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRemoteIDRefusesTypesItCannotCompare |
unit/verify | revert, verified |
| positive | TestRemoteIDAcceptsEveryMandatoryType |
unit/verify | unproven |
RFC7296-3.5-4
IPv6-capable implementations MUST additionally be configurable to accept ID_IPV6_ADDR (§3.5)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestIPv6IdentityLengthIsEnforced |
unit/verify | unproven |
| positive | TestRemoteIDAcceptsIPv6Identity |
unit/verify | unproven |
RFC7296-3.6-1
Implementations MUST be capable of being configured to send and accept up to four X.509 certificates in support of authentication (§3.6)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCcnCertificateCountIsBoundedAndConfigurable |
unit/verify | unproven |
| negative | TestCcnCertificateCountReachesFourInBothDirections |
unit/verify | unproven |
| negative | TestCcnOverlongChainKillsTheSAOnBothRoles |
unit/verify | unproven |
| negative | ipsec-certificate-count-range.ci |
functional/verify | unproven |
| positive | TestCcnCertificateCountReachesFourInBothDirections |
unit/verify | unproven |
RFC7296-3.6-2
and also MUST be capable of being configured to send and accept the two Hash and URL formats (with HTTP URLs). (§3.6)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 (independent judge). Send half unchanged: TestChuBothHashAndURLFormatsAreConfigurable fails unless buildCertPayloads emits encodings 12 and 13 with the SHA-1 and URL. Accept half now asserted: rfc7296_hash_url_accept_test.go::TestRFC7296ReceivedHashAndURLFormatsAreAcceptedWhenConfigured, hash-and-url ON, receives encoding 12 (leaf DER) and encoding 13 (DER bundle leaf+intermediate) with http URLs on a loopback server; acceptedCertEncoding admits each, storeRemoteCerts fetches (server hit), matches the SHA-1, stores the leaf as the peer cert and the bundle's intermediate in the chain. Negative: TestChuHashAndURLIsOffByDefault drops encodings 12 and 13 and refuses a live, hash-matching fetch with the option off, and the ON control admits it. Revert record observed red on cert_payload.go::acceptedCertEncoding. Re-judge 2026-10-12 (independent auditor) after 6e7a370dba changed test/parse/ipsec-hash-and-url-accepted.ci: the only edit adds bgp router-id 203.0.113.253 to the peer block, because a YANG mandatory leaf is now refused when absent (RFC 7950 7.6.5). The vpn ipsec block, the hash-and-url/certificate-url/certificate-url-allow leaves, the der-asn1-dn remote-id and the expectations (exit 0, stdout 'configuration valid') are unchanged. The edit keeps the buffer isolated: without it validate would fail on the bgp mandatory leaf, a neighbouring rule, rather than on the IPsec surface under test. RFC 7296 text re-read at the cited section. Verdict unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChuBothHashAndURLFormatsAreConfigurable |
unit/verify | revert, verified |
| negative | TestChuHashAndURLIsOffByDefault |
unit/verify | revert, verified |
| positive | TestChuBothHashAndURLFormatsAreConfigurable |
unit/verify | revert, verified |
| positive | TestRFC7296ReceivedHashAndURLFormatsAreAcceptedWhenConfigured |
unit/verify | revert, verified |
| positive | ipsec-hash-and-url-accepted.ci |
functional/verify | revert, verified |
RFC7296-3.6-3
Implementations MUST support the "http:" scheme for hash-and-URL lookup (§3.6, §1.7)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestChuHashURLLookupRefusesEverythingOutsideTheBound |
unit/verify | unproven |
| negative | TestChuHashURLLookupUsesHTTPAndVerifiesTheHash |
unit/verify | unproven |
| positive | TestChuHashURLLookupCacheIsContentAddressed |
unit/verify | unproven |
| positive | TestChuHashURLLookupUsesHTTPAndVerifiesTheHash |
unit/verify | unproven |
RFC7296-4-4
For an implementation to be called conforming to this specification, it MUST be possible to configure it to accept the following: o Public Key Infrastructure using X.509 (PKIX) Certificates containing and signed by RSA keys of size 1024 or 2048 bits, where the ID passed is any of ID_KEY_ID, ID_FQDN, ID_RFC822_ADDR, or ID_DER_ASN1_DN. o Shared key authentication where the ID passed is any of ID_KEY_ID, ID_FQDN, or ID_RFC822_ADDR. (§4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-read 2026-09-27. Forbidden: a configuration that cannot accept RSA-1024/2048 PKIX under ID_KEY_ID, ID_FQDN, ID_RFC822_ADDR, ID_DER_ASN1_DN, or PSK under ID_KEY_ID, ID_FQDN, ID_RFC822_ADDR. TestCfmConformanceConfigurationSetIsAcceptable fails if verifyRemoteAuth refuses RSA-1024+FQDN, RSA-2048+RFC822, RSA-2048+DN, RSA-2048+KEY_ID or PSK with each of the three; TestCfmConformanceSetDoesNotAcceptWhatItMustNot shows a mismatched identity is refused; the .ci tests show the DN remote-id commits and remote-id-type is a closed set. Every key size and every ID type is covered, not the full cross product. Re-judge 2026-10-12 (independent auditor) after 6e7a370dba changed test/parse/ipsec-hash-and-url-accepted.ci: the only edit adds bgp router-id 203.0.113.253 to the peer block, because a YANG mandatory leaf is now refused when absent (RFC 7950 7.6.5). The vpn ipsec block, the hash-and-url/certificate-url/certificate-url-allow leaves, the der-asn1-dn remote-id and the expectations (exit 0, stdout 'configuration valid') are unchanged. The edit keeps the buffer isolated: without it validate would fail on the bgp mandatory leaf, a neighbouring rule, rather than on the IPsec surface under test. RFC 7296 text re-read at the cited section. Verdict unchanged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestCfmConformanceConfigurationSetIsAcceptable |
unit/verify | unproven |
| negative | TestCfmConformanceSetDoesNotAcceptWhatItMustNot |
unit/verify | unproven |
| negative | ipsec-remote-id-type-enum.ci |
functional/verify | unproven |
| positive | TestCfmConformanceConfigurationSetIsAcceptable |
unit/verify | unproven |
| positive | ipsec-hash-and-url-accepted.ci |
functional/verify | unproven |
RFC7296-4-5
Every implementation MUST be capable of doing four-message IKE_SA_INIT and IKE_AUTH exchanges establishing two SAs (one for IKE, one for ESP or AH) (§4)
Audit verdict: not audited: no reader has judged these tests
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestFourmFirstPairEstablishesNeitherSA |
unit/verify | unproven |
| positive | TestResponderHandshakePSKEndToEnd |
unit/verify | unproven |
Extraction sign-off
| Field | Value |
|---|---|
| Reviewer | six /ze-implement agents, one per section range, spec-rfcgate-1b-rfc7296-pilot AC-5; merged and re-checked in the main thread; site 2.13:2 re-walked by the spec-rfc-verdict-fix-ike-eap crypto author |
| Signed off | 2026-09-30 |
| Register | rfc2119 |
| Source | rfc/full/rfc7296.txt |
| Source fingerprint | a6f1a101b818977b |
| Record | rfc/extraction/rfc7296.json |
| Mapped sentences | 230 |
| Declined as scope | 19 |
| Relocated to a spec, which Ze OWES | 12 |
| Unclassified | 0 |
Sections
| Section | Name | Sites | Disposition | Reason |
|---|---|---|---|---|
front |
not stated | 0 | skipped (front-matter) | The abstract, the status of this memo, the copyright notice and the table of contents. No protocol obligation appears before Section 1. |
1 |
not stated | 1 | walked | The introduction names the exchange types and their order. Its one keyword site is the exchange-order sentence, mapped to RFC7296-1-1. The rest of the section describes what each exchange carries. |
1.1 |
not stated | 0 | walked | One paragraph introducing the four usage scenarios below it. It states no obligation. |
1.1.1 |
not stated | 0 | walked | A figure and one paragraph on the security gateway to security gateway tunnel. It describes a deployment, not protocol behavior. |
1.1.2 |
The endpoint-to-endpoint transport mode scenario | 0 | walked | The endpoint-to-endpoint transport mode scenario. Its only keyword is a MAY on application-layer access control, which gates nothing. |
1.1.3 |
not stated | 0 | walked | The endpoint to security gateway tunnel scenario, including why the initiator asks for an address through configuration payloads. It states no obligation. |
1.1.4 |
not stated | 0 | walked | One paragraph on nested combinations of the earlier scenarios. It states no obligation. |
1.2 |
The initial exchanges | 5 | walked | The initial exchanges. Five keyword sites map to rows RFC7296-1.2-2 through RFC7296-1.2-6. Row RFC7296-1.2-1 is read from two indicative sentences, that the initial exchanges are four messages and that every message after IKE_SA_INIT is cryptographically protected, and neither carries a keyword. |
1.3 |
The CREATE_CHILD_SA exchange | 3 | walked | The CREATE_CHILD_SA exchange. Two of its three keyword sites map to RFC7296-1.3-1 and RFC7296-1.3-2; the third restates the first. The NO_ADDITIONAL_SAS paragraph carries no keyword and no row. |
1.3.1 |
Creating a new Child SA | 2 | walked | Creating a new Child SA. Both keyword sites sit in the USE_TRANSPORT_MODE paragraph and map to RFC7296-1.3.1-1 and RFC7296-1.3.1-2. The TFC padding and non-first-fragment paragraphs carry no keyword. |
1.3.2 |
Rekeying the IKE SA | 1 | walked | Rekeying the IKE SA. Its one keyword site makes the KEi payload mandatory, and row RFC7296-1.3.3-1 holds that obligation under an id and a citation that name Section 1.3.3 instead. |
1.3.3 |
Rekeying a Child SA | 1 | walked | Rekeying a Child SA. Its one keyword site binds the REKEY_SA notification into a CREATE_CHILD_SA exchange that replaces an ESP or AH SA. No row stated that obligation when the walk began: it was extracted during the walk as RFC7296-1.3.3-2, which site 1.3.3:1 now maps to. Note that RFC7296-1.3.3-1 is a different row whose obligation sits in section 1.3.2; its anchor is a recorded Known Limitation and was deliberately left alone. Rows RFC7296-1.3.3-3 and RFC7296-1.3.3-4 are read from the two sentences that give the rekey request its SA, Ni, optional KEi, TSi and TSr payloads and the rekey response its TS payloads; neither carries a keyword (added 2026-09-29, the mistagged-unit fix of spec-rfc-verdict-fix-ike-eap). |
1.4 |
The INFORMATIONAL exchange | 4 | walked | The INFORMATIONAL exchange. Four keyword sites map to RFC7296-1.4-5, to RFC7296-1.4-3 twice, and to RFC7296-1.4-4. |
1.4.1 |
Deleting an SA | 6 | walked | Deleting an SA. Six keyword sites map to RFC7296-1.4.1-1 twice and to RFC7296-1.4.1-4 through RFC7296-1.4.1-7. Row RFC7296-1.4-1 is read from the sentence that the response carries Delete payloads for the paired SAs in the other direction, which carries no keyword; that row cites Section 1.4. |
1.5 |
Informational messages outside an IKE SA | 1 | walked | Informational messages outside an IKE SA. Its one keyword site bars an answer to the unprotected message and maps to RFC7296-1.5-1. The closing paragraphs that build the response carry no keyword, and row RFC7296-2.21.4-2 cites Section 2.21.4 first. |
1.6 |
Requirements terminology | 0 | walked | Requirements terminology. It points at [IPSECARCH] for the primitive terms and gives the RFC 2119 reading of the keywords. It states no protocol obligation. |
1.7 |
The change list against RFC 4306 | 7 | walked | The change list against RFC 4306. Three sites carry obligations that live in Sections 2.5, 2.13 and 3.6, two are prose about the keywords themselves, one quotes the Section 1.3.2 change, and one states the configuration attribute type 5 rule that no row in rfc/short/rfc7296.md holds. |
1.8 |
The change list against RFC 5996 | 0 | walked | The change list against RFC 5996. Every entry names a section that was added, clarified or corrected. It states no obligation. |
2 |
IKE protocol details and variations | 2 | walked | IKE protocol details and variations. Two keyword sites: the 1280-octet message size and the four zero octets that prefix an IKE message on port 4500. |
2.1 |
Retransmission timers | 7 | walked | Retransmission timers. Seven keyword sites map to rows RFC7296-2.1-3 through RFC7296-2.1-8. The half-open IKE SA paragraphs and the one-way message paragraph that follow carry no keyword and no row. |
2.2 |
Message ID sequence numbers | 2 | walked | Message ID sequence numbers. Two keyword sites map to RFC7296-2.2-1 and RFC7296-2.2-2. The counter paragraph carries no keyword and states an obligation the capitalised scan cannot see: each endpoint maintains two INDEPENDENT current Message IDs. It is recorded as RFC7296-2.2-3 in unsourced-ids. The original-initiator paragraph carries no keyword and states no obligation. |
2.3 |
Window size for overlapping requests | 9 | walked | Window size for overlapping requests. Six sites map to the Section 2.3 rows, two map to RFC7296-2.1-5 which cites Section 2.1 and Section 2.3, and one restates the window limit that site 2.3:4 maps. |
2.4 |
not stated | 8 | walked | Walked the whole section: state loss after a crash, INITIAL_CONTACT, liveness detection, retransmission, and Child SA deletion. The eight sites carry every capitalised obligation. The empty INFORMATIONAL liveness exchange is described in indicative prose with no keyword. |
2.5 |
not stated | 11 | walked | Walked the version number and forward compatibility rules, including the critical flag paragraph. Eleven sites carry the obligations. Two sentences each carry two obligations while deriving one site, so the second obligation of each has no site. |
2.6 |
not stated | 4 | walked | Walked the SPI text, the cookie exchange, the worked cookie construction, and the terminology note. Four sites carry the obligations. The identification of an IKE SA by the SPI pair is stated in indicative prose in the first paragraph. |
2.6.1 |
not stated | 1 | walked | Walked the interaction of COOKIE and INVALID_KE_PAYLOAD, including the three round trip diagram. The section states one obligation, in its closing sentence, and the site carries it. |
2.7 |
not stated | 5 | walked | Walked the algorithm negotiation rules. The five sites state one rule set that the summary captures in two rows, so three sites restate obligations those rows already carry. |
2.8 |
not stated | 4 | walked | Walked the rekeying section: lifetime expiry, rekey failure, IKE SA replacement, proactive rekey, and the window where the two ends disagree about an SA. Four sites carry the capitalised obligations. Independent lifetime policy is written as a difference from IKEv1 in indicative prose. |
2.8.1 |
not stated | 1 | walked | Walked the simultaneous Child SA rekeying rules and both packet loss traces. The site carries the accept-on-either-SA obligation. The lowest-of-four-nonces collision rule is written as a SHOULD in this section, so it derives no MUST-level site. |
2.8.2 |
not stated | 1 | walked | Walked the simultaneous IKE SA rekeying case, the TEMPORARY_FAILURE path, and the message trace. The site carries the one capitalised obligation, that the surviving IKE SA inherits the Child SAs. |
2.8.3 |
not stated | 0 | walked | Walked the comparison of IKE SA rekeying against reauthentication. The section states what each mechanism does and how reauthentication is built from the existing exchanges. It imposes no obligation and derives no site. |
2.9 |
not stated | 1 | walked | Walked the traffic selector negotiation text, including the four narrowing bullets and the SINGLE_PAIR_REQUIRED discussion. One bullet carries a capitalised MUST and is mapped. The TS_UNACCEPTABLE bullet and the narrowing-not-widening rule are written in indicative prose. |
2.9.1 |
not stated | 0 | walked | Walked the section on selectors that violate the initiator's own policy. It is a worked example of dropped traffic and closes with a general statement of the hazard. It imposes no obligation and derives no site. |
2.9.2 |
not stated | 2 | walked | Walked the rekeying selector rules. The two sites carry the two prohibitions, one binding the new SA and one binding the responder. |
2.10 |
not stated | 1 | walked | Walked the nonce section. One sentence carries three obligations and derives one site, so the two size floors have no site of their own. |
2.11 |
not stated | 2 | walked | Walked the address and port agility section, four sentences long. It derives two sites. The first sentence carries two obligations, so the second has no site of its own. |
2.12 |
not stated | 1 | walked | Walked the Diffie-Hellman exponential reuse section. Its one obligation is the forget-the-keys sentence, which the site carries. The reuse strategies are stated as choices that do not affect interoperability. |
2.13 |
not stated | 4 | walked | Walked the keying material section through the prf+ definition and its 255-iteration limit. The four sites carry the key size and key derivation obligations. The prf+ construction is stated as a definition. |
2.14 |
not stated | 1 | walked | The section derives SKEYSEED and the seven SK_ values with prf and prf+. Its one MUST-level sentence fixes the length of SK_d, SK_pi and SK_pr, and the summary carries that obligation as RFC7296-2.13-3, which cites both sections. |
2.15 |
not stated | 2 | walked | The section defines the signed octets and the pre-shared-key AUTH computation. Its three MUST-level obligations sit in one management-interface passage that the extractor cut into two sites, so the null-terminator half has no site of its own and is recorded unsourced. |
2.16 |
not stated | 8 | walked | Every MUST-level sentence of the EAP section derives a site, and the eight sites map one to one onto the eight requirement ids anchored to this section. The remaining text is the message diagram and SHOULD NOT or MAY guidance. |
2.17 |
not stated | 2 | walked | The section gives KEYMAT and three ordering bullets. Both MUST-level sites map to the two §2.17 rows, and the first bullet's ordering rule is already inside the text of RFC7296-2.17-1. |
2.18 |
not stated | 3 | walked | The section derives SKEYSEED for a rekeyed IKE SA and states two obligations: a new Diffie-Hellman exchange, and a message-counter reset. Both §2.18 rows are the target of a site. |
2.19 |
not stated | 6 | walked | Two of the six MUST-level sentences map to the two §2.19 rows the summary carries. The other four are the Configuration payload obligations that the 2026-07-31 owner ruling moved to plan/immediate/spec-ipsec-remote-access.md as RFC7296-2.19-2, -3, -5 and -6; those ids are not in rfc/short/rfc7296.md, so their sites stay unclassified. |
2.20 |
not stated | 1 | walked | The section shows the APPLICATION_VERSION exchange. Its one MUST states what a peer that declines to give version information returns, and RFC7296-2.20-1 carries it. |
2.21 |
not stated | 0 | walked | The section states the general error-handling rule in indicative prose and MAY constructions: a badly formatted or unacceptable request draws a Notify, and a bad response draws none. It derives no MUST-level site and no summary row cites §2.21. |
2.21.1 |
not stated | 0 | walked | IKE_SA_INIT error handling is written with 'should' throughout, because every notification at that point is unauthenticated. The section derives no site and no summary row cites §2.21.1. |
2.21.2 |
not stated | 3 | walked | Three MUST-level sentences and three rows: whole-message rejection, the initiator not failing authentication over a piggybacked error, and the limit on new error notifications defined by extension documents. |
2.21.3 |
not stated | 1 | walked | The section's one MUST requires a response for every errored request once the IKE SA is authenticated. The rest is SHOULD NOT guidance against starting new exchanges to report errors. |
2.21.4 |
not stated | 5 | walked | Five sites carry the out-of-SA rules for a message on port 500 or 4500 with no known IKE SA. Two of those sentences state two obligations each, so RFC7296-2.21.4-4 and -6 have no site of their own and are recorded unsourced. RFC7296-2.21.4-8, the SHOULD to send a protected Notify over an existing IKE SA after a suspicious message, is below the MUST-level scan, so it is recorded unsourced too. |
2.22 |
not stated | 2 | walked | Both MUST-level sentences are IPComp obligations: where an IPCOMP_SUPPORTED notification can appear, and what an implementation accepts and compresses with. The 2026-07-31 owner ruling moved the four §2.22 rows to plan/spec-ipsec-ipcomp.md, so no id exists in rfc/short/rfc7296.md and both sites stay unclassified. |
2.23 |
not stated | 10 | walked | Nine of the ten sites map to a summary row and one is the section's own applicability statement. RFC7296-2.23-3, the four zero octets prepended to a tunnelled IKE header, and RFC7296-2.23-12, the SPI rule that lets a receiver tell ESP from IKE on port 4500, are stated in indicative prose with no MUST-level keyword, so they are recorded unsourced. RFC7296-2.23-13, the SHOULD to adopt the address and port of an integrity-validated packet that arrives from a new endpoint, is below the MUST-level scan, so it is recorded unsourced too. |
2.23.1 |
not stated | 3 | walked | Read the transport mode NAT traversal scenario and the client and responder rule lists. Three MUST sites, all mapped; every other rule in the section is SHOULD or MAY. |
2.24 |
not stated | 1 | walked | Read the ECN section. Its one normative sentence carries two MUSTs and yields one site, so RFC7296-2.24-2 (the [IPSECARCH] encapsulation and decapsulation processing) has no site of its own. |
2.25 |
not stated | 1 | walked | Read the exchange collision section. The TEMPORARY_FAILURE retry ban is its only MUST; the TEMPORARY_FAILURE and CHILD_SA_NOT_FOUND sending rules are SHOULD. |
2.25.1 |
not stated | 0 | walked | Read the Child SA rekey and close collision rules. Every rule in the section is SHOULD, so the section holds no MUST-level site and no requirement row cites it. |
2.25.2 |
not stated | 0 | walked | Read the IKE SA rekey and close collision rules. Every rule in the section is SHOULD, so the section holds no MUST-level site and no requirement row cites it. |
3 |
not stated | 0 | walked | Read the section head. Its one normative sentence is a SHOULD NOT about items marked UNSPECIFIED, so the section holds no MUST-level site. |
3.1 |
not stated | 13 | walked | Read the IKE header section and every field description. Two rows share a source sentence with the row mapped from the same site: RFC7296-3.1-2 (no Encrypted payload inside an Encrypted payload) sits in site 3.1:1, and RFC7296-3.1-8 (ignore X bits on receipt) sits in site 3.1:9. |
3.2 |
not stated | 6 | walked | Read the generic payload header section, the payload type table and the Critical bit paragraph. All six sites map. Sites 3.2:1 and 3.2:2 state the sender obligations for the Critical bit; they were unextracted and are now carried by RFC7296-3.2-5 and RFC7296-3.2-6. |
3.3 |
not stated | 7 | walked | Read the Security Association payload section, its nesting rules and its proposal example. RFC7296-3.3-1 (combined-mode ciphers and normal ciphers go in separate proposals) is written with a lowercase must, so it has no capitalised site. |
3.3.1 |
not stated | 4 | walked | Read the proposal substructure and every field description. Four sites, all mapped, two of them to the RESERVED rows that cite this section. |
3.3.2 |
not stated | 1 | walked | Read the transform substructure, the Transform Type table and the Transform ID tables. RFC7296-3.3.2-1 (an IKE SA proposal carries ENCR, PRF, INTEG and D-H) is read from the Used In column of that table, which carries no keyword. |
3.3.3 |
not stated | 1 | walked | Read the valid Transform Types section and its mandatory and optional table. Its one MUST is mapped. |
3.3.4 |
not stated | 5 | walked | Read the mandatory Transform IDs section. Three MUSTs bind the implementation and are mapped; two sentences use the keyword to describe other documents' suite specifications and are excluded. |
3.3.5 |
not stated | 5 | walked | Read the transform attribute section, the attribute format figure and the Key Length rules. Five sites, all mapped; the interoperability note at the end is SHOULD. |
3.3.6 |
not stated | 8 | walked | Read the whole section: the responder selection rules, the handling of an unknown Transform Type or Transform Attribute, and the three Diffie-Hellman negotiation paragraphs. Section 3.3.6 treats Diffie-Hellman negotiation in indicative prose; the mandate that an IKE proposal carries a D-H transform is the mandatory Transform Type table of Section 3.3.3, which RFC7296-3.3.2-1 carries (RFC7296-3.3.6-1, a duplicate of that span, was retired 2026-09-29). |
3.4 |
not stated | 4 | walked | Read the Key Exchange payload section, the payload figure and the two paragraphs that follow it. All four sites map, and the INVALID_KE_PAYLOAD rejection maps to the row the summary anchors at Section 1.3. |
3.5 |
not stated | 5 | walked | Read the Identification payload section, the ID Type table and the interoperability paragraph. RFC7296-3.5-3 has no site of its own: one sentence carries the send obligation and the accept obligation together, and site 3.5:4 maps the send half. |
3.6 |
not stated | 3 | walked | Read the Certificate payload section, the Certificate Encoding table, the CertBundle ASN.1 module and the two closing paragraphs. RFC7296-3.6-2 has no site of its own: one sentence carries the four-certificate obligation and the Hash and URL obligation together, and site 3.6:1 maps the first half. |
3.7 |
not stated | 0 | walked | Read the Certificate Request payload section in full. It derives no site: its obligations are written at SHOULD and MAY level, such as CERTREQ payloads MAY be included and a certificate chain SHOULD be sent back to the requestor. The summary declares no requirement anchored at Section 3.7. |
3.8 |
not stated | 1 | walked | Read the Authentication payload section and the Auth Method table. Its one site is the RESERVED field rule, which restates the forward compatibility rule of Section 2.5. The only summary row anchored at Section 3.8 is a SHOULD and never gates. |
3.9 |
not stated | 2 | walked | Read the Nonce payload section. Both sites map: the 16 to 256 octet size range, and the ban on reusing a nonce value. |
3.10 |
not stated | 3 | walked | Read the Notify payload section and its field list. All three sites map to the Protocol ID and SPI Size rules that the field descriptions state. |
3.10.1 |
not stated | 4 | walked | Read the Notify Message Types section, including the error type table and the status type table. Three sites map to the error handling paragraph and the INVALID_SYNTAX entry, and the fourth repeats the ignore rule for status types. |
3.11 |
not stated | 3 | walked | Read the Delete payload section and its field list. Two sites carry the same one-protocol-per-payload rule, and the third carries the SPI Size rule. |
3.12 |
not stated | 3 | walked | Read the Vendor ID payload section. All three sites map: the critical bit rule, the ignore rule for an unfamiliar Vendor ID, and the obligation on writers of documents that extend the protocol. |
3.13 |
not stated | 1 | walked | Read the Traffic Selector payload section, its field list and the TSi/TSr matching example. Its one site is the RESERVED field rule of Section 2.5. The summary declares no requirement anchored at Section 3.13. |
3.13.1 |
not stated | 4 | walked | Read the Traffic Selector substructure section, the Start Port and End Port descriptions, and the ANY and OPAQUE paragraph. Three sites map and one restates the port encoding that the first two carry. |
3.14 |
not stated | 6 | walked | Read the Encrypted payload section, its field list, and the padding and checksum rules. RFC7296-3.14-3 has no site of its own: one sentence binds the sender to a new unpredictable IV and the recipient to accept any value, and site 3.14:3 maps the sender half. |
3.15 |
Configuration payload header | 1 | walked | Configuration payload header. The one site is the 3-octet RESERVED field; the rest of the section names payload type 47, lists the four CFG Type values and says the attribute list can be empty. |
3.15.1 |
not stated | 8 | walked | Configuration Attribute format, the attribute-type table, the per-attribute entries and the CFG_REQUEST/CFG_REPLY and CFG_SET/CFG_ACK paragraphs. Eight sites. Three of them state obligations rfc/short/rfc7296.md carries no row for, recorded on those sites. |
3.15.2 |
not stated | 0 | walked | The meaning of INTERNAL_IP4_SUBNET and INTERNAL_IP6_SUBNET, given as four worked CFG_REPLY examples. It says what a gateway conveys with the attribute and closes by saying the attribute cannot be used reliably in a CFG_REQUEST. No sentence obliges a speaker. |
3.15.3 |
Configuration payloads for IPv6 | 0 | walked | Configuration payloads for IPv6. One worked exchange, the gateway's address-selection behavior at MAY level, and the limitation that an IKEv2 tunnel is not a full IPv6 interface. No obligation is stated. |
3.15.4 |
Address assignment failures | 0 | walked | Address assignment failures. The section states in indicative prose that a responder which cannot assign an address responds with INTERNAL_ADDRESS_FAILURE, and sends it only when no address can be assigned. That obligation carries no capitalised keyword and rfc/short/rfc7296.md declares no row for it, so unsourced-ids cannot name it. It needs a checklist row. |
3.16 |
The EAP payload and the EAP message format | 4 | walked | The EAP payload and the EAP message format. Four sites, one per field rule: Identifier, Length, Type presence and Type value. Each has its own row. |
4 |
Conformance requirements | 10 | walked | Conformance requirements. Ten sites: the section opener, the two payload-handling rules, the minimal-implementation paragraph, the three Configuration payload conditionals and the configurable-authentication list. RFC7296-3.2-3 is listed unsourced because Section 4 states it in the same sentence as site 4:2, which is mapped to RFC7296-2.5-8. |
5 |
Security considerations | 3 | walked | Security considerations. Three capitalised sites: the PRF output floor, the ban on NONE and ENCR_NULL inside the IKE SA, and public-key authentication of the server before EAP starts. The rest of the section is analysis and SHOULD-level advice. |
5.1 |
Traffic selector authorization | 0 | walked | Traffic selector authorization. It describes the Peer Authorization Database of [IPSECARCH] and reads an assigned inner address as a temporary PAD entry. The constraints it names belong to that document; the section states none of its own. |
6 |
IANA considerations | 0 | skipped (iana) | IANA considerations. It records that IANA registered the IKEv2 types and values in [IKEV2IANA], deprecated the Raw RSA Key certificate encoding and repointed the RFC 5996 references. |
7 |
References heading | 0 | skipped (references) | References heading. |
7.1 |
Normative references | 0 | skipped (references) | Normative references. |
7.2 |
Informative references | 0 | skipped (references) | Informative references. |
A |
Summary of changes from IKEv1 | 0 | skipped (appendix-non-normative) | Summary of changes from IKEv1. Twelve numbered goals of the revision, written as a design record. It obliges no implementation. |
B |
Diffie-Hellman groups | 0 | walked | Diffie-Hellman groups. It defines two groups for use in IKE and says group 1 is kept for historic reasons. The prime and generator it carries are data, not a sentence that binds a speaker, so the section yields no site. |
B.1 |
not stated | 0 | walked | Group 1, 768-bit MODP: the assigned id, the prime and the generator 2. Constants only. |
B.2 |
not stated | 0 | walked | Group 2, 1024-bit MODP: the assigned id, the prime and the generator 2. Constants only. |
C |
Exchanges and payloads | 0 | skipped (appendix-non-normative) | Exchanges and payloads. The appendix says of itself that it is purely informative, and that the body of the document is correct wherever the two disagree. |
C.1 |
not stated | 0 | skipped (appendix-non-normative) | IKE_SA_INIT payload diagram: request, normal response, cookie response and the INVALID_KE_PAYLOAD response. Diagram only, under Appendix C's informative statement. |
C.2 |
not stated | 0 | skipped (appendix-non-normative) | IKE_AUTH without EAP: request, response and the Child SA error response. Diagram only, under Appendix C's informative statement. |
C.3 |
not stated | 0 | skipped (appendix-non-normative) | IKE_AUTH with EAP: first pair, the repeated EAP pair and the last pair. Diagram only, under Appendix C's informative statement. |
C.4 |
not stated | 0 | skipped (appendix-non-normative) | CREATE_CHILD_SA for creating or rekeying Child SAs, with the error and INVALID_KE_PAYLOAD responses. Diagram only, under Appendix C's informative statement. |
C.5 |
not stated | 0 | skipped (appendix-non-normative) | CREATE_CHILD_SA for rekeying the IKE SA, where KEi and KEr are mandatory. Diagram only, under Appendix C's informative statement. |
C.6 |
not stated | 0 | skipped (appendix-non-normative) | INFORMATIONAL exchange: notify, delete and Configuration payloads in request and response. Diagram only, under Appendix C's informative statement. |
Excluded sentences
| Site | Excluded kind | Reason | Quote |
|---|---|---|---|
1.3:2 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The sentence restates the one before it from the side of the KEi: the group the initiator expects the responder to accept is the group set it proposes, which the parenthesis about additional groups confirms. Site 1.3:1 maps RFC7296-1.3-1. | The Diffie-Hellman group of the KEi MUST be an element of the group the initiator expects the responder to accept (additional Diffie-Hellman groups can be proposed). |
1.7:1 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The sentence reports what IKEv2 developers observed about RFC 4306. The keyword names a class of requirement in that earlier document and imposes nothing. | They also have noted that there are MUST- level requirements that are not related to interoperability. |
1.7:2 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The sentence sets how a reader interprets the lower-case words should and must in this document. It is a reading convention, and the keyword is the word being defined. | All non-capitalized uses of the words SHOULD and MUST now mean their normal English sense, not the interoperability sense of [MUSTSHOULD]. |
1.7:3 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, ignore proposals carrying configuration attribute type 5, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-1.7-3 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-1.7-3) | Implementations that conform to this document MUST ignore proposals that have configuration attribute type 5, the old value for INTERNAL_ADDRESS_EXPIRY. |
1.7:5 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The sentence quotes the Section 1.3.2 change that turned the KEi payload from SHOULD to MUST. Site 1.3.2:1 maps RFC7296-1.3.3-1, which is that obligation. | In Section 1.3.2, "The KEi payload SHOULD be included" was changed to be "The KEi payload MUST be included". |
2.3:5 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The RFC opens this sentence with 'In other words' and restates the window limit as a wait for the responses up through request X-N. Site 2.3:4 maps RFC7296-2.3-4. | In other words, if the responder stated its window size is N, then when the initiator needs to make a request X, it MUST wait until it has received responses to all requests up through request X-N. |
2.7:1 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
This sentence introduces the negotiation rules that follow it, and each of those rules restates the single-suite obligation with its own site. RFC7296-2.7-1 carries it, mapped from the exactly-one-transform-per-type site. | The responder MUST choose a single suite, which may be any subset of the SA proposal following the rules below. |
2.7:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Accepting one proposal or rejecting them all with an error is the second half of RFC7296-2.7-1, whose first half the exactly-one-transform-per-type site maps. | The responder MUST accept a single proposal or reject them all and return an error. |
2.7:5 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The sentence opens with 'For example' and applies the preceding rule to a named ESP proposal. It states no obligation the preceding sentence does not, and RFC7296-2.7-1 carries that obligation. | For example: if an ESP proposal includes transforms ENCR_3DES, ENCR_AES w/keysize 128, ENCR_AES w/keysize 256, AUTH_HMAC_MD5, and AUTH_HMAC_SHA, the accepted suite MUST contain one of the ENCR_ transforms and one of the AUTH_ transforms. |
2.13:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
The sentence binds the specification of a cryptographic transform: the transform's defining document must state how keys are derived from arbitrary values, and no implementation fills that role. Ze implements no transform the condition names either: encryptionRegistry (`internal/component/ike/crypto/transform.go`) holds AES CBC, GCM and CCM only, for which every value of the fixed size is a valid key. Row RFC7296-2.13-2 was retired on 2026-09-30. | For algorithms for which not all values are valid keys (such as DES or 3DES with key parity), the algorithm by which keys are derived from arbitrary values MUST be specified by the cryptographic transform. |
2.19:2 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, the CP payload's position in the responder's payload chain, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.19-2 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-2.19-2) | Initiator Responder ------------------------------------------------------------------- HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,] AUTH, CP(CFG_REQUEST), SAi2, TSi, TSr} --> <-- HDR, SK {IDr, [CERT,] AUTH, CP(CFG_REPLY), SAr2, TSi, TSr} In all cases, the CP payload MUST be inserted before the SA payload. |
2.19:3 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, never send an unsolicited CFG_REPLY, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.19-3 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-2.19-3) | In variations of the protocol where there are multiple IKE_AUTH exchanges, the CP payloads MUST be inserted in the messages containing the SA payloads. |
2.19:5 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, emit FAILED_CP_REQUIRED when a required CP is absent, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.19-5 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-2.19-5) | The responder MUST NOT send a CFG_REPLY without having first received a CP(CFG_REQUEST) from the initiator, because we do not want the IRAS to perform an unnecessary configuration lookup if the IRAC cannot process the REPLY. |
2.19:6 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, the SA state after a failed configuration exchange, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.19-6 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-2.19-6) | In the case where the IRAS's configuration requires that CP be used for a given identity IDi, but IRAC has failed to send a CP(CFG_REQUEST), IRAS MUST fail the request, and terminate the Child SA creation with a FAILED_CP_REQUIRED error. |
2.22:1 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, IPComp association negotiation, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.22-1 in plan/spec-ipsec-ipcomp.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/spec-ipsec-ipcomp.md as RFC7296-2.22-1) | These payloads MUST NOT occur in messages that do not contain SA payloads. |
2.22:2 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, IPComp CPI handling, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-2.22-2 in plan/spec-ipsec-ipcomp.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/spec-ipsec-ipcomp.md as RFC7296-2.22-2) | Although there has been discussion of allowing multiple compression algorithms to be accepted and to have different compression algorithms available for the two directions of a Child SA, implementations of this specification MUST NOT accept an IPComp algorithm that was not proposed, MUST NOT accept more than one, and MUST NOT compress using an algorithm other than one proposed and accepted in the setup of the Child SA. |
2.23:6 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
An applicability statement, not an obligation: it tells the reader that the MUSTs in the bullet list below bind only implementations that support NAT traversal, which the preceding sentence calls optional. | In this section only, requirements listed as MUST apply only to implementations supporting NAT traversal. |
3.1:5 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
The sentence sets the major version for implementations of previous IKE versions and of ISAKMP. Ze implements IKEv2 only, so the obligation binds an IKEv1 or ISAKMP implementation. The producer that would act as it if ze did is the IKE header codec, which writes and reads the version octet: `MajorVersion` (`internal/component/ike/wire/header.go`) is encoded at byte 17 and ze sets it for IKEv2 alone, so no IKEv1 or ISAKMP exchange exists here to carry the obligation. | Implementations based on previous versions of IKE and ISAKMP MUST set the major version to 1. |
3.3.4:1 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The keywords name the suite specifications that were removed from this document. The sentence records an editorial change and binds no implementation. | The specification of suites that MUST and SHOULD be supported for interoperability has been removed from this document because they are likely to change more rapidly than this document evolves. |
3.3.4:5 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The sentence removes an expectation: a suite that another document makes mandatory to implement need not sit in local policy. The keyword names that other document's obligation, not one this sentence imposes. | Note that cryptographic suites that MUST be implemented need not be configured as acceptable to local policy. |
3.3.6:2 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The sentence narrows the same selection rule to the proposal level. Site 3.3.6:1 maps RFC7296-2.7-1, which already binds the responder to one proposal or a rejection of all of them. | If there are multiple proposals, the responder MUST choose a single proposal. |
3.3.6:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The sentence narrows the same selection rule to one transform per Transform Type. Section 2.7 states it as the accepted suite containing exactly one transform of each type, which RFC7296-2.7-1 captures. | If the selected proposal has multiple transforms with the same type, the responder MUST choose a single one. |
3.10.1:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The paragraph on status types repeats the ignore rule of the preceding paragraph. Site 3.10.1:2 maps RFC7296-3.10.1-2, whose text already covers an unrecognized status type in a request or a response. | Notify payloads with status types MAY be added to any message and MUST be ignored if not recognized. |
3.11:2 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The mixing ban is the same obligation as the preceding sentence, written as a prohibition. Site 3.11:1 maps RFC7296-3.11-1, whose text carries both sentences. | Mixing of protocol identifiers MUST NOT be performed in the Delete payload. |
3.13.1:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
ANY ports means start port 0 and end port 65535, which is the port encoding the two field descriptions already state. Site 3.13.1:1 maps RFC7296-3.13.1-1 and site 3.13.1:2 maps RFC7296-3.13.1-2. | Systems that are complying with [IPSECARCH] that wish to indicate "ANY" ports MUST set the start port to 0 and the end port to 65535; note that according to [IPSECARCH], "ANY" includes "OPAQUE". |
3.15.1:2 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, at most one netmask, and only beside an INTERNAL_IP4_ADDRESS, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-3.15.1-1 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-3.15.1-1) | Only one netmask is allowed in the request and response messages (e.g., 255.255.255.0), and it MUST be used only with an INTERNAL_IP4_ADDRESS attribute. |
3.15.1:4 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, a SUPPORTED_ATTRIBUTES request carries zero length, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-3.15.1-3 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-3.15.1-3) | o SUPPORTED_ATTRIBUTES - When used within a Request, this attribute MUST be zero-length and specifies a query to the responder to reply back with all of the attributes that it supports. |
3.15.1:5 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, ignore attributes the responder does not recognize, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-3.15.1-4 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-3.15.1-4) | Unrecognized or unsupported attributes MUST be ignored in both requests and responses. |
4:1 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The opening sentence of Section 4, which describes what the section contains. Its capitalised words sit inside the quoted phrase "MUST support", naming the class of requirements that follow. It binds nobody. | In order to assure that all implementations of IKEv2 can interoperate, there are "MUST support" requirements in addition to those listed elsewhere. |
4:8 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, parse the CFG_REQUEST and recognize the address attribute, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-4-2 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-4-2) | If an implementation supports responding to such requests, it MUST parse the CP payload of type CFG_REQUEST in the first message in the IKE_AUTH exchange and recognize a field of type INTERNAL_IP4_ADDRESS or INTERNAL_IP6_ADDRESS. |
4:9 |
relocated-to-specZe owes it the obligation is real and unbuilt, and a named spec owes it |
The obligation, return a CFG_REPLY carrying an address of the requested type, was moved out of rfc/short/rfc7296.md by owner ruling D-1 (2026-07-31) and is reserved as RFC7296-4-3 in plan/immediate/spec-ipsec-remote-access.md. It is gated at that destination, so nothing is dropped: this site records where the obligation went, and the tripwire reds if that spec or that id disappears. (relocated to plan/immediate/spec-ipsec-remote-access.md as RFC7296-4-3) | If it supports leasing an address of the appropriate type, it MUST return a CP payload of type CFG_REPLY containing an address of the requested type. |
Superseded
No document obsoletes RFC 7296, so its obligations are stated where they were written.