code wiki / (root) / nx_ghash_kat_test.nx

nx_ghash_kat_test.nx source

↩ module page · 82 lines · 3116 B

1// nx_ghash_kat_test.nx -- canonical KAT for the GHASH primitive 2// using NIST SP 800-38D Appendix B Test Case 2 ("AES-128-GCM with 3// 16-byte plaintext, all-zero IV"). 4// 5// Test Case 2 inputs (NIST published): 6// K = 00000000000000000000000000000000 7// P = 00000000000000000000000000000000 (16-byte all-zero plaintext) 8// AAD = (empty) 9// IV = 000000000000000000000000 (12-byte all-zero IV) 10// 11// Derived intermediates: 12// H = E_K(0^128) = 66e94bd4ef8a2c3b884cfa59ca342b2e 13// C = ciphertext = 0388dace60b6a392f328c2b971b2fe78 14// GHASH(H, A=empty, C) = E_K(J0) XOR T 15// where T = AB6E47D42CEC13BDF53A67B21257BDDF (the published tag). 16// E_K(J0) where J0 = IV || 0^31 || 1 = 000000000000000000000000 00000001: 17// E_K(J0) = 58e2fccefa7e3061367f1d57a4e7455a 18// So GHASH = T XOR E_K(J0) 19// = AB6E47D42CEC13BDF53A67B21257BDDF XOR 58e2fccefa7e3061367f1d57a4e7455a 20// = F38CBB1AD692230AC3457AE5B6B0E885 21// 22// We verify the GHASH output (NOT the tag) against that derived value. 23// Inputs to ghash: A = empty, C = 0388dace60b6a392f328c2b971b2fe78. 24// Length block = 0^64 || 16*8=128 = 00 00 00 00 00 00 00 00 || 00 00 00 00 00 00 00 80 25// 26// expect_exit: 0. 27// license_tier: ORIGINAL 28 29import "nx_syscalls.nx" 30import "nx_ghash.nx" 31 32func hex_byte(out: *u8, idx: i64, hi: i64, lo: i64) -> i64 { 33 out[idx] = ((hi << 4) | lo) as u8 34 return 0 35} 36 37func main() -> i64 { 38 // H = 66e94bd4ef8a2c3b884cfa59ca342b2e 39 let h: *u8 = sys_mmap(16) 40 h[0]=0x66; h[1]=0xe9; h[2]=0x4b; h[3]=0xd4 41 h[4]=0xef; h[5]=0x8a; h[6]=0x2c; h[7]=0x3b 42 h[8]=0x88; h[9]=0x4c; h[10]=0xfa; h[11]=0x59 43 h[12]=0xca; h[13]=0x34; h[14]=0x2b; h[15]=0x2e 44 45 // C = 0388dace60b6a392f328c2b971b2fe78 (16-byte ciphertext) 46 let c: *u8 = sys_mmap(16) 47 c[0]=0x03; c[1]=0x88; c[2]=0xda; c[3]=0xce 48 c[4]=0x60; c[5]=0xb6; c[6]=0xa3; c[7]=0x92 49 c[8]=0xf3; c[9]=0x28; c[10]=0xc2; c[11]=0xb9 50 c[12]=0x71; c[13]=0xb2; c[14]=0xfe; c[15]=0x78 51 52 // Run GHASH: y starts as 0; accumulate empty AAD (no-op); 53 // accumulate C as one 16-byte block; finalize with length block 54 // (aad_len_bytes=0, ct_len_bytes=16). 55 let y: *u8 = sys_mmap(16) 56 var i: i64 = 0 57 while i < 16 { y[i] = 0; i = i + 1 } 58 nx_ghash_update_buf(y, h, c, 16) 59 nx_ghash_finalize(y, h, 0, 16) 60 61 // Expected y = F38CBB1AD69223DCC3457AE5B6B0F885 62 // (= T XOR E_K(J0) = AB6E47D42CEC13BDF53A67B21257BDDF XOR 63 // 58E2FCCEFA7E3061367F1D57A4E7455A) 64 let exp: *u8 = sys_mmap(16) 65 exp[0]=0xf3; exp[1]=0x8c; exp[2]=0xbb; exp[3]=0x1a 66 exp[4]=0xd6; exp[5]=0x92; exp[6]=0x23; exp[7]=0xdc 67 exp[8]=0xc3; exp[9]=0x45; exp[10]=0x7a; exp[11]=0xe5 68 exp[12]=0xb6; exp[13]=0xb0; exp[14]=0xf8; exp[15]=0x85 69 70 i = 0 71 while i < 16 { 72 if (y[i] & 0xff) != (exp[i] & 0xff) { return 10 + i } 73 i = i + 1 74 } 75 76 let msg: *u8 = sys_mmap(32) 77 msg[0]=0x47; msg[1]=0x48; msg[2]=0x4b; msg[3]=0x41 // "GHKA" 78 msg[4]=0x54; msg[5]=0x3D; msg[6]=0x4F; msg[7]=0x4B // "T=OK" 79 msg[8]=0x0A 80 sys_write(1, msg, 9) 81 return 0 82}