mix pkcs11ex.import_p12 (pkcs11ex v0.1.0)

Copy Markdown View Source

Imports the private key + leaf certificate from a PKCS#12 (.p12 / .pfx) bundle into a configured PKCS#11 slot.

Intended for: SoftHSM provisioning in dev/CI, one-shot loading of taxpayer / legal-proxy certificates into write-permitted file-backed tokens, fixture setup in test suites. Not suitable for production HSMs (most reject software-key import by design; cloud HSMs do so categorically).

See docs/specs/api.md §5.1 for the canonical contract.

Usage

mix pkcs11ex.import_p12 \
  --in legal_proxy.p12 \
  --slot legal_proxy \
  --label proxy-signing-key \
  [--cert-label proxy-cert] \
  [--id 0x01]

Required flags

  • --in PATH — path to the .p12 / .pfx bundle.
  • --slot SLOT_REF — atom of a configured slot (must exist in :pkcs11ex :slots config, must be write-permitted).
  • --label LABELCKA_LABEL for the imported private key.

Optional flags

  • --cert-label LABELCKA_LABEL for the certificate. Defaults to --label.
  • --id HEXCKA_ID (hex-encoded). Auto-generated if omitted.
  • --password-from-env VAR — read P12 password from env var (CI).
  • --pin-from-env VAR — read user PIN from env var (CI).

Prompts

When --password-from-env / --pin-from-env are not used, the task prompts for the bundle password and the slot's user PIN with terminal echo disabled.

Threat model — plaintext key in BEAM heap

This task is the only path in pkcs11ex that handles a software RSA private key in cleartext. The key flows through BEAM-managed binaries:

  1. openssl pkcs12 -in <bundle> -nocerts -nodes extracts the key as a PEM blob into the task's stdout (captured by System.cmd into a binary).
  2. :public_key.pem_decode/1 and pem_entry_decode/1 produce an Erlang RSAPrivateKey record — modulus, private exponent, the five CRT parameters, all as integers / binaries on the BEAM heap.
  3. The components are marshaled across the NIF as binaries, then the NIF zeroizes its Rust-side copies (cryptoki + Zeroizing).

Step 1 and step 2 BEAM heap memory cannot be wiped — the BEAM has no zeroization primitive for managed binaries / integers, and the GC may keep them around well past the task's nominal lifetime.

The only mitigations are:

  • Run the task in a short-lived process; let the BEAM exit immediately after the import.
  • Don't run on a multi-tenant box where another process can read /proc/<pid>/maps or trigger a core dump.
  • Treat the bundle on disk as the canonical secret — the BEAM-heap copy is a temporary echo of it.

Use pkcs11ex directly (HSM-only path) for any key that should never have a software copy in memory. This task is for provisioning fixtures, dev/CI, and importing dormant taxpayer / legal-proxy certificates into write-permitted file-backed tokens.

Both the bundle password and the user PIN are passed once into the flow and not stored after this task returns. They transit BEAM memory the same way and are subject to the same caveats.