Skip to content

test(tls): pin the TLS 1.3 stack to published RFC vectors#49

Merged
zemo-g merged 1 commit into
masterfrom
test/tls13-rfc-vectors
Jul 9, 2026
Merged

test(tls): pin the TLS 1.3 stack to published RFC vectors#49
zemo-g merged 1 commit into
masterfrom
test/tls13-rfc-vectors

Conversation

@zemo-g

@zemo-g zemo-g commented Jul 9, 2026

Copy link
Copy Markdown
Owner

What

Five new inline suite tests (182 → 187) covering the code that decides who to trust:

Test Pins Source of truth
tls13_rfc8448_handshake Full offline client handshake: key schedule, transcript, server Finished acceptance, both application-traffic secrets, client Finished verify_data RFC 8448 §3
ecdsa_p256_rfc6979_verify ECDSA-P256 + SHA-256 verify — the web-PKI certificate-signature primitive RFC 6979 §A.2.5
ecdsa_p256_reject_invalid Tampered r, tampered hash, r=0, s=0 all rejected derived from RFC 6979 §A.2.5
tls13_cert_verify_sig CertificateVerify path: ASN.1 cert parse → SPKI extract → DER sig parse → signed-content build → ECDSA verify P-256 cert KAT
cert_hostname_san SAN hostname validation: exact + case-fold accepted; different host and parent domain rejected captured real-world ECDSA-P256 leaf

Each test was proven as a standalone program first, then embedded verbatim; the originals in tools/tls/ remain as the long-form documented versions.

Bonus bug the new tests exposed

The suite hung 20+ minutes on entering test 183 — at the default 1GB arena, run_test kept every prior compile's garbage live, and by ~180 in-process compiles the arena was full and the GC crawled (the same test compiles in seconds standalone; at RAIL_ARENA_MB=6000 the full suite passes in minutes). Fix: each test now runs inside an arena_mark/arena_reset window — only the unboxed verdict bool escapes — so suite memory stays flat at any test count, and total suite time drops since late tests no longer run against a degraded heap.

Why

The TLS/PKI stack — handshake FSM, certificate verification, hostname matching (~3,400 LOC) — was covered only by manual tests that nothing gated. An undetected regression in exactly this code is the failure mode this project exists to prevent. With #48 (Ed25519 RFC 8032) and this, every trust-deciding primitive is pinned to published vectors on every push.

Seed

Suite tests compile into the binary, so the seed is rebuilt from the new source: in-process toolchain, fixed point verified (stage2 == stage3 byte-identical), sha256 ba9344da55733580a04c9593e9062fded821c86829fa326219de5a39297889f2. rail_safe rebuilt in lockstep — byte-identical to the seed, 19/19 adversarial gate. Suite: 187/187 with the committed binary — in 80 s at the default 1GB arena (see below). The as/ld fallback path (what CI exercises) was independently confirmed to reach its own byte-identical fixed point on this source.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pb4TJEdqhSKkRdLsDYD2JF

Five inline suite tests (182 -> 187): RFC 8448 §3 full offline handshake,
ECDSA-P256 verify per RFC 6979 §A.2.5 + 4-way invalid-signature rejection,
the CertificateVerify path, and SAN hostname validation on a real leaf.
Distilled from the manual tests in tools/tls/, each proven standalone first.

Adding them exposed a suite-harness bug: run_test kept every compile's
garbage live, so by test ~183 the default 1GB arena was full and the GC
crawled (20+ min hang on a test that runs in seconds standalone). Each
test now compiles inside an arena_mark/arena_reset window; suite memory
stays flat and the full 187-test run drops to ~80 s at the default arena.

Seed rebuilt via the in-process toolchain, fixed point verified
(stage2 == stage3), rail_safe in lockstep (byte-identical, 19/19 gate).
See CHANGELOG.md (Unreleased).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pb4TJEdqhSKkRdLsDYD2JF
@zemo-g zemo-g merged commit 51bfb14 into master Jul 9, 2026
3 checks passed
@zemo-g zemo-g deleted the test/tls13-rfc-vectors branch July 9, 2026 03:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant