code wiki / _hdl_build / nx_entropy_gate.nx
nx_entropy_gate.nx source
↩ module page · 79 lines · 3182 B
1// nx_entropy_gate.nx -- re-runnable GATE for the CSPRNG organ (Engineer verb: VERIFY).
2// 5 KATs; exit 0 only on 5/5. Statistical bounds are deliberately loose (monobit 40-60%)
3// so a healthy kernel CSPRNG never false-fails; a stuck/zeroed source ALWAYS fails.
4// license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_entropy.nx"
7
8func _p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func _pn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);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 }
10
11func eg_diff(a: *u8, b: *u8, n: i64) -> i64 {
12 var i: i64 = 0
13 while i < n { if a[i] != b[i] { return 1 } i = i + 1 }
14 return 0
15}
16
17func main() -> i64 {
18 _p("=== ENTROPY GATE: kernel CSPRNG organ (getrandom direct 318) ===\n" as *u8)
19 var pass: i64 = 0
20 let a: *u8 = sys_mmap(8192)
21 let b: *u8 = sys_mmap(8192)
22
23 // K1: fill works and is not all-zero
24 let r1: i64 = ent_fill(a, 64)
25 var nz: i64 = 0
26 var i: i64 = 0
27 while i < 64 { if a[i] != (0 as u8) { nz = 1 } i = i + 1 }
28 if r1 == 0 { if nz == 1 { pass = pass + 1; _p("K1 fill-nonzero OK\n" as *u8) } else { _p("K1 FAIL all-zero\n" as *u8) } }
29 else { _p("K1 FAIL rc\n" as *u8) }
30
31 // K2: two fills differ
32 ent_fill(b, 64)
33 if eg_diff(a, b, 64) == 1 { pass = pass + 1; _p("K2 fills-differ OK\n" as *u8) } else { _p("K2 FAIL identical\n" as *u8) }
34
35 // K3: pw exact length, charset-only
36 let pw1: *u8 = sys_mmap(64)
37 let r3: i64 = ent_pw(pw1, 24)
38 var ok3: i64 = 1
39 if r3 != 0 { ok3 = 0 }
40 var n3: i64 = 0
41 while pw1[n3] != (0 as u8) { n3 = n3 + 1 }
42 if n3 != 24 { ok3 = 0 }
43 i = 0
44 while i < n3 {
45 let c: i64 = pw1[i] as i64
46 var good: i64 = 0
47 if c >= 65 { if c <= 90 { good = 1 } }
48 if c >= 97 { if c <= 122 { good = 1 } }
49 if c >= 48 { if c <= 57 { good = 1 } }
50 if c == 45 { good = 1 }
51 if c == 95 { good = 1 }
52 if good == 0 { ok3 = 0 }
53 i = i + 1
54 }
55 if ok3 == 1 { pass = pass + 1; _p("K3 pw-len-charset OK\n" as *u8) } else { _p("K3 FAIL\n" as *u8) }
56
57 // K4: two pws differ
58 let pw2: *u8 = sys_mmap(64)
59 ent_pw(pw2, 24)
60 if eg_diff(pw1, pw2, 24) == 1 { pass = pass + 1; _p("K4 pws-differ OK\n" as *u8) } else { _p("K4 FAIL identical\n" as *u8) }
61
62 // K5: monobit smoke over 4096 bytes -- ones in [40%,60%] of 32768 bits
63 ent_fill(a, 4096)
64 var ones: i64 = 0
65 i = 0
66 while i < 4096 {
67 var v: i64 = a[i] as i64
68 while v != 0 { ones = ones + (v & 1); v = v >> 1 }
69 i = i + 1
70 }
71 if ones > 13107 { if ones < 19661 { pass = pass + 1; _p("K5 monobit OK ones=" as *u8); _pn(ones); _p("/32768\n" as *u8) } else { _p("K5 FAIL high\n" as *u8) } }
72 else { _p("K5 FAIL low ones=" as *u8); _pn(ones); _p("\n" as *u8) }
73
74 _p("GATE-VERDICT entropy " as *u8); _pn(pass); _p("/5" as *u8)
75 if pass == 5 { _p(" GREEN\n" as *u8); sys_exit(0); return 0 }
76 _p(" RED\n" as *u8)
77 sys_exit(1)
78 return 1
79}