code wiki / _hdl_build / nx_tls12_ske_verify_gate.nx
nx_tls12_ske_verify_gate.nx source
↩ module page · 115 lines · 6786 B
1// nx_tls12_ske_verify_gate.nx -- SOVEREIGN gate for TLS 1.2 ECDHE-RSA
2// ServerKeyExchange signature verification (nx_tls12_ske_verify.nx).
3//
4// FIXTURE (self-built, NOT a published vector -- there is no published KAT for
5// a TLS ServerKeyExchange): generated by openssl (scratchpad gen_ske_fixture.sh)
6// - RSA-2048 leaf key (e=65537), modulus MOD below
7// - client_random = 00..1f, server_random = 20..3f (deterministic)
8// - ECDHE_params = 03 0017 41 || real secp256r1 uncompressed point (69 B)
9// - SIG = openssl `dgst -sha256 -sign` over client_random||server_random||params
10// (RSASSA-PKCS1-v1_5, 256 bytes); openssl `-verify` reports "Verified OK".
11// openssl SIGNS; this sovereign NishiLang gate VERIFIES -- a cross-implementation
12// check of our RSA PKCS1-v1.5+SHA-256 path against OpenSSL's signer.
13//
14// Checks:
15// 1. verify PASSES against the genuine openssl signature.
16// 2. neg-control: flip one signature byte -> verify FAILS.
17// 3. neg-control: flip one server_random byte (signed data) -> verify FAILS.
18// 4. neg-control: flip one ECDHE point byte (signed params) -> verify FAILS.
19// 5. wire path: parse a full SKE body (params||sigalg||siglen||sig) + verify -> PASSES.
20// 6. wire neg-control: corrupt a point byte in the body -> verify FAILS.
21// expect_exit: 0
22// license_tier: ORIGINAL
23
24import "nx_syscalls.nx"
25import "nx_gate_emit_lib.nx"
26import "nx_tls12_ske_verify.nx"
27
28func g_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
29func ghx_nyb(c: i64) -> i64 {
30 if c >= 0x30 { if c <= 0x39 { return c - 0x30 } }
31 if c >= 0x61 { if c <= 0x66 { return c - 0x61 + 10 } }
32 if c >= 0x41 { if c <= 0x46 { return c - 0x41 + 10 } }
33 return 0
34}
35// Decode a null-terminated ASCII-hex string into `out`; returns byte count.
36func ghx_s(hex: *u8, out: *u8) -> i64 {
37 let hexlen: i64 = g_strlen(hex)
38 var i: i64 = 0
39 while i < hexlen {
40 let hi: i64 = ghx_nyb(hex[i] as i64)
41 let lo: i64 = ghx_nyb(hex[i + 1] as i64)
42 out[i / 2] = ((hi << 4) | lo) as u8
43 i = i + 2
44 }
45 return hexlen / 2
46}
47
48func main() -> i64 {
49 g_puts("nx_tls12_ske_verify gate (ECDHE-RSA SKE sig verify; openssl fixture)\n" as *u8)
50 var pass: i64 = 0
51 var total: i64 = 0
52
53 let cr: *u8 = sys_mmap(32)
54 ghx_s("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" as *u8, cr)
55 let sr: *u8 = sys_mmap(32)
56 ghx_s("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" as *u8, sr)
57 let params: *u8 = sys_mmap(80)
58 let params_len: i64 = ghx_s("03001741044019217a3cd50a3e6a717f6359aeb550d5566b5c787ad8038e38916093a8124b1dcf1fba5e451d7932ae032f783d9777f965dd44cc89b4206e4ca69edfa70969" as *u8, params)
59 let sig: *u8 = sys_mmap(256)
60 let sig_len: i64 = ghx_s("2aeba4592dcd1cb10c3c090dd52a1bb94e3747c393ae10b7f9c2f1548f104196b9784642e4125f091b2dcdfaac408948cc7a2a342522aa775dcb1d785b761b775b7ac22434832fa1b2ada93011e9c0ef8bcf33168ecd0be67ad55e828ed990e867068ebf2a0198060526b421a74406c0d5467214b461740ea9b4643270c295be0e0dc2b9192fdb0c09d71ec59670825091d713449287b5c378bab0547fa55d05c1f8e070028526e44d94f465dcae6e191c428e8ceb3dc9216228aad137c8cb16e5e554dfe46955183fb30144dd29ad329fb7145af3056d73d9b37b7dbed02faa2b0a750f5fcaef6e5095d17a78f82d73831a3a4e39c993ee1a8a31114805fc9d" as *u8, sig)
61 let modn: *u8 = sys_mmap(256)
62 let mod_len: i64 = ghx_s("e2ba9b69dc47677720314f586f88d901988191a74d273a36c857d3ae469498c401d5ee5775db1a63853464978ec05b06eb4454493952fe71fa3114914b8ab02db5dc6617859da18c171aadcb2ba9ce82d16878bcb8462d2eb150bfaa8e77aba60fbadee72cc7d6f2afed8db107afe79c4be81f9036da8995a23e9a56414f23647550aed45e8c6fa81d101cca1a44f7479015ac4b6732c7de3b558106160bf4757aed07d4564c2575a68dd6608f023187a6f2c89bb0500fd8895257a167f6d233d36892a36abeabdae10aec1b5eba20d881c88d15a5156c9c95840ddb4147f80733811b204ab7d86b6aea23b08af2fa486f5b906e87501ff2e195e180c381bb59" as *u8, modn)
63
64 // Sanity: decoded fixture lengths.
65 var lensok: i64 = 1
66 if params_len != 69 { lensok = 0 }
67 if sig_len != 256 { lensok = 0 }
68 if mod_len != 256 { lensok = 0 }
69 pass = pass + g_check("fixture decodes: params=69 sig=256 modulus=256" as *u8, lensok); total = total + 1
70
71 // ---- 1. genuine signature verifies ----
72 let v1: i64 = nx_tls12_ske_verify_n(cr, sr, params, 69, sig, 256, modn, 65537)
73 pass = pass + g_check("verify PASSES on genuine openssl signature" as *u8, (v1 == NX_TLS12_SKE_OK) as i64); total = total + 1
74
75 // ---- 2. flipped signature byte -> reject ----
76 sig[100] = (sig[100] ^ 0x01) as u8
77 let v2: i64 = nx_tls12_ske_verify_n(cr, sr, params, 69, sig, 256, modn, 65537)
78 pass = pass + g_check("neg: flipped signature byte -> verify FAILS" as *u8, (v2 != NX_TLS12_SKE_OK) as i64); total = total + 1
79 sig[100] = (sig[100] ^ 0x01) as u8 // restore
80
81 // ---- 3. flipped server_random (signed data) -> reject ----
82 sr[5] = (sr[5] ^ 0x01) as u8
83 let v3: i64 = nx_tls12_ske_verify_n(cr, sr, params, 69, sig, 256, modn, 65537)
84 pass = pass + g_check("neg: tampered server_random -> verify FAILS" as *u8, (v3 != NX_TLS12_SKE_OK) as i64); total = total + 1
85 sr[5] = (sr[5] ^ 0x01) as u8 // restore
86
87 // ---- 4. flipped ECDHE point (signed params) -> reject ----
88 params[40] = (params[40] ^ 0x01) as u8
89 let v4: i64 = nx_tls12_ske_verify_n(cr, sr, params, 69, sig, 256, modn, 65537)
90 pass = pass + g_check("neg: tampered ECDHE point -> verify FAILS" as *u8, (v4 != NX_TLS12_SKE_OK) as i64); total = total + 1
91 params[40] = (params[40] ^ 0x01) as u8 // restore
92
93 // ---- 5. full wire path: params || sigalg(0x0401) || siglen(0x0100) || sig ----
94 let body: *u8 = sys_mmap(400)
95 var bi: i64 = 0
96 while bi < 69 { body[bi] = params[bi]; bi = bi + 1 }
97 body[69] = 0x04 as u8 // SignatureAndHashAlgorithm: hash=sha256(4)
98 body[70] = 0x01 as u8 // sig =rsa(1)
99 body[71] = 0x01 as u8 // sig_len hi (0x0100 = 256)
100 body[72] = 0x00 as u8 // sig_len lo
101 bi = 0
102 while bi < 256 { body[73 + bi] = sig[bi]; bi = bi + 1 }
103 let body_len: i64 = 73 + 256
104 let v5: i64 = nx_tls12_ske_verify_wire(cr, sr, body, body_len, modn, 65537)
105 pass = pass + g_check("wire path: parse SKE body + verify -> PASSES" as *u8, (v5 == NX_TLS12_SKE_OK) as i64); total = total + 1
106
107 // ---- 6. wire neg-control: corrupt a point byte in the body ----
108 body[20] = (body[20] ^ 0x01) as u8
109 let v6: i64 = nx_tls12_ske_verify_wire(cr, sr, body, body_len, modn, 65537)
110 pass = pass + g_check("wire neg: corrupted point byte -> verify FAILS" as *u8, (v6 != NX_TLS12_SKE_OK) as i64); total = total + 1
111
112 g_puts("gate: " as *u8); g_pn(pass); g_puts("/" as *u8); g_pn(total); g_puts("\n" as *u8)
113 if pass == total { return 0 }
114 return 1
115}