code wiki / _hdl_build / nx_cenc_gate.nx

nx_cenc_gate.nx source

↩ module page · 85 lines · 5175 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_cenc_gate.nx -- proves the standards-based encrypted-media primitives: (1) AES-128-CTR is NIST-correct 4// (SP800-38A F.5.1 vectors, decrypt path), (2) CENC subsample decrypt preserves clear ranges + decrypts the 5// encrypted ranges (continuous keystream), (3) ClearKey JWK key acquisition (base64url). license_tier: ORIGINAL expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_aes.nx" 8import "nx_aes_ctr.nx" 9import "base64.nx" 10import "nx_cenc.nx" 11import "nx_gate_verdict.nx" 12 13func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 14" as *u8); return ok } 15func hexval(c: i64) -> i64 { if c>=48 { if c<=57 { return c-48 } } if c>=97 { if c<=102 { return c-87 } } if c>=65 { if c<=70 { return c-55 } } return 0 } 16func hx(s: *u8, out: *u8) -> i64 { var i: i64=0; var o: i64=0; while (s[i]&0xff)!=0 { let hi: i64=hexval(s[i]&0xff); let lo: i64=hexval(s[i+1]&0xff); out[o]=(hi*16+lo) as u8; o=o+1; i=i+2 } return o } 17func beq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if (a[i]&0xff)!=(b[i]&0xff){ return 0 } i=i+1 } return 1 } 18func gsl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 19 20func main() -> i64 { 21 gw("cenc/clearkey SOVEREIGN gate (AES-CTR NIST KAT + CENC subsample decrypt + ClearKey JWK)\n" as *u8) 22 var pass: i64 = 0 23 var ttl: i64 = 0 24 25 let key: *u8 = sys_mmap(16) 26 hx("2b7e151628aed2a6abf7158809cf4f3c\x00" as *u8, key) 27 let sched: *u8 = sys_mmap(176) 28 aes128_expand_key(key, sched) 29 let iv: *u8 = sys_mmap(16) 30 hx("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff\x00" as *u8, iv) 31 32 // K1: NIST SP800-38A F.5.1 block 1 -- decrypt CT -> PT (whole-sample, nsub=0). 33 let ct1: *u8 = sys_mmap(16); hx("874d6191b620e3261bef6864990db6ce\x00" as *u8, ct1) 34 let pt1: *u8 = sys_mmap(16); hx("6bc1bee22e409f96e93d7e117393172a\x00" as *u8, pt1) 35 let out1: *u8 = sys_mmap(16) 36 cenc_decrypt_subsamples(sched, iv, 16, ct1, 16, 0 as *i64, 0, out1) 37 ttl=ttl+1; pass=pass+grow("K1 AES-CTR NIST F.5.1 block1 decrypt\x00" as *u8, beq(out1, pt1, 16)) 38 39 // K2: NIST F.5.1 blocks 1+2 (32 bytes) -- proves the counter increments across blocks. 40 let ct2: *u8 = sys_mmap(32); hx("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff\x00" as *u8, ct2) 41 let pt2: *u8 = sys_mmap(32); hx("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51\x00" as *u8, pt2) 42 let out2: *u8 = sys_mmap(32) 43 cenc_decrypt_subsamples(sched, iv, 16, ct2, 32, 0 as *i64, 0, out2) 44 ttl=ttl+1; pass=pass+grow("K2 AES-CTR NIST F.5.1 blocks1+2 (counter carry)\x00" as *u8, beq(out2, pt2, 32)) 45 46 // K3: CENC SUBSAMPLE -- layout [clear 4, enc 16, clear 2, enc 16] (38B). Make a "ciphertext sample" by 47 // CTR-encrypting only the enc ranges of a known plaintext (CTR is symmetric), then decrypt it back: 48 // clear bytes must survive untouched, enc bytes must round-trip, and the cipher must differ from plain. 49 let subs: *i64 = sys_mmap(8*4) as *i64 50 subs[0]=4; subs[1]=16; subs[2]=2; subs[3]=16 51 let ptS: *u8 = sys_mmap(38) 52 var z: i64=0; while z<38 { ptS[z]=(z+1) as u8; z=z+1 } // known plaintext 1..38 53 let ctS: *u8 = sys_mmap(38) 54 cenc_decrypt_subsamples(sched, iv, 16, ptS, 38, subs, 2, ctS) // symmetric -> "encrypts" the enc ranges 55 let decS: *u8 = sys_mmap(38) 56 cenc_decrypt_subsamples(sched, iv, 16, ctS, 38, subs, 2, decS) // decrypt back 57 var m3: i64 = 1 58 if beq(decS, ptS, 38) == 0 { m3 = 0 } // round-trip 59 if (ctS[0]&0xff) != (ptS[0]&0xff) { m3 = 0 } // clear byte 0 untouched 60 if (ctS[20]&0xff) != (ptS[20]&0xff) { m3 = 0 } // clear byte 20 untouched 61 if (ctS[4]&0xff) == (ptS[4]&0xff) { m3 = 0 } // enc byte 4 actually changed 62 ttl=ttl+1; pass=pass+grow("K3 CENC subsample: clear kept, enc round-trips\x00" as *u8, m3) 63 64 // K4: ClearKey JWK -- k = base64url of bytes 01..10 -> 16-byte key. 65 let json: *u8 = "{\"keys\":[{\"kty\":\"oct\",\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":\"AAAAAAAAAAAAAAAAAAAAAA\"}],\"type\":\"temporary\"}" as *u8 66 let ckkey: *u8 = sys_mmap(32) 67 let kl: i64 = clearkey_first_key(json, gsl(json), ckkey) 68 let want: *u8 = sys_mmap(16) 69 var q: i64=0; while q<16 { want[q]=(q+1) as u8; q=q+1 } 70 var m4: i64 = 1 71 if kl != 16 { m4 = 0 } 72 if m4 == 1 { if beq(ckkey, want, 16) == 0 { m4 = 0 } } 73 ttl=ttl+1; pass=pass+grow("K4 ClearKey JWK -> 16-byte key\x00" as *u8, m4) 74 75 gw("pass=" as *u8); gn(pass); gw("/" as *u8); gn(ttl); gw("\n" as *u8) 76 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 77 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 78 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 79 let ctr__dry: *i64 = gv_ctr() 80 ctr__dry[0] = pass 81 ctr__dry[1] = ttl 82 let rc__dry: i64 = gv_verdict("CENC-GATE" as *u8, ctr__dry, "AES-CTR NIST-correct + CENC subsample decrypt + ClearKey key acquisition)" as *u8) 83 sys_exit(rc__dry) 84 return rc__dry 85}