Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/factory/factory-commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ Factory commands

Manufacturing-stage commands. Pre-personalization lays down the PIV applet's
*structure* — data containers, PIN/PUK verifiers, key objects — from a profile,
over the SCP03 admin channel. Operators normally never need these; development
and evaluation cards use them with ``--default-keys``. Production cards take
their admin keys from environment variables; production key management is a
manufacturing procedure outside this documentation.
over the SCP03 admin channel. Operators normally never need these. As shipped,
every card opens the admin channel with the GlobalPlatform test keys
(``--default-keys``); replacing them before production is described in
:ref:`piv-admin-key-rotation`, after which the commands take the keys from the
``PIV_SCP03_ENC`` / ``PIV_SCP03_MAC`` / ``PIV_SCP03_DEK`` environment
variables.

.. code-block:: text

Expand Down
24 changes: 14 additions & 10 deletions docs/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,28 @@ Development keys

.. warning::

Development and evaluation cards use well-known **default** keys, and the
examples in this documentation use them too:

* **SCP03 / GlobalPlatform ISD** — the published GlobalPlatform test key
``40 41 42 … 4F`` (``--default-keys``);
Cards ship with well-known **default** keys so that the first
personalization works out of the box, and the examples in this
documentation use them too:

* **PIV admin channel (SCP03)** — key version 1 of the card's PIV security
domain (``A00000015153504101``) holds the published GlobalPlatform test
key ``40 41 42 … 4F`` (``--default-keys``). The card manager (ISD) is a
separate domain with per-card keys that the CLI never uses;
* **PIV management key (9B)** — the same published GlobalPlatform test
value, doubled for an AES-256 key object (``--default-keys``);
* **DESFire** application keys after ``app create`` — all-zero AES
(``--zero-key``);
* **PIV PIN / PUK** in the examples — ``123456`` / ``12345678``.

These are **not secrets** — they are public, published values. A production
deployment must rotate all of them, which is exactly what the
environment-variable key input is for: ``PIV_SCP03_ENC`` /
``PIV_SCP03_MAC`` / ``PIV_SCP03_DEK`` for the admin channel,
``PIV_MGMT_KEY`` for the PIV management key,
deployment must replace them. The environment variables only
*authenticate* with keys that are already on the card; putting new admin
keys on the card is a separate step, see :ref:`piv-admin-key-rotation`.
After it, the admin channel takes ``PIV_SCP03_ENC`` / ``PIV_SCP03_MAC`` /
``PIV_SCP03_DEK``; ``PIV_MGMT_KEY`` carries the PIV management key,
``CRYPTNOX_PIV_PIN`` / ``CRYPTNOX_PIV_NEW_PIN`` / ``CRYPTNOX_PIV_NEW_PUK``
for PINs and PUKs, and the DESFire ``--key-env NAME`` form.
the PINs and PUKs, and DESFire keys use the ``--key-env NAME`` form.

Next
------
Expand Down
9 changes: 5 additions & 4 deletions docs/piv/piv-commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ 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`` (development cards) or 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.
admin keys come from ``--default-keys`` (the test keys every card ships with)
or, once replaced (:ref:`piv-admin-key-rotation`), 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
Expand Down
114 changes: 111 additions & 3 deletions docs/piv/piv-personalization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ For the condensed version, see the :doc:`/piv/quick-start-a-working-piv-card`.
application's PIN has its own retry counter and is managed separately.

Operator commands live under ``piv``; factory pre-personalization lives under
``factory piv preperso``. The SCP03 admin channel uses the card's GlobalPlatform
keys — development/evaluation cards use the GlobalPlatform test keys
(``--default-keys``); provisioned cards take theirs from the
``factory piv preperso``. The SCP03 admin channel uses the keys of the card's
PIV security domain — as shipped, the GlobalPlatform test keys
(``--default-keys``); after :ref:`piv-admin-key-rotation`, the
``PIV_SCP03_ENC`` / ``PIV_SCP03_MAC`` / ``PIV_SCP03_DEK`` environment variables.
``PIV_MGMT_KEY`` carries the PIV management key (``9B``) for cards that need it
(see Step 2).
Expand Down Expand Up @@ -223,12 +223,120 @@ you to type the token ``FINALIZE-PIV``; non-interactively it requires the
``--i-understand-this-is-irreversible`` flag instead — either satisfies the
gate.

``finalize`` locks the **structure** only: which containers, verifiers and
key objects exist, and their access rules. Administration with the security
domain keys continues afterwards — key generation and import, certificate
import, setting a new PIN or PUK, and rotating the admin keys themselves.
Rotate the admin keys *before* finalizing a production card
(:ref:`piv-admin-key-rotation`), so that finalize already runs with your
production keys.

.. code-block:: console

$ cryptnox-id factory piv preperso finalize --default-keys
# at the prompt: Type FINALIZE-PIV to continue
# (scripted/non-interactive: add --i-understand-this-is-irreversible)

.. _piv-admin-key-rotation:

Rotating the PIV admin keys
---------------------------

Every card ships with the published GlobalPlatform test key on **key version
1** of its PIV security domain (AID ``A00000015153504101``), so that the first
personalization works out of the box. Replace it before a card goes into
production. The key set is three AES-128 keys, key identifiers 1 = ENC,
2 = MAC, 3 = DEK.

**Key version 2** of the same domain holds a per-card Cryptnox key set. It
gives the same PIV administration rights and is the recovery path if your own
keys are lost. Leave it in place (see *Deleting key version 2* below). The
card manager (ISD) is a separate domain and is not involved.

The security domain keys *are* PIV administration: whoever holds them can
generate or replace keys, import certificates and set a new PIN or PUK
without knowing the current one, before and after ``finalize``. Protect them
like CA issuing keys, and use one key set per card.

The CLI has no rotation command. The rotation is a single GlobalPlatform
PUT KEY that replaces key version 1 in place; the steps below run it with
GlobalPlatformPro (``gp``, v25.10.20 or later), card on a contact reader.
The CLI keeps finding your keys afterwards without any configuration beyond
the environment variables.

1. Read the key table. No key is needed:

.. code-block:: text

SELECT 00 A4 04 00 09 A0 00 00 01 51 53 50 41 01
GET DATA 80 CA 00 E0 00

Expect key versions 1 and 2, three AES-128 keys each (key type ``88``,
length 16). The replacement key set must be AES-128 as well; a DES key set
is refused, and some tools send DES keys unless told otherwise.

2. Replace key version 1 in place, keeping version number 1. Generate three
independent random 16-byte keys first (in an HSM or key vault):

.. code-block:: console

$ gp -c A00000015153504101 --key 404142434445464748494A4B4C4D4E4F --key-ver 1 \
--lock-enc <ENC> --lock-mac <MAC> --lock-dek <DEK> --new-keyver 1

The card answers with the key version and the key check values of the
three new keys.

.. warning::

Never pass ``--new-keyver 2``. The card accepts it and silently
overwrites the Cryptnox key set in version 2, while version 1 stays on
the test key; the key table looks the same afterwards. Omitting
``--new-keyver`` is also correct — ``gp`` then replaces version 1.

3. Verify in a **new** session, with the new keys. The key table must still
list versions 1 and 2:

.. code-block:: console

$ gp -c A00000015153504101 --key-enc <ENC> --key-mac <MAC> --key-dek <DEK> --key-ver 1 -i

4. Switch the CLI to the new keys and stop passing ``--default-keys``:

.. code-block:: console

$ export PIV_SCP03_ENC=<ENC> PIV_SCP03_MAC=<MAC> PIV_SCP03_DEK=<DEK>
$ cryptnox-id piv admin authenticate

Do not try the old keys to confirm the rotation; the key table and the
successful authentication are the proof. The card counts every
authentication that does not end in a successful EXTERNAL AUTHENTICATE,
including attempts a host abandons after a card-cryptogram mismatch. After
five consecutive ones, every INITIALIZE UPDATE on the card, in any security
domain, is delayed by about 24 seconds until the next successful
authentication. There is no lockout, only the delay.

A PUT KEY with a malformed key block, a wrong key check value or keys wrapped
with the wrong DEK is refused (``6982``) and the key table is unchanged. If a
rotation is interrupted, read the key table, find out which MAC key the card
holds (INITIALIZE UPDATE with key version 1, then check the card cryptogram on
the host with the new MAC key and with the old one), and re-run step 2
authenticated with that key set.

Deleting key version 2
~~~~~~~~~~~~~~~~~~~~~~

If your policy requires sole custody, delete the Cryptnox key set after
rotating version 1, authenticated with your new keys:

.. code-block:: console

$ gp -c A00000015153504101 --key-enc <ENC> --key-mac <MAC> --key-dek <DEK> --key-ver 1 --delete-key 2

This cannot be undone. Afterwards Cryptnox cannot recover PIV administration
on that card if your keys are lost; the only remaining path is a full reset
of the PIV applet, which erases its contents (a Cryptnox operation — contact
Cryptnox support).

Next steps
------------

Expand Down
12 changes: 6 additions & 6 deletions docs/piv/quick-start-a-working-piv-card.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ Prerequisites
interface on this card; contactless works for reading once personalized.
* |cli| installed, and ``yubico-piv-tool`` if you want to run the verification
step (any recent version).
* The card's SCP03 administration keys. **Development/evaluation cards** use the
GlobalPlatform test keys — pass ``--default-keys``. **Provisioned cards** take
their keys from the ``PIV_SCP03_ENC`` / ``PIV_SCP03_MAC`` / ``PIV_SCP03_DEK``
environment variables (hex). Keys never go on the command line, and the
default keys are for development cards only — see the warning in
:doc:`/getting-started`.
* The card's SCP03 administration keys. As shipped, every card uses the
GlobalPlatform test keys — pass ``--default-keys``. Before a card goes into
production, replace them (:ref:`piv-admin-key-rotation`); from then on the
keys come from the ``PIV_SCP03_ENC`` / ``PIV_SCP03_MAC`` / ``PIV_SCP03_DEK``
environment variables (hex). Keys never go on the command line — see the
warning in :doc:`/getting-started`.

Check what you have:

Expand Down
4 changes: 3 additions & 1 deletion docs/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ throwaway dev root: ``genuine verify --anchors <dev-ca-dir>``.
**Genuineness is not the ISD / PIV-SSD check.**
``genuine verify`` proves the attestation applet's device key and certificate
chain. It does **not** verify the per-card ISD or PIV-SSD keys (KDF/HSM-derived)
— this tool has no access to those secrets, and the output says so.
— this tool has no access to those secrets, and the output says so. The
per-card PIV-SSD key set is key version 2 of the PIV security domain; see
:ref:`piv-admin-key-rotation` for what it is and why to leave it in place.

yubico-piv-tool interop
-------------------------
Expand Down
Loading