code wiki / _hdl_build / nx_fw_signed_robust_gate.nx
nx_fw_signed_robust_gate.nx source
↩ module page · 107 lines · 6247 B
1// nx_fw_signed_robust_gate.nx -- proves the fusion: signature-gated A/B + factory never-brick.
2//
3// T0 signed-clean-flash : a signed capsule flashes + commits to the inactive bank -> SR_OK + selectable + flipped
4// F1 forged-active-fallback : a FORGED image planted in the ACTIVE bank is NOT selected; -> selectable via signed factory
5// sr_select falls back to a signature-valid image (the headline)
6// F2 double-fault-factory : both banks dead -> the signed immutable factory -> selectable
7// N1 all-bad-teeth : both banks + the factory all forged/garbage -> NOT selectable (honest)
8// N2 forged-source-rejected : sr_safe_flash refuses to even WRITE a forged source -> SR_REJECTED, banks intact
9//
10// GREEN only if all five hold. ed25519 signs are minimized (auth + forged signed ONCE, copied per
11// scenario). Evidence -> knowledge/status/fw_signed_robust_gate.log.
12// Sovereign: imports nx_fw_signed_robust (-> nx_fw_capsule -> nx_ed25519) + nx_framed_append + nx_syscalls. license_tier: ORIGINAL
13import "nx_fw_signed_robust.nx"
14import "nx_framed_append.nx"
15import "nx_syscalls.nx"
16
17const SRG_LOG: *u8 = "knowledge/status/fw_signed_robust_gate.log"
18const SRG_PAY: *u8 = "NISHI-fw-signed-robust-payload"
19
20func srg_len(s: *u8) -> i64 { var i: i64 = 0; while s[i] != 0 as u8 { i = i + 1 } return i }
21func srg_garbage(path: *u8) -> i64 {
22 let g: *u8 = sys_mmap(64); var i: i64 = 0; while i < 32 { g[i] = 0xff as u8; i = i + 1 }
23 cp_write(path, g, 32)
24 return 0
25}
26func srg_row(name: *u8, pass: i64) -> i64 {
27 let buf: *u8 = sys_mmap(528)
28 var o: i64 = 0
29 o = cp_cat(buf, o, "SRG row=\x00" as *u8)
30 o = cp_cat(buf, o, name)
31 if pass == 1 { o = cp_cat(buf, o, " verdict=PASS\x00" as *u8) } else { o = cp_cat(buf, o, " verdict=FAIL\x00" as *u8) }
32 buf[o] = 0 as u8
33 fa_appendz(SRG_LOG, buf, 512)
34 cp_puts(" "); cp_puts(name)
35 if pass == 1 { cp_puts(" PASS\n") } else { cp_puts(" FAIL\n") }
36 return 0
37}
38
39func main() -> i64 {
40 cp_puts("fw-signed-robust gate (signature-gated A/B + factory never-brick)\n")
41 let e: i64 = sys_now_realtime_sec()
42 let p: i64 = __syscall(39, 0, 0, 0, 0, 0, 0)
43 let pl: i64 = srg_len(SRG_PAY)
44 let plat: *u8 = sys_mmap(32); cap_plat_seed(plat)
45 let forged: *u8 = sys_mmap(32); var i: i64 = 0; while i < 32 { forged[i] = ((i * 3 + 99) & 0xff) as u8; i = i + 1 }
46
47 // sign ONCE; copy these into bank/factory slots per scenario (no re-signing)
48 let srcA: *u8 = sys_mmap(256); cap_path(srcA, "/tmp/srg_auth." as *u8, e, p); cap_make(srcA, SRG_PAY, pl, plat)
49 let srcF: *u8 = sys_mmap(256); cap_path(srcF, "/tmp/srg_forg." as *u8, e, p); cap_make(srcF, SRG_PAY, pl, forged)
50 let srcG: *u8 = sys_mmap(256); cap_path(srcG, "/tmp/srg_garb." as *u8, e, p); srg_garbage(srcG)
51
52 let a: *u8 = sys_mmap(256); let b: *u8 = sys_mmap(256); let fac: *u8 = sys_mmap(256); let sel: *u8 = sys_mmap(256)
53
54 // ---- T0 signed clean flash ----
55 cap_path(a, "/tmp/srg_t0a." as *u8, e, p); cap_path(b, "/tmp/srg_t0b." as *u8, e, p); cap_path(fac, "/tmp/srg_t0f." as *u8, e, p); cap_path(sel, "/tmp/srg_t0s." as *u8, e, p)
56 sr_copy(srcA, a); sr_copy(srcA, b); sr_copy(srcA, fac); sr_write_sel_atomic(sel, SR_BANK_A)
57 let r0: i64 = sr_safe_flash(sel, a, b, fac, srcA, 0)
58 var t0: i64 = 0; if r0 == SR_OK { if sr_selectable(sel, a, b, fac) == 1 { if sr_read_sel(sel) == SR_BANK_B { t0 = 1 } } }
59
60 // ---- F1 forged in active bank -> rejected -> falls back to signed factory ----
61 cap_path(a, "/tmp/srg_f1a." as *u8, e, p); cap_path(b, "/tmp/srg_f1b." as *u8, e, p); cap_path(fac, "/tmp/srg_f1f." as *u8, e, p); cap_path(sel, "/tmp/srg_f1s." as *u8, e, p)
62 sr_copy(srcF, a); sr_copy(srcG, b); sr_copy(srcA, fac); sr_write_sel_atomic(sel, SR_BANK_A)
63 var f1: i64 = 0; if cap_verify(a) == 0 { if sr_selectable(sel, a, b, fac) == 1 { f1 = 1 } }
64
65 // ---- F2 double fault -> signed factory ----
66 cap_path(a, "/tmp/srg_f2a." as *u8, e, p); cap_path(b, "/tmp/srg_f2b." as *u8, e, p); cap_path(fac, "/tmp/srg_f2f." as *u8, e, p); cap_path(sel, "/tmp/srg_f2s." as *u8, e, p)
67 sr_copy(srcG, a); sr_copy(srcG, b); sr_copy(srcA, fac); sr_write_sel_atomic(sel, SR_BANK_A)
68 var f2: i64 = 0; if sr_selectable(sel, a, b, fac) == 1 { f2 = 1 }
69
70 // ---- N1 all bad incl forged factory -> NOT selectable (teeth) ----
71 cap_path(a, "/tmp/srg_n1a." as *u8, e, p); cap_path(b, "/tmp/srg_n1b." as *u8, e, p); cap_path(fac, "/tmp/srg_n1f." as *u8, e, p); cap_path(sel, "/tmp/srg_n1s." as *u8, e, p)
72 sr_copy(srcF, a); sr_copy(srcG, b); sr_copy(srcF, fac); sr_write_sel_atomic(sel, SR_BANK_A)
73 var n1: i64 = 0; if sr_selectable(sel, a, b, fac) == 0 { n1 = 1 }
74
75 // ---- N2 forged source refused by flash ----
76 cap_path(a, "/tmp/srg_n2a." as *u8, e, p); cap_path(b, "/tmp/srg_n2b." as *u8, e, p); cap_path(fac, "/tmp/srg_n2f." as *u8, e, p); cap_path(sel, "/tmp/srg_n2s." as *u8, e, p)
77 sr_copy(srcA, a); sr_copy(srcA, b); sr_copy(srcA, fac); sr_write_sel_atomic(sel, SR_BANK_A)
78 let r2: i64 = sr_safe_flash(sel, a, b, fac, srcF, 0)
79 var n2: i64 = 0; if r2 == SR_REJECTED { if sr_selectable(sel, a, b, fac) == 1 { n2 = 1 } }
80
81 var passes: i64 = 0
82 if t0 == 1 { passes = passes + 1 }
83 if f1 == 1 { passes = passes + 1 }
84 if f2 == 1 { passes = passes + 1 }
85 if n1 == 1 { passes = passes + 1 }
86 if n2 == 1 { passes = passes + 1 }
87 var green: i64 = 0
88 if passes == 5 { green = 1 }
89
90 srg_row("T0-signed-clean-flash \x00" as *u8, t0)
91 srg_row("F1-forged-active-fallback\x00" as *u8, f1)
92 srg_row("F2-double-fault-factory \x00" as *u8, f2)
93 srg_row("N1-all-bad-not-selectable\x00" as *u8, n1)
94 srg_row("N2-forged-source-rejected\x00" as *u8, n2)
95
96 let vb: *u8 = sys_mmap(528)
97 var o: i64 = 0
98 o = cp_cat(vb, o, "FW-SIGNED-ROBUST verdict=\x00" as *u8)
99 if green == 1 { o = cp_cat(vb, o, "GREEN\x00" as *u8) } else { o = cp_cat(vb, o, "RED\x00" as *u8) }
100 o = cp_cat(vb, o, " passes=\x00" as *u8); o = cp_catn(vb, o, passes); o = cp_cat(vb, o, "/5 END\x00" as *u8)
101 vb[o] = 0 as u8
102 fa_appendz(SRG_LOG, vb, 512)
103 cp_puts(vb); cp_puts("\n")
104
105 if green == 1 { return 0 }
106 return 1
107}