code wiki / _hdl_build / nx_doc_authz_gate.nx

nx_doc_authz_gate.nx source

↩ module page · 130 lines · 8372 B

1// nx_doc_authz_gate.nx -- MEASURED hermetic gate for per-client EYES-ONLY authz + the private-doc read route 2// (nx_doc_authz). Fresh nonce domains per run. Proves the vault is no longer write-only and cannot be read by the 3// wrong client / the wrong firm: 4// T1 owner reads OWN confidential doc -> ALLOWED + plaintext round-trips (through decrypt). 5// T2 NON-owner (different subject) -> DENIED (<0), even though the doc exists (T1 read it). 6// T3 public doc -> readable by ANY subject (no regression on the public corpus). 7// T4 cross-domain (free-param hole) -> a domainA subject is DENIED a domainB doc. 8// T5 fail-closed -> a confidential doc with NO owner record is DENIED (never defaulted-open). 9// Print pass=5 + GREEN/RED, append knowledge/status/dp_authz_gate.log. STANDALONE -- no daemon, no deploy. 10// (nx_chacha20_poly1305_decrypt prints one 'A' to STDERR on first decrypt -- shipped-AEAD marker; harmless.) 11// license_tier: ORIGINAL 12import "nx_doc_authz.nx" // authz_set_owner / authz_may_read / authz_doc_get 13import "nx_doc_at_rest.nx" // doc_put (seed encrypted/plaintext docs) 14import "nx_docportal_lib.nx" // dp_cid + DP_VIS_* 15 16func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 17func g_num(v: i64) -> i64 { 18 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 19 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 21 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 22} 23func g_w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 24func g_wn(fd: i64, v: i64) -> i64 { 25 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m } 26 let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 27 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 28 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(fd, bb, k); return 0 29} 30func g_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 31func g_cat(out: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 } return o } 32func g_catnum(out: *u8, o: i64, v: i64) -> i64 { 33 if v == 0 { out[o] = 48 as u8; return o + 1 } 34 var m: i64 = v; let t: *u8 = sys_mmap(28); var k: i64 = 0 35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 36 var i: i64 = 0; while i < k { out[o] = t[k - 1 - i]; o = o + 1; i = i + 1 } return o 37} 38func g_eqbytes(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 39 40func main() -> i64 { 41 g_puts("=== DP AUTHZ GATE (per-client eyes-only + authenticated private read; fail-closed) ===\n" as *u8) 42 let nonce: i64 = sys_now_realtime_sec() 43 let domA: *u8 = sys_mmap(64) 44 var a: i64 = g_cat(domA, 0, "dpauthza" as *u8); a = g_catnum(domA, a, nonce); domA[a] = 0 as u8 45 let domB: *u8 = sys_mmap(64) 46 var b: i64 = g_cat(domB, 0, "dpauthzb" as *u8); b = g_catnum(domB, b, nonce); domB[b] = 0 as u8 47 48 // subjects = the authenticated identity string (in production: the 64-hex uid hash from nx_sa_validate); here 49 // opaque distinct strings suffice -- the lib compares them as opaque bytes. 50 let subjOwner: *u8 = "OWNER-uid-1111" as *u8 51 let subjOther: *u8 = "OTHER-uid-2222" as *u8 52 let subjB: *u8 = "DOMB-uid-3333" as *u8 53 let LEVEL: i64 = 2 // the daemon's CURRENT hardcoded session level (no role model yet) 54 55 let ptConf: *u8 = "EYES-ONLY client matter memo -- attorney-client privileged, minimum-necessary." as *u8 56 let ptConfLen: i64 = g_slen(ptConf) 57 let ptPub: *u8 = "PUBLIC firm announcement, no access restriction." as *u8 58 let ptPubLen: i64 = g_slen(ptPub) 59 let ptB: *u8 = "DOMAIN-B confidential matter for a DIFFERENT firm." as *u8 60 let ptBLen: i64 = g_slen(ptB) 61 let ptNo: *u8 = "Confidential doc with NO ownership record -- must be denied by construction." as *u8 62 let ptNoLen: i64 = g_slen(ptNo) 63 64 let cidConf: i64 = dp_cid(ptConf, ptConfLen) 65 let cidPub: i64 = dp_cid(ptPub, ptPubLen) 66 let cidB: i64 = dp_cid(ptB, ptBLen) 67 let cidNo: i64 = dp_cid(ptNo, ptNoLen) 68 69 // SEED: domA confidential (encrypted) owned by subjOwner + a public doc + a no-owner confidential doc; domB 70 // confidential owned by subjB. 71 doc_put(domA, DP_VIS_PRIVATE, cidConf, ptConf, ptConfLen) 72 authz_set_owner(domA, DP_VIS_PRIVATE, cidConf, subjOwner) 73 doc_put(domA, DP_VIS_PUBLIC, cidPub, ptPub, ptPubLen) 74 doc_put(domA, DP_VIS_PRIVATE, cidNo, ptNo, ptNoLen) // NO authz_set_owner -> fail-closed target 75 doc_put(domB, DP_VIS_PRIVATE, cidB, ptB, ptBLen) 76 authz_set_owner(domB, DP_VIS_PRIVATE, cidB, subjB) 77 78 var pass: i64 = 0 79 80 // T1: owner reads own confidential doc -> allowed + plaintext round-trips (decrypt) 81 let o1: *u8 = sys_mmap(ptConfLen + 128) 82 let n1: i64 = authz_doc_get(domA, DP_VIS_PRIVATE, cidConf, subjOwner, LEVEL, o1) 83 var t1: i64 = 0 84 if n1 == ptConfLen { if g_eqbytes(o1, ptConf, ptConfLen) == 1 { t1 = 1 } } 85 pass = pass + t1 86 g_puts(" T1 owner reads own confidential doc (len=" as *u8); g_num(n1); g_puts(" of " as *u8); g_num(ptConfLen); g_puts("): " as *u8) 87 if t1 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 88 89 // T2: non-owner -> DENIED (the doc exists -- T1 just read it) 90 let o2: *u8 = sys_mmap(ptConfLen + 128) 91 let n2: i64 = authz_doc_get(domA, DP_VIS_PRIVATE, cidConf, subjOther, LEVEL, o2) 92 var t2: i64 = 0; if n2 < 0 { t2 = 1 } pass = pass + t2 93 g_puts(" T2 non-owner DENIED same confidential doc (rc=" as *u8); g_num(n2); g_puts(", expect <0): " as *u8) 94 if t2 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 95 96 // T3: public doc -> readable by anyone (subjOther is NOT the owner, but public) 97 let o3: *u8 = sys_mmap(ptPubLen + 128) 98 let n3: i64 = authz_doc_get(domA, DP_VIS_PUBLIC, cidPub, subjOther, LEVEL, o3) 99 var t3: i64 = 0 100 if n3 == ptPubLen { if g_eqbytes(o3, ptPub, ptPubLen) == 1 { t3 = 1 } } 101 pass = pass + t3 102 g_puts(" T3 public doc readable by anyone (len=" as *u8); g_num(n3); g_puts("): " as *u8) 103 if t3 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 104 105 // T4: cross-domain -- subjOwner (a valid owner in domA) is DENIED domB's doc (owned by subjB) 106 let o4: *u8 = sys_mmap(ptBLen + 128) 107 let n4: i64 = authz_doc_get(domB, DP_VIS_PRIVATE, cidB, subjOwner, LEVEL, o4) 108 var t4: i64 = 0; if n4 < 0 { t4 = 1 } pass = pass + t4 109 g_puts(" T4 cross-domain DENIED (domA subject vs domB doc, rc=" as *u8); g_num(n4); g_puts(", expect <0): " as *u8) 110 if t4 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 111 112 // T5: fail-closed -- confidential doc with NO owner record -> DENIED even to the would-be owner subject 113 let o5: *u8 = sys_mmap(ptNoLen + 128) 114 let n5: i64 = authz_doc_get(domA, DP_VIS_PRIVATE, cidNo, subjOwner, LEVEL, o5) 115 var t5: i64 = 0; if n5 < 0 { t5 = 1 } pass = pass + t5 116 g_puts(" T5 fail-closed: no owner record -> DENIED (rc=" as *u8); g_num(n5); g_puts(", expect <0): " as *u8) 117 if t5 == 1 { g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 118 119 g_puts("----\nDP-AUTHZ rows=5 pass=" as *u8); g_num(pass); g_puts("\n" as *u8) 120 let lg: i64 = sys_openat_append("knowledge/status/dp_authz_gate.log" as *u8, 0x1a4) 121 if lg >= 0 { 122 g_w(lg, "DP-AUTHZ owner_read=" as *u8); g_wn(lg, t1); g_w(lg, " nonowner_deny=" as *u8); g_wn(lg, t2) 123 g_w(lg, " public_open=" as *u8); g_wn(lg, t3); g_w(lg, " crossdomain_deny=" as *u8); g_wn(lg, t4) 124 g_w(lg, " failclosed=" as *u8); g_wn(lg, t5); g_w(lg, " rows=5 pass=" as *u8); g_wn(lg, pass) 125 if pass == 5 { g_w(lg, " verdict=GREEN\n" as *u8) } else { g_w(lg, " verdict=RED\n" as *u8) } 126 sys_close(lg) 127 } 128 if pass == 5 { g_puts("DP-AUTHZ GREEN (eyes-only owner read, non-owner + cross-domain + no-owner all fail-closed; public open -- measured)\n" as *u8); sys_exit(0); return 0 } 129 g_puts("DP-AUTHZ RED\n" as *u8); sys_exit(1); return 1 130}