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}