code wiki / _hdl_build / nx_x509_emit.nx
nx_x509_emit.nx source
↩ module page · 387 lines · 18294 B
1// nx_x509_emit.nx -- F103e RUNG 9: author a SELF-SIGNED X.509 v3 certificate.
2//
3// The cert that will carry our Secure Boot key. Real EDK2 with MS keys refuses our unsigned .efi
4// (Access Denied) while the same secboot firmware in SETUP mode runs it, so the blocker is the
5// enrolled key set (debt 1786237435). Enrolling means putting a CERT in db.
6//
7// ★OIDs ARE DERIVED, NOT RECALLED. An OID written as a byte string from memory is a fabricated
8// constant. Here `der_oid_from_arcs` ENCODES the arc numbers (X.690 §8.19: first byte = 40*a1 + a2,
9// then base-128 with continuation bits) -- and T1 validates that encoder against a known-good
10// encoding the estate already ships: the SHA-256 OID sitting inside the incumbent's
11// `rsa_pkcs1_sha256_di_byte` DigestInfo table. ★★★★★★**ONE VERIFIED ENCODER TURNS EVERY OTHER OID
12// FROM A REMEMBERED BYTE STRING INTO A DERIVED RESULT — AND THE ARC NUMBERS ARE SPEC FACTS, WHICH
13// THE ENCODER THEN PROVES.**
14//
15// ★THE ORACLE IS THE ESTATE'S OWN READER, END TO END: emit -> `x509_parse` must accept and report a
16// tbs region -> our signer signs exactly that region -> the incumbent `rsa_pkcs1_v1_5_sha256_verify`
17// must accept. Four independently written pieces agreeing. A cert that only round-trips through its
18// own emitter proves nothing.
19//
20// Structure (RFC 5280): Certificate ::= SEQUENCE { tbsCertificate, signatureAlgorithm, signatureValue }
21// TBSCertificate ::= SEQUENCE { [0] v3, serial, sigAlg, issuer, validity, subject, SPKI }
22// ⚠extensions ([3] basicConstraints CA:TRUE) are NOT emitted yet -- named as owed rather than
23// silently absent, because a db entry does not require them but a KEK/PK chain will.
24//
25// Usage: nx_x509_emit selftest
26// Exit: 0 GREEN | 1 RED. Log -> knowledge/status/nishi_os.log, verdict= LAST.
27// license_tier: ORIGINAL
28import "nx_syscalls.nx"
29import "nx_sha256.nx"
30import "nx_u2048.nx"
31import "nx_u2048_mul.nx"
32import "nx_rsa2048_mod.nx"
33import "nx_rsa2048_mod_exp.nx"
34import "nx_rsa2048_mont.nx"
35import "nx_rsa2048_mod_exp_big.nx"
36import "nx_asn1.nx"
37import "nx_x509.nx"
38import "nx_rsa_pkcs1_v1_5_sha256.nx"
39import "nx_u2048_millerrabin.nx"
40import "nx_u2048_smallops.nx"
41import "nx_rsa_keygen.nx"
42import "nx_rsa_pkcs1_sign.nx"
43const XE_MAGIC_65536: i64 = 65536
44const XE_MAGIC_1024: i64 = 1024
45const XE_MAGIC_113549: i64 = 113549
46const XE_MAGIC_20260808: i64 = 20260808
47const XE_MAGIC_65537: i64 = 65537
48const XE_MAGIC_4097: i64 = 4097
49
50const XE_BUF: i64 = 8192
51
52func xe_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
53func xe_fp(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
54func xe_fn(fd: i64, v: i64) -> i64 {
55 let bb: *u8 = sys_mmap(28); var m: i64 = v
56 if m < 0 { m = 0 - m; bb[0] = 45 as u8; sys_write(fd, bb, 1) }
57 let t: *u8 = sys_mmap(28); var k: i64 = 0
58 if m == 0 { t[0] = 48 as u8; k = 1 }
59 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
60 var i: i64 = 0
61 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
62 sys_write(fd, bb, k); return 0
63}
64
65// ---- DER length + TLV (minimal form; the same rules nx_asn1_der_emit proves) --------------------
66func xe_put_len(out: *u8, off: i64, n: i64) -> i64 {
67 if n < 128 { out[off] = n as u8; return off + 1 }
68 if n < 256 { out[off] = 0x81 as u8; out[off+1] = n as u8; return off + 2 }
69 if n < XE_MAGIC_65536 {
70 out[off] = 0x82 as u8
71 out[off+1] = ((n >> 8) & 0xff) as u8
72 out[off+2] = (n & 0xff) as u8
73 return off + 3
74 }
75 return 0 - 1
76}
77func xe_len_size(n: i64) -> i64 {
78 if n < 128 { return 1 }
79 if n < 256 { return 2 }
80 return 3
81}
82// wrap payload[0..plen) at `out+off` as tag||len||payload
83func xe_wrap(out: *u8, off: i64, tag: i64, payload: *u8, plen: i64) -> i64 {
84 out[off] = (tag & 0xff) as u8
85 var o: i64 = xe_put_len(out, off + 1, plen)
86 if o < 0 { return 0 - 1 }
87 var i: i64 = 0
88 while i < plen { out[o + i] = payload[i]; i = i + 1 }
89 return o + plen
90}
91
92// ---- OID: DERIVE from arcs (X.690 8.19). Never a remembered byte string. -----------------------
93func der_oid_from_arcs(out: *u8, off: i64, arcs: *i64, narcs: i64) -> i64 {
94 if narcs < 2 { return 0 - 1 }
95 let body: *u8 = sys_mmap(128)
96 var bl: i64 = 0
97 body[bl] = (40 * arcs[0] + arcs[1]) as u8 // first two arcs share a byte
98 bl = bl + 1
99 var i: i64 = 2
100 while i < narcs {
101 let v: i64 = arcs[i]
102 // base-128, most significant group first, continuation bit on all but the last
103 var tmp: *u8 = sys_mmap(16)
104 var t: i64 = 0
105 var x: i64 = v
106 if x == 0 { tmp[0] = 0 as u8; t = 1 }
107 while x > 0 { tmp[t] = (x & 0x7f) as u8; x = x >> 7; t = t + 1 }
108 var k: i64 = t - 1
109 while k >= 0 {
110 var b: i64 = tmp[k] as i64
111 if k > 0 { b = b | 0x80 }
112 body[bl] = b as u8
113 bl = bl + 1
114 k = k - 1
115 }
116 i = i + 1
117 }
118 return xe_wrap(out, off, ASN1_OID, body, bl)
119}
120
121// ---- AlgorithmIdentifier ::= SEQUENCE { OID, NULL } ---------------------------------------------
122func xe_algid(out: *u8, off: i64, arcs: *i64, narcs: i64) -> i64 {
123 let inner: *u8 = sys_mmap(256)
124 var o: i64 = der_oid_from_arcs(inner, 0, arcs, narcs)
125 if o < 0 { return 0 - 1 }
126 inner[o] = ASN1_NULL as u8; inner[o+1] = 0 as u8 // NULL params, as RSA algids carry
127 o = o + 2
128 return xe_wrap(out, off, ASN1_SEQUENCE, inner, o)
129}
130
131// ---- Name ::= SEQUENCE { SET { SEQUENCE { OID cn, PrintableString } } } -------------------------
132func xe_name(out: *u8, off: i64, cn: *u8) -> i64 {
133 var cl: i64 = 0
134 while cn[cl] != (0 as u8) { cl = cl + 1 }
135 let cnarcs: *i64 = sys_mmap(64) as *i64
136 cnarcs[0]=2; cnarcs[1]=5; cnarcs[2]=4; cnarcs[3]=3 // id-at-commonName 2.5.4.3
137 let atv: *u8 = sys_mmap(512)
138 var o: i64 = der_oid_from_arcs(atv, 0, cnarcs, 4)
139 o = xe_wrap(atv, o, ASN1_PRINTABLE, cn, cl)
140 let seq: *u8 = sys_mmap(512)
141 let sl: i64 = xe_wrap(seq, 0, ASN1_SEQUENCE, atv, o)
142 let set: *u8 = sys_mmap(512)
143 let stl: i64 = xe_wrap(set, 0, ASN1_SET, seq, sl)
144 return xe_wrap(out, off, ASN1_SEQUENCE, set, stl)
145}
146
147// ---- SubjectPublicKeyInfo ::= SEQUENCE { AlgId(rsaEncryption), BIT STRING { SEQ { n, e } } } ----
148func xe_spki(out: *u8, off: i64, n: *i64, e: i64) -> i64 {
149 let nb: *u8 = sys_mmap(256)
150 u2048_store_be(nb, n)
151 var s: i64 = 0
152 while s < 256 { if (nb[s] as i64) != 0 { s = 256 } else { s = s + 1 } } // find first nonzero
153 var start: i64 = 0
154 var scanning: i64 = 1
155 while scanning == 1 {
156 if start >= 256 { scanning = 0 } else {
157 if (nb[start] as i64) == 0 { start = start + 1 } else { scanning = 0 }
158 }
159 }
160 let nlen: i64 = 256 - start
161 // INTEGER n, with the leading 0x00 an RSA modulus always needs (top bit set)
162 let rsapub: *u8 = sys_mmap(XE_MAGIC_1024)
163 var o: i64 = 0
164 rsapub[o] = ASN1_INTEGER as u8; o = o + 1
165 var pad: i64 = 0
166 if ((nb[start] as i64) & 0x80) != 0 { pad = 1 }
167 o = xe_put_len(rsapub, o, nlen + pad)
168 if pad == 1 { rsapub[o] = 0 as u8; o = o + 1 }
169 var i: i64 = 0
170 while i < nlen { rsapub[o + i] = nb[start + i]; i = i + 1 }
171 o = o + nlen
172 // INTEGER e (65537 = 01 00 01, top bit clear -> no pad)
173 let eb: *u8 = sys_mmap(16)
174 var el: i64 = 0
175 if e < 256 { eb[0] = e as u8; el = 1 } else {
176 if e < XE_MAGIC_65536 { eb[0] = ((e >> 8) & 0xff) as u8; eb[1] = (e & 0xff) as u8; el = 2 } else {
177 eb[0] = ((e >> 16) & 0xff) as u8; eb[1] = ((e >> 8) & 0xff) as u8; eb[2] = (e & 0xff) as u8; el = 3 } }
178 o = xe_wrap(rsapub, o, ASN1_INTEGER, eb, el)
179 let pubseq: *u8 = sys_mmap(XE_MAGIC_1024)
180 let psl: i64 = xe_wrap(pubseq, 0, ASN1_SEQUENCE, rsapub, o)
181 // BIT STRING: one leading "unused bits" byte, always 0 here
182 let bits: *u8 = sys_mmap(XE_MAGIC_1024)
183 bits[0] = 0 as u8
184 var j: i64 = 0
185 while j < psl { bits[1 + j] = pubseq[j]; j = j + 1 }
186 let inner: *u8 = sys_mmap(XE_MAGIC_1024)
187 let rsaarcs: *i64 = sys_mmap(64) as *i64
188 rsaarcs[0]=1; rsaarcs[1]=2; rsaarcs[2]=840; rsaarcs[3]=XE_MAGIC_113549; rsaarcs[4]=1; rsaarcs[5]=1; rsaarcs[6]=1
189 var io: i64 = xe_algid(inner, 0, rsaarcs, 7)
190 io = xe_wrap(inner, io, ASN1_BIT_STRING, bits, psl + 1)
191 return xe_wrap(out, off, ASN1_SEQUENCE, inner, io)
192}
193
194// ---- tbsCertificate ----------------------------------------------------------------------------
195func xe_tbs(out: *u8, off: i64, n: *i64, e: i64, cn: *u8, serial: i64) -> i64 {
196 let body: *u8 = sys_mmap(XE_BUF)
197 var o: i64 = 0
198 // [0] EXPLICIT { INTEGER 2 } -- v3
199 let vin: *u8 = sys_mmap(16)
200 vin[0] = ASN1_INTEGER as u8; vin[1] = 1 as u8; vin[2] = 2 as u8
201 o = xe_wrap(body, o, 0xA0, vin, 3)
202 // serialNumber INTEGER (positive, so a high bit forces a leading zero)
203 let sb: *u8 = sys_mmap(16)
204 sb[0] = ((serial >> 8) & 0xff) as u8
205 sb[1] = (serial & 0xff) as u8
206 o = xe_wrap(body, o, ASN1_INTEGER, sb, 2)
207 // signature AlgorithmIdentifier: sha256WithRSAEncryption 1.2.840.113549.1.1.11
208 let sigarcs: *i64 = sys_mmap(64) as *i64
209 sigarcs[0]=1; sigarcs[1]=2; sigarcs[2]=840; sigarcs[3]=XE_MAGIC_113549; sigarcs[4]=1; sigarcs[5]=1; sigarcs[6]=11
210 o = xe_algid(body, o, sigarcs, 7)
211 // issuer == subject (self-signed)
212 o = xe_name(body, o, cn)
213 // validity SEQUENCE { UTCTime notBefore, UTCTime notAfter }
214 let vb: *u8 = sys_mmap(256)
215 let nb1: *u8 = "260808000000Z" as *u8
216 let na1: *u8 = "360808000000Z" as *u8
217 var vo: i64 = xe_wrap(vb, 0, ASN1_UTC_TIME, nb1, 13)
218 vo = xe_wrap(vb, vo, ASN1_UTC_TIME, na1, 13)
219 o = xe_wrap(body, o, ASN1_SEQUENCE, vb, vo)
220 o = xe_name(body, o, cn)
221 o = xe_spki(body, o, n, e)
222 return xe_wrap(out, off, ASN1_SEQUENCE, body, o)
223}
224
225// ---- the whole certificate; returns total length or negative ------------------------------------
226func x509_emit_selfsigned(out: *u8, n: *i64, d: *i64, e: i64, cn: *u8, serial: i64,
227 tbs_off_p: *i64, tbs_len_p: *i64) -> i64 {
228 let tbs: *u8 = sys_mmap(XE_BUF)
229 let tlen: i64 = xe_tbs(tbs, 0, n, e, cn, serial)
230 if tlen < 0 { return 0 - 1 }
231 // sign the tbs DER exactly as emitted (tag+len+value), which is what RFC 5280 hashes
232 let sig: *u8 = sys_mmap(300)
233 if rsa_pkcs1_v1_5_sha256_sign(sig, tbs, tlen, d, n) != 1 { return 0 - 2 }
234 let sigarcs: *i64 = sys_mmap(64) as *i64
235 sigarcs[0]=1; sigarcs[1]=2; sigarcs[2]=840; sigarcs[3]=XE_MAGIC_113549; sigarcs[4]=1; sigarcs[5]=1; sigarcs[6]=11
236 let body: *u8 = sys_mmap(XE_BUF)
237 var o: i64 = 0
238 var i: i64 = 0
239 while i < tlen { body[o + i] = tbs[i]; i = i + 1 }
240 tbs_off_p[0] = o // offset of tbs INSIDE body (pre-wrap)
241 tbs_len_p[0] = tlen
242 o = o + tlen
243 o = xe_algid(body, o, sigarcs, 7)
244 let bits: *u8 = sys_mmap(300)
245 bits[0] = 0 as u8
246 var j: i64 = 0
247 while j < 256 { bits[1 + j] = sig[j]; j = j + 1 }
248 o = xe_wrap(body, o, ASN1_BIT_STRING, bits, 257)
249 return xe_wrap(out, 0, ASN1_SEQUENCE, body, o)
250}
251
252// =================================================================================================
253func xe_selftest() -> i64 {
254 var pass: i64 = 0
255 var teeth: i64 = 0
256
257 // T1 THE OID ENCODER, validated against a known-good encoding the estate already ships:
258 // the SHA-256 OID (2.16.840.1.101.3.4.2.1) lives at bytes 4..14 of the DigestInfo table.
259 teeth = teeth + 1
260 // 9 arcs = 72 bytes. A 64-byte arena block here OVERRAN by 8 and the estate's own guard caught
261 // it (ARENA-OVERRUN prev_alloc_size=64) while every tooth still reported GREEN.
262 // ★★★★★★A HEAP OVERRUN DOES NOT FAIL THE TEST THAT CAUSED IT — IT CORRUPTS SOMETHING ELSE LATER.
263 // Only the allocator's guard separated "7/7" from "7/7 and a latent memory bug".
264 let arcs: *i64 = sys_mmap(128) as *i64
265 arcs[0]=2; arcs[1]=16; arcs[2]=840; arcs[3]=1; arcs[4]=101; arcs[5]=3; arcs[6]=4; arcs[7]=2; arcs[8]=1
266 let ob: *u8 = sys_mmap(128)
267 let ol: i64 = der_oid_from_arcs(ob, 0, arcs, 9)
268 var t1: i64 = 1
269 if ol != 11 { t1 = 0 } // 06 09 + 9 body bytes
270 var i: i64 = 0
271 while i < 11 {
272 if (ob[i] as i64) != (rsa_pkcs1_sha256_di_byte(4 + i) & 0xff) { t1 = 0 }
273 i = i + 1
274 }
275 if t1 == 1 { pass = pass + 1; xe_p("XE-T1 oid-encoder matches the estate's shipped SHA-256 OID GREEN\n" as *u8) }
276 else { xe_p("XE-T1 RED len=" as *u8); xe_fn(1, ol); xe_p("\n" as *u8) }
277
278 // T2 NEGATIVE CONTROL: a different arc list must NOT produce those bytes, or T1 proves nothing.
279 teeth = teeth + 1
280 arcs[8] = 2 // ...4.2.2 instead of ...4.2.1
281 let ol2: i64 = der_oid_from_arcs(ob, 0, arcs, 9)
282 var same: i64 = 1
283 var k: i64 = 0
284 while k < 11 { if (ob[k] as i64) != (rsa_pkcs1_sha256_di_byte(4 + k) & 0xff) { same = 0 } k = k + 1 }
285 if ol2 == 11 { if same == 0 { pass = pass + 1; xe_p("XE-T2 neg-control-different-arcs-differ GREEN\n" as *u8) }
286 else { xe_p("XE-T2 RED [VACUOUS: encoder ignores its input]\n" as *u8) } }
287 else { xe_p("XE-T2 RED\n" as *u8) }
288
289 // T3 multi-byte arc: 113549 must encode as three continuation bytes 86 F7 0D (DERIVED here, and
290 // checked by re-decoding base-128 rather than by comparing to a remembered string).
291 teeth = teeth + 1
292 let a2: *i64 = sys_mmap(64) as *i64
293 a2[0]=1; a2[1]=2; a2[2]=840; a2[3]=XE_MAGIC_113549
294 let o3: i64 = der_oid_from_arcs(ob, 0, a2, 4)
295 var acc: i64 = 0
296 var p: i64 = 2 + 1 + 2 // skip 06 len, first-two-arcs byte, 840's 2 bytes
297 var decoded: i64 = 0
298 var run: i64 = 1
299 while run == 1 {
300 if p >= o3 { run = 0 } else {
301 let b: i64 = ob[p] as i64
302 acc = (acc << 7) | (b & 0x7f)
303 if (b & 0x80) == 0 { decoded = acc; run = 0 }
304 p = p + 1
305 }
306 }
307 if decoded == XE_MAGIC_113549 { pass = pass + 1; xe_p("XE-T3 multi-byte-arc round-trips to 113549 GREEN\n" as *u8) }
308 else { xe_p("XE-T3 RED decoded=" as *u8); xe_fn(1, decoded); xe_p("\n" as *u8) }
309
310 // ---- generate a key and emit a real certificate ----
311 xe_p("TEST-KEY-DO-NOT-USE: generating a deterministic 2048-bit key...\n" as *u8)
312 let np: *i64 = u2048_alloc(); let qp: *i64 = u2048_alloc()
313 let n: *i64 = u2048_alloc(); let d: *i64 = u2048_alloc()
314 let st: *i64 = sys_mmap(16) as *i64
315 st[0] = XE_MAGIC_20260808
316 if kg_keygen(XE_MAGIC_1024, np, qp, n, d, st, 1) != 1 {
317 xe_p("XE RED: keygen failed\n" as *u8); sys_exit(1); return 1
318 }
319 xe_p("key ready\n" as *u8)
320
321 let cert: *u8 = sys_mmap(XE_BUF)
322 let toff: *i64 = sys_mmap(16) as *i64
323 let tlen: *i64 = sys_mmap(16) as *i64
324 let cn: *u8 = "Nishi Platform Key" as *u8
325 let clen: i64 = x509_emit_selfsigned(cert, n, d, XE_MAGIC_65537, cn, XE_MAGIC_4097, toff, tlen)
326
327 // T4 THE INCUMBENT PARSER MUST ACCEPT IT.
328 teeth = teeth + 1
329 let xc: *X509Cert = sys_mmap(512) as *X509Cert
330 var rcp: i64 = 0 - 999
331 if clen > 0 { rcp = x509_parse(cert, clen, xc) }
332 if rcp >= 0 { pass = pass + 1; xe_p("XE-T4 incumbent x509_parse ACCEPTS our cert GREEN len=" as *u8)
333 xe_fn(1, clen); xe_p("\n" as *u8) }
334 else { xe_p("XE-T4 RED clen=" as *u8); xe_fn(1, clen); xe_p(" rc=" as *u8); xe_fn(1, rcp); xe_p("\n" as *u8) }
335
336 // T5 THE SIGNATURE MUST VERIFY over the tbs region the PARSER found -- not the one we remember
337 // emitting. ★★★★★★A SELF-SIGNED CERT WHERE THE SIGNER AND THE PARSER DISAGREE ABOUT WHICH BYTES
338 // ARE SIGNED IS EXACTLY THE BUG THAT LOOKS CORRECT FROM BOTH SIDES.
339 teeth = teeth + 1
340 if rcp >= 0 {
341 let v: i64 = rsa_pkcs1_v1_5_sha256_verify((cert + xc.tbs_off) as *u8, xc.tbs_len,
342 (cert + clen - 256) as *u8, n, XE_MAGIC_65537)
343 if v == NX_RSA_PKCS1_V15_OK { pass = pass + 1
344 xe_p("XE-T5 signature verifies over the PARSER-reported tbs region GREEN\n" as *u8) }
345 else { xe_p("XE-T5 RED verify=" as *u8); xe_fn(1, v)
346 xe_p(" tbs_off=" as *u8); xe_fn(1, xc.tbs_off)
347 xe_p(" tbs_len=" as *u8); xe_fn(1, xc.tbs_len)
348 xe_p(" emitted_len=" as *u8); xe_fn(1, tlen[0]); xe_p("\n" as *u8) }
349 } else { xe_p("XE-T5 RED [parser failed, cannot locate tbs]\n" as *u8) }
350
351 // T6 the parser's tbs region must equal what we emitted -- an independent cross-check of T5.
352 teeth = teeth + 1
353 if rcp >= 0 { if xc.tbs_len == tlen[0] { pass = pass + 1
354 xe_p("XE-T6 parser tbs_len == emitted tbs_len GREEN\n" as *u8) }
355 else { xe_p("XE-T6 RED parser=" as *u8); xe_fn(1, xc.tbs_len)
356 xe_p(" emitted=" as *u8); xe_fn(1, tlen[0]); xe_p("\n" as *u8) } }
357 else { xe_p("XE-T6 RED\n" as *u8) }
358
359 // T7 NEGATIVE CONTROL: corrupt one tbs byte -> the signature must STOP verifying.
360 teeth = teeth + 1
361 if rcp >= 0 {
362 let sv: i64 = cert[xc.tbs_off + 20] as i64
363 cert[xc.tbs_off + 20] = ((sv ^ 0xff) & 0xff) as u8
364 let v2: i64 = rsa_pkcs1_v1_5_sha256_verify((cert + xc.tbs_off) as *u8, xc.tbs_len,
365 (cert + clen - 256) as *u8, n, XE_MAGIC_65537)
366 if v2 != NX_RSA_PKCS1_V15_OK { pass = pass + 1
367 xe_p("XE-T7 neg-control-tbs-tamper-breaks-signature GREEN\n" as *u8) }
368 else { xe_p("XE-T7 RED [VACUOUS]\n" as *u8) }
369 cert[xc.tbs_off + 20] = sv as u8
370 } else { xe_p("XE-T7 RED\n" as *u8) }
371
372 xe_p("XE-SELFTEST " as *u8); xe_fn(1, pass); xe_p("/" as *u8); xe_fn(1, teeth); xe_p("\n" as *u8)
373 let lf: i64 = sys_openat_append("knowledge/status/nishi_os.log" as *u8, 0x1a4)
374 if lf >= 0 {
375 xe_fp(lf, "X509EMIT selftest teeth=" as *u8); xe_fn(lf, pass)
376 xe_fp(lf, "of" as *u8); xe_fn(lf, teeth)
377 xe_fp(lf, " oracle=incumbent-x509_parse+rsa-verify verdict=" as *u8)
378 if pass == teeth { xe_fp(lf, "GREEN\n" as *u8) } else { xe_fp(lf, "RED\n" as *u8) }
379 sys_close(lf)
380 }
381 if pass == teeth { sys_exit(0); return 0 }
382 sys_exit(1); return 1
383}
384
385func main(argc: i64, argv: *i64) -> i64 {
386 return xe_selftest()
387}