code wiki / _hdl_build / nx_evattest_gate.nx

nx_evattest_gate.nx source

↩ module page · 221 lines · 11691 B

1// nx_evattest_gate.nx -- proves the signed-attestation layer accepts a genuine operator sign-off and 2// REFUSES every way of faking one. The clause it defends (`require_human`) is the single thing standing 3// between "an agent certified its own work" and a PROVEN verdict, so every refusal path here is 4// negative-controlled: a gate that only ever demonstrates acceptance has proven nothing. 5// license_tier: ORIGINAL expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_evattest.nx" 8 9func 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 wn(v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; 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} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 11func ck(pass: i64, label: *u8, fails: *i64) -> i64 { 12 w(" " as *u8); w(label); w(": " as *u8) 13 if pass==1 { w("PASS\n" as *u8) } else { w("FAIL\n" as *u8); fails[0]=fails[0]+1 } 14 return 0 15} 16func hexout(src: *u8, n: i64, dst: *u8, off: i64) -> i64 { 17 let hexd: *u8 = "0123456789abcdef" 18 var o: i64 = off 19 var i: i64 = 0 20 while i < n { 21 let b: i64 = src[i] as i64 22 dst[o] = hexd[(b >> 4) & 15]; o = o + 1 23 dst[o] = hexd[b & 15]; o = o + 1 24 i = i + 1 25 } 26 return o 27} 28func cat(dst: *u8, off: i64, s: *u8) -> i64 { 29 var o: i64 = off 30 var i: i64 = 0 31 while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } 32 return o 33} 34 35func main() -> i64 { 36 let fails: *i64 = sys_mmap(16) as *i64 37 fails[0]=0 38 w("=== nx_evattest_gate -- a genuine operator sign-off passes; every forgery is refused ===\n" as *u8) 39 40 // Two deterministic test keys. HUMAN = the operator's; MACHINE = one the automation might hold. 41 let hpriv: *u8 = sys_mmap(32) 42 let mpriv: *u8 = sys_mmap(32) 43 var i: i64 = 0 44 while i < 32 { hpriv[i] = (i + 11) as u8; mpriv[i] = (i + 200) as u8; i = i + 1 } 45 let hpub: *u8 = sys_mmap(32) 46 let mpub: *u8 = sys_mmap(32) 47 ed25519_pub_from_priv(hpriv, hpub) 48 ed25519_pub_from_priv(mpriv, mpub) 49 50 // Key registry: the human key is role=human, the machine key role=machine. A third key is left 51 // deliberately unregistered so "valid signature from a stranger" can be tested. 52 let conf: *u8 = sys_mmap(4096) 53 var c: i64 = 0 54 c = cat(conf, c, "# test registry\nrole=human pub=" as *u8) 55 c = hexout(hpub, 32, conf, c) 56 c = cat(conf, c, " name=operator\nrole=machine pub=" as *u8) 57 c = hexout(mpub, 32, conf, c) 58 c = cat(conf, c, " name=automation\n" as *u8) 59 60 // ---- build a genuine human attestation ---- 61 let row: *u8 = sys_mmap(4096) 62 var r: i64 = 0 63 r = cat(row, r, "class=human verdict=pass scope=reviewed-9-warden-axes-against-source signer=operator epoch=1785400000" as *u8) 64 let sig: *u8 = sys_mmap(64) 65 ed25519_sign_full(hpriv, row, r, sig) 66 var rf: i64 = cat(row, r, " pub=" as *u8) 67 rf = hexout(hpub, 32, row, rf) 68 rf = cat(row, rf, " sig=" as *u8) 69 rf = hexout(sig, 64, row, rf) 70 71 // T1: the genuine operator attestation is ACCEPTED (the layer is usable, not merely strict) 72 var t1: i64=0 73 if at_verify_row(row, 0, rf, AT_CLASS_HUMAN, conf, c)==AT_OK { t1=1 } 74 ck(t1, "T1 genuine operator-signed human row -> OK (accepts real sign-off)" as *u8, fails) 75 76 // T2: THE ATTACK THIS EXISTS TO STOP -- the automation signs a human-class row with ITS OWN key. 77 // Cryptographically valid, registered key, and still REFUSED on role. 78 let row2: *u8 = sys_mmap(4096) 79 var r2: i64 = 0 80 r2 = cat(row2, r2, "class=human verdict=pass scope=I-checked-my-own-work signer=automation epoch=1785400000" as *u8) 81 let sig2: *u8 = sys_mmap(64) 82 ed25519_sign_full(mpriv, row2, r2, sig2) 83 var rf2: i64 = cat(row2, r2, " pub=" as *u8) 84 rf2 = hexout(mpub, 32, row2, rf2) 85 rf2 = cat(row2, rf2, " sig=" as *u8) 86 rf2 = hexout(sig2, 64, row2, rf2) 87 var t2: i64=0 88 if at_verify_row(row2, 0, rf2, AT_CLASS_HUMAN, conf, c)==AT_ERR_ROLE { t2=1 } 89 ck(t2, "T2 MACHINE key signs a human row (valid sig, registered) -> REFUSED on role" as *u8, fails) 90 91 // T3: the same machine key IS accepted for a machine-class claim -- role separation is a boundary, 92 // not a blanket refusal of the automation. 93 var t3: i64=0 94 if at_verify_row(row2, 0, rf2, AT_CLASS_MECH, conf, c)==AT_OK { t3=1 } 95 ck(t3, "T3 same machine key for a MECH claim -> OK (separation, not blanket refusal)" as *u8, fails) 96 97 // T4: TAMPER -- flip one byte of the signed scope. Signature must fail. 98 let row3: *u8 = sys_mmap(4096) 99 var q: i64 = 0 100 while q < rf { row3[q] = row[q]; q = q + 1 } 101 row3[30] = (row3[30] as i64 + 1) as u8 102 var t4: i64=0 103 if at_verify_row(row3, 0, rf, AT_CLASS_HUMAN, conf, c)==AT_ERR_BADSIG { t4=1 } 104 ck(t4, "T4 one byte of the signed scope altered -> BAD-SIGNATURE (tamper-evident)" as *u8, fails) 105 106 // T5: an UNSIGNED row -- the pre-seq1367 format -- must not be honoured at all. 107 let row4: *u8 = sys_mmap(1024) 108 let r4: i64 = cat(row4, 0, "class=human verdict=pass scope=trust-me signer=whoever epoch=1785400000" as *u8) 109 var t5: i64=0 110 if at_verify_row(row4, 0, r4, AT_CLASS_HUMAN, conf, c)==AT_ERR_NOSIG { t5=1 } 111 ck(t5, "T5 legacy UNSIGNED row -> UNSIGNED (fails closed, not grandfathered)" as *u8, fails) 112 113 // T6: a VALID signature from an UNREGISTERED key is still refused -- a signature from a stranger is 114 // not an authorisation. 115 let upriv: *u8 = sys_mmap(32) 116 i = 0 117 while i < 32 { upriv[i] = (i + 77) as u8; i = i + 1 } 118 let upub: *u8 = sys_mmap(32) 119 ed25519_pub_from_priv(upriv, upub) 120 let row5: *u8 = sys_mmap(4096) 121 var r5: i64 = 0 122 r5 = cat(row5, r5, "class=human verdict=pass scope=stranger-signed signer=nobody epoch=1785400000" as *u8) 123 let sig5: *u8 = sys_mmap(64) 124 ed25519_sign_full(upriv, row5, r5, sig5) 125 var rf5: i64 = cat(row5, r5, " pub=" as *u8) 126 rf5 = hexout(upub, 32, row5, rf5) 127 rf5 = cat(row5, rf5, " sig=" as *u8) 128 rf5 = hexout(sig5, 64, row5, rf5) 129 var t6: i64=0 130 if at_verify_row(row5, 0, rf5, AT_CLASS_HUMAN, conf, c)==AT_ERR_UNKNOWNKEY { t6=1 } 131 ck(t6, "T6 valid signature from an UNREGISTERED key -> refused (a signature is not an authorisation)" as *u8, fails) 132 133 // T7: SIGNATURE-SWAP -- take the genuine human signature and paste it onto a different claim. 134 // The canonical message covers class/verdict/scope/epoch, so a lifted signature cannot be re-pointed. 135 let row6: *u8 = sys_mmap(4096) 136 var r6: i64 = 0 137 r6 = cat(row6, r6, "class=human verdict=pass scope=SOMETHING-ELSE-ENTIRELY signer=operator epoch=1785400000" as *u8) 138 var rf6: i64 = cat(row6, r6, " pub=" as *u8) 139 rf6 = hexout(hpub, 32, row6, rf6) 140 rf6 = cat(row6, rf6, " sig=" as *u8) 141 rf6 = hexout(sig, 64, row6, rf6) 142 var t7: i64=0 143 if at_verify_row(row6, 0, rf6, AT_CLASS_HUMAN, conf, c)==AT_ERR_BADSIG { t7=1 } 144 ck(t7, "T7 genuine signature lifted onto a DIFFERENT claim -> BAD-SIGNATURE (cannot be re-pointed)" as *u8, fails) 145 146 // ---- T8..T12: THE ORACLE CLASS -- DERIVED, NEVER DECLARED (added 2026-07-31 with AT_CLASS_ORACLE) ---- 147 // Before this, EV_CLASS_ORACLE(8) reached at_verify_row and matched NO rule, so it was authorised by 148 // fall-through and no tooth here could tell. A clause with no negative control has not been shown to 149 // measure anything -- so each of the three required fields gets its own failing case. 150 // The signature is REAL and the key is REGISTERED in every one of these rows: the only thing under test 151 // is whether the CLAIM carries its own re-derivation recipe. That isolation is the point -- it proves 152 // the refusal is about verifiability, not about the signer. 153 let ro: *u8 = sys_mmap(4096) 154 var q0: i64 = 0 155 q0 = cat(ro, q0, "class=oracle verdict=pass scope=sha256-native ref=FIPS 180-4 refdig=d719137726632612 gate=nx_sha256_native_kat_gate signer=automation epoch=1785400000" as *u8) 156 let sigo: *u8 = sys_mmap(64) 157 ed25519_sign_full(mpriv, ro, q0, sigo) 158 var rfo: i64 = cat(ro, q0, " pub=" as *u8) 159 rfo = hexout(mpub, 32, ro, rfo) 160 rfo = cat(ro, rfo, " sig=" as *u8) 161 rfo = hexout(sigo, 64, ro, rfo) 162 var t8: i64=0 163 if at_verify_row(ro, 0, rfo, AT_CLASS_ORACLE, conf, c)==AT_OK { t8=1 } 164 ck(t8, "T8 complete oracle row, MACHINE key -> OK (independence is in the REFERENCE, not the signer)" as *u8, fails) 165 166 // T9 NEG: drop refdig=. This is the field that makes the class ungameable -- prose can claim FIPS 180-4, 167 // only a digest commits to the bytes that were actually compared. 168 let r9: *u8 = sys_mmap(4096) 169 var q9: i64 = 0 170 q9 = cat(r9, q9, "class=oracle verdict=pass scope=sha256-native ref=FIPS 180-4 gate=nx_sha256_native_kat_gate signer=automation epoch=1785400000" as *u8) 171 let sig9: *u8 = sys_mmap(64) 172 ed25519_sign_full(mpriv, r9, q9, sig9) 173 var rf9: i64 = cat(r9, q9, " pub=" as *u8) 174 rf9 = hexout(mpub, 32, r9, rf9) 175 rf9 = cat(r9, rf9, " sig=" as *u8) 176 rf9 = hexout(sig9, 64, r9, rf9) 177 var t9: i64=0 178 if at_verify_row(r9, 0, rf9, AT_CLASS_ORACLE, conf, c)==AT_ERR_NOTDERIVED { t9=1 } 179 ck(t9, "T9 NEG oracle row without refdig= -> NOT-DERIVED (a claim that commits to no bytes)" as *u8, fails) 180 181 // T10 NEG: drop gate=. Without the recipe the reader cannot re-run the comparison, and re-runnability 182 // is the whole reason this class does not need to be trusted. 183 let r10: *u8 = sys_mmap(4096) 184 var q10: i64 = 0 185 q10 = cat(r10, q10, "class=oracle verdict=pass scope=sha256-native ref=FIPS 180-4 refdig=d719137726632612 signer=automation epoch=1785400000" as *u8) 186 let sig10: *u8 = sys_mmap(64) 187 ed25519_sign_full(mpriv, r10, q10, sig10) 188 var rf10: i64 = cat(r10, q10, " pub=" as *u8) 189 rf10 = hexout(mpub, 32, r10, rf10) 190 rf10 = cat(r10, rf10, " sig=" as *u8) 191 rf10 = hexout(sig10, 64, r10, rf10) 192 var t10: i64=0 193 if at_verify_row(r10, 0, rf10, AT_CLASS_ORACLE, conf, c)==AT_ERR_NOTDERIVED { t10=1 } 194 ck(t10, "T10 NEG oracle row without gate= -> NOT-DERIVED (no re-derivation recipe)" as *u8, fails) 195 196 // T11 NEG: THE PROSE FORGERY. Drop ref= -- an oracle that will not say what it matched. 197 let r11: *u8 = sys_mmap(4096) 198 var q11: i64 = 0 199 q11 = cat(r11, q11, "class=oracle verdict=pass scope=sha256-native refdig=d719137726632612 gate=nx_sha256_native_kat_gate signer=automation epoch=1785400000" as *u8) 200 let sig11: *u8 = sys_mmap(64) 201 ed25519_sign_full(mpriv, r11, q11, sig11) 202 var rf11: i64 = cat(r11, q11, " pub=" as *u8) 203 rf11 = hexout(mpub, 32, r11, rf11) 204 rf11 = cat(r11, rf11, " sig=" as *u8) 205 rf11 = hexout(sig11, 64, r11, rf11) 206 var t11: i64=0 207 if at_verify_row(r11, 0, rf11, AT_CLASS_ORACLE, conf, c)==AT_ERR_NOTDERIVED { t11=1 } 208 ck(t11, "T11 NEG oracle row without ref= -> NOT-DERIVED (it matched WHAT?)" as *u8, fails) 209 210 // T12: the derived contract binds ONLY the oracle class. The same recipe-less row is fine as a MECH 211 // claim -- so the new clause raised the bar for one class without silently tightening the others. 212 var t12: i64=0 213 if at_verify_row(r11, 0, rf11, AT_CLASS_MECH, conf, c)==AT_OK { t12=1 } 214 ck(t12, "T12 same recipe-less row as a MECH claim -> OK (the clause is scoped, not a blanket)" as *u8, fails) 215 216 w(" fails=" as *u8); wn(fails[0]); w("\n" as *u8) 217 if fails[0]==0 { w("VERDICT: verdict=GREEN (signed attestations: real sign-off accepted; machine-signed human rows, tampering, lifting, strangers and legacy unsigned rows all refused)\n" as *u8); sys_exit(0) } 218 w("VERDICT: verdict=RED\n" as *u8) 219 sys_exit(1) 220 return 1 221}