code wiki / _hdl_build / nx_x25519_extvec_gate.nx
nx_x25519_extvec_gate.nx source
↩ module page · 187 lines · 7966 B
1// nx_x25519_extvec_gate.nx -- THE FIRST PROVABLY THIRD-PARTY-VALIDATED CLAIM.
2// Proven GREEN on the laptop 2026-07-31 (pass=2 fail=0). Shipped here so it runs where claims are served.
3//
4// Every other KAT in this corpus embeds its expected values as constants a developer copied out of a
5// specification. Honest work, but NOT provably external: nothing in the artifact distinguishes a value
6// transcribed from the IETF from one an author -- or an AGENT -- merely believed. This gate closes that:
7// 1 it reads the vectors FROM knowledge/extvec/rfc7748.txt AT RUN TIME. NO expected value appears in
8// this source at all, so there is nothing here for anyone to have mistyped or invented.
9// 2 it PINS the acquisition digest: the file must sha256 to the value nx_vecfetch computed IN-PROCESS,
10// at the socket, before the bytes ever touched disk. Edited, truncated or substituted -> pin fails.
11// 3 only then does it run x25519() and compare.
12//
13// THE PIN IS THE SECURITY PROPERTY, NOT THE RUN-TIME PARSE. Parsing from a file is necessary but NOT
14// sufficient: an agent could edit the fetched file to contain whatever answers make its implementation
15// pass, and the parse would faithfully read the forgery. Pinning to an ACQUISITION-TIME digest is what
16// turns "we read it from a file" into evidence.
17// AND THE PIN MAKES TRANSPORT UNTRUSTED-BUT-VERIFIED: whoever carries rfc7748.txt to this host -- scp, an
18// agent, a USB stick -- cannot corrupt it undetected, because sha256 preimage resistance means bytes that
19// hash to ab200228.. ARE the fetched bytes. The carrier never has to be trusted. That is the whole point
20// of content-addressing, and it is why this gate is safe to ship even though its data file is not.
21//
22// TO MAKE IT GREEN HERE: place knowledge/extvec/rfc7748.txt (any byte-exact copy; the pin checks it), or
23// build+run nx_vecfetch on this host. Until then it reports RED-and-honest: absent file, never a fallback
24// to constants. license_tier: ORIGINAL expect_exit: 0
25import "nx_syscalls.nx"
26import "nx_sha256_wasm.nx"
27import "nx_x25519.nx"
28
29func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
30func wb(b: *u8, n: i64) -> i64 { sys_write(1, b, n); return 0 }
31
32func nn(v: i64) -> i64 {
33 var m: i64 = v
34 if m < 0 { w("-" as *u8); m = 0 - m }
35 let t: *u8 = sys_mmap(32)
36 var k: i64 = 0
37 if m == 0 { t[0] = 48 as u8; k = 1 }
38 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
39 let b: *u8 = sys_mmap(32)
40 var j: i64 = 0
41 while j < k { b[j] = t[k - 1 - j]; j = j + 1 }
42 sys_write(1, b, k)
43 return 0
44}
45
46func hexnib(v: i64) -> i64 { if v < 10 { return 48 + v } return 87 + v }
47
48func hexval(c: i64) -> i64 {
49 if c >= 48 { if c <= 57 { return c - 48 } }
50 if c >= 97 { if c <= 102 { return c - 87 } }
51 if c >= 65 { if c <= 70 { return c - 55 } }
52 return 0 - 1
53}
54
55func starts(b: *u8, n: i64, at: i64, s: *u8) -> i64 {
56 var i: i64 = 0
57 while s[i] != (0 as u8) {
58 if at + i >= n { return 0 }
59 if b[at + i] != s[i] { return 0 }
60 i = i + 1
61 }
62 return 1
63}
64
65func findfrom(b: *u8, n: i64, s: *u8, from: i64) -> i64 {
66 var p: i64 = from
67 while p < n {
68 if starts(b, n, p, s) == 1 { return p }
69 p = p + 1
70 }
71 return 0 - 1
72}
73
74// Strict: refuses a short hex run, so a reflowed or truncated document fails loudly rather than yielding
75// a half-vector that would then be compared as if complete.
76func parse32(b: *u8, n: i64, from: i64, out: *u8) -> i64 {
77 var p: i64 = from
78 var got: i64 = 0
79 while p < n {
80 if got >= 32 { return p }
81 let c: i64 = b[p] as i64
82 let hv: i64 = hexval(c)
83 if hv < 0 {
84 if got > 0 { if got < 32 { got = 0 } }
85 p = p + 1
86 } else {
87 if p + 1 >= n { return 0 - 1 }
88 let hv2: i64 = hexval(b[p + 1] as i64)
89 if hv2 < 0 { p = p + 1 }
90 else {
91 out[got] = ((hv * 16) + hv2) as u8
92 got = got + 1
93 p = p + 2
94 }
95 }
96 }
97 if got >= 32 { return p }
98 return 0 - 1
99}
100
101func eq32(a: *u8, b: *u8) -> i64 {
102 var i: i64 = 0
103 while i < 32 { if a[i] != b[i] { return 0 } i = i + 1 }
104 return 1
105}
106
107func main() -> i64 {
108 w("nx_x25519_extvec_gate -- x25519 vs RFC 7748 5.2, vectors READ FROM THE FETCHED DOCUMENT\n" as *u8)
109
110 let lp: *i64 = sys_mmap(16) as *i64
111 lp[0] = 0
112 let b: *u8 = sys_read_file("knowledge/extvec/rfc7748.txt\x00" as *u8, lp)
113 if lp[0] <= 0 {
114 w("RED: fetched vector file absent -- run nx_vecfetch first. NOT falling back to constants.\n" as *u8)
115 return 1
116 }
117
118 let ctx: *u8 = sys_mmap(1024)
119 let dig: *u8 = sys_mmap(64)
120 nx_sha256_one_shot(b, lp[0], ctx, dig)
121 let hx: *u8 = sys_mmap(80)
122 var i: i64 = 0
123 while i < 32 {
124 hx[i * 2] = hexnib(((dig[i] as i64) / 16) & 15) as u8
125 hx[i * 2 + 1] = hexnib((dig[i] as i64) & 15) as u8
126 i = i + 1
127 }
128 // A MODULE-LEVEL `const NAME: *u8 = "..." as *u8` DOES NOT COMPARE CORRECTLY IN nx_cc. First run printed
129 // this digest byte-for-byte identical to the constant and STILL reported PIN FAILED -- a check
130 // disagreeing with its own displayed evidence means the INSTRUMENT is broken, not the subject. Bound as
131 // a LOCAL literal. Had I trusted that RED and loosened the pin, I would have disabled the one clause
132 // that makes this gate evidence.
133 let want: *u8 = "ab200228b7369398bc112917a0e3dcf6dbb943105b5e170be565e309c104b8dd\x00" as *u8
134 var pin: i64 = 1
135 i = 0
136 while i < 64 { if hx[i] != want[i] { pin = 0 } i = i + 1 }
137 w(" acquisition digest: " as *u8); wb(hx, 64); w("\n" as *u8)
138 if pin == 0 {
139 w("RED: PIN FAILED -- this file is not the one nx_vecfetch acquired.\n" as *u8)
140 w(" Refusing to read vectors from an unpinned document: an edited file would let us\n" as *u8)
141 w(" grade ourselves against answers of our own choosing.\n" as *u8)
142 return 1
143 }
144 w(" PIN OK -- bytes match the digest computed in-process at the socket\n" as *u8)
145
146 var pass: i64 = 0
147 var fail: i64 = 0
148 let sc: *u8 = sys_mmap(64)
149 let uu: *u8 = sys_mmap(64)
150 let ex: *u8 = sys_mmap(64)
151 let got: *u8 = sys_mmap(64)
152
153 var cur: i64 = 0
154 var vec: i64 = 0
155 while vec < 2 {
156 let ls: i64 = findfrom(b, lp[0], "Input scalar:" as *u8, cur)
157 if ls < 0 { w(" RED: could not locate 'Input scalar:' in the document\n" as *u8); fail = fail + 1; vec = 2 }
158 else {
159 let p1: i64 = parse32(b, lp[0], ls + 13, sc)
160 let lu: i64 = findfrom(b, lp[0], "Input u-coordinate:" as *u8, p1)
161 let p2: i64 = parse32(b, lp[0], lu + 19, uu)
162 let lo: i64 = findfrom(b, lp[0], "Output u-coordinate:" as *u8, p2)
163 let p3: i64 = parse32(b, lp[0], lo + 20, ex)
164 if p1 < 0 { fail = fail + 1 } else { if p2 < 0 { fail = fail + 1 } else { if p3 < 0 { fail = fail + 1 } else {
165 x25519(sc, uu, got)
166 if eq32(got, ex) == 1 {
167 pass = pass + 1
168 w(" PASS vector " as *u8); nn(vec + 1)
169 w(": x25519(scalar,u) == the document's Output u-coordinate\n" as *u8)
170 } else {
171 fail = fail + 1
172 w(" FAIL vector " as *u8); nn(vec + 1); w(": output mismatch\n" as *u8)
173 }
174 cur = p3
175 } } }
176 vec = vec + 1
177 }
178 }
179
180 w("\n refsrc=https://www.rfc-editor.org/rfc/rfc7748.txt\n" as *u8)
181 w(" refsrcdig=" as *u8); wb(hx, 64); w("\n" as *u8)
182 w(" ref=RFC7748-5.2 gate=nx_x25519_extvec_gate\n" as *u8)
183 w("nx_x25519_extvec_gate: pass=" as *u8); nn(pass); w(" fail=" as *u8); nn(fail)
184 if fail == 0 { if pass == 2 { w(" verdict=GREEN\n" as *u8); return 0 } }
185 w(" verdict=RED\n" as *u8)
186 return 1
187}