PIV commands

Operator and personalization commands for the PIV function (SP 800-73). Administration runs over an SCP03 secure channel and is contact-only; admin keys come from --default-keys (the test keys every card ships with) or, once replaced (Rotating the PIV admin keys), the PIV_SCP03_ENC / PIV_SCP03_MAC / PIV_SCP03_DEK environment variables. PIN values come from masked prompts or CRYPTNOX_PIV_PIN / CRYPTNOX_PIV_NEW_PIN / CRYPTNOX_PIV_NEW_PUK — never the command line.

On-card generation of a large public key can also use the card’s PIV management key (key reference 9B), whose value comes from --default-keys or PIV_MGMT_KEY — never the command line. --default-keys covers both the admin channel and the management key: when it is given, PIV_MGMT_KEY is not read.

Inspection

piv info            applet AID/label, supported algorithms, key slots
piv status          lifecycle state, PIN/PUK status, object presence
piv discover        the Discovery object (PIN usage policy)
piv slots           key slots and which hold a certificate
piv inventory       key objects, verifiers, containers and config, with access rules
piv validate        consistency check (NOT a NIST/FIPS validation)
piv quickstart      one-shot personalization (see the PIV quick start)

piv inventory is the applet’s own listing of its structure, read without authentication: every key object with its mechanism, roles, attributes and access modes, every verifier with its length and retry limits, every container with its access modes, plus the applet version, its finalize state and its config flags. An applet whose restrict-enumeration flag is set withholds the structure (6986) and the command says so; version, state and config still answer.

PIN

piv pin status      PIN/PUK configured? retries left? (non-decrementing)
piv pin verify      verify the PIN (a wrong PIN consumes one retry)
piv pin change      change the PIN (cardholder; needs the current PIN)
piv pin unblock     unblock a blocked PIN via the PUK (RESET RETRY COUNTER;
                    a wrong PUK consumes a PUK retry — see warning below)

PUK

piv puk change      change the PUK (cardholder; needs the current PUK)

piv pin change and piv puk change are cardholder operations — they prove knowledge of the current value in-band (no SCP03 admin channel), unlike the piv perso set-pin / set-puk issuance commands. piv pin unblock resets a blocked PIN’s retry counter using the PUK. Current/new values come from masked prompts or the CRYPTNOX_PIV_PIN / CRYPTNOX_PIV_NEW_PIN / CRYPTNOX_PIV_PUK / CRYPTNOX_PIV_NEW_PUK environment variables — never the command line.

Warning

The PUK has its own retry counter, and every wrong PUK — entered through piv pin unblock, piv puk change, or any other tool — consumes one retry. Exhausting the PUK retries is permanent: a blocked PUK has no recovery path. A full reset of the PIV applet, which erases all keys and certificates, runs through the Cryptnox remote PIV service (Remote service guide). Check piv pin status (non-decrementing) before guessing.

Admin channel

piv admin status        the admin security domain: SCP version, key versions (no auth)
piv admin keys          its key table; --check-default tests key version 1 (one attempt)
piv admin authenticate  open the channel (mutual auth) + harmless self-test
piv admin rotate-keys   replace key version 1 in place (new keys from PIV_SCP03_NEW_*)
piv admin delete-factory-keyset
                        IRREVERSIBLY delete key version 2, Cryptnox's keyset

piv admin status selects the PIV security domain and reads its key information template. It never sends INITIALIZE UPDATE: on this chip an INITIALIZE UPDATE that is not followed by a successful EXTERNAL AUTHENTICATE counts as a failed authentication, and a status read must not spend one.

piv admin keys lists the same table. With --check-default it authenticates once to key version 1 with the publicly known GlobalPlatform test key: a success means anyone can administer the PIV applet, and leaves the card’s failed-authentication count clear; a wrong key costs one failed authentication, which the next successful piv admin authenticate clears. It never tries more than that one key, and skips the check when the table has no key version 1.

piv admin rotate-keys replaces key version 1 of the PIV security domain in place: one PUT KEY carrying ENC, MAC and DEK, encrypted under the current DEK, with the key version byte left at 1. The current keys come from --default-keys or PIV_SCP03_ENC / PIV_SCP03_MAC / PIV_SCP03_DEK; the new ones from PIV_SCP03_NEW_ENC / PIV_SCP03_NEW_MAC / PIV_SCP03_NEW_DEK (hex, 16 bytes each), never the command line. The command reads the key table first, refuses to write anything but key version 1, compares the key check values the card echoes with its own, authenticates once with the new keys, and re-reads the table to confirm key version 2 is as it was. Key version 2 is Cryptnox’s keyset for remote reset and attestation; the command never addresses it. --dry-run prints the plan with the new keys’ check values and sends nothing. A refused PUT KEY writes nothing, so the current keys still work. The new keys take the type the domain speaks, DES on SCP02 and AES on SCP03: a domain is bound to one of the two when it is created, and a keyset of the other type is accepted by the card yet can never open a session afterwards.

piv admin delete-factory-keyset deletes key version 2 (DELETE KEY by key version), authenticated with key version 1 from the PIV_SCP03_* variables. It refuses while those are the publicly known test keys, and needs the typed confirmation DELETE-FACTORY-KEYSET or --i-understand-this-is-irreversible. Afterwards Cryptnox’s remote reset and attestation cannot reach the card; key version 1 is the only way left to administer the PIV applet.

Certificates and objects

piv certs list          certificate slots, subjects, expiry
piv certs export        export a certificate (PEM/DER) - certificates are not secret
piv certs inspect       certificate details for a slot
piv objects list        PIV data objects and presence
piv objects read        read a data object (hex or --out FILE)

Attestation

piv export-attestation  export the on-card key-attestation leaf (PEM chain / DER)
piv verify-attestation  validate the attestation chain to the pinned Cryptnox root

The factory/issuance-time key-attestation leaf (slot 9C in this version) is stored in the retired-slot-95 certificate container and chains to the pinned Cryptnox attestation root. --csr additionally checks that the attested key is the one in a CSR. The Cryptnox production root ships bundled, so verify-attestation anchors the chain out of the box. Where no anchor covers a chain it reports that the chain cannot be verified — it never passes silently.

To add anchors without rebuilding the package, point CRYPTNOX_TRUST_DIR at a directory of PEM certificates:

$ export CRYPTNOX_TRUST_DIR=/etc/cryptnox/anchors
$ cryptnox-id piv verify-attestation

Certificates are classified by inspection: self-issued CAs become pinned roots, other CAs become intermediates, and non-CA material is ignored. The directory is added to whatever ships bundled (duplicates are collapsed), so it extends the trust store rather than replacing it. genuine verify --anchors DIR accepts a directory the same way for that command alone.

Personalization (piv perso)

piv perso set-pin                 set the initial PIN (over SCP03)
piv perso set-puk                 set the initial PUK (over SCP03)
piv perso generate-key            on-card key generation (per the slot's key objects)
piv perso import-key              inject an externally generated private key
piv perso import-p12              one-command PKCS#12 (.p12/.pfx) key + certificate import
piv perso generate-csr            PKCS#10 CSR, signed on-card
piv perso self-sign-cert          self-signed certificate (dev/test), signed on-card
piv perso import-cert             write a certificate into the slot container
                                  (--csr / --verify-pin check it is for the slot's key)
piv perso generate-chuid          build a minimal CHUID object
piv perso generate-ccc            build a minimal CCC object
piv perso generate-discovery      build the Discovery object
piv perso write-object            write any data object from a file
piv perso write-standard-objects  generate + write CHUID and CCC
piv perso smoke-test              verify PIN + one on-card signature

Notes

  • Signing needs a SIGN-role slot — 9C on this card; 9A (AUTHENTICATE role) returns 6985 for sign operations.

  • On-card generation works for whichever mechanisms the slot has a key object for, which is decided by the pre-personalization profile, not by the applet. On cryptnox-default every key object is ECC (P-256/P-384), so RSA has to be imported there. ms-logon also creates an RSA-2048 object on 9A, and generate-key --slot 9A --algorithm RSA2048 generates on-card on such a card. Asking for a mechanism the slot has no object for returns 6A80.

  • Some cards cannot return an RSA public-key template larger than 256 bytes over the admin channel. generate-key detects that from the card’s own response and finishes the generation over plain APDUs, authenticating the PIV management key (9B) first. The management key is contact-only and its value comes from --default-keys (development cards) or PIV_MGMT_KEY; a card whose 9B object holds no value is reported with the command that loads one (factory piv preperso set-mgmt-key). ECC is unaffected, and cards that return the full template take the admin channel as before.

  • When that path is taken, the key pair from the first attempt is replaced by the one generated over the plain path, whose public half is the one reported; RSA generation therefore runs twice on such a card.

  • piv quickstart defaults to ECC P-256, except with --profile ms-logon on slot 9A, the one built-in shape with an RSA key object and the Windows one, where it defaults to RSA-2048 because Windows does not enumerate EC keys. --algorithm RSA* is accepted there and rejected elsewhere. For other cards known to carry an RSA object, use piv perso generate-key directly.

  • piv quickstart reads the applet’s key-object listing before planning. A card with no structure at all needs --include-preperso (or a load-config); a card whose structure lacks the key object for the requested slot and mechanism gets that one object created with --include-preperso, never a second load-config over the existing structure, which the applet refuses with 6E27.

  • piv perso import-cert writes the certificate it is given. --csr FILE refuses one whose public key is not the CSR’s, with no PIN; --verify-pin has the slot sign a challenge and refuses unless the certificate’s key verifies it. Without either, a certificate for another key is written and fails only when used.

  • piv perso import-key is the way to place an externally generated RSA key. It sends the key as CHANGE REFERENCE DATA ADMIN elements over SCP03 and starts with a CLEAR, so re-runs are safe.

  • Large objects (certificates) are written with ISO command chaining automatically.