code wiki / (root) / nx_emitted_substrate_test.nx

nx_emitted_substrate_test.nx source

↩ module page · 217 lines · 9026 B

1// nx_emitted_substrate_test.nx -- smoke for Phase 5 substrate 2// emission. 3// 4// Exercises: 5// 1. Allocation + canary + initial state 6// 2. Add 3 expected hashes 7// 3. Duplicate add rejected 8// 4. Sign + verify roundtrip 9// 5. Frozen-after-sign: add_expected refused after signing 10// 6. Tamper detection: mutate target_tier / n_expected / a 11// stored hash field -> verify returns BAD_SIG 12// 7. Wrong pub key -> BAD_SIG 13// 8. populate downstream manifest from emitted record 14// 9. Bad-input gates + canary tamper 15 16import "nx_syscalls.nx" 17import "nx_blob_store.nx" 18import "nx_substrate_manifest.nx" 19import "nx_emitted_substrate.nx" 20 21// RFC 8032 §7.1 Test 1 keypair (same as the Ed25519-sign test). 22func _rfc_priv(buf: *u8) -> i64 { 23 buf[0] = 0x9d as u8; buf[1] = 0x61 as u8 24 buf[2] = 0xb1 as u8; buf[3] = 0x9d as u8 25 buf[4] = 0xef as u8; buf[5] = 0xfd as u8 26 buf[6] = 0x5a as u8; buf[7] = 0x60 as u8 27 buf[8] = 0xba as u8; buf[9] = 0x84 as u8 28 buf[10] = 0x4a as u8; buf[11] = 0xf4 as u8 29 buf[12] = 0x92 as u8; buf[13] = 0xec as u8 30 buf[14] = 0x2c as u8; buf[15] = 0xc4 as u8 31 buf[16] = 0x44 as u8; buf[17] = 0x49 as u8 32 buf[18] = 0xc5 as u8; buf[19] = 0x69 as u8 33 buf[20] = 0x7b as u8; buf[21] = 0x32 as u8 34 buf[22] = 0x69 as u8; buf[23] = 0x19 as u8 35 buf[24] = 0x70 as u8; buf[25] = 0x3b as u8 36 buf[26] = 0xac as u8; buf[27] = 0x03 as u8 37 buf[28] = 0x1c as u8; buf[29] = 0xae as u8 38 buf[30] = 0x7f as u8; buf[31] = 0x60 as u8 39 return 0 40} 41 42func _rfc_pub(buf: *u8) -> i64 { 43 buf[0] = 0xd7 as u8; buf[1] = 0x5a as u8 44 buf[2] = 0x98 as u8; buf[3] = 0x01 as u8 45 buf[4] = 0x82 as u8; buf[5] = 0xb1 as u8 46 buf[6] = 0x0a as u8; buf[7] = 0xb7 as u8 47 buf[8] = 0xd5 as u8; buf[9] = 0x4b as u8 48 buf[10] = 0xfe as u8; buf[11] = 0xd3 as u8 49 buf[12] = 0xc9 as u8; buf[13] = 0x64 as u8 50 buf[14] = 0x07 as u8; buf[15] = 0x3a as u8 51 buf[16] = 0x0e as u8; buf[17] = 0xe1 as u8 52 buf[18] = 0x72 as u8; buf[19] = 0xf3 as u8 53 buf[20] = 0xda as u8; buf[21] = 0xa6 as u8 54 buf[22] = 0x23 as u8; buf[23] = 0x25 as u8 55 buf[24] = 0xaf as u8; buf[25] = 0x02 as u8 56 buf[26] = 0x1a as u8; buf[27] = 0x68 as u8 57 buf[28] = 0xf7 as u8; buf[29] = 0x07 as u8 58 buf[30] = 0x51 as u8; buf[31] = 0x1a as u8 59 return 0 60} 61 62// Construct a synthetic 32-byte "emitter install_hash" — same shape 63// as a real install_hash would be after nx_install_hash_compute. 64func _make_emitter_hash(buf: *u8) -> i64 { 65 var i: i64 = 0 66 while i < 32 { 67 buf[i] = ((i * 11) & 255) as u8 68 i = i + 1 69 } 70 return 0 71} 72 73func _fill(buf: *u8, len: i64, seed: i64) -> i64 { 74 var i: i64 = 0 75 while i < len { 76 buf[i] = (((i * 29) + seed) & 255) as u8 77 i = i + 1 78 } 79 return 0 80} 81 82func _hash_of(bytes: *u8, len: i64) -> *NxBlobHash { 83 let s: *NxBlobStore = nx_blob_store_new() 84 let h: *NxBlobHash = nx_blob_hash_new() 85 nx_blob_store_put(s, bytes, len, h) 86 return h 87} 88 89func main() -> i64 { 90 let priv: *u8 = sys_mmap(64) 91 _rfc_priv(priv) 92 let pub: *u8 = sys_mmap(64) 93 _rfc_pub(pub) 94 let emitter_hash: *u8 = sys_mmap(64) 95 _make_emitter_hash(emitter_hash) 96 97 // ----- 1. Allocation + initial state ----- 98 let r: *NxEmittedSubstrate = nx_emitted_substrate_new( 99 emitter_hash, NX_TIER_INF_MOBILE, NX_ISA_RV64) 100 if nx_emitted_substrate_is_valid(r) != 1 { return 1 } 101 if nx_emitted_substrate_n_expected(r) != 0 { return 2 } 102 if nx_emitted_substrate_is_signed(r) != 0 { return 3 } 103 if r.target_tier != NX_TIER_INF_MOBILE { return 4 } 104 if r.target_isa != NX_ISA_RV64 { return 5 } 105 106 // ----- 2. Add 3 expected hashes ----- 107 let p1: *u8 = sys_mmap(64) 108 _fill(p1, 32, 1) 109 let h1: *NxBlobHash = _hash_of(p1, 32) 110 let p2: *u8 = sys_mmap(64) 111 _fill(p2, 32, 2) 112 let h2: *NxBlobHash = _hash_of(p2, 32) 113 let p3: *u8 = sys_mmap(64) 114 _fill(p3, 32, 3) 115 let h3: *NxBlobHash = _hash_of(p3, 32) 116 117 if nx_emitted_substrate_add_expected(r, h1) != NX_EMIT_OK { return 6 } 118 if nx_emitted_substrate_add_expected(r, h2) != NX_EMIT_OK { return 7 } 119 if nx_emitted_substrate_add_expected(r, h3) != NX_EMIT_OK { return 8 } 120 if nx_emitted_substrate_n_expected(r) != 3 { return 9 } 121 122 // ----- 3. Duplicate rejected ----- 123 if nx_emitted_substrate_add_expected(r, h1) != NX_EMIT_DUPLICATE { return 10 } 124 if nx_emitted_substrate_n_expected(r) != 3 { return 11 } // unchanged 125 126 // ----- 4. Sign + verify ----- 127 if nx_emitted_substrate_sign(r, priv) != NX_EMIT_OK { return 12 } 128 if nx_emitted_substrate_is_signed(r) != 1 { return 13 } 129 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_OK { return 14 } 130 131 // ----- 5. Frozen after sign: add_expected refused ----- 132 let h_late: *NxBlobHash = nx_blob_hash_new() 133 h_late.w0 = 0xCAFE 134 h_late.w1 = 0xBABE 135 if nx_emitted_substrate_add_expected(r, h_late) != NX_EMIT_TAMPER { return 15 } 136 if nx_emitted_substrate_n_expected(r) != 3 { return 16 } // unchanged 137 138 // ----- 6. Tamper detection: mutate target_tier ----- 139 let orig_tier: i64 = r.target_tier 140 r.target_tier = NX_TIER_INF_HPC 141 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_BAD_SIG { return 17 } 142 r.target_tier = orig_tier 143 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_OK { return 18 } 144 145 // Mutate a stored hash field directly. 146 let h_first: *NxBlobHash = (r.expected_hashes_ptrs[0]) as *NxBlobHash 147 let orig_w0: i64 = h_first.w0 148 h_first.w0 = h_first.w0 ^ 1 // flip 1 bit 149 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_BAD_SIG { return 19 } 150 h_first.w0 = orig_w0 151 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_OK { return 20 } 152 153 // Mutate ts_emit_us -- captured in canonical bytes; signature catches. 154 let orig_ts: i64 = r.ts_emit_us 155 r.ts_emit_us = r.ts_emit_us + 1 156 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_BAD_SIG { return 21 } 157 r.ts_emit_us = orig_ts 158 if nx_emitted_substrate_verify_sig(r, pub) != NX_EMIT_OK { return 22 } 159 160 // ----- 7. Wrong pub key ----- 161 let wrong_pub: *u8 = sys_mmap(64) 162 var w: i64 = 0 163 while w < 32 { 164 wrong_pub[w] = pub[w] 165 w = w + 1 166 } 167 wrong_pub[0] = ((wrong_pub[0] as i64) ^ 1) as u8 168 let rc_wp: i64 = nx_emitted_substrate_verify_sig(r, wrong_pub) 169 if rc_wp == NX_EMIT_OK { return 23 } 170 // BAD_SIG (math fails) or BAD_INPUT (decompress fails) both 171 // acceptable refusals. 172 173 // ----- 8. Populate downstream manifest from the verified record ----- 174 let downstream_store: *NxBlobStore = nx_blob_store_new() 175 let downstream_manifest: *NxSubstrateManifest = nx_substrate_manifest_new(downstream_store) 176 if nx_emitted_substrate_to_manifest(r, downstream_manifest) != NX_EMIT_OK { return 24 } 177 if downstream_manifest.n_expected != 3 { return 25 } 178 if nx_substrate_manifest_n_missing(downstream_manifest) != 3 { return 26 } 179 // Downstream ingests the 3 payloads -> manifest completes. 180 if nx_substrate_manifest_ingest(downstream_manifest, h1, p1, 32) != NX_SM_INGESTED { return 27 } 181 if nx_substrate_manifest_ingest(downstream_manifest, h2, p2, 32) != NX_SM_INGESTED { return 28 } 182 if nx_substrate_manifest_ingest(downstream_manifest, h3, p3, 32) != NX_SM_INGESTED { return 29 } 183 if nx_substrate_manifest_is_complete(downstream_manifest) != 1 { return 30 } 184 185 // ----- 9. Bad-input gates ----- 186 let null_hash: *u8 = (0 as i64) as *u8 187 let null_emit: *NxEmittedSubstrate = (0 as i64) as *NxEmittedSubstrate 188 // null emitter_install_hash -> new returns null 189 if (nx_emitted_substrate_new(null_hash, 0, 0) as i64) != 0 { return 31 } 190 // null hash in add_expected 191 let null_h: *NxBlobHash = (0 as i64) as *NxBlobHash 192 if nx_emitted_substrate_add_expected(null_emit, h1) != NX_EMIT_TAMPER { return 32 } 193 // sign with null priv 194 if nx_emitted_substrate_sign(r, null_hash) != NX_EMIT_BAD_INPUT { return 33 } 195 // verify with null pub 196 if nx_emitted_substrate_verify_sig(r, null_hash) != NX_EMIT_BAD_INPUT { return 34 } 197 198 // ----- 10. Canary tamper ----- 199 let tamper_emitter: *u8 = sys_mmap(64) 200 _make_emitter_hash(tamper_emitter) 201 let tr: *NxEmittedSubstrate = nx_emitted_substrate_new( 202 tamper_emitter, NX_TIER_INF_MOBILE, NX_ISA_RV64) 203 nx_emitted_substrate_add_expected(tr, h1) 204 tr.canary_post = 0xDEADBEEF 205 if nx_emitted_substrate_is_valid(tr) != 0 { return 35 } 206 if nx_emitted_substrate_add_expected(tr, h2) != NX_EMIT_TAMPER { return 36 } 207 if nx_emitted_substrate_sign(tr, priv) != NX_EMIT_TAMPER { return 37 } 208 if nx_emitted_substrate_verify_sig(tr, pub) != NX_EMIT_TAMPER { return 38 } 209 if nx_emitted_substrate_n_expected(tr) != -1 { return 39 } 210 211 // ----- 11. Sealed-enum gate ----- 212 if nx_emit_verdict_is_valid(NX_EMIT_OK) != 1 { return 40 } 213 if nx_emit_verdict_is_valid(-1) != 0 { return 41 } 214 if nx_emit_verdict_is_valid(NX_EMIT_N) != 0 { return 42 } 215 216 return 0 217}