code wiki / (root) / nx_clmul_kat.nx

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}