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
6985for 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-defaultevery key object is ECC (P-256/P-384), so RSA has to be imported there.ms-logonalso creates an RSA-2048 object on 9A, andgenerate-key --slot 9A --algorithm RSA2048generates on-card on such a card. Asking for a mechanism the slot has no object for returns6A80.Some cards cannot return an RSA public-key template larger than 256 bytes over the admin channel.
generate-keydetects 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) orPIV_MGMT_KEY; a card whose9Bobject 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 quickstartdefaults to ECC P-256, except with--profile ms-logonon 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, usepiv perso generate-keydirectly.piv quickstartreads the applet’s key-object listing before planning. A card with no structure at all needs--include-preperso(or aload-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 secondload-configover the existing structure, which the applet refuses with6E27.piv perso import-certwrites the certificate it is given.--csr FILErefuses one whose public key is not the CSR’s, with no PIN;--verify-pinhas 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-keyis 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.