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}