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}