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}