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}