Skip to content

Commit 14efd7e

Browse files
Port full TLS handshake state machine to CakeML (J3/L4 complete)
Ports extensions, certificate verification, and the client/server state machine (TlsExtensions, TlsCertVerify, TlsClient/TlsServer/Tls) onto the CakeML tower. The self-contained tls_handshake_test.cml runs a full in-process client<->server 1-RTT handshake under the pinned v3400 cake compiler: both sides reach CONNECTED, the coalesced-flight path works, and the client verifies the server's RSA-PSS CertificateVerify and Finished. 17/17 handshake checks PASS, independently re-verified (compiled to native arm8 and run). Completes the CakeML port of the entire stack (L0-L4). Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 4a740aa commit 14efd7e

3 files changed

Lines changed: 6721 additions & 5 deletions

File tree

cakeml/tls_PORT_NOTES.md

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@ verified previously in `cakeml/`.
1717
one file because, as a single CakeML compilation unit, `TlsRecordProtect` must
1818
follow `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

Comments
 (0)