nx_clmul_kat.nx source
↩ module page · 62 lines · 2551 B
1// nx_clmul_kat.nx -- end-to-end proof of the PCLMULQDQ pipeline (assembler `pclmulqdq`
2// mnemonic + compiler __clmul_ll/hh/lh/hl intrinsics). Carry-less (GF(2) polynomial)
3// multiply has hand-checkable known answers:
4// clmul(0x3,0x7) = (x+1)(x^2+x+1) = x^3+1 = 0x9
5// clmul(0xFF,0xFF) = carry-less square spreads bits 0..7 = 0x5555
6// clmul(x^63, x) = x^64 -> low=0, high=1 (spans the 128-bit result)
7// The decoy halves prove each variant reads the RIGHT 64-bit half (l/h) of each operand.
8// __clmul_XY(p,q) writes the 128-bit product back to *p in place; p[0]=low, p[1]=high.
9//
10// expect_exit: 0 (any nonzero = the check whose code it carries failed)
11
12import "nx_syscalls.nx"
13
14func main() -> i64 {
15 let p: *u8 = sys_mmap(16); let pi: *i64 = p as *i64
16 let q: *u8 = sys_mmap(16); let qi: *i64 = q as *i64
17
18 // 1) LL: 0x3 * 0x7 = 0x9 (decoy high halves must be ignored)
19 pi[0] = 3; pi[1] = 0x1111111111111111
20 qi[0] = 7; qi[1] = 0x2222222222222222
21 let r1: i64 = __clmul_ll(p, q)
22 if pi[0] != 9 { sys_exit(1); return 1 }
23 if pi[1] != 0 { sys_exit(2); return 2 }
24
25 // 2) LL: 0xFF * 0xFF = 0x5555 (carry-less square)
26 pi[0] = 0xFF; pi[1] = 0
27 qi[0] = 0xFF; qi[1] = 0
28 let r2: i64 = __clmul_ll(p, q)
29 if pi[0] != 0x5555 { sys_exit(3); return 3 }
30 if pi[1] != 0 { sys_exit(4); return 4 }
31
32 // 3) LL: x^63 * x = x^64 -> low=0, high=1 (the result genuinely spans 128 bits)
33 pi[0] = 0x8000000000000000; pi[1] = 0
34 qi[0] = 2; qi[1] = 0
35 let r3: i64 = __clmul_ll(p, q)
36 if pi[0] != 0 { sys_exit(5); return 5 }
37 if pi[1] != 1 { sys_exit(6); return 6 }
38
39 // 4) HH: reads the HIGH half of each. a.hi=3, b.hi=7 -> 9; los are decoys.
40 pi[0] = 0xAAAAAAAAAAAAAAAA; pi[1] = 3
41 qi[0] = 0xBBBBBBBBBBBBBBBB; qi[1] = 7
42 let r4: i64 = __clmul_hh(p, q)
43 if pi[0] != 9 { sys_exit(7); return 7 }
44 if pi[1] != 0 { sys_exit(8); return 8 }
45
46 // 5) LH: a.lo * b.hi. a.lo=3 (a.hi decoy), b.hi=7 (b.lo decoy) -> 9.
47 pi[0] = 3; pi[1] = 0xCCCCCCCCCCCCCCCC
48 qi[0] = 0xDDDDDDDDDDDDDDDD; qi[1] = 7
49 let r5: i64 = __clmul_lh(p, q)
50 if pi[0] != 9 { sys_exit(9); return 9 }
51 if pi[1] != 0 { sys_exit(10); return 10 }
52
53 // 6) HL: a.hi * b.lo. a.hi=3 (a.lo decoy), b.lo=7 (b.hi decoy) -> 9.
54 pi[0] = 0xEEEEEEEEEEEEEEEE; pi[1] = 3
55 qi[0] = 7; qi[1] = 0xFFFFFFFFFFFFFFFF
56 let r6: i64 = __clmul_hl(p, q)
57 if pi[0] != 9 { sys_exit(11); return 11 }
58 if pi[1] != 0 { sys_exit(12); return 12 }
59
60 sys_exit(0)
61 return 0
62}