@@ -17,9 +17,15 @@ verified previously in `cakeml/`.
1717one file because, as a single CakeML compilation unit, ` TlsRecordProtect ` must
1818follow ` Aead ` and ` TlsRecord ` in concatenation order.
1919
20- ** Harness:** ` cakeml/tls_test.cml ` — a SELF-CONTAINED single-compilation-unit
21- harness that inlines the full dependency-ordered tower + the ported TLS code + a
22- driver, and checks real TLS vectors. It PASSes only on byte/value match.
20+ The handshake state machine (` TlsExtensions ` , ` TlsCertVerify ` , ` TlsClient ` ,
21+ ` TlsServer ` , from ` extensions.sml ` /` certverify.sml ` /` tlsstate.sml ` ) is also
22+ ported, in ` cakeml/tls_state.sml ` — see the "Handshake state machine" section
23+ below.
24+
25+ ** Harnesses:** two SELF-CONTAINED single-compilation-unit harnesses that inline
26+ the full dependency-ordered tower + the ported TLS code + a driver, PASSing only
27+ on byte/value match: ` cakeml/tls_test.cml ` (52/52 core vectors) and
28+ ` cakeml/tls_handshake_test.cml ` (17/17 in-process handshake).
2329
2430### Result (real run on the cached ` cake ` )
2531
@@ -157,10 +163,66 @@ syntax / basis gaps. The notable ones for the TLS layer:
157163- PSK-resumption helpers (` resumptionMasterSecret ` , ` resumptionPsk ` ,
158164 ` binderKey ` , ` binderFinishedKey ` , ` pskBinder ` ) are ported for completeness.
159165
166+ ## Handshake state machine (the capstone — also ported & verified)
167+
168+ On top of the core, the handshake state machine was ported and verified with a
169+ real in-process client↔server 1-RTT handshake:
170+
171+ ** Ported source** — ` cakeml/tls_state.sml ` :
172+
173+ | Upstream | Ported structure | Notes |
174+ | ---| ---| ---|
175+ | ` extensions.sml ` | ` TlsExtensions ` | All extension codecs (key_share CH/SH/HRR, supported_versions, supported_groups, signature_algorithms, SNI, ALPN, cookie, psk_key_exchange_modes, early_data, pre_shared_key) + ` negotiateVersion/Group/SigAlg ` + downgrade sentinels. Word16/32/8 → ` int ` ; records → tuples. |
176+ | ` certverify.sml ` | ` TlsCertVerify ` | Full RFC 5280 path validation (chain build, validity window, BasicConstraints CA + pathLen, KeyUsage ` keyCertSign ` , EKU ` serverAuth ` , sig-alg enforcement, X509 signature verification, RFC 6125 wildcard hostnames). X509 record patterns (` {notBefore,notAfter} ` , ` {pathLen,…} ` , ` RsaPss {hash,…} ` ) → the ported tower's tuple/accessor + curried-constructor forms. ECDSA/Ed25519 unsupported (matches upstream). |
177+ | ` tlsstate.sml ` | ` TlsClient ` , ` TlsServer ` | ~ 22-field records → positional tuples (15-tuple client / 12-tuple server). Covers ` startHandshake ` , ` processServerHello ` , server-flight decrypt/` processFlight ` , client ` step ` (incl. the J2 coalesced ServerHello+CCS+flight in one step), and server ` receiveClientHello ` /` produceServerHello ` /` produceServerFlight ` /` step ` , plus the real CV sign+verify. |
178+
179+ ** Harness** — ` cakeml/tls_handshake_test.cml ` (self-contained: tower +
180+ ` x25519.sml ` + ` tls.sml ` + ` tls_state.sml ` + driver). Compiled with ` cake `
181+ v3400, linked, ran:
182+
183+ ```
184+ HANDSHAKE RESULT: 17 passed, 0 failed
185+ ALL HANDSHAKE CHECKS PASS
186+ ```
187+
188+ The PASSes are real: client and server opaque states are driven directly
189+ in-process (handshake records passed as byte strings between them, no sockets),
190+ reaching ** CONNECTED** ; "agree on app key" is tuple equality of independently
191+ derived ` (key,iv) ` pairs on each side; the coalesced ServerHello+CCS+flight is
192+ processed in a single ` step ` ; and "CertificateVerify verified" is a genuine
193+ ` Rsa.verifyPss ` over the transcript hash against the fixture leaf's public key.
194+
195+ ### Handshake concatenation order
196+
197+ ` cakeml/kdf.sml ` + ` bigint.sml ` + ` asn1.sml ` + ` pem.sml ` + ` aead.sml ` +
198+ ` rsa.sml ` + ` x509.sml ` + ** ` x25519.sml ` ** (inserted here for the ECDHE key
199+ exchange; ` pow2 ` is structure-local so it introduces no top-level clash) +
200+ ` tls.sml ` + ` tls_state.sml ` + driver.
201+
202+ ### Handshake-layer dialect notes / scope limits
203+
204+ - ** P256 is not ported.** Upstream ` tlsstate ` references P256 only for the
205+ optional P-256 key-exchange path; the tests use X25519 with
206+ ` p256PrivateKey = None ` , so every P256 branch is stubbed (unsupported/raise).
207+ - ** The ` Tls ` re-export bundle is not expressible.** CakeML's grammar forbids
208+ nested ` structure ` declarations and structure abbreviations, so the upstream
209+ ` structure Tls ` that re-exports the others has no equivalent — the six
210+ structures are simply top-level instead. (Confirmed with a 3-line probe.)
211+ - ** Out of scope** for the handshake harness (focused on the 1-RTT path):
212+ HelloRetryRequest, KeyUpdate, ` sendApplicationData ` , NewSessionTicket
213+ issuance, and post-handshake ` stepConnected ` . The encode/decode codecs for
214+ these messages are present in the ported ` TlsHandshake ` (and round-trip
215+ in ` tls_test.cml ` ); only the state-machine driving of them is omitted.
216+
160217## Files
161218
162219- ` cakeml/tls.sml ` — ported TLS core (TlsRecord/TlsAlert/TlsHandshake/
163220 TlsKeySchedule + TlsRecordProtect)
164- - ` cakeml/tls_test.cml ` — self-contained harness (tower + TLS + driver),
165- 52/52 PASS on ` cake ` v3400
221+ - ` cakeml/tls_state.sml ` — ported handshake state machine (TlsExtensions/
222+ TlsCertVerify/TlsClient/TlsServer)
223+ - ` cakeml/tls_test.cml ` — self-contained core-vector harness (tower + TLS +
224+ driver), ** 52/52 PASS** on ` cake ` v3400
225+ - ` cakeml/tls_handshake_test.cml ` — self-contained in-process client↔server
226+ handshake harness (tower + x25519 + TLS + tls_state + driver),
227+ ** 17/17 PASS** on ` cake ` v3400
166228- ` cakeml/tls_PORT_NOTES.md ` — this file
0 commit comments