code wiki / _hdl_build / nx_tls12_reconnect_stress_gate.nx

nx_tls12_reconnect_stress_gate.nx source

↩ module page · 134 lines · 6642 B

1// nx_tls12_reconnect_stress_gate.nx -- LIVE stress proof for the sovereign 2// TLS 1.3 -> 1.2 reconnect path (rung 1 read-correctness + rung 3 retry). 3// 4// The renewal transport (nx_acme_req) tries TLS 1.3, sees api.porkbun.com 5// refuse it, GRACEFULLY tears down the 1.3 socket, reconnects, and completes 6// over the sovereign TLS 1.2 client -- now wrapped in a BOUNDED reconnect- 7// retry so a transient first-flight failure / garbled ServerHello on the rapid 8// reconnect self-heals instead of failing the renewal. 9// 10// This gate drives that EXACT production path against the READ-ONLY Porkbun 11// ping endpoint N times in rapid succession (the condition under which the 12// intermittent 0xC02B cipher garble / -4 READ_FLIGHT was reported), and 13// asserts EVERY handshake completes and the ping returns HTTP 200 SUCCESS. 14// A garbled/unsupported ServerHello FAILS CLOSED (no session) -> the ping 15// would NOT be 200, so 200-every-time IS the zero-garble end-to-end proof. 16// (The record framer's byte-level immunity to fragmentation is proven 17// deterministically + offline in nx_tls12_frag_read_gate.) 18// 19// READ-ONLY: ping returns your IP; NO DNS record is created or modified, NO 20// Let's Encrypt challenge is triggered. Row 0 is a harmless LE 1.3 GET that 21// proves the 1.3 path is still intact through the same transport. 22// 23// Creds: run ./_offc/nx_secret_cli.elf get porkbun first (writes 24// /tmp/nxsecret.out: line1=apikey, line2=secretapikey; a UTF-8 BOM is stripped). 25// 26// expect_exit: 0 27// license_tier: ORIGINAL 28 29import "nx_syscalls.nx" 30import "nx_x509_trust_store.nx" 31import "nx_trust_store_load_from_certdata.nx" 32import "nx_acme_http.nx" 33import "nx_acme_porkbun.nx" 34import "nx_http_response_parse.nx" 35 36func s_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 37func s_n(v: i64) -> i64 { 38 var m: i64=v 39 if m<0 { s_w("-" as *u8); m=0-m } 40 let t: *u8=sys_mmap(24); var k: i64=0 41 if m==0 { t[0]=48 as u8; k=1 } 42 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 43 let o: *u8=sys_mmap(24); var i: i64=0 44 while i<k { o[i]=t[k-1-i]; i=i+1 } 45 sys_write(1,o,k); return 0 46} 47func s_read_file(path: *u8, out: *u8, cap: i64) -> i64 { 48 let fd: i64 = sys_openat_rd(path) 49 if fd <= 0 { return 0 - 1 } 50 let n: i64 = sys_read(fd, out, cap) 51 sys_close(fd) 52 return n 53} 54 55func main() -> i64 { 56 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0 57 var total: i64 = 0 58 s_w("=== NX-TLS12-RECONNECT-STRESS GATE (live 1.3->1.2 fallback x24 to Porkbun ping; zero garbles) ===\n" as *u8) 59 60 let lr: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt\x00" as *u8, 300, 4194304) 61 if lr <= 0 { s_w(" trust load FAIL rc=" as *u8); s_n(lr); s_w("\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 62 let store: *TrustStore = lr as *TrustStore 63 s_w(" trust store CAs=" as *u8); s_n(trust_store_count(store)); s_w("\n" as *u8) 64 let now: i64 = sys_now_realtime_sec() 65 66 // ---- creds from the sovereign vault (/tmp/nxsecret.out); strip UTF-8 BOM ---- 67 let raw: *u8 = sys_mmap(512) 68 let rawn: i64 = s_read_file("/tmp/nxsecret.out\x00" as *u8, raw, 512) 69 if rawn <= 0 { s_w(" VAULT creds read FAILED (run ./_offc/nx_secret_cli.elf get porkbun)\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 70 var base: i64 = 0 71 if rawn >= 3 { if raw[0]==(0xEF as u8) { if raw[1]==(0xBB as u8) { if raw[2]==(0xBF as u8) { base=3 } } } } 72 let creds: *u8 = (raw as i64 + base) as *u8 73 let clen: i64 = rawn - base 74 var nl: i64 = 0 75 while nl < clen { if creds[nl]==0x0a { break }; nl=nl+1 } 76 var ak_end: i64 = nl 77 if ak_end>0 { if creds[ak_end-1]==0x0d { ak_end=ak_end-1 } } 78 let ak: *u8 = creds 79 let akn: i64 = ak_end 80 let s2: i64 = nl + 1 81 var nl2: i64 = s2 82 while nl2 < clen { if creds[nl2]==0x0a { break }; nl2=nl2+1 } 83 var sk_end: i64 = nl2 84 if sk_end>s2 { if creds[sk_end-1]==0x0d { sk_end=sk_end-1 } } 85 let sk: *u8 = (creds as i64 + s2) as *u8 86 let skn: i64 = sk_end - s2 87 if akn<=0 { s_w(" apikey empty\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 88 if skn<=0 { s_w(" secret empty\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 89 s_w(" vault creds loaded (apikey len=" as *u8); s_n(akn); s_w(", secret len=" as *u8); s_n(skn); s_w(")\n" as *u8) 90 91 // ---- Row 0: TLS 1.3 regression (LE directory GET still works) ---- 92 let le_url: *u8 = "https://acme-v02.api.letsencrypt.org/directory\x00" as *u8 93 let lebuf: *u8 = sys_mmap(65536) 94 let letot: *i64 = sys_mmap(8) as *i64 95 var le_ok: i64 = 0 96 if nx_acme_req(le_url, 46, 0, 0 as *u8, 0, 0 as *u8, 0, store, now, lebuf, 65536, letot) == NX_ACME_HTTP_OK { 97 let rr: *i64 = nx_http_resp_alloc() 98 if nx_http_response_parse(lebuf, letot[0], rr) == 0 { if rr[1] == 200 { le_ok = 1 } } 99 } 100 total = total + 1 101 s_w(" row REGRESSION: LE directory (TLS 1.3) GET -> 200: " as *u8) 102 if le_ok==1 { s_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { s_w("FAIL\n" as *u8) } 103 104 // ---- Rows 1..N: rapid 1.3->1.2 fallback Porkbun ping; assert 200 each ---- 105 let ping_url: *u8 = "https://api.porkbun.com/api/json/v3/ping\x00" as *u8 106 let body: *u8 = sys_mmap(1024) 107 var bo: i64 = pk_creds(body, 0, ak, akn, sk, skn) 108 bo = pk_put(body, bo, "}" as *u8) 109 110 let N: i64 = 24 111 var ok_count: i64 = 0 112 var i: i64 = 0 113 while i < N { 114 let resp: *u8 = sys_mmap(16384) 115 let tot: *i64 = sys_mmap(8) as *i64 116 let rc: i64 = nx_acme_req(ping_url, 40, 1, "application/json" as *u8, 16, body, bo, store, now, resp, 16384, tot) 117 // pk_check asserts HTTP 200 AND JSON "status":"SUCCESS" -- a completed 118 // 0xC02F handshake AND a valid authed round trip. A garbled/failed 119 // handshake (FAIL CLOSED -> no session) cannot reach SUCCESS. 120 var good: i64 = 0 121 if rc == NX_ACME_HTTP_OK { if pk_check(resp, tot[0]) == NX_PORKBUN_OK { good = 1 } } 122 if good == 1 { ok_count = ok_count + 1 } 123 else { s_w(" ping " as *u8); s_n(i); s_w(" NOT SUCCESS: rc=" as *u8); s_n(rc); s_w("\n" as *u8) } 124 i = i + 1 125 } 126 total = total + 1 127 s_w(" row STRESS: " as *u8); s_n(N); s_w(" rapid 1.3->1.2 Porkbun pings -> HTTP 200 each: " as *u8) 128 s_w("(" as *u8); s_n(ok_count); s_w("/" as *u8); s_n(N); s_w(") " as *u8) 129 if ok_count == N { s_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { s_w("FAIL\n" as *u8) } 130 131 s_w("NX-TLS12-RECONNECT-STRESS rows=" as *u8); s_n(total); s_w(" pass=" as *u8); s_n(pass[0]) 132 if pass[0]==total { s_w(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 133 s_w(" verdict=RED\n" as *u8); sys_exit(1); return 1 134}