code wiki / _hdl_build / nx_access_audit_gate.nx

nx_access_audit_gate.nx source

↩ module page · 107 lines · 6148 B

1// nx_access_audit_gate.nx -- gate for the tamper-evident access audit log (nx_access_audit). Builds a chain of 2// real PDP decision records, proves an intact chain verifies, and that EDITING an entry (e.g. flipping a 3// DENY to ALLOW to hide an intrusion), tampering a stored hash, or REORDERING entries all break verification. 4// Positive AND negative controls. Appends "ACCESSGATE row=nx_access_audit audit-log ... verdict=PASS" to 5// knowledge/status/access_gate.log on all-pass. license_tier: ORIGINAL 6import "nx_access_audit.nx" 7import "nx_syscalls.nx" 8 9func au_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10func au_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 11func au_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var k: i64=0; while s[k]!=(0 as u8){dst[o]=s[k];o=o+1;k=k+1} return o } 12func au_catnum(dst: *u8, off: i64, v: i64) -> i64 { var o: i64=off; let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{dst[o]=t[k-1-i];o=o+1;i=i+1} return o } 13func au_row(id: i64, ok: i64, what: *u8) -> i64 { au_w("AUROW " as *u8); au_num(id); au_w(" " as *u8); if ok==1 { au_w("PASS " as *u8) } else { au_w("FAIL " as *u8) } au_w(what); au_w("\n" as *u8); return ok } 14func au_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 15 16func main() -> i64 { 17 let genesis: *u8 = sys_mmap(32) // zero-filled 18 19 // 4 real PDP decision records 20 let e: *i64 = sys_mmap(8*8) as *i64 21 let l: *i64 = sys_mmap(8*8) as *i64 22 e[0]="seq=1 ip=203.0.113.7 role=admin res=/admin/save act=W verdict=ALLOW" as *u8 as i64 23 e[1]="seq=2 ip=8.8.8.8 role=public res=/admin act=R verdict=DENY_TIER" as *u8 as i64 24 e[2]="seq=3 ip=10.8.0.5 role=admin res=/webdev act=R verdict=ALLOW" as *u8 as i64 25 e[3]="seq=4 ip=203.0.113.9 role=- res=/admin/login act=W verdict=DENY_RATE" as *u8 as i64 26 var z: i64 = 0; while z < 4 { l[z] = au_slen(e[z] as *u8); z = z + 1 } 27 let n: i64 = 4 28 29 // build the chain (the stored hashes) 30 let h: *i64 = sys_mmap(8*8) as *i64 31 let prev: *u8 = sys_mmap(32) 32 var p: i64 = 0; while p < 32 { prev[p] = genesis[p]; p = p + 1 } 33 var k: i64 = 0 34 while k < n { 35 let hk: *u8 = sys_mmap(32) 36 aa_chain(prev, e[k] as *u8, l[k], hk) 37 h[k] = hk as i64 38 var c: i64 = 0; while c < 32 { prev[c] = hk[c]; c = c + 1 } 39 k = k + 1 40 } 41 42 var pass: i64 = 0 43 var rows: i64 = 0 44 var ok: i64 = 0 45 46 // R0: intact chain verifies 47 ok = aa_verify(e, l, h, n, genesis) 48 rows=rows+1; pass=pass+au_row(0, ok, "intact decision chain verifies" as *u8) 49 50 // R1 (NEG): EDIT an entry (flip seq2's DENY_TIER -> ALLOW to hide a blocked access) -> chain breaks 51 let et: *i64 = sys_mmap(8*8) as *i64 52 let lt: *i64 = sys_mmap(8*8) as *i64 53 var q: i64 = 0; while q < 4 { et[q] = e[q]; lt[q] = l[q]; q = q + 1 } 54 et[1]="seq=2 ip=8.8.8.8 role=public res=/admin act=R verdict=ALLOW" as *u8 as i64 55 lt[1]=au_slen(et[1] as *u8) 56 ok = 0; if aa_verify(et, lt, h, n, genesis)==0 { ok=1 } 57 rows=rows+1; pass=pass+au_row(1, ok, "edited entry (DENY->ALLOW) breaks the chain (neg control)" as *u8) 58 59 // R2 (NEG): tamper a STORED hash -> chain breaks 60 let ht: *i64 = sys_mmap(8*8) as *i64 61 var w: i64 = 0; while w < 4 { ht[w] = h[w]; w = w + 1 } 62 let h2copy: *u8 = sys_mmap(32) 63 let h2src: *u8 = h[2] as *u8 64 var d: i64 = 0; while d < 32 { h2copy[d] = h2src[d]; d = d + 1 } 65 if (h2copy[0] as i64)==0 { h2copy[0]=1 as u8 } else { h2copy[0]=0 as u8 } 66 ht[2] = h2copy as i64 67 ok = 0; if aa_verify(e, l, ht, n, genesis)==0 { ok=1 } 68 rows=rows+1; pass=pass+au_row(2, ok, "tampered stored hash breaks the chain (neg control)" as *u8) 69 70 // R3 (NEG): REORDER two entries -> chain breaks (order is bound in) 71 let er: *i64 = sys_mmap(8*8) as *i64 72 let lr: *i64 = sys_mmap(8*8) as *i64 73 var x: i64 = 0; while x < 4 { er[x] = e[x]; lr[x] = l[x]; x = x + 1 } 74 er[1] = e[2]; lr[1] = l[2]; er[2] = e[1]; lr[2] = l[1] 75 ok = 0; if aa_verify(er, lr, h, n, genesis)==0 { ok=1 } 76 rows=rows+1; pass=pass+au_row(3, ok, "reordered entries break the chain (neg control)" as *u8) 77 78 // R4: append a 5th decision -> chain extends + still verifies 79 e[4]="seq=5 ip=203.0.113.7 role=admin res=/admin/publish act=W verdict=ALLOW" as *u8 as i64 80 l[4]=au_slen(e[4] as *u8) 81 let h4: *u8 = sys_mmap(32) 82 aa_chain(h[3] as *u8, e[4] as *u8, l[4], h4) 83 h[4] = h4 as i64 84 ok = aa_verify(e, l, h, 5, genesis) 85 rows=rows+1; pass=pass+au_row(4, ok, "append a decision extends the chain; still verifies" as *u8) 86 87 // R5: deterministic -- rebuild h[0] equals the stored h[0] 88 let hr0: *u8 = sys_mmap(32) 89 aa_chain(genesis, e[0] as *u8, l[0], hr0) 90 let h0: *u8 = h[0] as *u8 91 ok = 1; var b: i64 = 0; while b < 32 { if hr0[b] != h0[b] { ok = 0 } b = b + 1 } 92 rows=rows+1; pass=pass+au_row(5, ok, "deterministic: same entry -> same chained hash" as *u8) 93 94 au_w("NX-ACCESS-AUDIT-GATE rows=" as *u8); au_num(rows); au_w(" pass=" as *u8); au_num(pass); au_w("\n" as *u8) 95 if pass == rows { 96 let line: *u8 = sys_mmap(256) 97 var off: i64 = au_cat(line, 0, "ACCESSGATE row=nx_access_audit audit-log rows=" as *u8) 98 off = au_catnum(line, off, rows); off = au_cat(line, off, " pass=" as *u8); off = au_catnum(line, off, pass) 99 off = au_cat(line, off, " verdict=PASS\n" as *u8) 100 let gf: i64 = sys_openat_append("knowledge/status/access_gate.log" as *u8, 0x1a4) 101 if gf >= 0 { sys_write(gf, line, off); sys_close(gf) } 102 au_w("NX-ACCESS-AUDIT-GATE verdict=PASS -- tamper-evident audit log recorded in access_gate.log\n" as *u8) 103 sys_exit(0); return 0 104 } 105 au_w("NX-ACCESS-AUDIT-GATE verdict=FAIL -- NOT recorded (no fake-green)\n" as *u8) 106 sys_exit(1); return 1 107}