- wo_tls_client: a pure state machine (no sockets). Caller frames
records; driver runs ClientHello->ServerHello->flight->Finished and
hands back bytes to send. Keeps all I/O out of the security-critical FSM
- start_with (inject CH + ephemeral priv), push_record, take_output,
encrypt/decrypt (application traffic keys). Handshake-message reassembly
across records; per-message transcript timing (CertVerify signs CH..Cert,
Finished MACs CH..CertVerify); constant-time Finished compare; every
failure lands in FAILED (no warn-and-continue)
- verifies server CertificateVerify (phase E+D) + server Finished, emits
the client Finished, switches to application keys
- KAT: whole handshake driven offline against the RFC 8448 record trace —
client Finished record byte-for-byte, first client app record
byte-for-byte, NewSessionTicket + server app data decrypt to plaintext,
tampered flight -> FAILED. test_tls 90 pass, ASan/UBSan clean
- SECURITY TODO before live use (documented in tls.h + story): chain walk
to a trust anchor + SAN/hostname match; random ephemeral for production
start; the net.connect_tls socket glue
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 74c332d7efdb8bbfdbe90bd2fcc3defa2fe8da00)
- wo_tls_verify_cert_verify: verifies a server CertificateVerify
(RFC 8446 §4.4.3) — builds the 64-space || context || 0x00 ||
transcript-hash content, parses the leaf SPKI (phase E) and dispatches
to phase-D RSA-PSS / RSA-PKCS1 / ECDSA-P256; the scheme must match the
leaf key type. ECDSA sig r/s pulled from its DER SEQ
- reuses wo_tls_finished_verify (phase F2) for server + client Finished
- KAT: the whole handshake crypto driven offline from the RFC 8448 §3
recorded messages — CertificateVerify (RSA-PSS) VALID, wrong-transcript
/ tampered-sig / mismatched-scheme rejected, server Finished byte-exact,
and the client Finished we would send byte-exact. test_tls 78 pass,
ASan/UBSan clean
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit afd9f23508c648322712df91329aa117c975ccab)
- new tls.c/tls.h on the crypto ladder: wo_tls_record_seal/open
(RFC 8446 §5.2) — TLSInnerPlaintext (content||type, no padding),
5-byte header as AEAD additional-data, per-record nonce = iv XOR
seq big-endian (§5.3)
- suite dispatch: TLS_AES_128_GCM_SHA256 (mandatory) +
TLS_CHACHA20_POLY1305_SHA256 (AES-NI-less fallback), over phase-A AEAD
- open() strips trailing zero padding to recover the inner content type;
rejects a length-field lie before the AEAD, and auth failure after
- KAT vs python AEAD oracle (test/gen_tls_record.py): sealed record
byte-for-byte both suites, open() recovers it, 5-seq round-trip,
tamper + wrong-seq + bad-suite rejected. test_tls 51 pass, ASan/UBSan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 5021a99f8359f78a642bb0cc2b28ab66f6b624e2)