code wiki / (root) / nx_mtls_pkcs12.nx

nx_mtls_pkcs12.nx source

↩ module page · 230 lines · 16869 B

1// nx_mtls_pkcs12.nx -- sovereign PKCS#12 (.p12 / PFX) emitter for one-time browser/OS import (RFC 7292). 2// 3// mTLS rung R5b: package the OPAQUE-bound client identity (Ed25519 key + leaf cert) into a .p12 the user 4// imports ONCE into their browser/OS cert store, after which the browser presents it at the TLS layer on 5// every connection -- the no-cookie carrier. Structure (modern, widely-importable: OpenSSL 3 + Windows 11): 6// PFX = SEQ { version 3, 7// authSafe ContentInfo{data, OCTET STRING( AuthenticatedSafe )}, 8// macData SEQ{ DigestInfo{sha256, MAC}, macSalt, iter } } 9// AuthenticatedSafe = SEQ OF ContentInfo{data, OCTET STRING( SafeContents )} 10// SafeContents = SEQ OF { ShroudedKeyBag(PBES2: PBKDF2-HMAC-SHA256 + AES-128-CBC over PKCS#8), CertBag } 11// MAC key = PKCS12-KDF(BMPString(pw), macSalt, iter, id=3, 32); MAC = HMAC-SHA256 over the AuthenticatedSafe DER. 12// 13// Composes ONLY sovereign, KAT'd primitives: nx_asn1_emit · nx_pbkdf2 · nx_aes_cbc_enc (AES-CBC, NIST F.2.1) 14// · nx_pkcs12_kdf (RFC 7292 B.2) · nx_hmac · sha256 · nx_x509_leaf_emit. The emitted .p12 is validated 15// end-to-end by `openssl pkcs12` (dev-time oracle only; never shipped). license_tier: ORIGINAL expect_exit: 0 16import "nx_syscalls.nx" 17import "nx_asn1_emit.nx" 18import "sha256.nx" 19import "nx_hmac.nx" 20import "nx_pbkdf2.nx" 21import "nx_pkcs12_kdf.nx" 22import "nx_aes.nx" 23import "nx_aes_cbc_enc.nx" 24import "nx_ed25519_signature.nx" 25import "nx_x509_leaf_emit.nx" 26const K_MAGIC_2048: i64 = 2048 27const K_MAGIC_4096: i64 = 4096 28const K_MAGIC_8192: i64 = 8192 29 30// ---- OID DER value bytes (the content after tag 0x06 + length; nxae_put_oid adds those) ---- 31func p12oid_ed25519(o: *u8) -> i64 { o[0]=0x2b as u8;o[1]=0x65 as u8;o[2]=0x70 as u8; return 3 } 32func p12oid_pbes2(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x05 as u8;o[8]=0x0d as u8; return 9 } 33func p12oid_pbkdf2(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x05 as u8;o[8]=0x0c as u8; return 9 } 34func p12oid_hmacsha256(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x02 as u8;o[7]=0x09 as u8; return 8 } 35func p12oid_aes128cbc(o: *u8) -> i64 { o[0]=0x60 as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x01 as u8;o[4]=0x65 as u8;o[5]=0x03 as u8;o[6]=0x04 as u8;o[7]=0x01 as u8;o[8]=0x02 as u8; return 9 } 36func p12oid_sha256(o: *u8) -> i64 { o[0]=0x60 as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x01 as u8;o[4]=0x65 as u8;o[5]=0x03 as u8;o[6]=0x04 as u8;o[7]=0x02 as u8;o[8]=0x01 as u8; return 9 } 37func p12oid_data(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x07 as u8;o[8]=0x01 as u8; return 9 } 38func p12oid_shroudedkeybag(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x0c as u8;o[8]=0x0a as u8;o[9]=0x01 as u8;o[10]=0x02 as u8; return 11 } 39func p12oid_certbag(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x0c as u8;o[8]=0x0a as u8;o[9]=0x01 as u8;o[10]=0x03 as u8; return 11 } 40func p12oid_x509cert(o: *u8) -> i64 { o[0]=0x2a as u8;o[1]=0x86 as u8;o[2]=0x48 as u8;o[3]=0x86 as u8;o[4]=0xf7 as u8;o[5]=0x0d as u8;o[6]=0x01 as u8;o[7]=0x09 as u8;o[8]=0x16 as u8;o[9]=0x01 as u8; return 10 } 41 42// DER INTEGER for a small positive value (1..65535), minimal encoding + 0x00 sign-prefix if MSB set. 43func p12_put_uint(out: *u8, off: *i64, cap: i64, v: i64) -> i64 { 44 if v < 256 { 45 nxae_put(out, off, cap, 0x02) 46 if v >= 128 { nxae_put(out, off, cap, 2); nxae_put(out, off, cap, 0); return nxae_put(out, off, cap, v) } 47 nxae_put(out, off, cap, 1); return nxae_put(out, off, cap, v) 48 } 49 let hi: i64 = (v >> 8) & 0xff; let lo: i64 = v & 0xff 50 nxae_put(out, off, cap, 0x02) 51 if hi >= 128 { nxae_put(out, off, cap, 3); nxae_put(out, off, cap, 0); nxae_put(out, off, cap, hi); return nxae_put(out, off, cap, lo) } 52 nxae_put(out, off, cap, 2); nxae_put(out, off, cap, hi); return nxae_put(out, off, cap, lo) 53} 54 55// Emit a complete PFX (.p12) for (seed32, pub32, cert_der) protected by ASCII password pw. out_n = length. 56func nx_mtls_emit_pkcs12( 57 seed32: *u8, pub32: *u8, cert_der: *u8, cert_len: i64, 58 pw_ascii: *u8, pw_n: i64, out: *u8, cap: i64, out_n: *i64 59) -> i64 { 60 // ===== 1. PKCS#8 PrivateKeyInfo (Ed25519) ===== 61 let cpk: *u8 = sys_mmap(48); let cpk_o: *i64 = sys_mmap(8) as *i64; cpk_o[0] = 0 62 nxae_put_octet_string(cpk, cpk_o, 48, seed32, 32) // CurvePrivateKey = 04 20 <seed> 63 let edoid: *u8 = sys_mmap(8); let edn: i64 = p12oid_ed25519(edoid) 64 let alg: *u8 = sys_mmap(16); let alg_o: *i64 = sys_mmap(8) as *i64; alg_o[0] = 0 65 nxae_put_oid(alg, alg_o, 16, edoid, edn) 66 let pk8: *u8 = sys_mmap(96); let pk8_o: *i64 = sys_mmap(8) as *i64; pk8_o[0] = 0 67 nxae_put_int_u8(pk8, pk8_o, 96, 0) // version 0 68 nxae_put_tlv(pk8, pk8_o, 96, 0x30, alg, alg_o[0]) // privateKeyAlgorithm 69 nxae_put_octet_string(pk8, pk8_o, 96, cpk, cpk_o[0]) // privateKey OCTET STRING(CurvePrivateKey) 70 let pk8w: *u8 = sys_mmap(112); let pk8w_o: *i64 = sys_mmap(8) as *i64; pk8w_o[0] = 0 71 nxae_put_tlv(pk8w, pk8w_o, 112, 0x30, pk8, pk8_o[0]) 72 return nx_mtls_emit_pkcs12_from(pk8w, pk8w_o[0], cert_der, cert_len, pw_ascii, pw_n, out, cap, out_n) 73} 74 75// Generic PFX emitter (key-type AGNOSTIC): takes a wrapped PKCS#8 (pk8w) + cert DER. Used by the Ed25519 76// path above and by the ECDSA driver (nx_mtls_pkcs12_ecdsa). out_n = PFX length. 77func nx_mtls_emit_pkcs12_from( 78 pk8w: *u8, pk8w_len: i64, cert_der: *u8, cert_len: i64, 79 pw_ascii: *u8, pw_n: i64, out: *u8, cap: i64, out_n: *i64 80) -> i64 { 81 let iter: i64 = K_MAGIC_2048 82 // fixed salts/IV (deterministic for dev; production passes random via nx_csprng_fill) 83 let kdf_salt: *u8 = sys_mmap(16); var t: i64 = 0; while t < 16 { kdf_salt[t] = (0x11 + t) as u8; t = t + 1 } 84 let iv: *u8 = sys_mmap(16); t = 0; while t < 16 { iv[t] = (0x22 + t) as u8; t = t + 1 } 85 let mac_salt: *u8 = sys_mmap(8); t = 0; while t < 8 { mac_salt[t] = (0x33 + t) as u8; t = t + 1 } 86 let big: i64 = cert_len + K_MAGIC_2048 87 88 // ===== 2. PBES2-encrypt the PKCS#8 ===== 89 let aeskey: *u8 = sys_mmap(16) 90 pbkdf2_sha256(pw_ascii, pw_n, kdf_salt, 16, iter, 16, aeskey) 91 let sched: *u8 = sys_mmap(176); aes128_expand_key(aeskey, sched) 92 let padded: *u8 = sys_mmap(pk8w_len + 16); let pad_n: i64 = aes128_pkcs7_pad(pk8w, pk8w_len, padded) 93 let enc: *u8 = sys_mmap(pad_n); aes128_cbc_encrypt(padded, pad_n, sched, iv, enc) 94 // PBKDF2 AlgId 95 let prfoid: *u8 = sys_mmap(8); let prfn: i64 = p12oid_hmacsha256(prfoid) 96 let prf: *u8 = sys_mmap(16); let prf_o: *i64 = sys_mmap(8) as *i64; prf_o[0] = 0 97 nxae_put_oid(prf, prf_o, 16, prfoid, prfn); nxae_put_null(prf, prf_o, 16) 98 let kp: *u8 = sys_mmap(64); let kp_o: *i64 = sys_mmap(8) as *i64; kp_o[0] = 0 99 nxae_put_octet_string(kp, kp_o, 64, kdf_salt, 16) 100 p12_put_uint(kp, kp_o, 64, iter) 101 nxae_put_tlv(kp, kp_o, 64, 0x30, prf, prf_o[0]) 102 let pboid: *u8 = sys_mmap(12); let pbn: i64 = p12oid_pbkdf2(pboid) 103 let kdfalg: *u8 = sys_mmap(96); let kdfalg_o: *i64 = sys_mmap(8) as *i64; kdfalg_o[0] = 0 104 nxae_put_oid(kdfalg, kdfalg_o, 96, pboid, pbn) 105 nxae_put_tlv(kdfalg, kdfalg_o, 96, 0x30, kp, kp_o[0]) 106 // AES-128-CBC AlgId 107 let aesoid: *u8 = sys_mmap(12); let aesn: i64 = p12oid_aes128cbc(aesoid) 108 let encalg: *u8 = sys_mmap(48); let encalg_o: *i64 = sys_mmap(8) as *i64; encalg_o[0] = 0 109 nxae_put_oid(encalg, encalg_o, 48, aesoid, aesn) 110 nxae_put_octet_string(encalg, encalg_o, 48, iv, 16) 111 // PBES2-params SEQ { PBKDF2 AlgId, AES-CBC AlgId } 112 let pbes2p: *u8 = sys_mmap(256); let pbes2p_o: *i64 = sys_mmap(8) as *i64; pbes2p_o[0] = 0 113 nxae_put_tlv(pbes2p, pbes2p_o, 256, 0x30, kdfalg, kdfalg_o[0]) 114 nxae_put_tlv(pbes2p, pbes2p_o, 256, 0x30, encalg, encalg_o[0]) 115 // PBES2 AlgId SEQ { OID pbes2, params } 116 let pbes2oid: *u8 = sys_mmap(12); let pbes2n: i64 = p12oid_pbes2(pbes2oid) 117 let encinfo: *u8 = sys_mmap(320); let encinfo_o: *i64 = sys_mmap(8) as *i64; encinfo_o[0] = 0 118 nxae_put_oid(encinfo, encinfo_o, 320, pbes2oid, pbes2n) 119 nxae_put_tlv(encinfo, encinfo_o, 320, 0x30, pbes2p, pbes2p_o[0]) 120 // EncryptedPrivateKeyInfo SEQ { encinfo, OCTET STRING(enc) } 121 let epki_in: *u8 = sys_mmap(320 + pad_n); let epki_in_o: *i64 = sys_mmap(8) as *i64; epki_in_o[0] = 0 122 nxae_put_tlv(epki_in, epki_in_o, 320 + pad_n, 0x30, encinfo, encinfo_o[0]) 123 nxae_put_octet_string(epki_in, epki_in_o, 320 + pad_n, enc, pad_n) 124 let epki: *u8 = sys_mmap(360 + pad_n); let epki_o: *i64 = sys_mmap(8) as *i64; epki_o[0] = 0 125 nxae_put_tlv(epki, epki_o, 360 + pad_n, 0x30, epki_in, epki_in_o[0]) 126 127 // ===== 3. ShroudedKeyBag = SEQ { OID pkcs8ShroudedKeyBag, [0]{ epki } } ===== 128 let skboid: *u8 = sys_mmap(12); let skbn: i64 = p12oid_shroudedkeybag(skboid) 129 let keybag_in: *u8 = sys_mmap(400 + pad_n); let keybag_in_o: *i64 = sys_mmap(8) as *i64; keybag_in_o[0] = 0 130 nxae_put_oid(keybag_in, keybag_in_o, 400 + pad_n, skboid, skbn) 131 nxae_put_context_explicit(keybag_in, keybag_in_o, 400 + pad_n, 0, epki, epki_o[0]) 132 let keybag: *u8 = sys_mmap(420 + pad_n); let keybag_o: *i64 = sys_mmap(8) as *i64; keybag_o[0] = 0 133 nxae_put_tlv(keybag, keybag_o, 420 + pad_n, 0x30, keybag_in, keybag_in_o[0]) 134 135 // ===== 4. CertBag = SEQ { OID certBag, [0]{ SEQ { OID x509Certificate, [0]{ OCTET STRING(cert) } } } } ===== 136 let x509oid: *u8 = sys_mmap(12); let x509n: i64 = p12oid_x509cert(x509oid) 137 let certoctet: *u8 = sys_mmap(cert_len + 8); let certoctet_o: *i64 = sys_mmap(8) as *i64; certoctet_o[0] = 0 138 nxae_put_octet_string(certoctet, certoctet_o, cert_len + 8, cert_der, cert_len) 139 let cbval_in: *u8 = sys_mmap(cert_len + 32); let cbval_in_o: *i64 = sys_mmap(8) as *i64; cbval_in_o[0] = 0 140 nxae_put_oid(cbval_in, cbval_in_o, cert_len + 32, x509oid, x509n) 141 nxae_put_context_explicit(cbval_in, cbval_in_o, cert_len + 32, 0, certoctet, certoctet_o[0]) 142 let cbval: *u8 = sys_mmap(cert_len + 48); let cbval_o: *i64 = sys_mmap(8) as *i64; cbval_o[0] = 0 143 nxae_put_tlv(cbval, cbval_o, cert_len + 48, 0x30, cbval_in, cbval_in_o[0]) 144 let cboid: *u8 = sys_mmap(12); let cbn: i64 = p12oid_certbag(cboid) 145 let certbag_in: *u8 = sys_mmap(cert_len + 64); let certbag_in_o: *i64 = sys_mmap(8) as *i64; certbag_in_o[0] = 0 146 nxae_put_oid(certbag_in, certbag_in_o, cert_len + 64, cboid, cbn) 147 nxae_put_context_explicit(certbag_in, certbag_in_o, cert_len + 64, 0, cbval, cbval_o[0]) 148 let certbag: *u8 = sys_mmap(cert_len + 80); let certbag_o: *i64 = sys_mmap(8) as *i64; certbag_o[0] = 0 149 nxae_put_tlv(certbag, certbag_o, cert_len + 80, 0x30, certbag_in, certbag_in_o[0]) 150 151 // ===== 5. SafeContents = SEQ OF { keybag, certbag } ===== 152 let sc_in: *u8 = sys_mmap(big); let sc_in_o: *i64 = sys_mmap(8) as *i64; sc_in_o[0] = 0 153 nxae_put_bytes(sc_in, sc_in_o, big, keybag, keybag_o[0]) 154 nxae_put_bytes(sc_in, sc_in_o, big, certbag, certbag_o[0]) 155 let safec: *u8 = sys_mmap(big); let safec_o: *i64 = sys_mmap(8) as *i64; safec_o[0] = 0 156 nxae_put_tlv(safec, safec_o, big, 0x30, sc_in, sc_in_o[0]) 157 158 // ===== 6. AuthenticatedSafe = SEQ OF ContentInfo{ data, [0]{ OCTET STRING(SafeContents) } } ===== 159 let dataoid: *u8 = sys_mmap(12); let datan: i64 = p12oid_data(dataoid) 160 let scoctet: *u8 = sys_mmap(big); let scoctet_o: *i64 = sys_mmap(8) as *i64; scoctet_o[0] = 0 161 nxae_put_octet_string(scoctet, scoctet_o, big, safec, safec_o[0]) 162 let ci_in: *u8 = sys_mmap(big); let ci_in_o: *i64 = sys_mmap(8) as *i64; ci_in_o[0] = 0 163 nxae_put_oid(ci_in, ci_in_o, big, dataoid, datan) 164 nxae_put_context_explicit(ci_in, ci_in_o, big, 0, scoctet, scoctet_o[0]) 165 let ci: *u8 = sys_mmap(big); let ci_o: *i64 = sys_mmap(8) as *i64; ci_o[0] = 0 166 nxae_put_tlv(ci, ci_o, big, 0x30, ci_in, ci_in_o[0]) 167 let authsafe: *u8 = sys_mmap(big); let authsafe_o: *i64 = sys_mmap(8) as *i64; authsafe_o[0] = 0 168 nxae_put_tlv(authsafe, authsafe_o, big, 0x30, ci, ci_o[0]) 169 170 // ===== 7. MacData over the AuthenticatedSafe DER ===== 171 let bmp: *u8 = sys_mmap(pw_n*2 + 4); let bmp_n: i64 = nx_pkcs12_bmp_password(pw_ascii, pw_n, bmp) 172 let mackey: *u8 = sys_mmap(32); nx_pkcs12_kdf(bmp, bmp_n, mac_salt, 8, iter, 3, 32, mackey) 173 let mac: *u8 = sys_mmap(32); hmac_sha256(mackey, 32, authsafe, authsafe_o[0], mac) 174 let shaoid: *u8 = sys_mmap(12); let shan: i64 = p12oid_sha256(shaoid) 175 let digalg: *u8 = sys_mmap(24); let digalg_o: *i64 = sys_mmap(8) as *i64; digalg_o[0] = 0 176 nxae_put_oid(digalg, digalg_o, 24, shaoid, shan); nxae_put_null(digalg, digalg_o, 24) 177 let dig_in: *u8 = sys_mmap(80); let dig_in_o: *i64 = sys_mmap(8) as *i64; dig_in_o[0] = 0 178 nxae_put_tlv(dig_in, dig_in_o, 80, 0x30, digalg, digalg_o[0]) 179 nxae_put_octet_string(dig_in, dig_in_o, 80, mac, 32) 180 let diginfo: *u8 = sys_mmap(96); let diginfo_o: *i64 = sys_mmap(8) as *i64; diginfo_o[0] = 0 181 nxae_put_tlv(diginfo, diginfo_o, 96, 0x30, dig_in, dig_in_o[0]) 182 let md_in: *u8 = sys_mmap(128); let md_in_o: *i64 = sys_mmap(8) as *i64; md_in_o[0] = 0 183 nxae_put_bytes(md_in, md_in_o, 128, diginfo, diginfo_o[0]) 184 nxae_put_octet_string(md_in, md_in_o, 128, mac_salt, 8) 185 p12_put_uint(md_in, md_in_o, 128, iter) 186 let macdata: *u8 = sys_mmap(144); let macdata_o: *i64 = sys_mmap(8) as *i64; macdata_o[0] = 0 187 nxae_put_tlv(macdata, macdata_o, 144, 0x30, md_in, md_in_o[0]) 188 189 // ===== 8. PFX = SEQ { version 3, authSafe ContentInfo, macData } ===== 190 let asoctet: *u8 = sys_mmap(big); let asoctet_o: *i64 = sys_mmap(8) as *i64; asoctet_o[0] = 0 191 nxae_put_octet_string(asoctet, asoctet_o, big, authsafe, authsafe_o[0]) 192 let asci_in: *u8 = sys_mmap(big); let asci_in_o: *i64 = sys_mmap(8) as *i64; asci_in_o[0] = 0 193 nxae_put_oid(asci_in, asci_in_o, big, dataoid, datan) 194 nxae_put_context_explicit(asci_in, asci_in_o, big, 0, asoctet, asoctet_o[0]) 195 let asci: *u8 = sys_mmap(big); let asci_o: *i64 = sys_mmap(8) as *i64; asci_o[0] = 0 196 nxae_put_tlv(asci, asci_o, big, 0x30, asci_in, asci_in_o[0]) 197 let pfx_in: *u8 = sys_mmap(big); let pfx_in_o: *i64 = sys_mmap(8) as *i64; pfx_in_o[0] = 0 198 nxae_put_int_u8(pfx_in, pfx_in_o, big, 3) 199 nxae_put_bytes(pfx_in, pfx_in_o, big, asci, asci_o[0]) 200 nxae_put_bytes(pfx_in, pfx_in_o, big, macdata, macdata_o[0]) 201 var fo: i64 = 0 202 nxae_put_tlv(out, &fo, cap, 0x30, pfx_in, pfx_in_o[0]) 203 out_n[0] = fo 204 return 0 205} 206 207// ===================== GATE: emit a real .p12 to /tmp for openssl validation ===================== 208func p12_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 209func p12_putn(v: i64) -> i64 { let t: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0; if m==0 { t[0]=48 as u8; k=1 } while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } let o: *u8 = sys_mmap(24); var i: i64=0; while i<k { o[i]=t[k-1-i]; i=i+1 } sys_write(1,o,k); return 0 } 210 211func main() -> i64 { 212 p12_puts("nx_mtls_pkcs12 gate: emit a real .p12 -> /tmp/nishi_test.p12 (then validate with openssl)\n" as *u8) 213 let seed: *u8 = sys_mmap(32); var i: i64 = 0; while i < 32 { seed[i] = (0x40 + i) as u8; i = i + 1 } 214 let pub: *u8 = sys_mmap(32); ed25519_pub_from_priv(seed, pub) 215 let serial: *u8 = sys_mmap(8) 216 serial[0]=0x4a as u8; serial[1]=0x10 as u8; serial[2]=0x20 as u8; serial[3]=0x30 as u8 217 serial[4]=0x40 as u8; serial[5]=0x50 as u8; serial[6]=0x60 as u8; serial[7]=0x70 as u8 218 let cert: *u8 = sys_mmap(K_MAGIC_4096); let cl: *i64 = sys_mmap(8) as *i64 219 if nx_x509_leaf_emit_ed25519(seed, pub, "nishi-uid-test0001" as *u8, 18, serial, 8, "260101000000Z" as *u8, "360101000000Z" as *u8, cert, K_MAGIC_4096, cl) != 0 { p12_puts("CERT FAIL\n" as *u8); sys_exit(1) } 220 221 let p12: *u8 = sys_mmap(K_MAGIC_8192); let pn: *i64 = sys_mmap(8) as *i64 222 if nx_mtls_emit_pkcs12(seed, pub, cert, cl[0], "nishi" as *u8, 5, p12, K_MAGIC_8192, pn) != 0 { p12_puts("EMIT FAIL\n" as *u8); sys_exit(1) } 223 224 let fd: i64 = sys_openat_wr("/tmp/nishi_test.p12" as *u8, 0x1a4) 225 if fd >= 0 { sys_write(fd, p12, pn[0]); sys_close(fd) } else { p12_puts("WRITE FAIL\n" as *u8); sys_exit(1) } 226 p12_puts("wrote /tmp/nishi_test.p12 bytes="); p12_putn(pn[0]); p12_puts(" (password: nishi)\n" as *u8) 227 p12_puts("NX-MTLS-PKCS12 EMITTED -- validate: openssl pkcs12 -in /tmp/nishi_test.p12 -passin pass:nishi -info -noout\n" as *u8) 228 sys_exit(0) 229 return 0 230}