code wiki / (root) / nx_aes256_gcm_gate.nx

nx_aes256_gcm_gate.nx source

↩ module page · 82 lines · 5958 B

1// nx_aes256_gcm_gate.nx -- SOVEREIGN KAT referee for AES-256-GCM vs NIST SP 800-38D / McGrew GCM test vectors. 2// TC14: zero key/IV, 16-byte zero PT, no AAD -> CT=cea7403d.. Tag=d0d1c8a7.. 3// TC16: real key/IV + 20-byte AAD + 60-byte PT (ragged, exercises multi-block + tail) -> CT=522dc1f0.. Tag=76fc6ece.. 4// T1 seal(TC14) == CT+Tag ; T2 open(TC14) recovers PT + tag OK ; T3 seal(TC16) == CT+Tag ; T4 open(TC16) recovers PT 5// T5 NEG: open(TC16) with a corrupted tag -> -1 (authentication rejects) ; T6 aes256 KAT block (FIPS-197 C.3) 6// GREEN iff 6/6. license_tier: ORIGINAL expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_aes256_gcm.nx" 9import "nx_gate_verdict.nx" 10 11func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 12func gn(v: i64) -> i64 { let b: *u8 = sys_mmap(24); var m: i64 = v; if m < 0 { gw("-" as *u8); m = 0 - m }; let t: *u8 = sys_mmap(24); 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 }; var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }; sys_write(1, b, k); return 0 } 13func grow(name: *u8, ok: i64) -> i64 { if ok == 1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("\n" as *u8); return ok } 14// hex nibble 15func hx(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 } 16// parse a hex string into out; returns byte count 17func h2b(s: *u8, out: *u8) -> i64 { 18 var i: i64 = 0; var o: i64 = 0 19 while s[i] != (0 as u8) { if s[i+1] == (0 as u8) { i = i + 1 } else { out[o] = ((hx(s[i] as i64) << 4) | hx(s[i+1] as i64)) as u8; o = o + 1; i = i + 2 } } 20 return o 21} 22func beq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if (a[i] as i64) != (b[i] as i64) { return 0 } i = i + 1 } return 1 } 23 24func main() -> i64 { 25 gw("aes256-gcm SOVEREIGN KAT gate (NIST SP800-38D / McGrew TC14 + TC16 + FIPS-197 block)\n" as *u8) 26 var pass: i64 = 0 27 let key: *u8 = sys_mmap(64); let iv: *u8 = sys_mmap(32); let pt: *u8 = sys_mmap(128); let aad: *u8 = sys_mmap(64) 28 let ct: *u8 = sys_mmap(128); let tag: *u8 = sys_mmap(32) 29 let octb: *u8 = sys_mmap(128); let otag: *u8 = sys_mmap(32); let opt: *u8 = sys_mmap(128) 30 31 // ---- TC14: zero key/iv, 16-byte zero PT, no AAD ---- 32 let kn: i64 = h2b("0000000000000000000000000000000000000000000000000000000000000000" as *u8, key) 33 let vn: i64 = h2b("000000000000000000000000" as *u8, iv) 34 let pn: i64 = h2b("00000000000000000000000000000000" as *u8, pt) 35 let cn: i64 = h2b("cea7403d4d606b6e074ec5d3baf39d18" as *u8, ct) 36 let tn: i64 = h2b("d0d1c8a799996bf0265b98b5d48ab919" as *u8, tag) 37 nx_aes256_gcm_seal(key, iv, aad, 0, pt, pn, octb, otag) 38 var t1: i64 = 0; if beq(octb, ct, cn)==1 { if beq(otag, tag, 16)==1 { t1 = 1 } } 39 pass = pass + grow("T1 seal(TC14) == NIST CT + Tag\x00" as *u8, t1) 40 let r2: i64 = nx_aes256_gcm_open(key, iv, aad, 0, ct, cn, tag, opt) 41 var t2: i64 = 0; if r2==0 { if beq(opt, pt, pn)==1 { t2 = 1 } } 42 pass = pass + grow("T2 open(TC14) tag-OK + recovers PT\x00" as *u8, t2) 43 44 // ---- TC16: real key/iv + AAD + 60-byte ragged PT ---- 45 h2b("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308" as *u8, key) 46 h2b("cafebabefacedbaddecaf888" as *u8, iv) 47 let an: i64 = h2b("feedfacedeadbeeffeedfacedeadbeefabaddad2" as *u8, aad) 48 let pn2: i64 = h2b("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39" as *u8, pt) 49 let cn2: i64 = h2b("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662" as *u8, ct) 50 h2b("76fc6ece0f4e1768cddf8853bb2d551b" as *u8, tag) 51 nx_aes256_gcm_seal(key, iv, aad, an, pt, pn2, octb, otag) 52 var t3: i64 = 0; if beq(octb, ct, cn2)==1 { if beq(otag, tag, 16)==1 { t3 = 1 } } 53 pass = pass + grow("T3 seal(TC16 +AAD +ragged 60B) == NIST CT + Tag\x00" as *u8, t3) 54 let r4: i64 = nx_aes256_gcm_open(key, iv, aad, an, ct, cn2, tag, opt) 55 var t4: i64 = 0; if r4==0 { if beq(opt, pt, pn2)==1 { t4 = 1 } } 56 pass = pass + grow("T4 open(TC16) tag-OK + recovers PT\x00" as *u8, t4) 57 58 // ---- T5 NEG: corrupt the tag -> open must reject ---- 59 let badtag: *u8 = sys_mmap(32); var i: i64 = 0; while i < 16 { badtag[i] = tag[i]; i = i + 1 } badtag[0] = ((tag[0] as i64) ^ 0xff) as u8 60 let r5: i64 = nx_aes256_gcm_open(key, iv, aad, an, ct, cn2, badtag, opt) 61 pass = pass + grow("T5 NEG open(corrupt tag) -> -1 (auth rejects)\x00" as *u8, r5 == 0 - 1) 62 63 // ---- T6 FIPS-197 C.3 AES-256 block KAT ---- 64 // key=000102..1f pt=00112233445566778899aabbccddeeff ct=8ea2b7ca516745bfeafc49904b496089 65 let k6: *u8 = sys_mmap(64); h2b("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" as *u8, k6) 66 let p6: *u8 = sys_mmap(16); h2b("00112233445566778899aabbccddeeff" as *u8, p6) 67 let c6: *u8 = sys_mmap(16); h2b("8ea2b7ca516745bfeafc49904b496089" as *u8, c6) 68 let sched: *u8 = sys_mmap(240); aes256_expand_key(k6, sched) 69 let o6: *u8 = sys_mmap(16); aes256_encrypt_block(p6, sched, o6) 70 pass = pass + grow("T6 FIPS-197 C.3 AES-256 block encrypt == KAT\x00" as *u8, beq(o6, c6, 16)) 71 72 gw("pass=" as *u8); gn(pass); gw("/6\n" as *u8) 73 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 74 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 75 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 76 let ctr__dry: *i64 = gv_ctr() 77 ctr__dry[0] = pass 78 ctr__dry[1] = 6 79 let rc__dry: i64 = gv_verdict("AES256-GCM-GATE" as *u8, ctr__dry, "AES-256-GCM: NIST GCM TC14+TC16 seal/open + auth-reject + FIPS-197 block KAT -- full cipher coverage)" as *u8) 80 sys_exit(rc__dry) 81 return rc__dry 82}