code wiki / _hdl_build / nx_opaque_rfc_kat.nx

nx_opaque_rfc_kat.nx source

↩ module page · 327 lines · 17294 B

1// nx_opaque_rfc_kat.nx -- ENGINEER gate: OPAQUE-3DH (RFC 9807) vs the RFC's OWN P-256 vectors. 2// 3// Drives the deterministic cores with the fixed randomness from RFC 9807 Appendix 4// C.1.5 (default identities) + C.1.6 (explicit identities "alice"/"bob") and asserts 5// BYTE-EXACT equality on every output message: registration_request, registration_ 6// response, registration_upload, export_key, KE1, KE2, KE3, session_key. One green 7// run validates the ENTIRE stack: VOPRF blind/evaluate/finalize, HashToScalar, 8// DeriveKeyPair, envelope Store/Recover, masking, preamble, 3DH, HKDF key schedule, 9// transcript MACs -- against the standard, not against ourselves. 10// 11// Negative KATs: wrong password => ENVELOPE_AUTH_FAIL; tampered server_mac => 12// SERVER_AUTH_FAIL; tampered KE3 => CLIENT_AUTH_FAIL. Production-randomness round 13// trip: register+login via the CSPRNG wrappers => client/server session keys agree, 14// register/login export keys agree. 15// 16// Vectors staged: knowledge/specs/2026-06-10-rfc9807-opaque-p256-vectors.ref 17// license_tier: ORIGINAL 18import "hub/nx_opaque_pake.nx" 19import "nx_syscalls.nx" 20 21func ok_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 22func ok_nib(c: i64) -> i64 { 23 if c >= 48 { if c <= 57 { return c - 48 } } 24 if c >= 97 { if c <= 102 { return c - 87 } } 25 return 0 26} 27func ok_hex(hexs: *u8, out: *u8) -> i64 { 28 var i: i64 = 0 29 while hexs[i*2] != (0 as u8) { 30 out[i] = ((ok_nib(hexs[i*2] as i64) << 4) | ok_nib(hexs[i*2+1] as i64)) as u8 31 i = i + 1 32 } 33 return i 34} 35func ok_eq(a: *u8, b: *u8, n: i64) -> i64 { 36 var i: i64 = 0 37 while i < n { if (a[i] as i64) != (b[i] as i64) { return 0 } i = i + 1 } 38 return 1 39} 40func ok_dump(label: *u8, b: *u8, n: i64) -> i64 { 41 ok_w(label) 42 let hx: *u8 = "0123456789abcdef" as *u8 43 let line: *u8 = sys_mmap(2*n + 2) 44 var i: i64 = 0 45 while i < n { 46 line[i*2] = hx[((b[i] as i64) >> 4) & 15] 47 line[i*2+1] = hx[(b[i] as i64) & 15] 48 i = i + 1 49 } 50 line[2*n] = 10 as u8 51 sys_write(1, line, 2*n + 1) 52 return 0 53} 54 55// shared fixed inputs (identical across C.1.5 and C.1.6) 56struct OkVec { 57 oprf_seed: *u8 58 cred_id: *u8 // "1234" 59 password: *u8 // 25 bytes 60 password_n: i64 61 envelope_nonce: *u8 62 masking_nonce: *u8 63 server_priv: *u8 64 server_pub: *u8 65 server_nonce: *u8 66 client_nonce: *u8 67 client_ks_seed: *u8 68 server_ks_seed: *u8 69 blind_reg: *u8 70 blind_login: *u8 71 context: *u8 // "OPAQUE-POC" (10) 72} 73 74func ok_load_inputs(v: *OkVec) -> i64 { 75 v.oprf_seed = sys_mmap(32) 76 ok_hex("62f60b286d20ce4fd1d64809b0021dad6ed5d52a2c8cf27ae6582543a0a8dce2" as *u8, v.oprf_seed) 77 v.cred_id = "1234" as *u8 78 v.password = sys_mmap(32) 79 v.password_n = ok_hex("436f7272656374486f72736542617474657279537461706c65" as *u8, v.password) 80 v.envelope_nonce = sys_mmap(32) 81 ok_hex("a921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf65670e51f" as *u8, v.envelope_nonce) 82 v.masking_nonce = sys_mmap(32) 83 ok_hex("38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d" as *u8, v.masking_nonce) 84 v.server_priv = sys_mmap(32) 85 ok_hex("c36139381df63bfc91c850db0b9cfbec7a62e86d80040a41aa7725bf0e79d5e5" as *u8, v.server_priv) 86 v.server_pub = sys_mmap(33) 87 ok_hex("035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd9f2092d6067784874" as *u8, v.server_pub) 88 v.server_nonce = sys_mmap(32) 89 ok_hex("71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e138e3d4a1" as *u8, v.server_nonce) 90 v.client_nonce = sys_mmap(32) 91 ok_hex("ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f91fdaeeb1" as *u8, v.client_nonce) 92 v.client_ks_seed = sys_mmap(32) 93 ok_hex("633b875d74d1556d2a2789309972b06db21dfcc4f5ad51d7e74d783b7cfab8dc" as *u8, v.client_ks_seed) 94 v.server_ks_seed = sys_mmap(32) 95 ok_hex("05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a1e85ff80da12f982f" as *u8, v.server_ks_seed) 96 v.blind_reg = sys_mmap(32) 97 ok_hex("411bf1a62d119afe30df682b91a0a33d777972d4f2daa4b34ca527d597078153" as *u8, v.blind_reg) 98 v.blind_login = sys_mmap(32) 99 ok_hex("c497fddf6056d241e6cf9fb7ac37c384f49b357a221eb0a802c989b9942256c1" as *u8, v.blind_login) 100 v.context = sys_mmap(16) 101 ok_hex("4f50415155452d504f43" as *u8, v.context) 102 return 0 103} 104 105func ok_mk_ccfg(v: *OkVec, client_id: *u8, client_id_n: i64, server_id: *u8, server_id_n: i64) -> *NxOpqClientCfg { 106 let c: *NxOpqClientCfg = sys_mmap(80) as *NxOpqClientCfg 107 c.server_id = server_id 108 c.server_id_n = server_id_n 109 c.client_id = client_id 110 c.client_id_n = client_id_n 111 c.context = v.context 112 c.context_n = 10 113 c.ksf_mode = NX_OPQ_KSF_IDENTITY 114 c.ksf_m_kib = 0 115 c.ksf_t = 0 116 return c 117} 118 119func ok_mk_scfg(v: *OkVec, server_id: *u8, server_id_n: i64) -> *NxOpqServerCfg { 120 let s: *NxOpqServerCfg = sys_mmap(64) as *NxOpqServerCfg 121 s.server_priv_32 = v.server_priv 122 s.server_pub_33 = v.server_pub 123 s.oprf_seed_32 = v.oprf_seed 124 s.server_id = server_id 125 s.server_id_n = server_id_n 126 s.context = v.context 127 s.context_n = 10 128 return s 129} 130 131// run one full vector (registration + login). wants are the expected outputs. 132// returns number of failures; prints a FAIL line per mismatch tagged `tag`. 133func ok_run_vector( 134 v: *OkVec, 135 ccfg: *NxOpqClientCfg, scfg: *NxOpqServerCfg, 136 client_id: *u8, client_id_n: i64, 137 want_upload_129: *u8, want_ke2_259: *u8, want_ke3_32: *u8, 138 want_export_32: *u8, want_session_32: *u8, 139 tag: *u8 140) -> i64 { 141 var bad: i64 = 0 142 143 // --- registration --- 144 let req: *u8 = sys_mmap(33) 145 if nx_opaque_create_registration_request_det(v.password, v.password_n, v.blind_reg, req) != NX_OPQ_OK { 146 ok_w("FAIL reg_request rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return 1 147 } 148 let want_req: *u8 = sys_mmap(33) 149 ok_hex("029e949a29cfa0bf7c1287333d2fb3dc586c41aa652f5070d26a5315a1b50229f8" as *u8, want_req) 150 if ok_eq(req, want_req, 33) == 0 { bad = bad + 1; ok_w("FAIL reg_request bytes " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, req, 33) } 151 152 let resp: *u8 = sys_mmap(66) 153 if nx_opaque_create_registration_response(req, v.server_pub, v.cred_id, 4, v.oprf_seed, resp) != NX_OPQ_OK { 154 ok_w("FAIL reg_response rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return bad + 1 155 } 156 let want_resp: *u8 = sys_mmap(66) 157 ok_hex("0350d3694c00978f00a5ce7cd08a00547e4ab5fb5fc2b2f6717cdaa6c89136efef035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd9f2092d6067784874" as *u8, want_resp) 158 if ok_eq(resp, want_resp, 66) == 0 { bad = bad + 1; ok_w("FAIL reg_response bytes " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, resp, 66) } 159 160 let record: *u8 = sys_mmap(129) 161 let export1: *u8 = sys_mmap(32) 162 if nx_opaque_finalize_registration_det(ccfg, v.password, v.password_n, v.blind_reg, resp, v.envelope_nonce, record, export1) != NX_OPQ_OK { 163 ok_w("FAIL finalize_reg rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return bad + 1 164 } 165 if ok_eq(record, want_upload_129, 129) == 0 { bad = bad + 1; ok_w("FAIL registration_upload " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, record, 129) } 166 if ok_eq(export1, want_export_32, 32) == 0 { bad = bad + 1; ok_w("FAIL export_key(reg) " as *u8); ok_w(tag); ok_w("\n" as *u8) } 167 168 // --- login --- 169 let ke1: *u8 = sys_mmap(98) 170 let client_secret: *u8 = sys_mmap(32) 171 if nx_opaque_generate_ke1_det(v.password, v.password_n, v.blind_login, v.client_nonce, v.client_ks_seed, ke1, client_secret) != NX_OPQ_OK { 172 ok_w("FAIL ke1 rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return bad + 1 173 } 174 let want_ke1: *u8 = sys_mmap(98) 175 ok_hex("037342f0bcb3ecea754c1e67576c86aa90c1de3875f390ad599a26686cdfee6e07ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f91fdaeeb1022ed3f32f318f81bab80da321fecab3cd9b6eea11a95666dfa6beeaab321280b6" as *u8, want_ke1) 176 if ok_eq(ke1, want_ke1, 98) == 0 { bad = bad + 1; ok_w("FAIL KE1 bytes " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, ke1, 98) } 177 178 let ke2: *u8 = sys_mmap(259) 179 let expected_cmac: *u8 = sys_mmap(32) 180 let session_s: *u8 = sys_mmap(32) 181 if nx_opaque_generate_ke2_det(scfg, record, v.cred_id, 4, client_id, client_id_n, ke1, v.masking_nonce, v.server_nonce, v.server_ks_seed, ke2, expected_cmac, session_s) != NX_OPQ_OK { 182 ok_w("FAIL ke2 rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return bad + 1 183 } 184 if ok_eq(ke2, want_ke2_259, 259) == 0 { bad = bad + 1; ok_w("FAIL KE2 bytes " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, ke2, 259) } 185 if ok_eq(session_s, want_session_32, 32) == 0 { bad = bad + 1; ok_w("FAIL session_key(server) " as *u8); ok_w(tag); ok_w("\n" as *u8) } 186 187 let ke3: *u8 = sys_mmap(32) 188 let session_c: *u8 = sys_mmap(32) 189 let export2: *u8 = sys_mmap(32) 190 if nx_opaque_generate_ke3(ccfg, v.password, v.password_n, v.blind_login, client_secret, ke1, ke2, ke3, session_c, export2) != NX_OPQ_OK { 191 ok_w("FAIL ke3 rc " as *u8); ok_w(tag); ok_w("\n" as *u8); return bad + 1 192 } 193 if ok_eq(ke3, want_ke3_32, 32) == 0 { bad = bad + 1; ok_w("FAIL KE3 bytes " as *u8); ok_w(tag); ok_w("\n" as *u8); ok_dump(" got=" as *u8, ke3, 32) } 194 if ok_eq(session_c, want_session_32, 32) == 0 { bad = bad + 1; ok_w("FAIL session_key(client) " as *u8); ok_w(tag); ok_w("\n" as *u8) } 195 if ok_eq(export2, want_export_32, 32) == 0 { bad = bad + 1; ok_w("FAIL export_key(login) " as *u8); ok_w(tag); ok_w("\n" as *u8) } 196 if nx_opaque_server_finish(ke3, expected_cmac) != NX_OPQ_OK { 197 bad = bad + 1; ok_w("FAIL server_finish " as *u8); ok_w(tag); ok_w("\n" as *u8) 198 } 199 200 // --- negative: wrong password fails at envelope recovery --- 201 let wrong_pw: *u8 = sys_mmap(32) 202 var wp: i64 = 0 203 while wp < v.password_n { wrong_pw[wp] = v.password[wp]; wp = wp + 1 } 204 wrong_pw[0] = ((wrong_pw[0] as i64) ^ 1) as u8 205 let ke1w: *u8 = sys_mmap(98) 206 let csw: *u8 = sys_mmap(32) 207 nx_opaque_generate_ke1_det(wrong_pw, v.password_n, v.blind_login, v.client_nonce, v.client_ks_seed, ke1w, csw) 208 let ke2w: *u8 = sys_mmap(259) 209 let ecmw: *u8 = sys_mmap(32) 210 let ssw: *u8 = sys_mmap(32) 211 nx_opaque_generate_ke2_det(scfg, record, v.cred_id, 4, client_id, client_id_n, ke1w, v.masking_nonce, v.server_nonce, v.server_ks_seed, ke2w, ecmw, ssw) 212 let ke3w: *u8 = sys_mmap(32) 213 let scw: *u8 = sys_mmap(32) 214 let exw: *u8 = sys_mmap(32) 215 let rc_wrong: i64 = nx_opaque_generate_ke3(ccfg, wrong_pw, v.password_n, v.blind_login, csw, ke1w, ke2w, ke3w, scw, exw) 216 if rc_wrong != (0 - NX_OPQ_ENVELOPE_AUTH_FAIL) { 217 bad = bad + 1; ok_w("FAIL wrong-password not rejected " as *u8); ok_w(tag); ok_w("\n" as *u8) 218 } 219 220 // --- negative: tampered server_mac rejected by client --- 221 let ke2t: *u8 = sys_mmap(259) 222 var t: i64 = 0 223 while t < 259 { ke2t[t] = ke2[t]; t = t + 1 } 224 ke2t[227] = ((ke2t[227] as i64) ^ 1) as u8 225 let ke3t: *u8 = sys_mmap(32) 226 let sct: *u8 = sys_mmap(32) 227 let ext: *u8 = sys_mmap(32) 228 let rc_smac: i64 = nx_opaque_generate_ke3(ccfg, v.password, v.password_n, v.blind_login, client_secret, ke1, ke2t, ke3t, sct, ext) 229 if rc_smac != (0 - NX_OPQ_SERVER_AUTH_FAIL) { 230 bad = bad + 1; ok_w("FAIL tampered server_mac not rejected " as *u8); ok_w(tag); ok_w("\n" as *u8) 231 } 232 233 // --- negative: tampered client_mac rejected by server --- 234 let ke3x: *u8 = sys_mmap(32) 235 var x: i64 = 0 236 while x < 32 { ke3x[x] = ke3[x]; x = x + 1 } 237 ke3x[0] = ((ke3x[0] as i64) ^ 1) as u8 238 if nx_opaque_server_finish(ke3x, expected_cmac) != (0 - NX_OPQ_CLIENT_AUTH_FAIL) { 239 bad = bad + 1; ok_w("FAIL tampered KE3 not rejected " as *u8); ok_w(tag); ok_w("\n" as *u8) 240 } 241 242 return bad 243} 244 245// production-randomness round trip: CSPRNG wrappers end to end, fresh keys. 246func ok_run_random_roundtrip(v: *OkVec) -> i64 { 247 var bad: i64 = 0 248 let ccfg: *NxOpqClientCfg = ok_mk_ccfg(v, 0 as *u8, 0, 0 as *u8, 0) 249 let scfg: *NxOpqServerCfg = ok_mk_scfg(v, 0 as *u8, 0) 250 251 let blind_r: *u8 = sys_mmap(32) 252 let req: *u8 = sys_mmap(33) 253 if nx_opaque_create_registration_request(v.password, v.password_n, blind_r, req) != NX_OPQ_OK { return 1 } 254 let resp: *u8 = sys_mmap(66) 255 if nx_opaque_create_registration_response(req, v.server_pub, v.cred_id, 4, v.oprf_seed, resp) != NX_OPQ_OK { return 1 } 256 let record: *u8 = sys_mmap(129) 257 let export1: *u8 = sys_mmap(32) 258 if nx_opaque_finalize_registration(ccfg, v.password, v.password_n, blind_r, resp, record, export1) != NX_OPQ_OK { return 1 } 259 260 let blind_l: *u8 = sys_mmap(32) 261 let ke1: *u8 = sys_mmap(98) 262 let cs: *u8 = sys_mmap(32) 263 if nx_opaque_generate_ke1(v.password, v.password_n, blind_l, ke1, cs) != NX_OPQ_OK { return 1 } 264 let ke2: *u8 = sys_mmap(259) 265 let ecm: *u8 = sys_mmap(32) 266 let ss: *u8 = sys_mmap(32) 267 if nx_opaque_generate_ke2(scfg, record, v.cred_id, 4, 0 as *u8, 0, ke1, ke2, ecm, ss) != NX_OPQ_OK { return 1 } 268 let ke3: *u8 = sys_mmap(32) 269 let sc: *u8 = sys_mmap(32) 270 let export2: *u8 = sys_mmap(32) 271 if nx_opaque_generate_ke3(ccfg, v.password, v.password_n, blind_l, cs, ke1, ke2, ke3, sc, export2) != NX_OPQ_OK { return 1 } 272 if nx_opaque_server_finish(ke3, ecm) != NX_OPQ_OK { bad = bad + 1; ok_w("FAIL rnd server_finish\n" as *u8) } 273 if ok_eq(sc, ss, 32) == 0 { bad = bad + 1; ok_w("FAIL rnd session keys differ\n" as *u8) } 274 if ok_eq(export1, export2, 32) == 0 { bad = bad + 1; ok_w("FAIL rnd export keys differ\n" as *u8) } 275 return bad 276} 277 278func main() -> i64 { 279 let v: *OkVec = sys_mmap(160) as *OkVec 280 ok_load_inputs(v) 281 var bad: i64 = 0 282 283 // ===== Vector C.1.5: default identities ===== 284 let up5: *u8 = sys_mmap(129) 285 ok_hex("03b218507d978c3db570ca994aaf36695a731ddb2db272c817f79746fc37ae52147f0ed53532d3ae8e505ecc70d42d2b814b6b0e48156def71ea029148b2803aafa921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf65670e51fad30bbcfc1f8eda0211553ab9aaf26345ad59a128e80188f035fe4924fad67b8" as *u8, up5) 286 let ke2_5: *u8 = sys_mmap(259) 287 ok_hex("0246da9fe4d41d5ba69faa6c509a1d5bafd49a48615a47a8dd4b0823cc1476481138fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d2f0c547f70deaeca54d878c14c1aa5e1ab405dec833777132eea905c2fbb12504a67dcbe0e66740c76b62c13b04a38a77926e19072953319ec65e41f9bfd2ae26837b6ce688bf9af2542f04eec9ab96a1b9328812dc2f5c89182ed47fead61f09f71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e138e3d4a103c1701353219b53acf337bf6456a83cefed8f563f1040b65afbf3b65d3bc9a19b50a73b145bc87a157e8c58c0342e2047ee22ae37b63db17e0a82a30fcc4ecf7b" as *u8, ke2_5) 288 let ke3_5: *u8 = sys_mmap(32) 289 ok_hex("e97cab4433aa39d598e76f13e768bba61c682947bdcf9936035e8a3a3ebfb66e" as *u8, ke3_5) 290 let ex5: *u8 = sys_mmap(32) 291 ok_hex("c3c9a1b0e33ac84dd83d0b7e8af6794e17e7a3caadff289fbd9dc769a853c64b" as *u8, ex5) 292 let ses5: *u8 = sys_mmap(32) 293 ok_hex("484ad345715ccce138ca49e4ea362c6183f0949aaaa1125dc3bc3f80876e7cd1" as *u8, ses5) 294 let ccfg5: *NxOpqClientCfg = ok_mk_ccfg(v, 0 as *u8, 0, 0 as *u8, 0) 295 let scfg5: *NxOpqServerCfg = ok_mk_scfg(v, 0 as *u8, 0) 296 bad = bad + ok_run_vector(v, ccfg5, scfg5, 0 as *u8, 0, up5, ke2_5, ke3_5, ex5, ses5, "[C.1.5]" as *u8) 297 298 // ===== Vector C.1.6: identities alice/bob ===== 299 let alice: *u8 = "alice" as *u8 300 let bob: *u8 = "bob" as *u8 301 let up6: *u8 = sys_mmap(129) 302 ok_hex("03b218507d978c3db570ca994aaf36695a731ddb2db272c817f79746fc37ae52147f0ed53532d3ae8e505ecc70d42d2b814b6b0e48156def71ea029148b2803aafa921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf65670e51f4d7773a36a208a866301dbb2858e40dc5638017527cf91aef32d3848eebe0971" as *u8, up6) 303 let ke2_6: *u8 = sys_mmap(259) 304 ok_hex("0246da9fe4d41d5ba69faa6c509a1d5bafd49a48615a47a8dd4b0823cc1476481138fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d2f0c547f70deaeca54d878c14c1aa5e1ab405dec833777132eea905c2fbb12504a67dcbe0e66740c76b62c13b04a38a77926e19072953319ec65e41f9bfd2ae268d7f106042021c80300e4c6f585980cf39fc51a4a6bba41b0729f9b240c729e5671cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e138e3d4a103c1701353219b53acf337bf6456a83cefed8f563f1040b65afbf3b65d3bc9a19b84922c7e5d074838a8f278592c53f61fb59f031e85ad480c0c71086b871e1b24" as *u8, ke2_6) 305 let ke3_6: *u8 = sys_mmap(32) 306 ok_hex("46833578cee137775f6be3f01b80748daac5a694101ad0e9e7025480552da56a" as *u8, ke3_6) 307 let ses6: *u8 = sys_mmap(32) 308 ok_hex("27766fabd8dd88ff37fbd0ef1a491e601d10d9f016c2b28c4bd1b0fb7511a3c3" as *u8, ses6) 309 let ccfg6: *NxOpqClientCfg = ok_mk_ccfg(v, alice, 5, bob, 3) 310 let scfg6: *NxOpqServerCfg = ok_mk_scfg(v, bob, 3) 311 bad = bad + ok_run_vector(v, ccfg6, scfg6, alice, 5, up6, ke2_6, ke3_6, ex5, ses6, "[C.1.6]" as *u8) 312 313 // ===== production-randomness round trip ===== 314 bad = bad + ok_run_random_roundtrip(v) 315 316 if bad == 0 { 317 ok_w("OPAQUE RFC9807 KAT GREEN (C.1.5 + C.1.6 byte-exact: reg/KE1/KE2/KE3/export/session; wrong-pw + 2 tamper rejections; random round trip)\n" as *u8) 318 sys_exit(0) 319 } 320 ok_w("OPAQUE KAT FAILED bad=" as *u8) 321 let d: *u8 = sys_mmap(4) 322 d[0] = (48 + (bad % 10)) as u8 323 d[1] = 10 as u8 324 sys_write(1, d, 2) 325 sys_exit(1) 326 return 1 327}