docs(rv2-tls,jarvis,status): outbound TLS client complete — jarvis unblocked
- rv2 9 §F3c-net marked LANDED + live-gated; phase-F row COMPLETE (client); frontmatter review_pending updated (client complete, remaining = G server + deferred park-handshake/TlsConn/pooling + doctrine-doc corrections) - jarvis 00-story + 01: the outbound-TLS blocker is cleared (net.connect_tls landed) — jarvis 1 (chat loop) is now buildable - status board: rv2 9 row + NEXT PLAN rewritten to the completed client; next step is jarvis 1 or rv2 9 G Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 732c2216b501dd226d306f9abcbd1ddd846809dc)
This commit is contained in:
parent
72ed35773d
commit
cf31bb4ebd
4 changed files with 51 additions and 44 deletions
|
|
@ -76,40 +76,36 @@ behind this board; live Obsidian Dataview views:
|
||||||
|
|
||||||
## ▶ NEXT PLAN
|
## ▶ NEXT PLAN
|
||||||
|
|
||||||
### Landed 2026-09-08 — the TLS 1.3 client security engine (rv2 9, A–F3c minus the socket glue)
|
### Landed 2026-09-09 — the outbound TLS 1.3 client is COMPLETE (rv2 9 A–F3c), live-gated; jarvis unblocked
|
||||||
|
|
||||||
**What happened this session (code + docs):** the entire security-critical logic
|
**What happened (code + docs):** a whole hand-rolled TLS 1.3 client, in
|
||||||
of a hand-rolled TLS 1.3 client is implemented and gold-KAT'd, in `runtime/src/`
|
`runtime/src/crypto.c` + new `tls.c`/`tls.h` + the `net.*_tls` builtins, gated
|
||||||
`crypto.c` + new `tls.c`/`tls.h`. Landed and vector-gated (ASan/UBSan clean):
|
end to end. All vector-gated against **RFC 8448** / real certs, ASan/UBSan clean:
|
||||||
**E** X.509 chain-link verify + SPKI + validity + **SAN/hostname** (RFC 6125);
|
**E** X.509 (chain-link verify, SPKI, validity, **SAN/hostname** RFC 6125,
|
||||||
**F1** record layer (RFC 8446 §5.2, both suites, byte-for-byte vs python);
|
**basicConstraints/EKU**); **F1** record layer; **F2** key schedule (byte-for-byte
|
||||||
**F2** key schedule (§7.1, byte-for-byte vs **RFC 8448**); **F3a** ClientHello
|
vs RFC 8448); **F3a** ClientHello builder + ServerHello parser; **F3b** offline
|
||||||
builder + ServerHello parser; **F3b** offline CertificateVerify + Finished
|
CertificateVerify + Finished; **F3c-core** the sans-io handshake driver (whole
|
||||||
verify; **F3c-core** the **sans-io handshake driver** (`wo_tls_client`, whole
|
handshake driven offline vs the RFC 8448 record trace); **F3c-net** the socket/VM
|
||||||
handshake driven offline against the RFC 8448 record trace — client Finished +
|
slice — `wo_tls_verify_chain`, the PEM CA-bundle loader, and
|
||||||
app records byte-for-byte, tampered flight refused); **F3c-net security core**
|
**`net.connect_tls` / `net.read_tls` / `net.write_tls`** (ids 115–117,
|
||||||
`wo_tls_verify_chain` (chain-link + anchor + host + validity, no partial trust).
|
`WO_B_MAX`→117) with a per-shard fd-keyed no-lock slot table, a deadline-bounded
|
||||||
Tests: `test_tls` 100/0, `test_crypto` 95/0, full runtime suite 0 fail. Forks
|
handshake, and a parked data plane. **Live gate** `just tls`
|
||||||
auto-approved 2026-09-08, marked `review_pending` in the story frontmatter for a
|
(`scripts/tls-accept.sh`, `docs/examples/tls-client`): dials a local TLS 1.3 stub
|
||||||
developer second review before this drives a live connection.
|
from `.wo`, validates the chain + host, round-trips app data, and refuses the
|
||||||
|
untrusted-chain + hostname-mismatch negatives — **5 checks, 0 failures**, no live
|
||||||
|
network. Tests: `test_tls` 107/0, `test_crypto` 104/0, full runtime suite 0 fail.
|
||||||
|
Six integration forks implemented as locked (blocking deadline-bounded
|
||||||
|
connect+handshake then parked data plane; per-shard slot table no-locks; failures
|
||||||
|
trap `WO_T_IO`; per-shard lazy read-only CA bundle `WO_CA_BUNDLE`; handshake
|
||||||
|
deadline `WO_TLS_HANDSHAKE_MS`; basicConstraints+EKU hardening). Forks
|
||||||
|
auto-approved 2026-09-08/09, `review_pending` for a developer second review.
|
||||||
|
|
||||||
**Next step — BUILD F3c-net (the only remaining rung before jarvis unblocks).**
|
**Next step — jarvis 1 (the chat loop) is now buildable** (its outbound seam is
|
||||||
Its spec is now `ready`: [rv2 9 §F3c-net](runtime-v2/09-in-process-tls.md)
|
open); or rv2 9 **G** (inbound TLS server) for porch, which also lets the
|
||||||
brainstormed 2026-09-09 with **six** integration forks **locked** (four grounded
|
proxy-termination doctrine docs (34/38/porch) be corrected. Deferred rv2 9
|
||||||
in the runtime, two from a gofiber/Go `crypto/x509` comparison): (1) blocking
|
follow-ups: a park-based handshake, a first-class `TlsConn` object, connection
|
||||||
connect+handshake then park the data plane, mirroring `net.connect` — park-based
|
pooling. (Separately still open: language 41's marshal fix — below — unblocking
|
||||||
handshake a named follow-up; (2) a per-shard fd-keyed `wo_tls_conn` slot table,
|
porch 9.)
|
||||||
no locks (the `wo_child` pattern); (3) failures trap `WO_T_IO` loudly incl.
|
|
||||||
chain/hostname; (4) per-shard lazy read-only CA bundle (`/etc/ssl/certs/…`,
|
|
||||||
`WO_CA_BUNDLE` override); (5) a **bounded handshake deadline**
|
|
||||||
(`WO_TLS_HANDSHAKE_MS`, non-blocking connect+poll + `SO_RCVTIMEO/SNDTIMEO`) so a
|
|
||||||
stalled server can't hang the shard; (6) **chain hardening** — basicConstraints
|
|
||||||
CA:TRUE + pathLen + leaf EKU `serverAuth`, not just signatures. Builtins:
|
|
||||||
`net.connect_tls`/`read_tls`/`write_tls` (ids 115–117, `WO_B_MAX`→117), wiring
|
|
||||||
across `wob.h`/`emit.ml`/`types.ml`/`loader.c`/`builtin.c`/`sysio.c`, live-gated
|
|
||||||
against a local TLS server. Then **G** (inbound server) for porch; after that
|
|
||||||
jarvis 1 is buildable. (Separately still open: language 41's marshal fix — below
|
|
||||||
— unblocking porch 9.)
|
|
||||||
|
|
||||||
### Brainstormed 2026-09-06 — the porch track (2–8) and language 41's fix, both to `ready`
|
### Brainstormed 2026-09-06 — the porch track (2–8) and language 41's fix, both to `ready`
|
||||||
|
|
||||||
|
|
@ -1578,7 +1574,7 @@ starts. Edges in [dependency graph section 6](../00-dependency-graph.md).
|
||||||
| 6 | [term.size + term.width](runtime-v2/06-term-size-width.md) | ✅ **DONE 2026-09-02** — TIOCGWINSZ read twin (nil = not a tty) and libc wcwidth under C.UTF-8; the only runtime work the whole wmux parity ladder needs |
|
| 6 | [term.size + term.width](runtime-v2/06-term-size-width.md) | ✅ **DONE 2026-09-02** — TIOCGWINSZ read twin (nil = not a tty) and libc wcwidth under C.UTF-8; the only runtime work the whole wmux parity ladder needs |
|
||||||
| 7 | [observability](runtime-v2/07-observability.md) | ⬜ `refine` — **moved here 2026-09-06** from language iteration 30 (`was_language_iteration: 30`). Runtime metrics/gauges, a `pprof`-equivalent profile, stack-trace-on-trap; consumers named (porch [8](porch/08-static-and-lifecycle.md)/[39](language-runtime-database/39-web-framework-parity.md), databasev2 [5](databasev2/05-bounded-tables-eviction.md), the limiter's lazy expiry). Forks: counters-only vs profiling, exposition format, pull vs push, trace-on-trap as a separable first slice. Stretches the track's charter (instrumentation, not processes/terminals/signals) — noted in the story |
|
| 7 | [observability](runtime-v2/07-observability.md) | ⬜ `refine` — **moved here 2026-09-06** from language iteration 30 (`was_language_iteration: 30`). Runtime metrics/gauges, a `pprof`-equivalent profile, stack-trace-on-trap; consumers named (porch [8](porch/08-static-and-lifecycle.md)/[39](language-runtime-database/39-web-framework-parity.md), databasev2 [5](databasev2/05-bounded-tables-eviction.md), the limiter's lazy expiry). Forks: counters-only vs profiling, exposition format, pull vs push, trace-on-trap as a separable first slice. Stretches the track's charter (instrumentation, not processes/terminals/signals) — noted in the story |
|
||||||
| 8 | [symmetric cipher (AEAD)](runtime-v2/08-symmetric-cipher.md) | 🔄 **in-progress** — the **first rung of the TLS ladder** (gates rv2 9). **Phases A + B + C LANDED 2026-09-08**: A ChaCha20-Poly1305 (ids 111/112, RFC 8439 §2.8.2); B AES-128/256-GCM (ids 113/114) via AES-NI+PCLMULQDQ; C portable constant-time software AES-GCM fallback (S-box via GF-inverse ladder, bit-by-bit GHASH) — AES-GCM now on any CPU, dispatched hw-or-sw. All hand-rolled, constant-time, both AES paths NIST cases 4 & 16 byte-exact, KAT-gated in test_crypto (**48/0**), ASan/UBSan clean. Remaining: D cookie wrapper → E gate (ARMv8 hw path deferred). Consumers: rv2 9 TLS + porch encrypted cookies |
|
| 8 | [symmetric cipher (AEAD)](runtime-v2/08-symmetric-cipher.md) | 🔄 **in-progress** — the **first rung of the TLS ladder** (gates rv2 9). **Phases A + B + C LANDED 2026-09-08**: A ChaCha20-Poly1305 (ids 111/112, RFC 8439 §2.8.2); B AES-128/256-GCM (ids 113/114) via AES-NI+PCLMULQDQ; C portable constant-time software AES-GCM fallback (S-box via GF-inverse ladder, bit-by-bit GHASH) — AES-GCM now on any CPU, dispatched hw-or-sw. All hand-rolled, constant-time, both AES paths NIST cases 4 & 16 byte-exact, KAT-gated in test_crypto (**48/0**), ASan/UBSan clean. Remaining: D cookie wrapper → E gate (ARMv8 hw path deferred). Consumers: rv2 9 TLS + porch encrypted cookies |
|
||||||
| 9 | [in-process TLS](runtime-v2/09-in-process-tls.md) | 🔄 **in-progress** (`ready` 2026-09-07) — TLS **both directions**, **retiring the "TLS is the proxy's job" doctrine** (34/38/porch). Locked: **hand-roll TLS 1.3**, **1.3-only**, **RSA+ECDSA+full X.509**. Ladder (all KAT'd vs **RFC 8448** / real certs, ASan/UBSan clean, 2026-09-08): **A AEAD ✅ → B HKDF ✅ → C X25519 ✅ → D signatures ✅ → E X.509 ✅ + SAN/hostname ✅ → F1 record ✅ → F2 key schedule ✅ → F3a messages ✅ → F3b offline handshake verify ✅ → F3c-core sans-io handshake driver ✅** (whole handshake driven offline vs the RFC 8448 record trace: client Finished + app records byte-for-byte, tampered flight refused). New `tls.c`/`tls.h`; test_tls 91/0, test_crypto 95/0. **Remaining F3c-net**: random ephemeral for production, system CA trust-anchor walk, `net.connect_tls` VM plumbing (live-gated) → then **G** server. `net.connect` (110) landed. Forks auto-approved 2026-09-08, marked `review_pending`. The project's **highest-risk** work; mandatory reference-tested/constant-time/negative-test gates |
|
| 9 | [in-process TLS](runtime-v2/09-in-process-tls.md) | 🔄 **in-progress** — **outbound client COMPLETE 2026-09-09**, **retiring the "TLS is the proxy's job" doctrine** (34/38/porch). Locked: **hand-roll TLS 1.3**, **1.3-only**, **RSA+ECDSA+full X.509**. Ladder (KAT'd vs **RFC 8448** / real certs, ASan/UBSan clean): **A AEAD ✅ → B HKDF ✅ → C X25519 ✅ → D signatures ✅ → E X.509 + SAN/hostname + basicConstraints/EKU ✅ → F1 record ✅ → F2 key schedule ✅ → F3a messages ✅ → F3b offline verify ✅ → F3c-core sans-io driver ✅ → F3c-net `net.connect_tls`/`read_tls`/`write_tls` ✅** (ids 115–117; deadline-bounded blocking handshake then parked data plane; per-shard fd-keyed no-lock slots; CA bundle via `WO_CA_BUNDLE`). **Live-gated** `just tls` (5/0) from `.wo` incl. untrusted-chain + hostname-mismatch negatives. `tls.c`/`tls.h`; test_tls 107/0, test_crypto 104/0, full suite 0 fail. **Remaining: G inbound server** (porch) + deferred park-handshake/`TlsConn`/pooling. Forks auto-approved 2026-09-08/09, `review_pending`. The project's **highest-risk** work; mandatory reference-tested/constant-time/negative-test gates |
|
||||||
|
|
||||||
### ▸ wmux — the terminal multiplexer track
|
### ▸ wmux — the terminal multiplexer track
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ Blockers, which must land before iteration 1 starts:
|
||||||
| Blocker | Owner | State |
|
| Blocker | Owner | State |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| outbound TCP (`net.connect`) | language [38](../language-runtime-database/38-content-platform-capabilities.md) | ✅ **landed 2026-09-07** (`wob.h` id 110) |
|
| outbound TCP (`net.connect`) | language [38](../language-runtime-database/38-content-platform-capabilities.md) | ✅ **landed 2026-09-07** (`wob.h` id 110) |
|
||||||
| outbound TLS client | runtime-v2 [9](../runtime-v2/09-in-process-tls.md) — in-process TLS; **retires the proxy-termination doctrine** | 🔄 in progress — A AEAD ✅, B HKDF ✅, C X25519 ✅, D signatures ✅, E X.509 ✅, F1 record ✅, F2 key schedule ✅, F3a messages ✅, F3b offline verify ✅, F3c-core sans-io handshake driver ✅, SAN/hostname ✅ (all KAT'd vs RFC 8448 / real certs); **remaining F3c-net**: system CA trust-anchor walk + `net.connect_tls` VM plumbing (live-gated), then G server |
|
| outbound TLS client | runtime-v2 [9](../runtime-v2/09-in-process-tls.md) — in-process TLS; **retires the proxy-termination doctrine** | ✅ **LANDED 2026-09-09** — the full client: A–E crypto, F1–F3c handshake, SAN/hostname + basicConstraints/EKU chain validation, and **`net.connect_tls` / `net.read_tls` / `net.write_tls`** (ids 115–117), live-gated (`just tls`, 5/0) from `.wo` incl. untrusted-chain + hostname-mismatch negatives. **jarvis's outbound seam is open** (G inbound server is porch's, not jarvis's) |
|
||||||
|
|
||||||
## What this track does NOT own
|
## What this track does NOT own
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,15 @@ review_pending: "forks auto-approved 2026-09-08 for autonomous execution — dev
|
||||||
> `review_pending` for the developer's second review** — the defaults below are
|
> `review_pending` for the developer's second review** — the defaults below are
|
||||||
> reasonable but were not individually confirmed.
|
> reasonable but were not individually confirmed.
|
||||||
|
|
||||||
## Blocked until the outbound seam lands
|
## The outbound seam has landed
|
||||||
|
|
||||||
This iteration cannot run until `net.connect` (✅ landed) and runtime-v2
|
The blockers are cleared: `net.connect` (✅) and runtime-v2
|
||||||
[9](../runtime-v2/09-in-process-tls.md) TLS expose **`net.connect_tls`**. The
|
[9](../runtime-v2/09-in-process-tls.md)'s **`net.connect_tls` / `net.read_tls` /
|
||||||
crypto + handshake engine is landed and RFC-8448-gated (A–E, F1–F3c-core, the
|
`net.write_tls`** (✅ landed 2026-09-09, live-gated `just tls`) expose outbound
|
||||||
sans-io client driver, SAN/hostname); what remains is **F3c-net** — the socket
|
HTTPS from `.wo`, with the full hand-rolled TLS 1.3 handshake + chain/hostname
|
||||||
glue that drives the driver over a real fd, plus a system CA trust-anchor walk.
|
validation. Everything below is now buildable `.wo` on top of that seam plus
|
||||||
Everything below is buildable `.wo` on top of that seam plus porch 2/3/6/7.
|
porch 2/3/6/7. (Note: the TLS builtins return the connection as an `Int` fd, per
|
||||||
|
the F3c-net object-model decision — the chat loop dials with them directly.)
|
||||||
|
|
||||||
## Decisions locked (auto-approved, review pending)
|
## Decisions locked (auto-approved, review pending)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ track: runtime-v2
|
||||||
iteration: "9"
|
iteration: "9"
|
||||||
status: in-progress
|
status: in-progress
|
||||||
readiness: ready
|
readiness: ready
|
||||||
review_pending: "forks auto-approved 2026-09-08/09 for autonomous execution — developer second review before this ships. Landed + KAT'd (RFC 8448 / real certs): A–E crypto, F1 record, F2 key schedule, F3a messages, F3b offline verify, F3c-core sans-io driver, SAN/hostname, F3c-net chain validation. §F3c-net (socket/VM slice) brainstormed to READY 2026-09-09 with six integration forks locked (blocking connect+handshake then park data I/O; per-shard fd-keyed slot table no-locks; failures trap WO_T_IO; per-shard lazy read-only CA bundle; a bounded handshake deadline WO_TLS_HANDSHAKE_MS; chain hardening = basicConstraints CA:TRUE + EKU serverAuth — the last two added from the gofiber/Go crypto/x509 comparison). Remaining to BUILD: F3c-net (net.connect_tls/read_tls/write_tls, ids 115-117, live-gated), then G inbound server"
|
review_pending: "forks auto-approved 2026-09-08/09 for autonomous execution — developer second review before this ships. OUTBOUND CLIENT COMPLETE + live-gated (just tls, 5/0): A–E crypto, F1 record, F2 key schedule, F3a messages, F3b offline verify, F3c-core sans-io driver, SAN/hostname, F3c-net chain validation + basicConstraints/EKU, and the net.connect_tls/read_tls/write_tls builtins (ids 115-117). Six integration forks implemented as locked. REMAINING: G inbound server (porch); deferred park-based handshake + TlsConn object + connection pooling; correcting the doctrine docs (34/38/porch)"
|
||||||
---
|
---
|
||||||
|
|
||||||
# runtime-v2 9 — in-process TLS: retiring the proxy-termination doctrine
|
# runtime-v2 9 — in-process TLS: retiring the proxy-termination doctrine
|
||||||
|
|
@ -79,10 +79,20 @@ they may split into their own runtime-v2 iterations as they are picked up.
|
||||||
| C — key exchange | ✅ **LANDED 2026-09-08** — `wo_x25519` (RFC 7748), constant-time Montgomery ladder + mask-based cswap, radix-2⁵¹ field arithmetic (curve25519-donna-c64, `__int128`). Internal C. KAT-gated in `test_crypto.c`: RFC 7748 §5.2 both direct vectors **and the 1000-iteration test**, ASan/UBSan clean |
|
| C — key exchange | ✅ **LANDED 2026-09-08** — `wo_x25519` (RFC 7748), constant-time Montgomery ladder + mask-based cswap, radix-2⁵¹ field arithmetic (curve25519-donna-c64, `__int128`). Internal C. KAT-gated in `test_crypto.c`: RFC 7748 §5.2 both direct vectors **and the 1000-iteration test**, ASan/UBSan clean |
|
||||||
| D — signatures | ✅ **LANDED 2026-09-08** — **RSA** `wo_rsa_pkcs1_sha256_verify` + `wo_rsa_pss_sha256_verify` (bignum Montgomery modexp) and **ECDSA-P256** `wo_ecdsa_p256_sha256_verify` (Jacobian point arithmetic, a=-3, on-curve check, Fermat inverses reusing the bignum). Verification is public data so **not** constant-time by design. Both match python vectors (RSA-2048 PKCS1+PSS; P-256), tamper/wrong-hash rejected, KAT-gated, ASan/UBSan clean |
|
| D — signatures | ✅ **LANDED 2026-09-08** — **RSA** `wo_rsa_pkcs1_sha256_verify` + `wo_rsa_pss_sha256_verify` (bignum Montgomery modexp) and **ECDSA-P256** `wo_ecdsa_p256_sha256_verify` (Jacobian point arithmetic, a=-3, on-curve check, Fermat inverses reusing the bignum). Verification is public data so **not** constant-time by design. Both match python vectors (RSA-2048 PKCS1+PSS; P-256), tamper/wrong-hash rejected, KAT-gated, ASan/UBSan clean |
|
||||||
| E — X.509 | 🔄 **CORE LANDED 2026-09-08** — a defensive ASN.1/DER reader (every length/bound checked, malformation is rejection not over-read) + certificate parse (tbsCertificate span, sig-alg OID, signature, SubjectPublicKeyInfo→RSA n/e or EC P-256 x/y, validity) + `wo_x509_verify_one` (one chain link's signature, dispatching to D's RSA-PKCS1/PSS + ECDSA-P256) + `wo_x509_parse_spki` + `wo_x509_check_validity` (caller supplies the time). KAT-gated in `test_crypto.c` against **real python-generated chains** — RSA CA+leaf (SHA256withRSA) and EC P-256 CA+leaf (ecdsa-with-SHA256): leaf-vs-CA, self-signed CA, wrong-issuer/tampered/truncated rejected, validity window, SPKI extraction — ASan/UBSan clean. **Deferred to F**: SAN/hostname match (needs the target host) and the multi-cert chain walk to a system CA bundle | notoriously bug-prone; consumes D |
|
| E — X.509 | 🔄 **CORE LANDED 2026-09-08** — a defensive ASN.1/DER reader (every length/bound checked, malformation is rejection not over-read) + certificate parse (tbsCertificate span, sig-alg OID, signature, SubjectPublicKeyInfo→RSA n/e or EC P-256 x/y, validity) + `wo_x509_verify_one` (one chain link's signature, dispatching to D's RSA-PKCS1/PSS + ECDSA-P256) + `wo_x509_parse_spki` + `wo_x509_check_validity` (caller supplies the time). KAT-gated in `test_crypto.c` against **real python-generated chains** — RSA CA+leaf (SHA256withRSA) and EC P-256 CA+leaf (ecdsa-with-SHA256): leaf-vs-CA, self-signed CA, wrong-issuer/tampered/truncated rejected, validity window, SPKI extraction — ASan/UBSan clean. **Deferred to F**: SAN/hostname match (needs the target host) and the multi-cert chain walk to a system CA bundle | notoriously bug-prone; consumes D |
|
||||||
| F — record + handshake (client) | 🔄 **F1–F3b LANDED 2026-09-08** — new `tls.c`/`tls.h`. **F1 record layer** (`wo_tls_record_seal`/`open`, RFC 8446 §5.2, per-record nonce = iv XOR seq, both suites) KAT'd byte-for-byte vs python. **F2 key schedule** (`wo_tls_derive_handshake`/`_application`/`_traffic_keys`/`_finished_verify`, §7.1) KAT'd byte-for-byte vs **RFC 8448 §3**. **F3a message layer** (`wo_tls_parse_server_hello` — attacker input, bounded, rejects HRR/bad suite/truncation; `wo_tls_build_client_hello` — SNI, x25519, sig-algs) KAT'd vs RFC 8448 SH + validated by an independent parser. **F3b offline handshake verification** (`wo_tls_verify_cert_verify` over phase E+D; server + client Finished) — the whole handshake **crypto** proven end-to-end offline vs RFC 8448. **F3c-core sans-io driver** (`wo_tls_client` — pure FSM, caller frames records: CH→SH→flight→Finished, message reassembly, per-message transcript timing, constant-time Finished, application encrypt/decrypt) KAT'd against the **full RFC 8448 record trace** — client Finished + first app record byte-for-byte, NewSessionTicket + server app data decrypt, tampered flight refused. **SAN/hostname** (`wo_x509_check_host`, RFC 6125) + driver enforcement landed. **F3c-net chain validation** (`wo_tls_verify_chain` — chain-link + trust anchor + host + validity, no partial trust) KAT'd offline vs the phase-E RSA + EC chains. **Remaining to build (F3c-net, spec now `ready` — see §F3c-net below)**: `getrandom` ephemeral, per-shard lazy CA-bundle loader, and the `net.connect_tls` / `net.read_tls` / `net.write_tls` builtins (ids 115–117, blocking connect+handshake then park the data plane, per-shard fd-keyed slot table), gated live against `openssl s_server` | jarvis's path; the reason the story exists |
|
| F — record + handshake (client) | ✅ **COMPLETE 2026-09-08/09** (client). F1–F3b LANDED 2026-09-08 — new `tls.c`/`tls.h`. **F1 record layer** (`wo_tls_record_seal`/`open`, RFC 8446 §5.2, per-record nonce = iv XOR seq, both suites) KAT'd byte-for-byte vs python. **F2 key schedule** (`wo_tls_derive_handshake`/`_application`/`_traffic_keys`/`_finished_verify`, §7.1) KAT'd byte-for-byte vs **RFC 8448 §3**. **F3a message layer** (`wo_tls_parse_server_hello` — attacker input, bounded, rejects HRR/bad suite/truncation; `wo_tls_build_client_hello` — SNI, x25519, sig-algs) KAT'd vs RFC 8448 SH + validated by an independent parser. **F3b offline handshake verification** (`wo_tls_verify_cert_verify` over phase E+D; server + client Finished) — the whole handshake **crypto** proven end-to-end offline vs RFC 8448. **F3c-core sans-io driver** (`wo_tls_client` — pure FSM, caller frames records: CH→SH→flight→Finished, message reassembly, per-message transcript timing, constant-time Finished, application encrypt/decrypt) KAT'd against the **full RFC 8448 record trace** — client Finished + first app record byte-for-byte, NewSessionTicket + server app data decrypt, tampered flight refused. **SAN/hostname** (`wo_x509_check_host`, RFC 6125) + driver enforcement landed. **F3c-net chain validation** (`wo_tls_verify_chain`) + **basicConstraints/EKU** hardening KAT'd offline. **F3c-net socket/VM ✅ LANDED 2026-09-09**: `getrandom` ephemeral, per-shard lazy CA-bundle loader (`WO_CA_BUNDLE`), and the `net.connect_tls` / `net.read_tls` / `net.write_tls` builtins (ids 115–117; blocking deadline-bounded connect+handshake then a parked data plane; per-shard fd-keyed slot table, no locks). **Live-gated** (`just tls`, 5/0) from `.wo` against a local TLS 1.3 stub incl. untrusted-chain + hostname-mismatch negatives. Client side complete | jarvis's path; the reason the story exists |
|
||||||
| G — server (inbound) | the server handshake half, cert+key loading, signing CertificateVerify; porch terminates TLS | retires the inbound proxy requirement, and the doctrine docs |
|
| G — server (inbound) | the server handshake half, cert+key loading, signing CertificateVerify; porch terminates TLS | retires the inbound proxy requirement, and the doctrine docs |
|
||||||
|
|
||||||
## F3c-net — the socket/VM slice (READY — decisions locked 2026-09-09; forks auto-approved, `review_pending`)
|
## F3c-net — the socket/VM slice (✅ **LANDED 2026-09-09**; decisions locked, forks auto-approved, `review_pending`)
|
||||||
|
|
||||||
|
> **Landed and live-gated.** `net.connect_tls` / `net.read_tls` / `net.write_tls`
|
||||||
|
> (ids 115–117) are wired into the VM and dial a real TLS 1.3 server end to end
|
||||||
|
> from `.wo`: the hand-rolled handshake, the chain + hostname + basicConstraints/
|
||||||
|
> EKU validation against the system (or `WO_CA_BUNDLE`) trust store, and an
|
||||||
|
> application round-trip. The `just tls` gate (`scripts/tls-accept.sh`,
|
||||||
|
> `docs/examples/tls-client`) proves the happy path against a local TLS 1.3 stub
|
||||||
|
> and refuses the untrusted-chain and hostname-mismatch negatives — 5 checks, 0
|
||||||
|
> failures, no live network. All six decisions below were implemented as locked.
|
||||||
|
> **This completes the outbound client; jarvis is unblocked.**
|
||||||
|
|
||||||
Everything security-critical is landed and offline-KAT'd. What is left is I/O
|
Everything security-critical is landed and offline-KAT'd. What is left is I/O
|
||||||
integration that can only be gated **live** (a local `openssl s_server` / python
|
integration that can only be gated **live** (a local `openssl s_server` / python
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue