From ca572086ee40589977e8cd38b5590a4c50ef0ae7 Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Tue, 8 Sep 2026 16:51:55 +0200 Subject: [PATCH] docs(rv2-tls): rv2 9 phase D complete (RSA + ECDSA-P256 verify) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ECDSA-P256 verify landed; phase D done (both signature verifiers) - rv2 9 story, board ladder, jarvis 00-story deps, and dependency-graph §7 synced: A-D landed, E-F remain (cherry picked from commit 3eab98cc268e524c7b4e2ab72a4b093692a67d03) --- docs/00-dependency-graph.md | 4 ++-- docs/stories/00-status.md | 2 +- docs/stories/jarvis/00-story.md | 8 ++++---- docs/stories/runtime-v2/09-in-process-tls.md | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/00-dependency-graph.md b/docs/00-dependency-graph.md index 9bf4aff..0208933 100644 --- a/docs/00-dependency-graph.md +++ b/docs/00-dependency-graph.md @@ -442,7 +442,7 @@ flowchart TD A["rv2 9 A — AEAD ✅ (= rv2 8 A–C: ChaCha20-Poly1305 + AES-GCM)"]:::done B["rv2 9 B — HKDF ✅"]:::done C["rv2 9 C — X25519 ✅"]:::done - D["rv2 9 D — signatures: RSA-PSS/PKCS1 + ECDSA-P256"]:::refine + D["rv2 9 D — signatures: RSA-PSS/PKCS1 + ECDSA-P256 ✅"]:::done E["rv2 9 E — ASN.1/DER + X.509 chain + trust store"]:::refine F["rv2 9 F — record layer + handshake FSM (client), net.connect_tls"]:::refine G["rv2 9 G — inbound server (porch TLS termination)"]:::refine @@ -474,7 +474,7 @@ flowchart TD J1 --> J3 ``` -The outbound path is the critical one: **A/B/C landed, D→E→F remain** (G is +The outbound path is the critical one: **A/B/C/D landed, E→F remain** (G is inbound, not needed for jarvis dialling out). The framework path (porch 2/3/6/7) is entirely `ready` and unblocked — buildable in parallel with the TLS ladder. jarvis 1 itself is not yet written; jarvis 2/3 follow it. diff --git a/docs/stories/00-status.md b/docs/stories/00-status.md index 1e2d670..136462f 100644 --- a/docs/stories/00-status.md +++ b/docs/stories/00-status.md @@ -1543,7 +1543,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 | | 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 | -| 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: **A AEAD ✅ → B HKDF ✅ → C X25519 ✅ → D signatures 🔄 (RSA PKCS1+PSS ✅ 2026-09-08, KAT-gated; ECDSA-P256 next)** signatures/RSA → E ASN.1/X.509 → F record+FSM client → G server. `net.connect` (110) landed. The project's **highest-risk** work; mandatory reference-tested/constant-time/negative-test gates; C/D/E may each split into own iterations | +| 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: **A AEAD ✅ → B HKDF ✅ → C X25519 ✅ → D signatures ✅ (RSA PKCS1+PSS + ECDSA-P256, 2026-09-08, KAT-gated)** → E ASN.1/X.509 → F record+FSM client → G server. `net.connect` (110) landed. The project's **highest-risk** work; mandatory reference-tested/constant-time/negative-test gates; C/D/E may each split into own iterations | ### ▸ wmux — the terminal multiplexer track diff --git a/docs/stories/jarvis/00-story.md b/docs/stories/jarvis/00-story.md index 99a3130..c0b8225 100644 --- a/docs/stories/jarvis/00-story.md +++ b/docs/stories/jarvis/00-story.md @@ -33,9 +33,9 @@ runtime work, now **partly built**: **retires the standing "TLS is the proxy's job" doctrine**. In progress: its crypto foundations are landed and vector-gated — **A AEAD** (ChaCha20-Poly1305 + AES-GCM, runtime-v2 [8](../runtime-v2/08-symmetric-cipher.md) A–C), - **B HKDF**, **C X25519** — and the remaining rungs (**D** signatures + RSA/X.509, - **E** ASN.1/X.509 chain, **F** record layer + handshake FSM, **G** server) are - what jarvis still waits on. + **B HKDF**, **C X25519**, **D signatures** (RSA PKCS1/PSS + ECDSA-P256) — and + the remaining rungs (**E** ASN.1/X.509 chain, **F** record layer + handshake + FSM, **G** server) are what jarvis still waits on. A **local-gateway alternative was considered and set aside**: jarvis could speak to a small companion process over a unix socket (`net.connect_unix`, id 107) or @@ -90,7 +90,7 @@ Blockers, which must land before iteration 1 starts: | 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 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–G remain** | +| 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 ✅ (RSA + ECDSA-P256); **E–G remain** | ## What this track does NOT own diff --git a/docs/stories/runtime-v2/09-in-process-tls.md b/docs/stories/runtime-v2/09-in-process-tls.md index 57fa3f1..838ee51 100644 --- a/docs/stories/runtime-v2/09-in-process-tls.md +++ b/docs/stories/runtime-v2/09-in-process-tls.md @@ -76,7 +76,7 @@ they may split into their own runtime-v2 iterations as they are picked up. | A — AEAD | AES-128/256-GCM (TLS 1.3 mandates AES-128-GCM) and ChaCha20-Poly1305 | **is runtime-v2 [8](08-symmetric-cipher.md)** — so 8 must include AES-GCM, not only ChaCha; this rung consumes it | | B — key schedule | ✅ **LANDED 2026-09-08** — `wo_hkdf_sha256_extract`/`expand` (RFC 5869) + `expand_label` (RFC 8446 §7.1), internal C over `hmac_sha256`; SHA-256 (the mandatory suites' hash; SHA-384 a later add). KAT-gated in `test_crypto.c` (RFC 5869 case 1 + Expand-Label vectors), ASan/UBSan clean. No builtin, no compiler change | | 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 | 🔄 **RSA landed 2026-09-08** — `wo_rsa_pkcs1_sha256_verify` + `wo_rsa_pss_sha256_verify` (bignum Montgomery modexp, public exponent; verification is public data so **not** constant-time by design). Matches python RSA-2048 vectors (PKCS#1 v1.5 + PSS), tamper/wrong-hash rejected, KAT-gated, ASan/UBSan clean. **Remaining: ECDSA-P256 verify** (D2, next slice) | +| 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 | ASN.1/DER parser, chain validation to a trust anchor, dates, hostname/SAN, system CA bundle | notoriously bug-prone; consumes D | | F — record + handshake (client) | TLS record framing, the ClientHello→Finished FSM, transcript hash, wiring A–E; `net.connect_tls` outbound | 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 |