code wiki / (root) / nx_sealed_sender.nx

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}