nx_tls13_client_session_recv_sh.nx
buildroot/runtime/nx_tls13_client_session_recv_sh.nx
about
nx_tls13_client_session_recv_sh.nx -- step 3c.2 of the
nx_https_client wiring arc.
Consumes the bytes of a TLS 1.3 ServerHello handshake message
(provided by the caller -- this step doesn't do fd IO; that's
the orchestrator wrapper 3c.6 in a later commit) and walks the
full handshake-key-derivation cascade:
1. Parse the ServerHello message (via shipped tls13_server_hello_parse)
2. Find the key_share extension + extract server's X25519 pubkey
3. Compute shared_secret = x25519(my_priv, server_pub)
4. Run TLS 1.3 key schedule cascade (RFC 8446 ยง7.1):
early_secret = HKDF-Extract(0, 0)
derived_1 = Derive-Secret(early, "derived", "")
handshake_secret = HKDF-Extract(derived_1, shared_secret)
5. Feed ServerHello bytes into transcript (so H1 = hash(CH || SH))
6. Snapshot transcript -> H1
7. Derive c_hs_traffic_secret + s_hs_traffic_secret using H1
8. Expand each into AEAD key (32B) + IV (12B for ChaCha20-Poly1305
or AES-GCM)
9. Reset per-direction sequence numbers to 0
10. Advance state CH_SENT -> WAIT_EE
After this primitive returns OK, the session is ready for the
3c.3 step (recv encrypted handshake records, decrypt with
server_hs_traffic_key, dispatch via tls13_client_dispatch_with_validation).
Public API:
nx_tls13_client_session_recv_sh(session, sh_bytes, sh_len) -> verdict
nx_tls13_recv_sh_verdict_is_valid(v) -> 0|1
Sealed verdict enum:
NX_TLS13_RECV_SH_OK keys derived, state advanced
NX_TLS13_RECV_SH_BAD_STATE session not in CH_SENT
NX_TLS13_RECV_SH_BAD_FORMAT SH parse failed
NX_TLS13_RECV_SH_NO_KEYSHARE SH extensions missing key_share
NX_TLS13_RECV_SH_BAD_GROUP key_share group != X25519 (29)
NX_TLS13_RECV_SH_BAD_KEYSHARE_LEN server keyshare != 32 bytes
NX_TLS13_RECV_SH_INTERNAL HKDF/SHA-256/x25519 failed
dependencies 10 imports · 11 importers
diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.
imports: nx_syscalls.nxnx_sha256.nxnx_x25519.nxnx_tls13.nxnx_tls13_hello.nxnx_tls13_transcript.nxnx_tls13_kdf.nxnx_tls13_schedule.nxnx_tls13_client_session.nxnx_p256_ecdh.nx
imported by: nx_porkbun_ping_probe.nxnx_sites_sni_cert_gate.nxnx_tls13_ch_compat_test.nxnx_tls13_client_h2run.nxnx_tls13_client_session_recv_hs_test.nxnx_tls13_client_session_recv_sh_test.nxnx_tls13_client_session_run.nxnx_tls13_p256_loopback_test.nxnx_tls13_recv_hs_diff_test.nxnx_tls13_recv_hs_probe_test.nxnx_tls13_sh_probe_test.nx
structs
| none |
consts
| 69 | const NX_TLS13_RECV_SH_OK: i64 = 1 |
| 70 | const NX_TLS13_RECV_SH_BAD_STATE: i64 = 2 |
| 71 | const NX_TLS13_RECV_SH_BAD_FORMAT: i64 = 3 |
| 72 | const NX_TLS13_RECV_SH_NO_KEYSHARE: i64 = 4 |
| 73 | const NX_TLS13_RECV_SH_BAD_GROUP: i64 = 5 |
| 74 | const NX_TLS13_RECV_SH_BAD_KEYSHARE_LEN: i64 = 6 |
| 75 | const NX_TLS13_RECV_SH_INTERNAL: i64 = 7 |
| 76 | const NX_TLS13_RECV_SH_BAD_CIPHER: i64 = 8 // server picked cipher we don't speak |
| 83 | const NX_TLS13_RECV_SH_NOT_TLS13: i64 = 9 // server negotiated DOWN: chose a non-0x13xx suite |
| 84 | const NX_TLS13_RECV_SH_VERDICT_N: i64 = 10 |
| 86 | const NX_TLS13_GROUP_X25519: i64 = 29 |
| 87 | const NX_TLS13_GROUP_SECP256R1: i64 = 23 |
functions
| 89 | func nx_tls13_recv_sh_verdict_is_valid(v: i64) -> i64 called by 1: main |
| 96 | func nx_tls13_client_session_recv_sh( |
| 268 | func main() -> i64 |