nx_homefwd_adversary.nx source
↩ module page · 104 lines · 3227 B
1// nx_homefwd_adversary.nx -- SELF-CHECKING adversary KAT for G10 home-
2// forwarding + G11 chain fusion. Prints each answer AND returns the number of
3// FAILED checks (0 = all pass), so the differential gauntlet catches wrong
4// VALUES (baseline exit 0 vs candidate exit N), not just crashes.
5// T1 G10 STORE-GUARD: a = x; x = x + 1; b += (x - a) -> b == n (3).
6// (X86_NEGCTL_FWD_IGNORE_STORE forwards a's load past the store -> b=0.)
7// T2 POSITIVE: s += arr[j] -> 600.
8// T3 DOUBLE-USE: y += t + t, t = x2 (use_count 2, never forwarded) -> 36.
9// T4 G11 MID-CHAIN READ: x3 = x3*3 + 1 + x3 -- the second read of x3 sits
10// INSIDE the would-be chain window; the scan must ABORT the fusion. 2
11// iters from 2: 9 -> 37. (X86_NEGCTL_CHAIN_IGNORE_READ fuses anyway ->
12// the second read sees the mutated home -> 14 -> 86 -> RED.)
13// T5 G11 PURE CHAIN: x4 = x4*3 + 1 fuses in place; 3 iters from 2:
14// 7 -> 22 -> 67.
15// Seeds come from mmap'd memory so const-prop cannot fold them.
16// license_tier: ORIGINAL No hw writes (Rule 26).
17import "nx_syscalls_x86_64.nx"
18
19func hf_emit_i64(fd: i64, n: i64) -> i64 {
20 let scratch: *u8 = sys_mmap(32)
21 var v: i64 = n
22 var neg: i64 = 0
23 if v < 0 { neg = 1; v = 0 - v }
24 var k: i64 = 0
25 if v == 0 { scratch[0] = 0x30 as u8; k = 1 }
26 while v > 0 { scratch[k] = (0x30 + (v - (v / 10) * 10)) as u8; v = v / 10; k = k + 1 }
27 let rev: *u8 = sys_mmap(48)
28 var ro: i64 = 0
29 if neg == 1 { rev[0] = 0x2D as u8; ro = 1 }
30 var j: i64 = 0
31 while j < k { rev[ro + j] = scratch[k - 1 - j]; j = j + 1 }
32 rev[ro + k] = 0x0A as u8
33 sys_write(fd, rev, ro + k + 1)
34 return 0
35}
36
37func main() -> i64 {
38 let cfg: *i64 = sys_mmap(64) as *i64
39 cfg[0] = 3
40 cfg[1] = 10
41 cfg[2] = 5
42 cfg[3] = 2
43 let n: i64 = cfg[0]
44 var fails: i64 = 0
45
46 // T1: G10 store-guard.
47 var x: i64 = cfg[1]
48 var b: i64 = 0
49 var i: i64 = 0
50 while i < n {
51 let a: i64 = x
52 x = x + 1
53 b = b + (x - a)
54 i = i + 1
55 }
56 hf_emit_i64(1, b)
57 if b != 3 { fails = fails + 1 }
58
59 // T2: positive coverage.
60 let arr: *i64 = sys_mmap(64) as *i64
61 var f: i64 = 0
62 while f < 8 { arr[f] = (f + 1) * 100; f = f + 1 }
63 var s: i64 = 0
64 var j: i64 = 0
65 while j < n { s = s + arr[j]; j = j + 1 }
66 hf_emit_i64(1, s)
67 if s != 600 { fails = fails + 1 }
68
69 // T3: double-use load never killed.
70 var x2: i64 = cfg[2]
71 var y: i64 = 0
72 var k: i64 = 0
73 while k < n {
74 let t: i64 = x2
75 y = y + t + t
76 x2 = x2 + 1
77 k = k + 1
78 }
79 hf_emit_i64(1, y)
80 if y != 36 { fails = fails + 1 }
81
82 // T4: G11 mid-chain read -- fusion must ABORT (second read of x3 inside
83 // the window). 2 iters from 2: x3 = 3*x3 + 1 + x3 -> 9 -> 37.
84 var x3: i64 = cfg[3]
85 var m: i64 = 0
86 while m < 2 {
87 x3 = x3 * 3 + 1 + x3
88 m = m + 1
89 }
90 hf_emit_i64(1, x3)
91 if x3 != 37 { fails = fails + 1 }
92
93 // T5: G11 pure chain fuses in place. 3 iters from 2: 7 -> 22 -> 67.
94 var x4: i64 = cfg[3]
95 var q: i64 = 0
96 while q < n {
97 x4 = x4 * 3 + 1
98 q = q + 1
99 }
100 hf_emit_i64(1, x4)
101 if x4 != 67 { fails = fails + 1 }
102
103 return fails
104}