code wiki / (root) / nx_tls12_probe_test.nx

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}