nx_tls12_probe_test.nx source
↩ module page · 139 lines · 6707 B
1// nx_tls12_probe_test.nx -- LIVE probe of the sovereign TLS 1.2 ClientHello + ServerHello parse (rung 5 step 1).
2// Connects to a host (default news.ycombinator.com, override via argv[1]), sends our rung-1 1.2 ClientHello,
3// reads the first response record, and reports:
4// CT= outer record ContentType (22=handshake=GOOD, 21=alert)
5// if alert: AL= alert description (40=handshake_failure, 70=protocol_version, ...)
6// if handshake: HT= first handshake type (2=ServerHello) ; CI= negotiated cipher suite ; SR0= server_random[0]
7// Exit 0 iff we got a ServerHello (the live proof HN accepts our 1.2 ClientHello). license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_url.nx"
10import "nx_https_url_for_fetch.nx"
11import "nx_https_url_connect.nx"
12import "nx_tls13_read_record_from_fd.nx"
13import "nx_tls12_hello.nx"
14import "nx_tls12_parse.nx"
15
16func pb_dec(c1: i64, c2: i64, v: i64) -> i64 {
17 let lab: *u8 = sys_mmap(8); lab[0] = c1 as u8; lab[1] = c2 as u8; lab[2] = 0x3D as u8
18 sys_write(2, lab, 3)
19 var m: i64 = v
20 if m < 0 { sys_write(2, "-" as *u8, 1); m = 0 - m }
21 let t: *u8 = sys_mmap(24); var k: i64 = 0
22 if m == 0 { t[0] = 48 as u8; k = 1 }
23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
24 let o: *u8 = sys_mmap(24); var i: i64 = 0
25 while i < k { o[i] = t[k - 1 - i]; i = i + 1 }
26 sys_write(2, o, k); sys_write(2, "\n" as *u8, 1)
27 return 0
28}
29
30func main(argc: i64, argv: *i64) -> i64 {
31 var url: *u8 = "https://news.ycombinator.com/\x00" as *u8
32 if argc >= 2 { url = argv[1] as *u8 }
33
34 // ---- connect ----
35 let url_p: *NxUrl = nx_url_new()
36 let target_raw: *u8 = sys_mmap(32)
37 let target: *NxHttpsTarget = target_raw as *NxHttpsTarget
38 target.url = url_p
39 target.port = 0
40 if nx_https_url_for_fetch(url, target) != NX_HTTPS_URL_OK { return 12 }
41 let host_len: i64 = target.url.host_len
42 let fd_p: *i64 = sys_mmap(16) as *i64
43 let ucv: i64 = nx_https_url_connect(target, url, 1781100001, fd_p)
44 pb_dec(0x55, 0x43, ucv) // UC=
45 if ucv != NX_HTTPS_CONNECT_OK { return 13 }
46 let fd: i64 = *fd_p
47 sys_set_socket_timeout(fd, 10)
48 let host: *u8 = url + target.url.host_off
49
50 // ---- emit + send our TLS 1.2 ClientHello as a handshake record ----
51 let rnd: *u8 = sys_mmap(32)
52 var i: i64 = 0
53 while i < 32 { rnd[i] = (0xC0 + i) as u8; i = i + 1 }
54 let ch: *u8 = sys_mmap(1024)
55 let ch_n: i64 = tls12_client_hello_emit(rnd, host, host_len, ch, 1024)
56 pb_dec(0x43, 0x48, ch_n) // CH=
57 if ch_n < 0 { sys_close(fd); return 14 }
58
59 let rec: *u8 = sys_mmap(2048)
60 rec[0] = 22 as u8 // ContentType handshake
61 rec[1] = 0x03 as u8; rec[2] = 0x03 as u8 // record version TLS 1.2
62 rec[3] = ((ch_n >> 8) & 0xff) as u8
63 rec[4] = (ch_n & 0xff) as u8
64 i = 0
65 while i < ch_n { rec[5 + i] = ch[i]; i = i + 1 }
66 var sent: i64 = 0
67 let want: i64 = 5 + ch_n
68 while sent < want {
69 let w: i64 = sys_write(fd, (rec as i64 + sent) as *u8, want - sent)
70 if w <= 0 { sys_close(fd); pb_dec(0x57, 0x52, w); return 15 } // WR=
71 sent = sent + w
72 }
73
74 // ---- read records, reassemble the handshake stream, parse messages until ServerHelloDone ----
75 let resp: *u8 = sys_mmap(20000)
76 let hs: *u8 = sys_mmap(131072) // accumulated handshake bytes
77 var hlen: i64 = 0
78 var hpos: i64 = 0
79 let srand: *u8 = sys_mmap(64)
80 let cipher: *i64 = sys_mmap(16) as *i64
81 var got_sh: i64 = 0
82 var got_cert: i64 = 0
83 var got_skx: i64 = 0
84 var got_done: i64 = 0
85 var recs: i64 = 0
86 while got_done == 0 {
87 if recs >= 16 { got_done = 1 }
88 else {
89 let rt: i64 = nx_tls13_read_record_from_fd(fd, resp, 20000)
90 if rt < 5 { got_done = 1 }
91 else {
92 recs = recs + 1
93 let ct: i64 = resp[0] as i64
94 if ct == 21 { pb_dec(0x41, 0x4C, resp[6] as i64); sys_close(fd); return 20 } // AL= alert
95 if ct != 22 { sys_close(fd); return 21 }
96 var bi: i64 = 5
97 while bi < rt { hs[hlen] = resp[bi]; hlen = hlen + 1; bi = bi + 1 }
98 // parse complete handshake messages
99 var more: i64 = 1
100 while more == 1 {
101 if hpos + 4 > hlen { more = 0 }
102 else {
103 let mtype: i64 = hs[hpos] as i64
104 let mlen: i64 = ((hs[hpos+1] as i64) << 16) | ((hs[hpos+2] as i64) << 8) | (hs[hpos+3] as i64)
105 if hpos + 4 + mlen > hlen { more = 0 }
106 else {
107 let body: *u8 = (hs as i64 + hpos + 4) as *u8
108 if mtype == 2 {
109 if tls12_parse_server_hello(body, mlen, srand, cipher) == 1 { got_sh = 1; pb_dec(0x43, 0x49, cipher[0]) }
110 }
111 if mtype == 11 { got_cert = 1; pb_dec(0x43, 0x45, mlen) } // CE= Certificate msg len
112 if mtype == 12 {
113 let curve: *i64 = sys_mmap(16) as *i64
114 let pub: *u8 = sys_mmap(256); let publen: *i64 = sys_mmap(16) as *i64
115 let sigalg: *i64 = sys_mmap(16) as *i64
116 let sig: *u8 = sys_mmap(1024); let siglen: *i64 = sys_mmap(16) as *i64
117 if tls12_parse_server_key_exchange(body, mlen, curve, pub, publen, sigalg, sig, siglen) == 1 {
118 got_skx = 1
119 pb_dec(0x43, 0x56, curve[0]) // CV= named_curve
120 pb_dec(0x50, 0x4C, publen[0]) // PL= server ECDHE pubkey len
121 pb_dec(0x53, 0x41, sigalg[0]) // SA= signature algorithm
122 }
123 }
124 if mtype == 14 { got_done = 1 } // ServerHelloDone
125 hpos = hpos + 4 + mlen
126 }
127 }
128 }
129 }
130 }
131 }
132 sys_close(fd)
133 pb_dec(0x44, 0x4E, got_done) // DN= reached ServerHelloDone
134 if got_sh == 1 { if got_cert == 1 { if got_skx == 1 {
135 sys_write(1, "TLS12-PROBE: full server flow parsed (ServerHello+Certificate+ServerKeyExchange)\n" as *u8, 81)
136 return 0
137 } } }
138 return 30
139}