nx_sealed_sender.nx source
↩ module page · 404 lines · 18335 B
1// nx_sealed_sender.nx -- C9 of the comms lane: SEALED SENDER (metadata privacy). Contract symbol
2// ss_seal == the /compare/comms C9 watch. REFEREE: nx_sealed_sender_gate.
3// DONE-RULE (comms.plan): the relay routes a message whose sender identity appears in no
4// relay-readable byte, proven by reading the relay's own capture in the gate.
5//
6// SIGNAL'S FRONTIER, sovereign. A relay must be able to DELIVER a message without learning WHO sent
7// it. The envelope the relay sees carries only an opaque per-room ROUTING TOKEN (a keyed hash of the
8// room key -- reveals neither the room name nor its members) plus ciphertext and a MAC. The sender's
9// identity, the content, and the room name are ALL inside the E2EE payload. The recipient (who holds
10// the room key) opens it and learns the sender -- authenticated by an Ed25519 signature the relay
11// never sees, so within the group the sender is UNFORGEABLE, while to the relay it is INVISIBLE.
12// This is the full sealed-sender shape: a sender certificate (the Ed25519 pubkey) + a signature over
13// (routing_token || seq || plaintext), sealed inside the encrypted envelope.
14//
15// HONEST METADATA SCOPE: the delivery SEQUENCE (seq) is relay-visible by design -- ordering is
16// delivery metadata, not sender identity, exactly as Signal's sealed sender still carries envelope
17// timing. What is provably ABSENT from every relay-readable byte is the SENDER, the CONTENT, and the
18// ROOM NAME. The gate proves that by scanning the envelope bytes.
19//
20// PURE COMPOSITION, no new crypto: ed25519 (RFC 8032 sign/verify) + sha256 (HMAC/HKDF) + chacha20
21// (RFC 8439). No WebRTC, no OpenSSL. In production the room key is the C7 epoch secret, so sealed
22// sender rides the ratchet -- forward-secret and (with C8) post-quantum -- with no relay changes.
23// DEBT: the HMAC/HKDF/hex/file helpers are shared with C7 and C8; extraction to nx_kdf_lib is filed
24// (comms.plan kdf-lib-extract, now three consumers) -- named, not silently re-copied.
25// license_tier: ORIGINAL No hw writes (Rule 26).
26import "nx_syscalls.nx"
27import "nx_itoa_lib.nx"
28import "nx_sha256.nx"
29import "nx_chacha20.nx"
30import "nx_ed25519_signature.nx"
31
32const SMS_EXIT_OK: i64 = 0
33const SMS_EXIT_USAGE: i64 = 2
34const SMS_EXIT_REFUSED: i64 = 3
35const SMS_EXIT_CORRUPT: i64 = 5
36const SMS_KEY: i64 = 32
37const SMS_PUB: i64 = 32
38const SMS_SIG: i64 = 64
39const SMS_MAC: i64 = 32
40const SMS_NONCE: i64 = 12
41const SMS_ROUTE: i64 = 16 // routing-token bytes (128-bit opaque room handle)
42const SMS_BLOCK: i64 = 64
43const SMS_IPAD: i64 = 54
44const SMS_OPAD: i64 = 92
45const SMS_NL: i64 = 10
46const SMS_PIPE: i64 = 124
47const SMS_FILECAP: i64 = 262144
48const SMS_HDR: i64 = 96 // sender_pub(32) || sig(64) inside the sealed payload
49
50func sms_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
51func sms_wn(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 }
52func sms_num(v: i64) -> i64 { nxi_out(v); return 0 }
53func sms_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
54func sms_eq(a: *u8, b: *u8) -> i64 {
55 var i: i64 = 0
56 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
57 if b[i] != (0 as u8) { return 0 }
58 return 1
59}
60func sms_memeq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 }
61func sms_hexe(src: *u8, n: i64, dst: *u8) -> i64 {
62 var i: i64 = 0
63 while i < n {
64 let b: i64 = src[i] as i64
65 let hi: i64 = b / 16
66 let lo: i64 = b % 16
67 if hi < 10 { dst[i*2] = (48 + hi) as u8 } else { dst[i*2] = (87 + hi) as u8 }
68 if lo < 10 { dst[i*2+1] = (48 + lo) as u8 } else { dst[i*2+1] = (87 + lo) as u8 }
69 i = i + 1
70 }
71 dst[n*2] = 0 as u8
72 return n * 2
73}
74func sms_hexv(c: i64) -> i64 {
75 if c >= 48 { if c <= 57 { return c - 48 } }
76 if c >= 97 { if c <= 102 { return c - 87 } }
77 if c >= 65 { if c <= 70 { return c - 55 } }
78 return 0 - 1
79}
80func sms_hexd(src: *u8, n: i64, dst: *u8) -> i64 {
81 if n % 2 != 0 { return 0 - 1 }
82 var i: i64 = 0
83 while i < n {
84 let h: i64 = sms_hexv(src[i] as i64)
85 let l: i64 = sms_hexv(src[i+1] as i64)
86 if h < 0 { return 0 - 1 }
87 if l < 0 { return 0 - 1 }
88 dst[i/2] = (h * 16 + l) as u8
89 i = i + 2
90 }
91 return n / 2
92}
93func sms_read(path: *u8, buf: *u8, cap: i64) -> i64 {
94 let fd: i64 = sys_openat_rd(path)
95 if fd < 0 { return 0 - 1 }
96 var tot: i64 = 0
97 while tot < cap { let r: i64 = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot); if r <= 0 { break } tot = tot + r }
98 sys_close(fd)
99 return tot
100}
101func sms_writef(path: *u8, buf: *u8, n: i64) -> i64 {
102 let fd: i64 = sys_openat_wr(path, 420)
103 if fd < 0 { return 0 - 1 }
104 var w: i64 = 0
105 while w < n { let r: i64 = sys_write(fd, (buf as i64 + w) as *u8, n - w); if r <= 0 { break } w = w + r }
106 sys_fsync(fd)
107 sys_close(fd)
108 return 0
109}
110func sms_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o] = s[i]; o = o + 1; i = i + 1 } return o }
111func sms_catn(d: *u8, o: i64, v: i64) -> i64 {
112 if v == 0 { d[o] = 48 as u8; return o + 1 }
113 var tmp: *u8 = sys_mmap(24)
114 var k: i64 = 0
115 var m: i64 = v
116 while m > 0 { tmp[k] = (48 + m % 10) as u8; m = m / 10; k = k + 1 }
117 var j: i64 = k - 1
118 while j >= 0 { d[o] = tmp[j]; o = o + 1; j = j - 1 }
119 return o
120}
121func sms_field(line: *u8, n: i64, idx: i64, out: *u8) -> i64 {
122 var f: i64 = 0
123 var i: i64 = 0
124 var st: i64 = 0
125 while i < n { if f == idx { st = i; break } if line[i] == (SMS_PIPE as u8) { f = f + 1 } i = i + 1 }
126 if f != idx { return 0 - 1 }
127 var e: i64 = st
128 while e < n { if line[e] == (SMS_PIPE as u8) { break } if line[e] == (SMS_NL as u8) { break } e = e + 1 }
129 var o: i64 = 0
130 while st < e { out[o] = line[st]; o = o + 1; st = st + 1 }
131 out[o] = 0 as u8
132 return o
133}
134func sms_hmac(key: *u8, klen: i64, msg: *u8, mlen: i64, out: *u8) -> i64 {
135 let k0: *u8 = sys_mmap(SMS_BLOCK)
136 var i: i64 = 0
137 if klen > SMS_BLOCK {
138 sha256_digest(key, klen, k0)
139 i = SMS_KEY
140 while i < SMS_BLOCK { k0[i] = 0 as u8; i = i + 1 }
141 } else {
142 i = 0
143 while i < klen { k0[i] = key[i]; i = i + 1 }
144 while i < SMS_BLOCK { k0[i] = 0 as u8; i = i + 1 }
145 }
146 let inner: *u8 = sys_mmap(SMS_BLOCK + mlen + 16)
147 i = 0
148 while i < SMS_BLOCK { inner[i] = ((k0[i] as i64) ^ SMS_IPAD) as u8; i = i + 1 }
149 var j: i64 = 0
150 while j < mlen { inner[SMS_BLOCK + j] = msg[j]; j = j + 1 }
151 let ih: *u8 = sys_mmap(SMS_KEY)
152 sha256_digest(inner, SMS_BLOCK + mlen, ih)
153 let outer: *u8 = sys_mmap(SMS_BLOCK + SMS_KEY + 16)
154 i = 0
155 while i < SMS_BLOCK { outer[i] = ((k0[i] as i64) ^ SMS_OPAD) as u8; i = i + 1 }
156 j = 0
157 while j < SMS_KEY { outer[SMS_BLOCK + j] = ih[j]; j = j + 1 }
158 sha256_digest(outer, SMS_BLOCK + SMS_KEY, out)
159 return 0
160}
161// HKDF-Expand one block with label + numeric context (seq)
162func sms_derive(secret: *u8, label: *u8, seq: i64, out: *u8) -> i64 {
163 let info: *u8 = sys_mmap(128)
164 var o: i64 = sms_cat(info, 0, "sealed 1.0 " as *u8)
165 o = sms_cat(info, o, label)
166 info[o] = SMS_PIPE as u8
167 o = o + 1
168 o = sms_catn(info, o, seq)
169 info[o] = 1 as u8
170 o = o + 1
171 sms_hmac(secret, SMS_KEY, info, o, out)
172 return 0
173}
174// the routing token: keyed hash of the room key, SEQ-INDEPENDENT so the relay can group a room's
175// traffic without learning the room. Reveals nothing (HMAC).
176func sms_route(room_key: *u8, tok: *u8) -> i64 {
177 let full: *u8 = sys_mmap(SMS_KEY)
178 sms_hmac(room_key, SMS_KEY, "sealed-route" as *u8, 12, full)
179 var i: i64 = 0
180 while i < SMS_ROUTE { tok[i] = full[i]; i = i + 1 }
181 return 0
182}
183// the signed transcript: routing_token(16) || seq_le(8) || plaintext -- binds the sender to THIS
184// message and room, verifiable only after decryption.
185func sms_transcript(tok: *u8, seq: i64, pt: *u8, ptlen: i64, out: *u8) -> i64 {
186 var i: i64 = 0
187 while i < SMS_ROUTE { out[i] = tok[i]; i = i + 1 }
188 var s: i64 = seq
189 var j: i64 = 0
190 while j < 8 { out[SMS_ROUTE + j] = (s & 255) as u8; s = s / 256; j = j + 1 }
191 var k: i64 = 0
192 while k < ptlen { out[SMS_ROUTE + 8 + k] = pt[k]; k = k + 1 }
193 return SMS_ROUTE + 8 + ptlen
194}
195// THE CONTRACT SYMBOL: seal (sender_priv, sender_pub, room_key, seq, plaintext) into a relay-blind
196// envelope. Writes env bytes into out; returns length. The relay sees ONLY routing_token + seq + ct + mac.
197func ss_seal(room_key: *u8, sender_priv: *u8, sender_pub: *u8, seq: i64, pt: *u8, ptlen: i64, out: *u8) -> i64 {
198 let tok: *u8 = sys_mmap(SMS_ROUTE)
199 sms_route(room_key, tok)
200 // sign the transcript with the sender's Ed25519 identity
201 let tr: *u8 = sys_mmap(SMS_ROUTE + 8 + ptlen + 16)
202 let trlen: i64 = sms_transcript(tok, seq, pt, ptlen, tr)
203 let sig: *u8 = sys_mmap(SMS_SIG)
204 ed25519_sign_full(sender_priv, tr, trlen, sig)
205 // inner = sender_pub(32) || sig(64) || plaintext
206 let inner: *u8 = sys_mmap(SMS_HDR + ptlen + 16)
207 var i: i64 = 0
208 while i < SMS_PUB { inner[i] = sender_pub[i]; i = i + 1 }
209 i = 0
210 while i < SMS_SIG { inner[SMS_PUB + i] = sig[i]; i = i + 1 }
211 i = 0
212 while i < ptlen { inner[SMS_HDR + i] = pt[i]; i = i + 1 }
213 let innerlen: i64 = SMS_HDR + ptlen
214 let fk: *u8 = sys_mmap(SMS_KEY)
215 sms_derive(room_key, "key" as *u8, seq, fk)
216 let nb: *u8 = sys_mmap(SMS_KEY)
217 sms_derive(room_key, "nonce" as *u8, seq, nb)
218 let nz: *u8 = sys_mmap(SMS_NONCE)
219 i = 0
220 while i < SMS_NONCE { nz[i] = nb[i]; i = i + 1 }
221 let ct: *u8 = sys_mmap(innerlen + 16)
222 chacha20_encrypt(fk, 0, nz, inner, innerlen, ct)
223 // mac binds routing_token || ct so a ciphertext cannot be re-pointed to another room
224 let macin: *u8 = sys_mmap(SMS_ROUTE + innerlen + 16)
225 i = 0
226 while i < SMS_ROUTE { macin[i] = tok[i]; i = i + 1 }
227 i = 0
228 while i < innerlen { macin[SMS_ROUTE + i] = ct[i]; i = i + 1 }
229 let mac: *u8 = sys_mmap(SMS_MAC)
230 sms_hmac(fk, SMS_KEY, macin, SMS_ROUTE + innerlen, mac)
231 // envelope: env|<tok_hex>|<seq>|<ct_hex>|<mac_hex>
232 var o: i64 = sms_cat(out, 0, "env|" as *u8)
233 let toh: *u8 = sys_mmap(SMS_ROUTE * 2 + 4)
234 sms_hexe(tok, SMS_ROUTE, toh)
235 o = sms_cat(out, o, toh)
236 out[o] = SMS_PIPE as u8
237 o = o + 1
238 o = sms_catn(out, o, seq)
239 out[o] = SMS_PIPE as u8
240 o = o + 1
241 let cth: *u8 = sys_mmap(innerlen * 2 + 4)
242 sms_hexe(ct, innerlen, cth)
243 o = sms_cat(out, o, cth)
244 out[o] = SMS_PIPE as u8
245 o = o + 1
246 let mh: *u8 = sys_mmap(SMS_MAC * 2 + 4)
247 sms_hexe(mac, SMS_MAC, mh)
248 o = sms_cat(out, o, mh)
249 out[o] = SMS_NL as u8
250 o = o + 1
251 return o
252}
253// ==== VERBS =====================================================================================
254func sms_keygen(priv_out: *u8, seed_hex: *u8) -> i64 {
255 let seed: *u8 = sys_mmap(4096)
256 let sl: i64 = sms_hexd(seed_hex, sms_len(seed_hex), seed)
257 if sl < 0 { sms_w("SEAL-REFUSED bad-hex seed\n" as *u8) return SMS_EXIT_REFUSED }
258 let priv: *u8 = sys_mmap(SMS_KEY)
259 sha256_digest(seed, sl, priv)
260 let ph: *u8 = sys_mmap(SMS_KEY * 2 + 4)
261 sms_hexe(priv, SMS_KEY, ph)
262 if sms_writef(priv_out, ph, SMS_KEY * 2) != 0 { sms_w("SEAL-RED priv-write-failed\n" as *u8) return SMS_EXIT_CORRUPT }
263 let pub: *u8 = sys_mmap(SMS_PUB)
264 ed25519_pub_from_priv(priv, pub)
265 let pubh: *u8 = sys_mmap(SMS_PUB * 2 + 4)
266 sms_hexe(pub, SMS_PUB, pubh)
267 sms_w("SEAL-KEYGEN-OK priv=" as *u8)
268 sms_w(priv_out)
269 sms_w(" PUB " as *u8)
270 sms_w(pubh)
271 sms_w("\n" as *u8)
272 return SMS_EXIT_OK
273}
274// seal <room_key_hex> <sender_priv_file> <seq> <plaintext> <env_out>
275func sms_seal_verb(room_key_hex: *u8, priv_file: *u8, seq: i64, pt: *u8, env_out: *u8) -> i64 {
276 let rk: *u8 = sys_mmap(SMS_KEY)
277 if sms_hexd(room_key_hex, sms_len(room_key_hex), rk) != SMS_KEY { sms_w("SEAL-REFUSED bad room_key (need 64 hex)\n" as *u8) return SMS_EXIT_REFUSED }
278 let ph: *u8 = sys_mmap(4096)
279 if sms_read(priv_file, ph, 4096) < SMS_KEY * 2 { sms_w("SEAL-REFUSED priv-file-short\n" as *u8) return SMS_EXIT_REFUSED }
280 let priv: *u8 = sys_mmap(SMS_KEY)
281 if sms_hexd(ph, SMS_KEY * 2, priv) != SMS_KEY { sms_w("SEAL-REFUSED bad-priv-hex\n" as *u8) return SMS_EXIT_REFUSED }
282 let pub: *u8 = sys_mmap(SMS_PUB)
283 ed25519_pub_from_priv(priv, pub)
284 let ptlen: i64 = sms_len(pt)
285 let env: *u8 = sys_mmap(SMS_FILECAP)
286 let n: i64 = ss_seal(rk, priv, pub, seq, pt, ptlen, env)
287 if sms_writef(env_out, env, n) != 0 { sms_w("SEAL-RED env-write-failed\n" as *u8) return SMS_EXIT_CORRUPT }
288 sms_w("SEAL-OK env=" as *u8)
289 sms_w(env_out)
290 sms_w(" seq=" as *u8)
291 sms_num(seq)
292 sms_w(" (sender identity and content are inside the sealed payload; the relay sees only a routing token)\n" as *u8)
293 return SMS_EXIT_OK
294}
295// route <env_file> -- MODELS THE RELAY: prints ONLY what a relay can extract to deliver the message.
296func sms_route_verb(env_file: *u8) -> i64 {
297 let eb: *u8 = sys_mmap(SMS_FILECAP)
298 let en: i64 = sms_read(env_file, eb, SMS_FILECAP)
299 if en <= 0 { sms_w("SEAL-REFUSED env-absent\n" as *u8) return SMS_EXIT_REFUSED }
300 let tok: *u8 = sys_mmap(256)
301 let seqf: *u8 = sys_mmap(64)
302 sms_field(eb, en, 1, tok)
303 sms_field(eb, en, 2, seqf)
304 sms_w("RELAY-VIEW routing_token=" as *u8)
305 sms_w(tok)
306 sms_w(" seq=" as *u8)
307 sms_w(seqf)
308 sms_w(" -- this is EVERYTHING the relay can read: an opaque room handle and a delivery sequence. No sender, no content, no room name.\n" as *u8)
309 return SMS_EXIT_OK
310}
311// open <room_key_hex> <env_file>
312func sms_open_verb(room_key_hex: *u8, env_file: *u8) -> i64 {
313 let rk: *u8 = sys_mmap(SMS_KEY)
314 if sms_hexd(room_key_hex, sms_len(room_key_hex), rk) != SMS_KEY { sms_w("SEAL-REFUSED bad room_key\n" as *u8) return SMS_EXIT_REFUSED }
315 let eb: *u8 = sys_mmap(SMS_FILECAP)
316 let en: i64 = sms_read(env_file, eb, SMS_FILECAP)
317 if en <= 0 { sms_w("SEAL-REFUSED env-absent\n" as *u8) return SMS_EXIT_REFUSED }
318 let seqf: *u8 = sys_mmap(64)
319 let cth: *u8 = sys_mmap(SMS_FILECAP)
320 let mh: *u8 = sys_mmap(256)
321 sms_field(eb, en, 2, seqf)
322 sms_field(eb, en, 3, cth)
323 sms_field(eb, en, 4, mh)
324 var seq: i64 = 0
325 var z: i64 = 0
326 while seqf[z] != (0 as u8) { seq = seq * 10 + (seqf[z] as i64 - 48); z = z + 1 }
327 let tok: *u8 = sys_mmap(SMS_ROUTE)
328 sms_route(rk, tok)
329 let ctlen_hex: i64 = sms_len(cth)
330 let ct: *u8 = sys_mmap(ctlen_hex / 2 + 4)
331 let ctlen: i64 = sms_hexd(cth, ctlen_hex, ct)
332 if ctlen < 0 { sms_w("SEAL-CORRUPT bad-ct-hex\n" as *u8) return SMS_EXIT_CORRUPT }
333 let fk: *u8 = sys_mmap(SMS_KEY)
334 sms_derive(rk, "key" as *u8, seq, fk)
335 // verify mac over routing_token || ct
336 let macin: *u8 = sys_mmap(SMS_ROUTE + ctlen + 16)
337 var i: i64 = 0
338 while i < SMS_ROUTE { macin[i] = tok[i]; i = i + 1 }
339 i = 0
340 while i < ctlen { macin[SMS_ROUTE + i] = ct[i]; i = i + 1 }
341 let mac: *u8 = sys_mmap(SMS_MAC)
342 sms_hmac(fk, SMS_KEY, macin, SMS_ROUTE + ctlen, mac)
343 let gotmac: *u8 = sys_mmap(SMS_MAC)
344 if sms_hexd(mh, sms_len(mh), gotmac) != SMS_MAC { sms_w("SEAL-CORRUPT bad-mac-hex\n" as *u8) return SMS_EXIT_CORRUPT }
345 if sms_memeq(mac, gotmac, SMS_MAC) == 0 {
346 sms_w("SEAL-OPEN-DENIED mac-fail -- wrong room key or tampered envelope; nothing decrypted\n" as *u8)
347 return SMS_EXIT_REFUSED
348 }
349 let nb: *u8 = sys_mmap(SMS_KEY)
350 sms_derive(rk, "nonce" as *u8, seq, nb)
351 let nz: *u8 = sys_mmap(SMS_NONCE)
352 i = 0
353 while i < SMS_NONCE { nz[i] = nb[i]; i = i + 1 }
354 let inner: *u8 = sys_mmap(ctlen + 16)
355 chacha20_encrypt(fk, 0, nz, ct, ctlen, inner)
356 if ctlen < SMS_HDR { sms_w("SEAL-CORRUPT inner-too-short\n" as *u8) return SMS_EXIT_CORRUPT }
357 let sender_pub: *u8 = sys_mmap(SMS_PUB)
358 i = 0
359 while i < SMS_PUB { sender_pub[i] = inner[i]; i = i + 1 }
360 let sig: *u8 = sys_mmap(SMS_SIG)
361 i = 0
362 while i < SMS_SIG { sig[i] = inner[SMS_PUB + i]; i = i + 1 }
363 let ptlen: i64 = ctlen - SMS_HDR
364 let pt: *u8 = sys_mmap(ptlen + 16)
365 i = 0
366 while i < ptlen { pt[i] = inner[SMS_HDR + i]; i = i + 1 }
367 // verify the sender's Ed25519 signature over the transcript
368 let tr: *u8 = sys_mmap(SMS_ROUTE + 8 + ptlen + 16)
369 let trlen: i64 = sms_transcript(tok, seq, pt, ptlen, tr)
370 let vr: i64 = ed25519_verify_full(sender_pub, tr, trlen, sig)
371 let pubh: *u8 = sys_mmap(SMS_PUB * 2 + 4)
372 sms_hexe(sender_pub, SMS_PUB, pubh)
373 if vr != 1 {
374 sms_w("SEAL-OPEN-FORGED sender_pub=" as *u8)
375 sms_w(pubh)
376 sms_w(" -- the sealed signature does NOT verify: this envelope was not signed by that identity. Rejected.\n" as *u8)
377 return SMS_EXIT_REFUSED
378 }
379 sms_w("SEAL-OPEN-OK sender_pub=" as *u8)
380 sms_w(pubh)
381 sms_w(" sig=VALID plaintext=" as *u8)
382 sms_wn(pt, ptlen)
383 sms_w("\n" as *u8)
384 return SMS_EXIT_OK
385}
386func sms_usage() -> i64 {
387 sms_w("usage: nx_sealed_sender keygen <priv_out> <seed_hex> | seal <room_key_hex> <sender_priv_file> <seq> <plaintext> <env_out> | route <env_file> | open <room_key_hex> <env_file>\n" as *u8)
388 return SMS_EXIT_USAGE
389}
390func main(argc: i64, argv: *i64) -> i64 {
391 if argc < 2 { let u: i64 = sms_usage() sys_exit(u) return u }
392 let v: *u8 = argv[1] as *u8
393 if sms_eq(v, "keygen" as *u8) == 1 { if argc < 4 { let u: i64 = sms_usage() sys_exit(u) return u } let r: i64 = sms_keygen(argv[2] as *u8, argv[3] as *u8) sys_exit(r) return r }
394 if sms_eq(v, "seal" as *u8) == 1 {
395 if argc < 7 { let u: i64 = sms_usage() sys_exit(u) return u }
396 let s: *u8 = argv[4] as *u8; var sq: i64 = 0; var z: i64 = 0; while s[z] != (0 as u8) { sq = sq * 10 + (s[z] as i64 - 48); z = z + 1 }
397 let r: i64 = sms_seal_verb(argv[2] as *u8, argv[3] as *u8, sq, argv[5] as *u8, argv[6] as *u8) sys_exit(r) return r
398 }
399 if sms_eq(v, "route" as *u8) == 1 { if argc < 3 { let u: i64 = sms_usage() sys_exit(u) return u } let r: i64 = sms_route_verb(argv[2] as *u8) sys_exit(r) return r }
400 if sms_eq(v, "open" as *u8) == 1 { if argc < 4 { let u: i64 = sms_usage() sys_exit(u) return u } let r: i64 = sms_open_verb(argv[2] as *u8, argv[3] as *u8) sys_exit(r) return r }
401 let u2: i64 = sms_usage()
402 sys_exit(u2)
403 return u2
404}