code wiki / _hdl_build / nx_cenc_gate.nx
nx_cenc_gate.nx source
↩ module page · 77 lines · 4800 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"
11
12func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
13" as *u8); return ok }
14func 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 }
15func 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 }
16func 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 }
17func gsl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
18
19func main() -> i64 {
20 gw("cenc/clearkey SOVEREIGN gate (AES-CTR NIST KAT + CENC subsample decrypt + ClearKey JWK)\n" as *u8)
21 var pass: i64 = 0
22 var ttl: i64 = 0
23
24 let key: *u8 = sys_mmap(16)
25 hx("2b7e151628aed2a6abf7158809cf4f3c\x00" as *u8, key)
26 let sched: *u8 = sys_mmap(176)
27 aes128_expand_key(key, sched)
28 let iv: *u8 = sys_mmap(16)
29 hx("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff\x00" as *u8, iv)
30
31 // K1: NIST SP800-38A F.5.1 block 1 -- decrypt CT -> PT (whole-sample, nsub=0).
32 let ct1: *u8 = sys_mmap(16); hx("874d6191b620e3261bef6864990db6ce\x00" as *u8, ct1)
33 let pt1: *u8 = sys_mmap(16); hx("6bc1bee22e409f96e93d7e117393172a\x00" as *u8, pt1)
34 let out1: *u8 = sys_mmap(16)
35 cenc_decrypt_subsamples(sched, iv, 16, ct1, 16, 0 as *i64, 0, out1)
36 ttl=ttl+1; pass=pass+grow("K1 AES-CTR NIST F.5.1 block1 decrypt\x00" as *u8, beq(out1, pt1, 16))
37
38 // K2: NIST F.5.1 blocks 1+2 (32 bytes) -- proves the counter increments across blocks.
39 let ct2: *u8 = sys_mmap(32); hx("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff\x00" as *u8, ct2)
40 let pt2: *u8 = sys_mmap(32); hx("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51\x00" as *u8, pt2)
41 let out2: *u8 = sys_mmap(32)
42 cenc_decrypt_subsamples(sched, iv, 16, ct2, 32, 0 as *i64, 0, out2)
43 ttl=ttl+1; pass=pass+grow("K2 AES-CTR NIST F.5.1 blocks1+2 (counter carry)\x00" as *u8, beq(out2, pt2, 32))
44
45 // K3: CENC SUBSAMPLE -- layout [clear 4, enc 16, clear 2, enc 16] (38B). Make a "ciphertext sample" by
46 // CTR-encrypting only the enc ranges of a known plaintext (CTR is symmetric), then decrypt it back:
47 // clear bytes must survive untouched, enc bytes must round-trip, and the cipher must differ from plain.
48 let subs: *i64 = sys_mmap(8*4) as *i64
49 subs[0]=4; subs[1]=16; subs[2]=2; subs[3]=16
50 let ptS: *u8 = sys_mmap(38)
51 var z: i64=0; while z<38 { ptS[z]=(z+1) as u8; z=z+1 } // known plaintext 1..38
52 let ctS: *u8 = sys_mmap(38)
53 cenc_decrypt_subsamples(sched, iv, 16, ptS, 38, subs, 2, ctS) // symmetric -> "encrypts" the enc ranges
54 let decS: *u8 = sys_mmap(38)
55 cenc_decrypt_subsamples(sched, iv, 16, ctS, 38, subs, 2, decS) // decrypt back
56 var m3: i64 = 1
57 if beq(decS, ptS, 38) == 0 { m3 = 0 } // round-trip
58 if (ctS[0]&0xff) != (ptS[0]&0xff) { m3 = 0 } // clear byte 0 untouched
59 if (ctS[20]&0xff) != (ptS[20]&0xff) { m3 = 0 } // clear byte 20 untouched
60 if (ctS[4]&0xff) == (ptS[4]&0xff) { m3 = 0 } // enc byte 4 actually changed
61 ttl=ttl+1; pass=pass+grow("K3 CENC subsample: clear kept, enc round-trips\x00" as *u8, m3)
62
63 // K4: ClearKey JWK -- k = base64url of bytes 01..10 -> 16-byte key.
64 let json: *u8 = "{\"keys\":[{\"kty\":\"oct\",\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":\"AAAAAAAAAAAAAAAAAAAAAA\"}],\"type\":\"temporary\"}" as *u8
65 let ckkey: *u8 = sys_mmap(32)
66 let kl: i64 = clearkey_first_key(json, gsl(json), ckkey)
67 let want: *u8 = sys_mmap(16)
68 var q: i64=0; while q<16 { want[q]=(q+1) as u8; q=q+1 }
69 var m4: i64 = 1
70 if kl != 16 { m4 = 0 }
71 if m4 == 1 { if beq(ckkey, want, 16) == 0 { m4 = 0 } }
72 ttl=ttl+1; pass=pass+grow("K4 ClearKey JWK -> 16-byte key\x00" as *u8, m4)
73
74 gw("pass=" as *u8); gn(pass); gw("/" as *u8); gn(ttl); gw("\n" as *u8)
75 if pass == ttl { gw("verdict=GREEN (AES-CTR NIST-correct + CENC subsample decrypt + ClearKey key acquisition)\n" as *u8); sys_exit(0); return 0 }
76 gw("verdict=RED\n" as *u8); sys_exit(1); return 1
77}