Partial

RFC 5216 - The EAP-TLS Authentication Protocol

Every requirement this repository extracted from RFC 5216, 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

Tested both ways70.2%33 of 47 gated MUSTs

a positive test proves Ze does what the requirement demands and a negative one proves it refuses what the requirement forbids

One polarity plus reason8.5%4 of 47 gated MUSTs

the requirement admits no counter-case, so one polarity plus a recorded reason is the whole proof available for it

One polarity, unexcused0.0%0 of 47 gated MUSTs

one direction is tested, the other is neither tested nor excused, and nothing states which

Partial proof; remaining gap0.0%0 of 47 gated MUSTs

scoped tests exist; the remaining obligation is unmet or unproven, with zero whole-requirement credit

Proven by a recorded break86.1%87 of 101 tagged units

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

Gated MUSTs47of 54 this summary declares

MUST-level requirements the gate HOLDS. A population, not a result: the shares beside it are what says how Ze stands

Out of scope0of 47 gated MUSTs

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

Not applicable0.0%0 of 47 gated MUSTs

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

Met below Ze4.3%2 of 47 gated MUSTs

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

Optional feature declined0.0%0 of 47 gated MUSTs

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

No test at all17.0%8 of 47 gated MUSTs

no test carries the requirement id, whether or not a gap states why

Audit verdicts40of 47 gated MUSTs judged

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 47 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.

CardTone hereWhy 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 bad 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

FieldValue
Public status Partial
Enrolment Enrolled
Requirements 54
Gated MUST-level 47
Not applicable, so out of scope 0
Declared gaps 9
Declared gaps a test demonstrates 0
Gated with no test 0
Nightly-only evidence 0
Test tags 101
Tagged units 101
Recorded audit verdicts 40
Discrimination records 87
Summary rfc/short/rfc5216.md
Requirement shard rfc/requirements/rfc5216.md
RFC text rfc/full/rfc5216.txt

Enrolment

Enrolled: EAP-TLS (RFC 5216, EAP inside IKEv2): 52 rows, 47 of them MUST-level. 11 are MET in both polarities (fragmentation, L-bit, mutual-auth handshake, and all seven Section 2.1.3 termination MUSTs: EAP-Failure answers a peer TLS alert, the authenticator waits for the peer reply after its own alert, that reply is answered with EAP-Failure, the authenticator sends its change_cipher_spec and Finished closing flight before it concludes, the peer replies to the authenticator before it terminates, the peer answers the closing flight with a no-data EAP-Response, and the authenticator answers that with EAP-Success), and 5 carry a single-polarity positive proof (reserved flags, TLS>=1.0 both sides, no cipher-leak, MSK label); no compression (RFC5216-2.4-3) is proven in both polarities since 2026-09-29. RFC5216-2.4-5, the mandatory TLS_RSA_WITH_3DES_EDE_CBC_SHA ciphersuite, is a gap. The 2026-09-21 extraction walk read the document against this checklist and added 27 MUST-level rows it did not carry: the Section 2.1.1 base-case flight and the Section 2.1.2 resumption flight, the six Section 2.1.5 fragment-ACK and Identifier obligations, TLS v1.0 support (2.4-7), the four Section 3 packet-field obligations, the five Section 5.2 certificate naming obligations, and the two Section 5.3 authorization obligations. None of the 27 carries a tagged test, so each is an open gap. The same walk corrected RFC5216-5.3-1 from MUST to SHOULD, which is the level Section 5.3 states for RFC 3280 path validation, and moved the section reference of RFC5216-2.4-1 and RFC5216-2.4-2 to Section 2.1.1, where the two TLS version sentences are written. Handshake harness enabled by the eap deadlock+cert-validation fix (commit 0816c2b74)

What the public ledger says

Status: Partial

What the ledger says is covered
  • Full EAP-TLS handshake as both authenticator (RequireAndVerifyClientCert + ClientCAs) and peer (RootCAs), L/M/S fragmentation with a 64KB reassembly bound and empty-message fragment ACK, and MSK export via the label "client EAP encryption" feeding the IKEv2 AUTH payload
  • certs from the PKI store. Section 2.1.3 termination in both directions: a rejected peer receives the fatal TLS alert in an EAP-Request, the authenticator waits for its EAP-Response and only then sends EAP-Failure, and a peer TLS alert that rejects the authenticator is answered with EAP-Failure in the round that carries it. A peer that rejects the authenticator replies first and reports the cause on the round after. Section 2.1.3 termination on the success path: the authenticator sends its change_cipher_spec and Finished closing flight, the peer answers with a no-data EAP-Response, and the authenticator answers that with EAP-Success. One reachability limit is not a conformance gap and is stated here so no reader assumes otherwise: the Section 2.3 derivation is a crypto/tls ExportKeyingMaterial call, and Go refuses that export on a TLS 1.2 session that did not negotiate the RFC 7627 extended master secret, so a peer such as strongSwan 5.9.14 cannot be authenticated over TLS 1.2 at all. That peer lands on TLS 1.2 by default rather than by limitation, and charon.tls.version_max = 1.3 moves the same build onto the RFC 9190 path that scenario eap-tls13 proves. Ze implements the derivation correctly and reports the refusal with the peer, the negotiated version, RFC 7627 and the operator's answers (eapTLS12ExportRefused, internal/core/eap/eap_tls.go)
  • Go 1.27 removed the GODEBUG setting that once lifted the refusal and offers no replacement, and RFC 9190 covers the TLS 1.3 path, which needs none of it.
What the ledger says remains

RFC5216-2.4-5, the mandatory TLS_RSA_WITH_3DES_EDE_CBC_SHA ciphersuite, is not offered (TLS 1.2+ Go defaults exclude insecure 3DES). The 15 rows the 2026-09-21 extraction walk added were classified the same day under the owner ruling that every MUST is a requirement. Five TLS handshake obligations crypto/tls performs on the tls.Config Ze installs (the resumption ciphersuite, the server_certificate flight, the peer's full and resumed flights, and the server's resumed flight) are proven at that boundary in rfc5216_tls_config_test.go; the server_key_exchange (RFC5216-2.1.1-7) is decided by the crypto/tls default suites and carries a lower-layer annotation. RFC5216-2.1.1-4 is audited wrong: the server does not choose a sessionId for a new session, because crypto/tls, as newTLSMethod configures it, sends an empty ServerHello session_id on a TLS 1.2 full handshake, and its tags prove the session-ticket rule instead. Eight are gaps.

Seven are scheduled: TLS 1.0 support (RFC5216-2.4-7, which RFC 8996 forbids, plan/spec-eap-tls-tls10.md, the owner decides which document governs); the Peer-Id and Server-Id derivation and authorization (RFC5216-5.2-1, RFC5216-5.3-2, RFC5216-5.3-3, plan/immediate/spec-eap-tls-identity-authorization.md); and the certificate naming profile on issuers and verifiers (RFC5216-5.2-2, RFC5216-5.2-3, RFC5216-5.2-4, plan/spec-eap-tls-certificate-profile.md). RFC5216-5.2-5 is structural in crypto/x509 and carries a lower-layer annotation. The 12 rows the same walk added that are now proven in both polarities are the Section 2.1.1 Start and first Response, the six Section 2.1.5 fragment-ACK and Identifier obligations, and the four Section 3 packet-field obligations (rfc5216_flight_rules_test.go and rfc5216_fragment_ack_test.go, internal/core/eap). RFC5216-5.4-2 is no longer among them: the peer re-checks the revocation status of the authenticator certificate once the CHILD_SA gives it a network, over https, and closes the SA when the responder reports it revoked (startServerCertRecheck, internal/component/ike/engine/postauth_revocation.go, reached from runEstablished). It runs whichever TLS version the exchange negotiated, which is what this RFC asks for, and the chain it re-reads is the one the peer accepted (eap.PeerSession.ServerChains). RFC5216-5.4-1 is no longer among them either: checkChainRevocation (internal/core/eap/revocation.go) checks every certificate on each verified chain except the trust anchor against the crl leaf-list its CA publishes, on the authenticator through tls.Config.VerifyConnection and on the peer through serverChainCheck.verifyConnection, and it is proven in both polarities on TLS 1.2, which is the version this RFC governs. The eighth is RFC5216-5.3-5: Section 5.3 asks the server to retrieve the intermediate certificates a path needs (RFC 3280 Section 4.2.2.1, Authority Information Access), and Ze performs no such fetch. What Ze implements is the fallback the same section names for a server unable to retrieve them: the authenticator completes the client chain from the intermediate-certificate list the operator configures (PKI ca entries, never trust anchors) beside the intermediates the peer sends (clientChainVerifier, internal/core/eap/client_chain.go).

Coverage

BucketCountWhat it counts
Positive and negative tests 33 one part of the gated population
Annotated (including scoped evidence) 14 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 requirements47every gated MUST falls in exactly one bucket above

Positive and negative tests (33): RFC5216-3-1, RFC5216-2.4-3, RFC5216-2.4-4, RFC5216-2.1.1-1, RFC5216-2.1.1-2, RFC5216-2.1.5-1, RFC5216-5.4-1, RFC5216-5.4-2, RFC5216-2.1.3-1, RFC5216-2.1.3-3, RFC5216-2.1.3-4, RFC5216-2.1.3-5, RFC5216-2.1.3-6, RFC5216-2.1.3-7, RFC5216-2.1.3-8, RFC5216-2.1.1-3, RFC5216-2.1.1-4, RFC5216-2.1.1-5, RFC5216-2.1.1-6, RFC5216-2.1.1-8, RFC5216-2.1.1-9, RFC5216-2.1.1-10, RFC5216-2.1.2-1, RFC5216-2.1.5-2, RFC5216-2.1.5-3, RFC5216-2.1.5-4, RFC5216-2.1.5-5, RFC5216-2.1.5-6, RFC5216-2.1.5-7, RFC5216-3-3, RFC5216-3-4, RFC5216-3-5, RFC5216-3-6

Annotated (including scoped evidence) (14): RFC5216-3-2, RFC5216-2.4-1, RFC5216-2.4-2, RFC5216-2.4-5, RFC5216-2.3-1, RFC5216-2.1.1-7, RFC5216-2.4-7, RFC5216-5.2-1, RFC5216-5.2-2, RFC5216-5.2-3, RFC5216-5.2-4, RFC5216-5.2-5, RFC5216-5.3-2, RFC5216-5.3-3

Requirements

RequirementLevelSectionTests
RFC5216-3-1The L bit (length included) is set to indicate the presence of the four-octet TLS Message Length field, and MUST be set for the first fragment of a fragmented TLS message or set of messages. (§3, Flags)
MUST 3
RFC5216-3-2Implementations of this specification MUST set the reserved bits to zero (§3, Flags)
MUST 3
negativeno testno negative test

{single-polarity}: the flags byte is assembled only from L/M in nextFragment (and S alone in Start), so no code path can set reserved bits 3-7 and only the positive assertion is reachable (internal/core/eap/eap_tls.go:106, :190)

RFC5216-2.4-1The version offered by the peer MUST correspond to TLS v1.0 or later. (§2.1.1)
MUST 2.1.1
negativeno testno negative test

{single-polarity}: the peer's tls.Config forces MinVersion TLS 1.2, so its ClientHello always offers at least TLS 1.0 and no path can offer lower (internal/core/eap/peer.go:334)

RFC5216-2.4-2The version offered by the server MUST correspond to TLS v1.0 or later. (§2.1.1)
MUST 2.1.1
negativeno testno negative test

{single-polarity}: the server's tls.Config forces MinVersion TLS 1.2, so any ServerHello it emits is at least TLS 1.0 and it never negotiates lower (internal/core/eap/eap_tls.go:167)

RFC5216-2.4-3However, during the EAP-TLS conversation the EAP peer and server MUST NOT request or negotiate compression. (§2.4)
MUST NOT 2.4
RFC5216-2.4-4Since the ciphersuite negotiated within EAP-TLS applies only to the EAP conversation, TLS ciphersuite negotiation MUST NOT be used to negotiate the ciphersuites used to secure data. (§2.4)
MUST NOT 2.4
RFC5216-2.4-5To ensure interoperability, EAP-TLS peers and servers MUST support the TLS [RFC4346] mandatory-to-implement ciphersuite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (§2.4)
MUST 2.4
positiveno testno positive test
negativeno testno negative test

{gap}: the server sets no CipherSuites and requires TLS 1.2+, so it inherits Go's secure defaults which classify 3DES as insecure and do not enable TLS_RSA_WITH_3DES_EDE_CBC_SHA, leaving the RFC's mandatory-to-implement ciphersuite unavailable (internal/core/eap/eap_tls.go:163, peer.go:330)

RFC5216-2.1.1-1If the EAP server sent a certificate_request message in the preceding EAP-Request packet, then unless the peer is configured for privacy (see Section 2.1.4) the peer MUST send, in addition, certificate and certificate_verify messages. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-2The EAP-TLS conversation will then begin, with the peer sending an EAP-Response packet with EAP-Type=EAP-TLS. The data field of that packet will encapsulate one or more TLS records in TLS record layer format, containing a TLS client_hello handshake message. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.5-1As a result, an EAP-TLS implementation MUST provide its own support for fragmentation and reassembly. (§2.1.5)
MUST 2.1.5
RFC5216-5.3-1Since the EAP-TLS server is typically connected to the Internet, it SHOULD support validating the peer certificate using RFC 3280 [RFC3280] compliant path validation (§5.3)
SHOULD 5.3
RFC5216-5.3-4Therefore, the EAP-TLS server SHOULD provide its entire certificate chain minus the root to facilitate certificate validation by the peer. The EAP-TLS peer SHOULD support validating the server certificate using RFC 3280 [RFC3280] compliant path validation. (§5.3)
SHOULD 5.3
RFC5216-5.3-5including the ability to retrieve intermediate certificates that may be necessary to validate the peer certificate. (§5.3)
SHOULD 5.3
positiveno testno positive test
negativeno testno negative test

{gap}: the authenticator performs no Authority Information Access caIssuers retrieval (RFC 3280 Section 4.2.2.1), so it does not retrieve an intermediate the peer left out; it implements only the fallback the next paragraph names for a server unable to retrieve, pre-configuration through the intermediate-certificate list (clientChainVerifier, internal/core/eap/client_chain.go); the four intermediate-pool tests that claimed this row prove only that fallback, and their tags were taken off after the independent audit of 2026-10-18 found the claim wider than the assertions

RFC5216-5.4-1EAP-TLS peer and server implementations MUST support the use of Certificate Revocation Lists (CRLs); for details, see Section 3.3 of [RFC3280]. (§5.4)
MUST 5.4
RFC5216-5.4-2peer implementations MUST also support checking for certificate revocation after authentication completes and network connectivity is available (§5.4)
MUST 5.4
RFC5216-2.1.3-1The EAP Server MUST reply with an EAP-Failure packet since server authentication failure is a terminal condition. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-3To ensure that the peer receives the TLS alert message, the EAP server MUST wait for the peer to reply with an EAP-Response packet. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-4it MAY contain an EAP-Response packet with EAP-Type=EAP-TLS and no data, in which case the EAP-Server MUST send an EAP-Failure packet and terminate the conversation. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-5If the peer authenticates successfully, the EAP server MUST respond with an EAP-Request packet with EAP-Type=EAP-TLS, which includes, in the case of a new TLS session, one or more TLS records containing TLS change_cipher_spec and finished handshake messages. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-6To ensure that the EAP Server receives the TLS alert message, the peer MUST wait for the EAP Server to reply before terminating the conversation. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-7If the EAP server authenticates successfully, the peer MUST send an EAP-Response packet of EAP-Type=EAP-TLS, and no data. (§2.1.3)
MUST 2.1.3
RFC5216-2.1.3-8The EAP Server then MUST respond with an EAP-Success message. (§2.1.3)
MUST 2.1.3
RFC5216-2.3-1Key_Material = TLS-PRF-128(master_secret, "client EAP encryption", client.random || server.random) MSK = Key_Material(0,63) EMSK = Key_Material(64,127) (§2.3)
MUST 2.3
negativeno testno negative test

{single-polarity}: both server and peer export the 64-octet MSK via ExportKeyingMaterial with the exact RFC label 'client EAP encryption', the only key the IKEv2 lower layer consumes (internal/core/eap/eap_tls.go:268, peer.go:381)

RFC5216-2.1.1-3Once having received the peer's Identity, the EAP server MUST respond with an EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type=EAP-TLS, the Start (S) bit set, and no data. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-4If the peer's sessionId is null or unrecognized by the server, the server MUST choose the sessionId to establish a new session. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-5If the session matches the peer's, then the ciphersuite MUST match the one negotiated during the handshake protocol execution that established the session. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-6If the EAP server is not resuming a previously established session, then it MUST include a TLS server_certificate handshake message, and a server_hello_done handshake message MUST be the last handshake message encapsulated in this EAP-Request packet. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-7The certificate message contains a public key certificate chain for either a key exchange public key (such as an RSA or Diffie-Hellman key exchange public key) or a signature public key (such as an RSA or Digital Signature Standard (DSS) signature public key). In the latter case, a TLS server_key_exchange handshake message MUST also be included to allow the key exchange to take place. (§2.1.1)
MUST 2.1.1
positiveno testno positive test
negativeno testno negative test

{lower-layer}: Go crypto/tls; internal/core/eap/eap_tls.go::newTLSMethod sets no CipherSuites, so the default ECDHE suites of crypto/tls decide that a server_key_exchange is written and no value Ze writes chooses it

RFC5216-2.1.1-8If the peer supports EAP-TLS and is configured to use it, it MUST respond to the EAP-Request with an EAP-Response packet of EAP- Type=EAP-TLS. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-9If the preceding server_hello message sent by the EAP server in the preceding EAP-Request packet did not indicate the resumption of a previous session, the data field of this packet MUST encapsulate one or more TLS records containing a TLS client_key_exchange, change_cipher_spec, and finished messages. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.1-10If the preceding server_hello message sent by the EAP server in the preceding EAP-Request packet indicated the resumption of a previous session, then the peer MUST send only the change_cipher_spec and finished handshake messages. (§2.1.1)
MUST 2.1.1
RFC5216-2.1.2-1If the EAP server is resuming a previously established session, then it MUST include only a TLS change_cipher_spec message and a TLS finished handshake message after the server_hello message. (§2.1.2)
MUST 2.1.2
RFC5216-2.1.5-2When an EAP-TLS peer receives an EAP-Request packet with the M bit set, it MUST respond with an EAP-Response with EAP-Type=EAP-TLS and no data. (§2.1.5)
MUST 2.1.5
RFC5216-2.1.5-3The EAP server MUST wait until it receives the EAP-Response before sending another fragment. (§2.1.5)
MUST 2.1.5
RFC5216-2.1.5-4In order to prevent errors in processing of fragments, the EAP server MUST increment the Identifier field for each fragment contained within an EAP-Request, and the peer MUST include this Identifier value in the fragment ACK contained within the EAP-Response. (§2.1.5)
MUST 2.1.5
RFC5216-2.1.5-5Similarly, when the EAP server receives an EAP-Response with the M bit set, it MUST respond with an EAP-Request with EAP-Type=EAP-TLS and no data. (§2.1.5)
MUST 2.1.5
RFC5216-2.1.5-6The EAP peer MUST wait until it receives the EAP-Request before sending another fragment. (§2.1.5)
MUST 2.1.5
RFC5216-2.1.5-7In order to prevent errors in the processing of fragments, the EAP server MUST increment the Identifier value for each fragment ACK contained within an EAP-Request, and the peer MUST include this Identifier value in the subsequent fragment contained within an EAP- Response. (§2.1.5)
MUST 2.1.5
RFC5216-2.4-7EAP-TLS implementations MUST support TLS v1.0. (§2.4)
MUST 2.4
positiveno testno positive test
negativeno testno negative test

{gap}: both roles set MinVersion TLS 1.2 and RFC 8996 forbids TLS 1.0, so the owner decides which document governs; plan/spec-eap-tls-tls10.md

RFC5216-3-3The Identifier field MUST be changed on each Request packet. (§3)
MUST 3
RFC5216-3-4Octets outside the range of the Length field should be treated as Data Link Layer padding and MUST be ignored on reception. (§3)
MUST 3
RFC5216-3-5Implementations of this specification MUST set the reserved bits to zero, and MUST ignore them on reception. (§3)
MUST 3
RFC5216-3-6The Identifier field is one octet and MUST match the Identifier field from the corresponding request. (§3.2)
MUST 3.2
RFC5216-5.2-1Where the subjectAltName field is present in the peer or server certificate, the Peer-Id or Server-Id MUST be set to the contents of the subjectAltName. (§5.2)
MUST 5.2
positiveno testno positive test
negativeno testno negative test

{gap}: eapTLSPeerName reads the subject and never the subjectAltName, and no Server-Id is exported; plan/immediate/spec-eap-tls-identity-authorization.md

RFC5216-5.2-2If subject naming information is present only in the subjectAltName extension of a peer or server certificate, then the subject field MUST be an empty sequence and the subjectAltName extension MUST be critical. (§5.2)
MUST 5.2
positiveno testno positive test
negativeno testno negative test

{gap}: no verifier refuses an empty-subject leaf whose subjectAltName is not critical; plan/spec-eap-tls-certificate-profile.md

RFC5216-5.2-3Conforming implementations generating new certificates with Network Access Identifiers (NAIs) MUST use the rfc822Name in the subject alternative name field to describe such identities. (§5.2)
MUST 5.2
positiveno testno positive test
negativeno testno negative test

{gap}: no Ze issuer takes an NAI to write as an rfc822Name; plan/spec-eap-tls-certificate-profile.md

RFC5216-5.2-4The use of the subject name field to contain an emailAddress Relative Distinguished Name (RDN) is deprecated, and MUST NOT be used. (§5.2)
MUST NOT 5.2
positiveno testno positive test
negativeno testno negative test

{gap}: no verifier refuses a subject carrying an emailAddress RDN; plan/spec-eap-tls-certificate-profile.md

RFC5216-5.2-5Where it is non-empty, the subject name field MUST contain an X.500 distinguished name (DN). (§5.2)
MUST 5.2
positiveno testno positive test
negativeno testno negative test

{lower-layer}: Go crypto/x509; internal/component/pki/ca.go::LoadOrGenerateRoot issues every subject as a pkix.Name and x509.ParseCertificate accepts no other encoding, so no value Ze writes can make a non-empty subject anything but a distinguished name

RFC5216-5.3-2Once a TLS session is established, EAP-TLS peer and server implementations MUST validate that the identities represented in the certificate are appropriate and authorized for use with EAP-TLS. (§5.3)
MUST 5.3
positiveno testno positive test
negativeno testno negative test

{gap}: neither role authorizes the Peer-Id or Server-Id against configuration; plan/immediate/spec-eap-tls-identity-authorization.md

RFC5216-5.3-3When performing this comparison, implementations MUST follow the validation rules specified in Section 3.1 of [RFC2818]. (§5.3)
MUST 5.3
positiveno testno positive test
negativeno testno negative test

{gap}: the peer sets no expected server identity, so no RFC 2818 Section 3.1 comparison runs; plan/immediate/spec-eap-tls-identity-authorization.md

RFC5216-5.4-3EAP-TLS peer and server implementations SHOULD also support the Online Certificate Status Protocol (OCSP) (§5.4)
SHOULD 5.4
positiveno testno positive test
negativeno testno negative test
RFC5216-5.4-4EAP-TLS peers and servers SHOULD implement Certificate Status Request messages (§5.4)
SHOULD 5.4
positiveno testno positive test
negativeno testno negative test
RFC5216-2.4-6EAP-TLS peers and servers SHOULD also support and be able to negotiate the following TLS ciphersuites: TLS_RSA_WITH_RC4_128_SHA [RFC4346] TLS_RSA_WITH_AES_128_CBC_SHA [RFC3268] (§2.4)
SHOULD 2.4
positiveno testno positive test
negativeno testno negative test
RFC5216-2.1.3-2in which case the EAP server MAY allow the EAP-TLS conversation to be restarted, or it MAY contain an EAP-Response packet with EAP-Type=EAP-TLS and no data, in which case the EAP-Server MUST send an EAP-Failure packet and terminate the conversation. It is up to the EAP server whether to allow restarts, and if so, how many times the conversation can be restarted. An EAP Server implementing restart capability SHOULD impose a per-peer limit on the number of restarts, so as to protect against denial-of-service attacks. (§2.1.3)
MAY 2.1.3
positiveno testno positive test
negativeno testno negative test

Gaps and untested MUSTs

RequirementStateReason
RFC5216-2.4-5 To ensure interoperability, EAP-TLS peers and servers MUST support the TLS [RFC4346] mandatory-to-implement ciphersuite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (§2.4) {gap}, no test the server sets no CipherSuites and requires TLS 1.2+, so it inherits Go's secure defaults which classify 3DES as insecure and do not enable TLS_RSA_WITH_3DES_EDE_CBC_SHA, leaving the RFC's mandatory-to-implement ciphersuite unavailable (internal/core/eap/eap_tls.go:163, peer.go:330)
RFC5216-5.3-5 including the ability to retrieve intermediate certificates that may be necessary to validate the peer certificate. (§5.3) {gap} the authenticator performs no Authority Information Access caIssuers retrieval (RFC 3280 Section 4.2.2.1), so it does not retrieve an intermediate the peer left out; it implements only the fallback the next paragraph names for a server unable to retrieve, pre-configuration through the intermediate-certificate list (clientChainVerifier, internal/core/eap/client_chain.go); the four intermediate-pool tests that claimed this row prove only that fallback, and their tags were taken off after the independent audit of 2026-10-18 found the claim wider than the assertions
RFC5216-2.1.1-7 The certificate message contains a public key certificate chain for either a key exchange public key (such as an RSA or Diffie-Hellman key exchange public key) or a signature public key (such as an RSA or Digital Signature Standard (DSS) signature public key). In the latter case, a TLS server_key_exchange handshake message MUST also be included to allow the key exchange to take place. (§2.1.1) no test no test carries this requirement id; annotated {lower-layer}: Go crypto/tls; internal/core/eap/eap_tls.go::newTLSMethod sets no CipherSuites, so the default ECDHE suites of crypto/tls decide that a server_key_exchange is written and no value Ze writes chooses it
RFC5216-2.4-7 EAP-TLS implementations MUST support TLS v1.0. (§2.4) {gap}, no test both roles set MinVersion TLS 1.2 and RFC 8996 forbids TLS 1.0, so the owner decides which document governs; plan/spec-eap-tls-tls10.md
RFC5216-5.2-1 Where the subjectAltName field is present in the peer or server certificate, the Peer-Id or Server-Id MUST be set to the contents of the subjectAltName. (§5.2) {gap}, no test eapTLSPeerName reads the subject and never the subjectAltName, and no Server-Id is exported; plan/immediate/spec-eap-tls-identity-authorization.md
RFC5216-5.2-2 If subject naming information is present only in the subjectAltName extension of a peer or server certificate, then the subject field MUST be an empty sequence and the subjectAltName extension MUST be critical. (§5.2) {gap}, no test no verifier refuses an empty-subject leaf whose subjectAltName is not critical; plan/spec-eap-tls-certificate-profile.md
RFC5216-5.2-3 Conforming implementations generating new certificates with Network Access Identifiers (NAIs) MUST use the rfc822Name in the subject alternative name field to describe such identities. (§5.2) {gap}, no test no Ze issuer takes an NAI to write as an rfc822Name; plan/spec-eap-tls-certificate-profile.md
RFC5216-5.2-4 The use of the subject name field to contain an emailAddress Relative Distinguished Name (RDN) is deprecated, and MUST NOT be used. (§5.2) {gap}, no test no verifier refuses a subject carrying an emailAddress RDN; plan/spec-eap-tls-certificate-profile.md
RFC5216-5.2-5 Where it is non-empty, the subject name field MUST contain an X.500 distinguished name (DN). (§5.2) no test no test carries this requirement id; annotated {lower-layer}: Go crypto/x509; internal/component/pki/ca.go::LoadOrGenerateRoot issues every subject as a pkix.Name and x509.ParseCertificate accepts no other encoding, so no value Ze writes can make a non-empty subject anything but a distinguished name
RFC5216-5.3-2 Once a TLS session is established, EAP-TLS peer and server implementations MUST validate that the identities represented in the certificate are appropriate and authorized for use with EAP-TLS. (§5.3) {gap}, no test neither role authorizes the Peer-Id or Server-Id against configuration; plan/immediate/spec-eap-tls-identity-authorization.md
RFC5216-5.3-3 When performing this comparison, implementations MUST follow the validation rules specified in Section 3.1 of [RFC2818]. (§5.3) {gap}, no test the peer sets no expected server identity, so no RFC 2818 Section 3.1 comparison runs; plan/immediate/spec-eap-tls-identity-authorization.md

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.

RFC5216-3-1

The L bit (length included) is set to indicate the presence of the four-octet TLS Message Length field, and MUST be set for the first fragment of a fragmented TLS message or set of messages. (§3, Flags)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-01 (owner ruling 5, ruling 2 reading). Positive TestTLSFragmenterFirstFragmentHasLength: Ze's first fragment of a multi-fragment message carries L, M and the exact 4-octet TLS Message Length (2000). Negative TestRFC5216FirstFragmentWithoutLengthIsRefused (new, D-8 fix in reassemble): the peer's handleTLSRequest refuses a first fragment with M set and L clear, isolated from a clean state, with an error naming the L bit, no fragment ACK and 0 octets buffered; the same payload with L+M is ACKed as control. Producer checked: the guard fires only when no message is in progress (inExpected 0, inBuf empty), so middle fragments of an L-opened train and unfragmented messages without L pass; shared by authenticator Process and peer. TestTLSFragmenterMiddleAndLastFragmentsHaveNoLength stays tagged negative as supplementary: its prose now states L-only-on-first is Ze's choice, not an RFC ban. All three units hold observed-red revert records.

PolarityTestKind and tierProof state
negative TestTLSFragmenterMiddleAndLastFragmentsHaveNoLength unit/verify revert, verified
negative TestRFC5216FirstFragmentWithoutLengthIsRefused unit/verify revert, verified
positive TestTLSFragmenterFirstFragmentHasLength unit/verify revert, verified

RFC5216-3-2

Implementations of this specification MUST set the reserved bits to zero (§3, Flags)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Single-polarity positive. Forbidden: an emitted flags octet with any of bits 3-7 set. TestTLSFragmentReservedFlagBitsAreZero fatals if the S constant or any flags octet nextFragment produces for first (L+M), middle (M), last and single-fragment (L) sends intersects 0x1F. The only other flags octet sent is the literal 0x00 ACK.

PolarityTestKind and tierProof state
positive TestTLSFragmentReservedFlagBitsAreZero unit/verify unproven

RFC5216-2.4-1

The version offered by the peer MUST correspond to TLS v1.0 or later. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Unchanged after comment-only edits to TestEAPTLSMutualAuthHandshakeSucceeds. Single-polarity positive (row marker): TestRFC5216BothRolesInstallAVersionFloor reads the peer tls.Config tlsClientConfig builds, MinVersion TLS 1.2; the handshake unit asserts the negotiated version >= TLS 1.0. Recorded.

PolarityTestKind and tierProof state
positive TestRFC5216BothRolesInstallAVersionFloor unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified

RFC5216-2.4-2

The version offered by the server MUST correspond to TLS v1.0 or later. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Unchanged after comment-only edits to TestEAPTLSMutualAuthHandshakeSucceeds. Single-polarity positive (row marker): the tls.Config newTLSMethod installs carries MinVersion TLS 1.2; the handshake unit asserts the authenticator's negotiated version >= TLS 1.0. Recorded.

PolarityTestKind and tierProof state
positive TestRFC5216BothRolesInstallAVersionFloor unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified

RFC5216-2.4-3

However, during the EAP-TLS conversation the EAP peer and server MUST NOT request or negotiate compression. (§2.4)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. The weak HandshakeComplete tag on TestEAPTLSMutualAuthHandshakeSucceeds is gone. What remains reads the wire in both polarities, both recorded: the peer's ClientHello offers compression_methods [0] and the ServerHello selects 0 (TestRFC5216NeitherSideNegotiatesCompression); an injected ClientHello offering [1, 0] is answered with null compression (TestRFC5216ServerRefusesTheCompressionAPeerOffers).

PolarityTestKind and tierProof state
negative TestRFC5216ServerRefusesTheCompressionAPeerOffers unit/verify revert, verified
positive TestRFC5216NeitherSideNegotiatesCompression unit/verify revert, verified

RFC5216-2.4-4

Since the ciphersuite negotiated within EAP-TLS applies only to the EAP conversation, TLS ciphersuite negotiation MUST NOT be used to negotiate the ciphersuites used to secure data. (§2.4)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-09-30 (ike-eap judge, R6). The {single-polarity} marker is removed and a genuine negative is held in internal/component/ike/engine: TestRFC5216DataCipherComesFromTheESPProposal runs a real EAP-TLS exchange (Ze as authenticator, TLS 1.3 by Go's default, whose suites are all AEAD), sets EAPSession/EAPMSK on the IKE SA as responder_eap.go does, and createFirstChildSA installs the ESP proposal's aes256/sha256 non-AEAD transform; TestRFC5216TLSSessionDoesNotChooseTheDataCipher has one TLS session authenticate two IKE SAs with different ESP proposals and requires the installed transforms to differ and follow each proposal (aes128/sha512 on the second), so data ciphers taken from or pinned by the TLS session go red. Both carry records on child.go createFirstChildSA. The negotiated TLS version/suite is not asserted in the body (the fixture relies on Go's TLS 1.3 default). HEAD tag on eap TestEAPTLSMutualAuthHandshakeSucceeds is supplementary, holds no record, and its prose ('not reused as the lower-layer key') claims more than its 64-octet-MSK body: rewording is author work; the verdict does not rest on it.

PolarityTestKind and tierProof state
negative TestRFC5216TLSSessionDoesNotChooseTheDataCipher unit/verify revert, verified
positive TestRFC5216DataCipherComesFromTheESPProposal unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified

RFC5216-2.4-5

To ensure interoperability, EAP-TLS peers and servers MUST support the TLS [RFC4346] mandatory-to-implement ciphersuite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (§2.4)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-2.4-5, so no unit is bound to it.

RFC5216-2.1.1-1

If the EAP server sent a certificate_request message in the preceding EAP-Request packet, then unless the peer is configured for privacy (see Section 2.1.4) the peer MUST send, in addition, certificate and certificate_verify messages. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. Re-judged 2026-09-30 after the D-8 peer certificate fix (answerCertificateRequest). D-8 fixed: tlsClientConfig answers every certificate_request through GetClientCertificate (answerCertificateRequest, peer.go), so the peer no longer drops to an empty certificate_list when the request names another CA. Positive: TestRFC5216PeerSendsItsCertificateWhateverTheRequestNames reads the TLS 1.2 peer flight off the wire after a certificate_request naming a CA other than the peer certificate's issuer: a certificate message whose first entry is the configured DER, and a certificate_verify (red before the fix, record on answerCertificateRequest); TestRFC5216PeerFlightAnswersTheCertificateRequest keeps the exact compliant flight. Negative (R1 a, non-compliant form on the wire): TestRFC5216AuthenticatorRefusesAPeerThatSendsNoCertificate configures a TRUSTED client cert, empties the peer's answer after the TLS client starts, asserts the empty certificate_list and absent certificate_verify on the wire, and the authenticator sends no EAP-Success, does not succeed or complete its handshake, and refuses with an error that is not a certificate verification failure. Privacy (Section 2.1.4) is not implemented, so the unless-clause never applies. Every tagged unit carries an observed-red record.

PolarityTestKind and tierProof state
negative TestRFC5216AuthenticatorRefusesAPeerThatSendsNoCertificate unit/verify revert, verified
negative TestEAPTLSAuthenticatorRequiresClientCert unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified
positive TestRFC5216PeerFlightAnswersTheCertificateRequest unit/verify revert, verified
positive TestRFC5216PeerSendsItsCertificateWhateverTheRequestNames unit/verify revert, verified

RFC5216-2.1.1-2

The EAP-TLS conversation will then begin, with the peer sending an EAP-Response packet with EAP-Type=EAP-TLS. The data field of that packet will encapsulate one or more TLS records in TLS record layer format, containing a TLS client_hello handshake message. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the answer to the Start is not an EAP-Response of Type 13, or its data is not a TLS record carrying client_hello. TestEAPTLSPeerFirstResponseCarriesClientHello fatals on Code != CodeResponse or Type != TypeTLS, and assertHandshakeRecord fails unless the TypeData holds a handshake record of type client_hello. Negative: TestEAPTLSPeerStalledClientFailsRatherThanAcknowledging fatals if a peer whose TLS engine produced nothing sends any Response instead of errTLSClientStalled, so an EAP-TLS Response with no client_hello is refused.

PolarityTestKind and tierProof state
negative TestEAPTLSPeerStalledClientFailsRatherThanAcknowledging unit/verify unproven
positive TestEAPTLSPeerFirstResponseCarriesClientHello unit/verify unproven

RFC5216-2.1.5-1

As a result, an EAP-TLS implementation MUST provide its own support for fragmentation and reassembly. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-01 (owner ruling 5). Positive TestTLSFragmenterRoundTrip: a 3000-octet message is split into >=3 fragments and reassembled byte-for-byte. Negatives (inconsistent reassembly is refused): TestRFC5216ReassemblyLongerThanDeclaredIsRefused declares 30, sends 20+20, and the overrunning fragment is refused with 'exceeds declared length', no answer, buffer keeps the 20-octet prefix; TestRFC5216ReassemblyShorterThanDeclaredIsRefused declares 3000 and ends at 1524 (M clear), refused naming '1524 of 3000', no answer, not drained to crypto/tls. Both drive the peer's handleTLSRequest; the authenticator shares reassemble/reassemblyComplete. TestTLSReassemblyRejectsOversized (cap) stays as a supplementary DoS bound. All four units hold observed-red revert records.

PolarityTestKind and tierProof state
negative TestTLSReassemblyRejectsOversized unit/verify revert, verified
negative TestRFC5216ReassemblyLongerThanDeclaredIsRefused unit/verify revert, verified
negative TestRFC5216ReassemblyShorterThanDeclaredIsRefused unit/verify revert, verified
positive TestTLSFragmenterRoundTrip unit/verify revert, verified

RFC5216-5.3-1

Since the EAP-TLS server is typically connected to the Internet, it SHOULD support validating the peer certificate using RFC 3280 [RFC3280] compliant path validation (§5.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-09-30 after the D-8 peer certificate fix (answerCertificateRequest). Server path-validation SHOULD. Positive: a valid peer chain is path-validated and accepted (TestEAPTLSMutualAuthHandshakeSucceeds). Negative no longer confounded: since D-8 the peer sends its untrusted certificate, and TestEAPTLSServerRejectsUntrustedClientChain asserts the authenticator's refusal is a tls.CertificateVerificationError wrapping x509.UnknownAuthorityError whose UnverifiedCertificates[0] is the configured untrusted leaf, besides no EAP-Success and an incomplete handshake; it is distinct from the certless refusal of 2.1.1-1, which asserts NOT a verification error. Records observed red on newTLSMethod for both polarities.

PolarityTestKind and tierProof state
negative TestEAPTLSServerRejectsUntrustedClientChain unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified

RFC5216-5.3-4

Therefore, the EAP-TLS server SHOULD provide its entire certificate chain minus the root to facilitate certificate validation by the peer. The EAP-TLS peer SHOULD support validating the server certificate using RFC 3280 [RFC3280] compliant path validation. (§5.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. Re-judged 2026-09-30 after the D-8 peer certificate fix (answerCertificateRequest). Server clause now exercised with a real intermediate: TestRFC5216ServerSendsItsIntermediateButNotTheRoot configures leaf+intermediate under the peer's root and reads the certificate message off the wire: exactly [leaf, intermediate], the root absent (the root is also the authenticator's ClientCAs anchor, so a server appending its pool would fail), peer validates and reaches EAP-Success. Negative (R1 a): TestRFC5216PeerRefusesAServerChainMissingItsIntermediate puts [leaf] alone on the wire and the peer refuses with x509.UnknownAuthorityError, never concluding. Peer clause also by TestEAPTLSPeerRejectsUntrustedServerChain and TestEAPTLSPeerWithoutCARefusesToStart (record re-observed on the changed startTLSClient). Limit named: Ze sends the chain the operator configures; it does not strip a configured root nor complete a leaf-only configuration, so the minus-the-root property rests on the configured chain.

PolarityTestKind and tierProof state
negative TestEAPTLSPeerRejectsUntrustedServerChain unit/verify revert, verified
negative TestEAPTLSPeerWithoutCARefusesToStart unit/verify revert, verified
negative TestRFC5216PeerRefusesAServerChainMissingItsIntermediate unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified
positive TestRFC5216ServerSendsItsChainWithoutTheRoot unit/verify revert, verified
positive TestRFC5216ServerSendsItsIntermediateButNotTheRoot unit/verify revert, verified

RFC5216-5.3-5

including the ability to retrieve intermediate certificates that may be necessary to validate the peer certificate. (§5.3)

Audit verdict: unimplemented (no code path enforces the requirement), fresh. Re-judged 2026-10-18 (independent auditor, after f6c2374f02). RFC 5216 Section 5.3: "it SHOULD support validating the peer certificate using RFC 3280 [RFC3280] compliant path validation, including the ability to retrieve intermediate certificates that may be necessary to validate the peer certificate. For details, see Section 4.2.2.1 of [RFC3280]." The cited section is Authority Information Access, the fetch. The next paragraph names the alternatives for a server that does NOT meet this: "Where the EAP-TLS server is unable to retrieve intermediate certificates, either it will need to be pre-configured with the necessary intermediate certificates to complete path validation or it will rely on the EAP-TLS peer to provide this information". f6c2374f02 implements the first alternative: the intermediate-certificate list (responder_eap.go eapTLSServerConfig) feeds clientChainVerifier.verify (client_chain.go), which path-validates against ca-certificate roots only, with configured plus peer-sent certificates as Intermediates, clientAuth EKU and the current time, and newTLSMethod (eap_tls.go) runs it in VerifyConnection on TLS 1.2, 1.3 and resumed sessions before checkChainRevocation. The tagged tests prove that alternative well (mutants putting the pool in Roots, dropping EKU, time or revocation, or ignoring the verify error each go red). They do not prove retrieval, because the code performs none: no AIA caIssuers lookup exists in internal/core/eap or internal/component/ike, and verify's own comment says Ze retrieves nothing over the network. Pre-configuration is the RFC's named fallback for a server unable to retrieve, not this SHOULD, so the row stays an implementation gap (a SHOULD deviation, not a defect). The row needs its {gap} annotation restored (naming AIA retrieval absent and pre-configuration implemented), and Support remaining must stop saying RFC5216-5.3-5 is no longer among the gaps.

No test carries RFC5216-5.3-5, so no unit is bound to it.

RFC5216-5.4-1

EAP-TLS peer and server implementations MUST support the use of Certificate Revocation Lists (CRLs); for details, see Section 3.3 of [RFC3280]. (§5.4)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. Server half: a CRL revoking the client certificate refuses the TLS 1.2 exchange, a CRL naming nobody completes. Peer half (new, TestRFC5216PeerRefusesARevokedServerCertificateOverTLS12): a peer CRL revoking the authenticator certificate over TLS 1.2 gives a peer error, no EAP-Success, no MSK; isolated by TestEAPTLS12CompletesWithAnUnrevokedChain, where the peer holds a CRL that revokes nothing and completes. Every tagged unit carries a record.

PolarityTestKind and tierProof state
negative TestEAPTLS12CompletesWithAnUnrevokedChain unit/verify revert, verified
positive TestRFC5216PeerRefusesARevokedServerCertificateOverTLS12 unit/verify revert, verified
positive TestEAPTLS12RefusesARevokedClientCertificate unit/verify revert, verified

RFC5216-5.4-2

peer implementations MUST also support checking for certificate revocation after authentication completes and network connectivity is available (§5.4)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: a peer with no revocation check after authentication. TestPostAuthenticationCheckClosesTheSAWhenTheResponderReportsRevoked fatals if startServerCertRecheck (called from established.go after the exchange) starts no check or reports no verdict when the OCSP responder says revoked; TestPostAuthenticationCheckLeavesTheSAUpWhenTheResponderReportsGood fatals on any verdict when it says good. The eap units prove the accepted TLS 1.2 chain is kept for the check and none is published on a refused handshake. The first unit's name claims the SA closes; it asserts only the verdict.

PolarityTestKind and tierProof state
negative TestPostAuthenticationCheckLeavesTheSAUpWhenTheResponderReportsGood unit/verify revert, verified
negative TestEAPTLSPeerPublishesNoChainWhenTheHandshakeRefusedIt unit/verify revert, verified
positive TestPostAuthenticationCheckClosesTheSAWhenTheResponderReportsRevoked unit/verify revert, verified
positive TestEAPTLS12PeerKeepsTheChainItAcceptedForTheLaterCheck unit/verify revert, verified

RFC5216-2.1.3-1

The EAP Server MUST reply with an EAP-Failure packet since server authentication failure is a terminal condition. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the server answering the peer's alert with anything but EAP-Failure, or later than the next packet. TestRFC5216ServerRepliesEAPFailureToPeerAlert fatals if no Failure is sent, errors on any Success, and errors unless failureAt == alertAt+1. Negative: TestRFC5216ServerSendsNoEAPFailureWhenBothSidesAuthenticate errors if a mutually authenticated conversation draws any Failure.

PolarityTestKind and tierProof state
negative TestRFC5216ServerSendsNoEAPFailureWhenBothSidesAuthenticate unit/verify unproven
positive TestRFC5216ServerRepliesEAPFailureToPeerAlert unit/verify unproven

RFC5216-2.1.3-3

To ensure that the peer receives the TLS alert message, the EAP server MUST wait for the peer to reply with an EAP-Response packet. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the server concluding (EAP-Failure) on the round it sends its alert, instead of waiting for the peer's Response. alertFlight fatals if the round that records the cause carries CodeFailure, TestEAPTLSAuthenticatorSendsTheAlertBeforeItReportsTheFailure errors unless that round is an EAP-Request with a TLS alert record, and only the later Response draws the Failure. Negative: TestEAPTLSAuthenticatorReportsTheFailureWithNoAlertToSend fatals if a failure with no alert to send reports no error, so the wait is bound to an alert.

PolarityTestKind and tierProof state
negative TestEAPTLSAuthenticatorReportsTheFailureWithNoAlertToSend unit/verify unproven
positive TestEAPTLSAuthenticatorSendsTheAlertBeforeItReportsTheFailure unit/verify revert, verified

RFC5216-2.1.3-4

it MAY contain an EAP-Response packet with EAP-Type=EAP-TLS and no data, in which case the EAP-Server MUST send an EAP-Failure packet and terminate the conversation. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. Both clauses asserted: the no-data Response after the authenticator's alert draws EAP-Failure, and later Responses (same one, Identifiers at and after the Failure's) draw nothing with Succeeded false; the alert is on the wire before EAP-Failure. Control negative: a mutually authenticated exchange sends no EAP-Failure and reaches EAP-Success, so the Failure answers the rejection only. All units recorded.

PolarityTestKind and tierProof state
negative TestRFC5216ServerSendsNoEAPFailureWhenBothSidesAuthenticate unit/verify revert, verified
positive TestEAPTLSAuthenticatorSendsTheAlertBeforeItReportsTheFailure unit/verify revert, verified
positive TestEAPTLSSessionPutsTheAlertOnTheWireBeforeEAPFailure unit/verify revert, verified
positive TestRFC5216AuthenticatorEndsTheConversationAfterItsFailure unit/verify revert, verified

RFC5216-2.1.3-5

If the peer authenticates successfully, the EAP server MUST respond with an EAP-Request packet with EAP-Type=EAP-TLS, which includes, in the case of a new TLS session, one or more TLS records containing TLS change_cipher_spec and finished handshake messages. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the packet before EAP-Success is not an EAP-TLS Request carrying change_cipher_spec then the Finished handshake record, or a rejected peer receives that flight. TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess fatals on a non-Request/non-TLS packet or a bare ACK there, errors unless record types are [change_cipher_spec, handshake], and requires equal non-zero MSKs. Negative: TestRFC5216NoClosingFlightOrSuccessWhenThePeerIsRejected errors on any change_cipher_spec record sent to a rejected peer.

PolarityTestKind and tierProof state
negative TestRFC5216NoClosingFlightOrSuccessWhenThePeerIsRejected unit/verify unproven
positive TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess unit/verify unproven

RFC5216-2.1.3-6

To ensure that the EAP Server receives the TLS alert message, the peer MUST wait for the EAP Server to reply before terminating the conversation. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the peer terminating on the round it discovers the failure, before the server replies. TestRFC5216PeerRepliesBeforeItTerminates fatals if that round returns Err or no Response, errors if the Response is a bare ACK rather than the alert, and requires the error only from the round that processes the server's EAP-Failure. Negative: TestRFC5216PeerDoesNotWaitWhenItSentNothing errors if a peer that sent nothing parks its error or sends a Response.

PolarityTestKind and tierProof state
negative TestRFC5216PeerDoesNotWaitWhenItSentNothing unit/verify unproven
positive TestRFC5216PeerRepliesBeforeItTerminates unit/verify unproven

RFC5216-2.1.3-7

If the EAP server authenticates successfully, the peer MUST send an EAP-Response packet of EAP-Type=EAP-TLS, and no data. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the peer answering the server's closing flight with anything but a no-data EAP-TLS Response. TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess errors unless bareEAPTLSResponse(peerSent[successAt-1]). Negative: TestRFC5216PeerSendsItsAlertRatherThanTheNoDataResponse errors if a peer refusing the server sends the no-data Response as its last packet.

PolarityTestKind and tierProof state
negative TestRFC5216PeerSendsItsAlertRatherThanTheNoDataResponse unit/verify unproven
positive TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess unit/verify unproven

RFC5216-2.1.3-8

The EAP Server then MUST respond with an EAP-Success message. (§2.1.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the server answering the peer's no-data Response with anything but EAP-Success. TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess errors unless serverSent[successAt].Code == CodeSuccess directly after that Response. Negative: TestRFC5216NoClosingFlightOrSuccessWhenThePeerIsRejected errors on any Success to a rejected peer.

PolarityTestKind and tierProof state
negative TestRFC5216NoClosingFlightOrSuccessWhenThePeerIsRejected unit/verify unproven
positive TestRFC5216SuccessfulTerminationSendsFlightAckThenSuccess unit/verify unproven

RFC5216-2.3-1

Key_Material = TLS-PRF-128(master_secret, "client EAP encryption", client.random || server.random) MSK = Key_Material(0,63) EMSK = Key_Material(64,127) (§2.3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Unchanged after comment-only edits. Single-polarity positive (row marker): with the literal label 'client EAP encryption' and the 128-octet export read from the TLS session, the authenticator MSK equals octets 0-63 and the EMSK 64-127 (TLS 1.2); MSKs identical on both ends. Recorded.

PolarityTestKind and tierProof state
positive TestRFC3748EAPTLSExportsASixtyFourOctetEMSK unit/verify revert, verified
positive TestEAPTLSMutualAuthHandshakeSucceeds unit/verify revert, verified
positive TestRFC5216MSKIsTheExportUnderTheRFCLabel unit/verify revert, verified

RFC5216-2.1.1-3

Once having received the peer's Identity, the EAP server MUST respond with an EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type=EAP-TLS, the Start (S) bit set, and no data. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: after the Identity the server sends anything but a Request of Type 13 with only the S flag, or sends a Start before an Identity. TestRFC5216StartAnswersTheIdentityResponse fatals on Code != CodeRequest, Type != TypeTLS, or TypeData != {S}; TestRFC5216NoStartBeforeTheIdentityIsReceived fatals if Begin opens with an EAP-TLS packet or a stale Identity Response draws any packet.

PolarityTestKind and tierProof state
negative TestRFC5216NoStartBeforeTheIdentityIsReceived unit/verify revert, verified
positive TestRFC5216StartAnswersTheIdentityResponse unit/verify revert, verified

RFC5216-2.1.1-4

If the peer's sessionId is null or unrecognized by the server, the server MUST choose the sessionId to establish a new session. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 53c17be5e3. RFC 5216 Section 2.1.1: 'If the peer's sessionId is null or unrecognized by the server, the server MUST choose the sessionId to establish a new session.' Producer: the patched GOROOT doFullHandshake (internal/le/go/stdpatch/patches/crypto-tls-server-session-id.patch) writes a fresh 32-octet session_id when the TLS 1.2 full handshake issues no ticket, and eap_tls.go::tls12WithoutTickets disables tickets for every handshake negotiatesTLS13 classifies as TLS 1.2. UNRECOGNIZED half: rfc5216_session_id_test.go::TestRFC5216TLS12FullHandshakeServerHelloSessionID offers ze's peer's non-empty random id and requires a 32-octet ServerHello session_id differing from it, no SessionTicket extension and no NewSessionTicket. NULL half: TestRFC5216TLS12NullSessionIDServerChooses rewrites the TLS 1.2 ClientHello to an empty session_id (asserted), replays it at two fresh authenticators and requires each ServerHello to carry a 32-octet id, no ticket, and the two ids to differ. Its recorded break is a panic in tls12WithoutTickets, which shows reachability only, so the auditor ran targeted mutants through go test overlays: a patched doFullHandshake that chooses an id only when the client offered one ('!ticketSupported && len(clientHello.sessionId) > 0') leaves the unrecognized-id test green and turns the null-id test red on 'session_id is 0 octets'; tls12WithoutTickets without SessionTicketsDisabled turns both red. Limit: the null-id ClientHello still carries the SessionTicket extension; the null-id ClientHello without it is not sent.

PolarityTestKind and tierProof state
negative TestRFC5216TLS12FullHandshakeServerHelloSessionID unit/verify revert, verified
positive TestRFC5216TLS12FullHandshakeServerHelloSessionID unit/verify revert, verified
positive TestRFC5216TLS12NullSessionIDServerChooses unit/verify revert, verified

RFC5216-2.1.1-5

If the session matches the peer's, then the ciphersuite MUST match the one negotiated during the handshake protocol execution that established the session. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 56e67411be, where the authenticator's GetConfigForClient (eap_tls.go) answers every handshake negotiatesTLS13 classifies as TLS 1.2 with tls12WithoutTickets, so ze issues no TLS 1.2 ticket, while UnwrapSession redeemTLS13Only/refuseResumption (resumption.go) still refuses a TLS 1.2 session. Section 2.1.1 'If the session matches the peer's, then the ciphersuite MUST match' binds the resuming server. TestRFC5216ResumedFlightsCarryOnlyChangeCipherSpecAndFinished mints and resumes a TLS 1.2 session on a stock-resumption TEST server (stockTLS12Resumption) only to give the peer a live ticket encrypted under ze's own ticket keys; the suite-equality check there is a harness check on that test server and proves nothing about ze. The ze assertion is the last attempt, run with ze's unmodified authenticator config (tune nil): offered that ticket it does not resume and answers a full handshake (certificate, no change_cipher_spec). Ze therefore never matches a TLS 1.2 session, so no matched-session ciphersuite arises, and any TLS 1.2 resumption goes red. The test-server ticket does not weaken this: the subject of the assertion is ze's own authenticator and the input is the strongest one (a ticket ze's keys decrypt). Negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights: UnwrapSession answers no session at TLS 1.2 (on and off) and redeems at TLS 1.3, so the refusal is not vacuous.

PolarityTestKind and tierProof state
negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights unit/verify revert, verified
positive TestRFC5216ResumedFlightsCarryOnlyChangeCipherSpecAndFinished unit/verify revert, verified
positive TestRFC5216TLSConfigBothRolesInstallWhatTheFlightsCarry unit/verify revert, verified

RFC5216-2.1.1-6

If the EAP server is not resuming a previously established session, then it MUST include a TLS server_certificate handshake message, and a server_hello_done handshake message MUST be the last handshake message encapsulated in this EAP-Request packet. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 56e67411be, where the authenticator's GetConfigForClient (eap_tls.go) answers every handshake negotiatesTLS13 classifies as TLS 1.2 with tls12WithoutTickets, so ze issues no TLS 1.2 ticket, while UnwrapSession redeemTLS13Only/refuseResumption (resumption.go) still refuses a TLS 1.2 session. Units changed only by withdrawal of the 2.1.1-4 tag lines. TestRFC5216ServerFlightCarriesItsCertificateAndEndsWithServerHelloDone requires the authenticator's first TLS 1.2 flight to carry a certificate and end with server_hello_done; the negative refuses a config with an unparsable certificate. Both polarities hold.

PolarityTestKind and tierProof state
negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights unit/verify revert, verified
positive TestRFC5216ServerFlightCarriesItsCertificateAndEndsWithServerHelloDone unit/verify revert, verified
positive TestRFC5216TLSConfigBothRolesInstallWhatTheFlightsCarry unit/verify revert, verified

RFC5216-2.1.1-7

The certificate message contains a public key certificate chain for either a key exchange public key (such as an RSA or Diffie-Hellman key exchange public key) or a signature public key (such as an RSA or Digital Signature Standard (DSS) signature public key). In the latter case, a TLS server_key_exchange handshake message MUST also be included to allow the key exchange to take place. (§2.1.1)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-2.1.1-7, so no unit is bound to it.

RFC5216-2.1.1-8

If the peer supports EAP-TLS and is configured to use it, it MUST respond to the EAP-Request with an EAP-Response packet of EAP- Type=EAP-TLS. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: a peer configured for EAP-TLS answering the EAP-TLS Request with anything but an EAP-TLS Response (a Nak, another type). TestRFC5216ConfiguredPeerAnswersEAPTLSWithEAPTLS fatals on Code != CodeResponse or Type != TypeTLS and on TypeData without a handshake record. Negative for the condition: TestRFC5216PeerNotConfiguredForEAPTLSDoesNotAnswerWithEAPTLS fatals if an MS-CHAPv2 peer answers with Type 13 and wantLegacyNak requires the Nak.

PolarityTestKind and tierProof state
negative TestRFC5216PeerNotConfiguredForEAPTLSDoesNotAnswerWithEAPTLS unit/verify revert, verified
positive TestRFC5216ConfiguredPeerAnswersEAPTLSWithEAPTLS unit/verify revert, verified

RFC5216-2.1.1-9

If the preceding server_hello message sent by the EAP server in the preceding EAP-Request packet did not indicate the resumption of a previous session, the data field of this packet MUST encapsulate one or more TLS records containing a TLS client_key_exchange, change_cipher_spec, and finished messages. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 56e67411be, where the authenticator's GetConfigForClient (eap_tls.go) answers every handshake negotiatesTLS13 classifies as TLS 1.2 with tls12WithoutTickets, so ze issues no TLS 1.2 ticket, while UnwrapSession redeemTLS13Only/refuseResumption (resumption.go) still refuses a TLS 1.2 session. Units changed only by withdrawal of the 2.1.1-4 tag lines. TestRFC5216PeerFlightAnswersTheCertificateRequest requires ze's peer, after a non-resuming server_hello, to send certificate, client_key_exchange, certificate_verify, then change_cipher_spec and exactly one sealed handshake record (finished). The config negative (no session cache with resumption off) is weaker but the positive asserts the exact flight.

PolarityTestKind and tierProof state
negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights unit/verify revert, verified
positive TestRFC5216PeerFlightAnswersTheCertificateRequest unit/verify revert, verified
positive TestRFC5216TLSConfigBothRolesInstallWhatTheFlightsCarry unit/verify revert, verified

RFC5216-2.1.1-10

If the preceding server_hello message sent by the EAP server in the preceding EAP-Request packet indicated the resumption of a previous session, then the peer MUST send only the change_cipher_spec and finished handshake messages. (§2.1.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 56e67411be, where the authenticator's GetConfigForClient (eap_tls.go) answers every handshake negotiatesTLS13 classifies as TLS 1.2 with tls12WithoutTickets, so ze issues no TLS 1.2 ticket, while UnwrapSession redeemTLS13Only/refuseResumption (resumption.go) still refuses a TLS 1.2 session. The obligation binds ze's PEER. TestRFC5216ResumedFlightsCarryOnlyChangeCipherSpecAndFinished resumes against a TEST server (stockTLS12Resumption: ze's config with GetConfigForClient and UnwrapSession removed, i.e. stock crypto/tls), which is the counterpart, not the subject, and is needed because ze's authenticator never resumes TLS 1.2. It requires peer.Resumed() and that ze's peer answers the resuming server_hello with no plaintext handshake message, change_cipher_spec and one sealed record. A peer that sent client_key_exchange or certificate goes red. The test server does not weaken the proof of ze's own behaviour.

PolarityTestKind and tierProof state
negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights unit/verify revert, verified
positive TestRFC5216ResumedFlightsCarryOnlyChangeCipherSpecAndFinished unit/verify revert, verified
positive TestRFC5216TLSConfigBothRolesInstallWhatTheFlightsCarry unit/verify revert, verified

RFC5216-2.1.2-1

If the EAP server is resuming a previously established session, then it MUST include only a TLS change_cipher_spec message and a TLS finished handshake message after the server_hello message. (§2.1.2)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-14 (independent auditor) after 56e67411be, where the authenticator's GetConfigForClient (eap_tls.go) answers every handshake negotiatesTLS13 classifies as TLS 1.2 with tls12WithoutTickets, so ze issues no TLS 1.2 ticket, while UnwrapSession redeemTLS13Only/refuseResumption (resumption.go) still refuses a TLS 1.2 session. Section 2.1.2: 'If the EAP server is resuming a previously established session, then it MUST include only a TLS change_cipher_spec message and a TLS finished handshake message after the server_hello message.' TestRFC5216AuthenticatorAnswersATLS12TicketWithAFullHandshake mints the TLS 1.2 ticket on a TEST server (issueTLS12Tickets: ze's config with GetConfigForClient removed, same Resumption store and ticket keys) because ze issues none, then offers it to ze's unmodified authenticator (tune nil); ticketedTLS12Attempt fails unless the ClientHello really offers the ticket. Ze must not resume and its flight must be the full one (certificate, server_hello_done last, no change_cipher_spec). The precondition 'is resuming' therefore never holds for TLS 1.2 in ze, and any TLS 1.2 resumption goes red. The minted ticket is a fixture input, not the subject, so the test still proves ze's own behaviour; it proves compliance by non-resumption, not the resumed flight's content (TLS 1.3 resumption is RFC 9190's). Negative: UnwrapSession refuses TLS 1.2 on and off and redeems TLS 1.3.

PolarityTestKind and tierProof state
negative TestRFC5216TLSConfigRefusesWhatWouldBreakTheFlights unit/verify revert, verified
positive TestRFC5216AuthenticatorAnswersATLS12TicketWithAFullHandshake unit/verify revert, verified
positive TestRFC5216TLSConfigBothRolesInstallWhatTheFlightsCarry unit/verify revert, verified

RFC5216-2.1.5-2

When an EAP-TLS peer receives an EAP-Request packet with the M bit set, it MUST respond with an EAP-Response with EAP-Type=EAP-TLS and no data. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the peer answering an M-set Request with data or with anything but an EAP-TLS Response. TestRFC5216PeerAcksEachServerFragmentWithNoData errors unless every M-set Request is answered by bareEAPTLSResponse, and errors if the last fragment (M clear) draws the no-data ACK instead of the TLS flight; driveFragmentedFlight fatals unless both sides fragment and the MSKs match.

PolarityTestKind and tierProof state
negative TestRFC5216PeerAcksEachServerFragmentWithNoData unit/verify revert, verified
positive TestRFC5216PeerAcksEachServerFragmentWithNoData unit/verify revert, verified

RFC5216-2.1.5-3

The EAP server MUST wait until it receives the EAP-Response before sending another fragment. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the server sending another fragment before the ACK for the current one arrives. driveFragmentedFlight feeds a Response carrying the previous Identifier after every server fragment and fatals if it draws any packet or moves outOffset; TestRFC5216ServerSendsTheNextFragmentOnlyInAnswerToTheAck fatals unless the packet after each fragment is the continuation Request carrying data with neither S nor L.

PolarityTestKind and tierProof state
negative TestRFC5216ServerSendsTheNextFragmentOnlyInAnswerToTheAck unit/verify revert, verified
positive TestRFC5216ServerSendsTheNextFragmentOnlyInAnswerToTheAck unit/verify revert, verified

RFC5216-2.1.5-4

In order to prevent errors in processing of fragments, the EAP server MUST increment the Identifier field for each fragment contained within an EAP-Request, and the peer MUST include this Identifier value in the fragment ACK contained within the EAP-Response. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Clause 1 forbidden: a fragment Request whose Identifier is not the previous plus one; TestRFC5216ServerFragmentIdentifiersIncrementAndTheAckEchoesThem errors on req.Identifier != prev+1. Clause 2 forbidden: an ACK carrying another Identifier; the same test errors on ack.Identifier != req.Identifier, and driveFragmentedFlight fatals if a stale-Identifier ACK draws a packet.

PolarityTestKind and tierProof state
negative TestRFC5216ServerFragmentIdentifiersIncrementAndTheAckEchoesThem unit/verify revert, verified
positive TestRFC5216ServerFragmentIdentifiersIncrementAndTheAckEchoesThem unit/verify revert, verified

RFC5216-2.1.5-5

Similarly, when the EAP server receives an EAP-Response with the M bit set, it MUST respond with an EAP-Request with EAP-Type=EAP-TLS and no data. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the server answering an M-set Response with data or with a non-EAP-TLS Request. TestRFC5216ServerAcksEachPeerFragmentWithNoData errors unless each M-set Response is followed by a Request of Type 13 with TypeData exactly 0x00, and errors if the peer's last fragment is answered with an ACK instead of the closing flight.

PolarityTestKind and tierProof state
negative TestRFC5216ServerAcksEachPeerFragmentWithNoData unit/verify revert, verified
positive TestRFC5216ServerAcksEachPeerFragmentWithNoData unit/verify revert, verified

RFC5216-2.1.5-6

The EAP peer MUST wait until it receives the EAP-Request before sending another fragment. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: the peer sending its next fragment before an EAP-Request arrives. driveFragmentedFlight feeds the peer an undefined-Code packet after each of its fragments and fatals if probe.Response != nil or peer.outOffset moves; TestRFC5216PeerSendsTheNextFragmentOnlyInAnswerToTheAck fatals unless the packet after each fragment is a continuation Response carrying TLS data without L.

PolarityTestKind and tierProof state
negative TestRFC5216PeerSendsTheNextFragmentOnlyInAnswerToTheAck unit/verify revert, verified
positive TestRFC5216PeerSendsTheNextFragmentOnlyInAnswerToTheAck unit/verify revert, verified

RFC5216-2.1.5-7

In order to prevent errors in the processing of fragments, the EAP server MUST increment the Identifier value for each fragment ACK contained within an EAP-Request, and the peer MUST include this Identifier value in the subsequent fragment contained within an EAP- Response. (§2.1.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Clause 1 forbidden: an ACK Identifier that is not the previous Request plus one; TestRFC5216ServerAckIdentifiersIncrementAndTheNextFragmentEchoesThem errors on ack.Identifier != serverSent[i].Identifier+1. Clause 2 forbidden: the peer fragment after an ACK carries another Identifier; the same test errors on next.Identifier != ack.Identifier, and driveFragmentedFlight fatals if the authenticator accepts a fragment re-numbered with a stale Identifier.

PolarityTestKind and tierProof state
negative TestRFC5216ServerAckIdentifiersIncrementAndTheNextFragmentEchoesThem unit/verify revert, verified
positive TestRFC5216ServerAckIdentifiersIncrementAndTheNextFragmentEchoesThem unit/verify revert, verified

RFC5216-2.4-7

EAP-TLS implementations MUST support TLS v1.0. (§2.4)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-2.4-7, so no unit is bound to it.

RFC5216-3-3

The Identifier field MUST be changed on each Request packet. (§3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: a Request that repeats the Identifier of the packet before it. TestRFC5216IdentifierChangesOnEveryRequest errors on cur.Identifier == prev.Identifier for every Request of a full TLS 1.2 conversation and fatals if fewer than 3 Requests ran; the negative pins that EAP-Success (not a Request) repeats the answered Identifier.

PolarityTestKind and tierProof state
negative TestRFC5216IdentifierChangesOnEveryRequest unit/verify revert, verified
positive TestRFC5216IdentifierChangesOnEveryRequest unit/verify revert, verified

RFC5216-3-4

Octets outside the range of the Length field should be treated as Data Link Layer padding and MUST be ignored on reception. (§3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: octets past the Length field read as packet data. TestRFC5216PaddingPastTheLengthIsIgnored decodes a packet with seven padding octets shaped like flags and a TLS record header and errors if TypeData differs from the unpadded TypeData, if its length exceeds Length less 5, or if the padding bytes appear inside TypeData; the unpadded decode is the positive.

PolarityTestKind and tierProof state
negative TestRFC5216PaddingPastTheLengthIsIgnored unit/verify revert, verified
positive TestRFC5216PaddingPastTheLengthIsIgnored unit/verify revert, verified

RFC5216-3-5

Implementations of this specification MUST set the reserved bits to zero, and MUST ignore them on reception. (§3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-12 (independent auditor) after 37dbe54095, where the authenticator with resumption on installs redeemTLS13Only (resumption.go), which refuses every TLS 1.2 ticket. This unit is byte-identical; the file around it changed. Its helpers (tls12Exchange, fullTLS12Flights) gained a tune argument passed as nil to driveTunedEAPTLSFlight, which driveEAPTLSFlight itself calls with nil, and fresh stores offer no ticket, so the producer change never runs here. Verdict stands. Set clause: TestRFC5216SendersWriteZeroReservedFlagBits reads the flags octet of every EAP-TLS packet both roles sent in a full TLS 1.2 conversation and fails on any of bits 0x1f. Reception clause: all five reserved bits set on a Start and on a whole client_hello are ignored by peer and authenticator. Every tagged unit carries a record.

PolarityTestKind and tierProof state
negative TestRFC5216ReservedFlagBitsAreIgnoredOnReception unit/verify revert, verified
positive TestRFC5216SendersWriteZeroReservedFlagBits unit/verify revert, verified
positive TestRFC5216ReservedFlagBitsAreIgnoredOnReception unit/verify revert, verified

RFC5216-3-6

The Identifier field is one octet and MUST match the Identifier field from the corresponding request. (§3.2)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden: a Response whose Identifier differs from the Request it answers. TestRFC5216ResponseIdentifierMatchesTheRequest errors on res.Identifier != serverSent[i].Identifier over a full conversation; TestRFC5216ResponseIdentifierIsCopiedNotCounted fatals if Requests 0x80 then 0x05 are not answered 0x80 then 0x05, which refuses a peer that counts its own Identifiers.

PolarityTestKind and tierProof state
negative TestRFC5216ResponseIdentifierIsCopiedNotCounted unit/verify revert, verified
positive TestRFC5216ResponseIdentifierMatchesTheRequest unit/verify revert, verified

RFC5216-5.2-1

Where the subjectAltName field is present in the peer or server certificate, the Peer-Id or Server-Id MUST be set to the contents of the subjectAltName. (§5.2)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.2-1, so no unit is bound to it.

RFC5216-5.2-2

If subject naming information is present only in the subjectAltName extension of a peer or server certificate, then the subject field MUST be an empty sequence and the subjectAltName extension MUST be critical. (§5.2)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.2-2, so no unit is bound to it.

RFC5216-5.2-3

Conforming implementations generating new certificates with Network Access Identifiers (NAIs) MUST use the rfc822Name in the subject alternative name field to describe such identities. (§5.2)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.2-3, so no unit is bound to it.

RFC5216-5.2-4

The use of the subject name field to contain an emailAddress Relative Distinguished Name (RDN) is deprecated, and MUST NOT be used. (§5.2)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.2-4, so no unit is bound to it.

RFC5216-5.2-5

Where it is non-empty, the subject name field MUST contain an X.500 distinguished name (DN). (§5.2)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.2-5, so no unit is bound to it.

RFC5216-5.3-2

Once a TLS session is established, EAP-TLS peer and server implementations MUST validate that the identities represented in the certificate are appropriate and authorized for use with EAP-TLS. (§5.3)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.3-2, so no unit is bound to it.

RFC5216-5.3-3

When performing this comparison, implementations MUST follow the validation rules specified in Section 3.1 of [RFC2818]. (§5.3)

Audit verdict: not audited: no reader has judged these tests

No test carries RFC5216-5.3-3, so no unit is bound to it.

Extraction sign-off

FieldValue
Reviewer claude
Signed off 2026-09-21
Register rfc2119
Source rfc/full/rfc5216.txt
Source fingerprint fbadcfb857b6d879
Record rfc/extraction/rfc5216.json
Mapped sentences 45
Declined as scope 8
Relocated to a spec, which Ze OWES 0
Unclassified 0

Sections

SectionNameSitesDispositionReason
front not stated 0 walked not stated
1 not stated 0 walked not stated
1.1 not stated 0 walked not stated
1.2 not stated 0 walked not stated
2 not stated 0 walked not stated
2.1 not stated 0 walked not stated
2.1.1 not stated 11 walked not stated
2.1.2 not stated 1 walked not stated
2.1.3 not stated 7 walked not stated
2.1.4 not stated 5 walked not stated
2.1.5 not stated 8 walked not stated
2.2 not stated 0 walked not stated
2.3 not stated 0 walked not stated
2.4 not stated 4 walked not stated
3 not stated 0 walked not stated
3.1 not stated 4 walked not stated
3.2 not stated 4 walked not stated
4 not stated 0 walked not stated
5 not stated 0 walked not stated
5.1 not stated 0 walked not stated
5.2 not stated 5 walked not stated
5.3 not stated 2 walked not stated
5.4 not stated 2 walked not stated
5.5 not stated 0 walked not stated
6 not stated 0 walked not stated
6.1 not stated 0 walked not stated
6.2 not stated 0 walked not stated

Excluded sentences

SiteExcluded kindReasonQuote
2.1.4:1 feature-out-of-scope
never bound Ze
the RFC makes a feature OPTIONAL, Ze decided not to offer it, and this obligation is conditional on offering it
Section 2.1.4 makes privacy optional: "EAP-TLS peer and server implementations MAY support privacy." Ze declined it: internal/core/eap carries no privacy mode, no anonymous-NAI identity path and no empty-certificate-list handling, so every obligation this sentence conditions on supporting or being configured for privacy is out of scope. In order to avoid disclosing the peer username, an EAP-TLS peer configured for privacy MUST negotiate a TLS ciphersuite supporting confidentiality and MUST provide a client certificate list containing no entries in response to the initial certificate_request from the EAP-TLS server.
2.1.4:2 feature-out-of-scope
never bound Ze
the RFC makes a feature OPTIONAL, Ze decided not to offer it, and this obligation is conditional on offering it
Section 2.1.4 makes privacy optional: "EAP-TLS peer and server implementations MAY support privacy." Ze declined it: internal/core/eap carries no privacy mode, no anonymous-NAI identity path and no empty-certificate-list handling, so every obligation this sentence conditions on supporting or being configured for privacy is out of scope. An EAP-TLS server supporting privacy MUST NOT treat a certificate list containing no entries as a terminal condition; instead, it MUST bring up the TLS session and then send a hello_request.
2.1.4:3 feature-out-of-scope
never bound Ze
the RFC makes a feature OPTIONAL, Ze decided not to offer it, and this obligation is conditional on offering it
Section 2.1.4 makes privacy optional: "EAP-TLS peer and server implementations MAY support privacy." Ze declined it: internal/core/eap carries no privacy mode, no anonymous-NAI identity path and no empty-certificate-list handling, so every obligation this sentence conditions on supporting or being configured for privacy is out of scope. An EAP-TLS peer supporting privacy MUST provide a certificate list containing at least one entry in response to the subsequent certificate_request sent by the server.
2.1.4:4 feature-out-of-scope
never bound Ze
the RFC makes a feature OPTIONAL, Ze decided not to offer it, and this obligation is conditional on offering it
Section 2.1.4 makes privacy optional: "EAP-TLS peer and server implementations MAY support privacy." Ze declined it: internal/core/eap carries no privacy mode, no anonymous-NAI identity path and no empty-certificate-list handling, so every obligation this sentence conditions on supporting or being configured for privacy is out of scope. If the EAP-TLS server supporting privacy does not receive a client certificate in response to the subsequent certificate_request, then it MUST abort the session.
2.1.4:5 feature-out-of-scope
never bound Ze
the RFC makes a feature OPTIONAL, Ze decided not to offer it, and this obligation is conditional on offering it
Section 2.1.4 makes privacy optional: "EAP-TLS peer and server implementations MAY support privacy." Ze declined it: internal/core/eap carries no privacy mode, no anonymous-NAI identity path and no empty-certificate-list handling, so every obligation this sentence conditions on supporting or being configured for privacy is out of scope. EAP-TLS servers supporting privacy MUST request a client certificate, and MUST be able to accept a client certificate offered by the EAP-TLS peer, in order to preserve interoperability with EAP- TLS peers that do not support privacy.
2.1.5:2 duplicate-of
never bound Ze
the same obligation is already captured under another requirement id
Section 2.1.5 restates the L-flag obligation that Section 3.1 states for the Request packet and RFC5216-3-1 already maps. The L flag is set to indicate the presence of the four-octet TLS Message Length field, and MUST be set for the first fragment of a fragmented TLS message or set of messages.
3.2:2 duplicate-of
never bound Ze
the same obligation is already captured under another requirement id
Section 3.2 repeats the Section 3.1 sentence about octets outside the Length field word for word; RFC5216-3-4 maps it. Octets outside the range of the Length field should be treated as Data Link Layer padding and MUST be ignored on reception.
3.2:3 duplicate-of
never bound Ze
the same obligation is already captured under another requirement id
Section 3.2 repeats the Section 3.1 L-bit sentence word for word; RFC5216-3-1 maps it. The L bit (length included) is set to indicate the presence of the four-octet TLS Message Length field, and MUST be set for the first fragment of a fragmented TLS message or set of messages.

Superseded

No document obsoletes RFC 5216, so its obligations are stated where they were written.