Référence en anglais
Cette page technique est disponible en anglais. Les guides d’utilisation et d’installation sont traduits en français.
PIV card application¶
Status: normative description of the feuristic PIV application (product
spec F04, F07, §6.2, §6.3; acceptance test R10). Implementation:
src/feuristic/apps/card/piv/. Tests: tests/host/card/piv/.
feuristic implements the commands and data objects of NIST SP 800-73-4
(Parts 1 and 2) needed by the common PIV middleware — OpenSC's piv driver
(pkcs15-tool, pkcs11-tool, piv-tool, hence TLS client authentication,
SSH via PKCS#11, S/MIME…) and the usual yubico-piv-tool / ykman piv
operations — with the algorithms of SP 800-78-4 listed below. It is not a
FIPS 201 / federal PIV credential: it carries no issuer-signed CHUID or
security object and makes no claim of conformance certification.
1. Application identifier and selection¶
- AID
A0 00 00 03 08 00 00 10 00 01 00; partial selection byA0 00 00 03 08(or any prefix) is accepted. - SELECT response: Application Property Template (SP 800-73-4 Part 1 Table 3):
61 37
4F 06 000010000100 PIX
79 07 4F 05 A000000308 coexistent tag allocation authority
50 0D "feuristic PIV" application label
AC 15 80 01 03 80 01 08 80 01 0A 80 01 0C 80 01 07 80 01 11 06 01 00
- Selecting another application (OpenPGP, AES), a card reset, a device lock or a USB re-enumeration clears the security status (PIN verified, administration key authenticated). Re-selecting PIV keeps it.
2. Key slots and algorithms¶
| Slot | Role (shown on the device) | Algorithms | PIN policy | Operations |
|---|---|---|---|---|
9A |
PIV Authentication | ECC P-256 (11), RSA 2048 (07) |
once per session | ECDSA sign, RSA raw |
9C |
Digital Signature | ECC P-256, RSA 2048 | before every use | ECDSA sign, RSA raw |
9D |
Key Management | ECC P-256, RSA 2048 | once per session | ECDH (P-256), RSA raw (decryption) |
9E |
Card Authentication | ECC P-256, RSA 2048 | none | ECDSA sign, RSA raw (challenge-response) |
9B |
Card Application Administration Key | 3DES (03), AES-128 (08), AES-192 (0A, default), AES-256 (0C) |
— | mutual / external authentication |
- Key-usage separation (spec §6.2): ECDH is only allowed with
9D; ECDSA is refused with9D. RSA operations cannot be told apart (signing and decryption are the same raw private operation) and are allowed on every slot. - Retired key slots (
82–95), the secure-messaging key (04), P-384, RSA-1024/3072/4096, Ed25519/X25519 PIV extensions and pairing codes are not supported. - GENERATE may make the PIN policy of a slot stricter (YubiKey tag
AA:01never,02once,03always) but never weaker (6A80).
3. Commands¶
| Command | APDU | Access condition | Notes |
|---|---|---|---|
| SELECT | 00 A4 04 00 |
always | §1 (handled with the dispatcher) |
| GET DATA | 00 CB 3F FF {5C tag} |
always (Printed Information: PIN) | §4 |
| PUT DATA | 00 DB 3F FF {5C tag}{53 …} |
administration key | §4 |
| VERIFY | 00 20 00 80 {PIN padded to 8} |
— | also 00 20 00 80 (no data: status) and 00 20 FF 80 (reset status) |
| CHANGE REFERENCE DATA | 00 24 00 80/81 {old ‖ new} |
old PIN/PUK | 16 bytes |
| RESET RETRY COUNTER | 00 2C 00 80 {PUK ‖ new PIN} |
PUK | 16 bytes |
| GENERAL AUTHENTICATE | 00 87 alg slot {7C …} |
per slot (§5) | §6 |
| GENERATE ASYMMETRIC KEY PAIR | 00 47 00 slot {AC {80 alg}[AA pin][AB touch]} |
administration key + device confirmation | response 7F49 {86 point} or 7F49 {81 n, 82 e} |
| GET VERSION (YubiKey) | 00 FD 00 00 |
always | 05 07 00 |
| GET SERIAL (YubiKey) | 00 F8 00 00 |
always | 4 bytes derived from the device |
| GET METADATA (YubiKey) | 00 F7 00 ref |
always | refs 80, 81, 9B, 9A/9C/9D/9E |
| SET MANAGEMENT KEY (YubiKey) | 00 FF FF FF/FE {alg 9B len key} |
administration key + device confirmation | |
| RESET (YubiKey) | 00 FB 00 00 |
PIN and PUK blocked + device confirmation | erases PIV |
| IMPORT ASYMMETRIC KEY (YubiKey) | 00 FE … |
— | 6D00: keys are generated on the device (spec §6.2) |
| ATTEST, SET PIN RETRIES, MOVE KEY | F9, FA, F6 |
— | 6D00 |
GET RESPONSE (00 C0) and command chaining are handled by the card
dispatcher: long certificates and RSA signatures work with short APDUs.
GET VERSION reports the PIV feature level of YubiKey firmware 5.7 so that
yubico-piv-tool/ykman use the AES-192 default administration key and the
metadata command; it does not claim the device is a YubiKey (the APT label is
"feuristic PIV").
4. Data objects¶
| Object | Tag | GET DATA | PUT DATA (cap) |
|---|---|---|---|
| Card Capability Container | 5FC107 |
generated (YubiKey-style template, card id derived from the device) or stored | ≤ 128 B |
| CHUID | 5FC102 |
generated (below) or stored | ≤ 960 B |
| Discovery Object | 7E |
7E {4F AID, 5F2F 4000} (PIV PIN only) |
read-only (6A80) |
| Key History | 5FC10C |
generated C1 00, C2 00 (no retired keys) or stored |
≤ 128 B |
| X.509 cert. 9A / 9C / 9D / 9E | 5FC105 / 5FC10A / 5FC10B / 5FC101 |
53 {70 cert, 71 info, FE} |
certificate ≤ 2048 B |
| Security Object | 5FC106 |
stored only | ≤ 768 B |
| Printed Information | 5FC109 |
stored only, PIN required | ≤ 256 B |
| anything else | 6A82 |
6A80 |
- Generated CHUID:
30FASC-N for non-federal issuers (D4E739DA739CED39CE739D836858210842108421C84210C3EB: agency code 9999, system 9999, credential 999999, as used byyubico-piv-tool),34GUID (16 bytes,HKDF(master secret, "card/serial", "piv-guid"), stable for the device),35expiration20301231,3Eempty issuer signature,FE. - PUT DATA content must be well-formed BER-TLV. An empty
53deletes the object (a generated one then reappears). Certificate objects accept70(1..2048 bytes, mandatory),71(00, or01= gzip) and an emptyFE; the certificate is stored next to the slot key (one record). - Storage: one record per slot (key + certificate ≤ 2400 bytes), one record
for the data objects, one for the credentials; all PIV records ≤ 10 KiB
(
6A84beyond). - Generating a new key in a slot deletes its (now mismatched) certificate.
5. PIN, PUK and administration key¶
5.1 Default values — decision¶
The PIV application starts with the standard PIV defaults: PIN 123456,
PUK 12345678, administration key AES-192
010203040506070801020304050607080102030405060708. Rationale: the spec
requires all configuration to be possible on the device (§1.2, §9) but must
not make PIV unusable for a user who skips the PIV set-up step; standard
tools also expect these defaults. To keep this safe:
- the menu "Cryptographie → PIV" shows a warning for every default still in
use (
piv.warn.default_pin,…_puk,…_mgmt) until it is changed; - the PIV set-up step (
localmgmt.init_identity) asks for a new PIN and PUK on the device (digits only, 6–8); the administration key can be replaced by a random one shown on the device screen (generate_mgmt_key) so that it can be typed into host tools; - the host can also change PIN/PUK with CHANGE REFERENCE DATA (any printable ASCII, 6–8 characters) and the administration key with SET MANAGEMENT KEY (requires the current key and an on-device confirmation);
- setting a value back to its default re-enables the warning.
5.2 Rules¶
- PIN and PUK: 6–8 printable ASCII bytes padded with
FFto 8 bytes (SP 800-73-4 Part 2 §2.4.3). A malformed value answers6A80without consuming a try. - Retry counters: 3 tries each. The failure counter is written to flash
before the comparison and cleared after a success (a power cut can only
cost a try, never give one).
63Cx= wrong value,xtries left;6983= blocked. A failed VERIFY clears the PIN security status. - Blocked PIN: RESET RETRY COUNTER with the PUK, or "Définir le PIN PIV" on
the device (the device is already unlocked with the device PIN). Blocked
PIN and PUK: YubiKey-style RESET (
00 FB) with a device confirmation, or "Réinitialiser PIV" on the device. - Changing PIN, PUK or the administration key (from the host or the device) voids the current security status; the host must verify / authenticate again.
- PIN and PUK are stored as
HMAC-SHA-256(salt, padded value)with a random 16-byte salt in the protected (storage-DEK encrypted) namespace; the administration key is stored in the same protected namespace.
5.3 Administration key authentication (GENERAL AUTHENTICATE, slot 9B)¶
P1 must be the configured algorithm (6A86 otherwise); witness, challenge
and response have the cipher block size (8 bytes for 3DES, 16 for AES).
| Flow | Step 1 | Card | Step 2 | Card |
|---|---|---|---|---|
mutual (yubico-piv-tool, piv-tool -A M:9B:…) |
7C 02 80 00 |
7C {80 E(W)} |
7C {80 W, 81 C} |
7C {82 E(C)} |
external (piv-tool -A A:9B:…) |
7C 02 81 00 |
7C {81 C} |
7C {82 E(C)} |
9000 |
- Step 2 must immediately follow step 1 (any other command discards the
pending witness/challenge,
6985afterwards). A wrong witness or response answers6982and revokes a previous authentication. - Internal authentication with the administration key (
7C {81 C, 82 ∅}) is refused (6A80): it would be an encryption oracle answering the external-authentication challenge. - 3DES is TDEA keying option 1 (SP 800-67), implemented in pure Python.
6. Private-key operations (GENERAL AUTHENTICATE)¶
| Operation | Command data | Response |
|---|---|---|
| ECDSA P-256 | 7C {82 ∅, 81 hash} (tags in any order) |
7C {82 DER ECDSA-Sig-Value} |
| RSA 2048 raw (sign / decrypt / challenge) | 7C {82 ∅, 81 256-byte block} |
7C {82 256-byte result} |
ECDH P-256 (9D only) |
7C {82 ∅, 85 04‖X‖Y} |
7C {82 X coordinate (32 B)} |
- ECDSA input: the host-computed hash. Longer than 32 bytes → leftmost 32
bytes (FIPS 186-4 §6.4); shorter → left-padded with zeros; 1..64 bytes
accepted (
6A80otherwise). - RSA input: exactly 256 bytes, numerically below the modulus (the host does the PKCS #1 v1.5 / PSS padding or the OAEP/v1.5 decoding).
- ECDH: the peer point must be an uncompressed point on P-256; it is checked
before the confirmation (
6A80). - Challenge-response (spec F07, R10): signing a host challenge with
9E(no PIN; "Card Authentication" prompt) or9Ais the PIV challenge-response; the device shows "Challenge-response" for9E.
6.1 On-device confirmation (spec §6.3)¶
Every private-key operation shows a confirmation screen; PIN
verification never replaces it. The prompt (Prompt.kind piv.sign,
piv.rsa, piv.ecdh, piv.card_auth) contains:
- the operation (Signature / RSA private operation / ECDH key agreement / Challenge-response);
- the slot role and number, e.g. "Digital Signature (9C)";
- the algorithm ("ECC P-256", "RSA 2048");
- the public-key fingerprint: the first 8 bytes of SHA-256 over the
SubjectPublicKeyInfo DER, in hex — comparable on the host with
openssl x509 -in cert.pem -pubkey -noout | openssl pkey -pubin -outform DER | sha256sum; - for signatures and RSA operations, the label "Signature d'empreinte non interprétée" / "Uninterpreted digest signature": PIV only receives a hash or a padded block, which the device cannot interpret, so no semantic description is invented.
Refusal or timeout answers 6982. For 9C the PIN is consumed by the
attempt, even if refused. The PIN is checked before the prompt is shown.
GENERATE and SET MANAGEMENT KEY also require a confirmation (DANGER-level
when an existing key is replaced).
7. Status words¶
| SW | Meaning |
|---|---|
9000 |
success |
61xx |
more data: GET RESPONSE |
63Cx |
wrong PIN/PUK, x tries left |
6581 |
stored PIV data corrupted |
6700 |
wrong length (dispatcher: de-chained data > 4096 bytes) |
6881 / 6882 |
logical channels / secure messaging not supported |
6982 |
security status not satisfied (PIN, administration key) or operation refused on the device; wrong witness/response |
6983 |
PIN/PUK blocked |
6985 |
9B step 2 without step 1; RESET while PIN or PUK is still usable |
6A80 |
malformed data, unsupported algorithm/policy, key-usage violation, invalid point/input, unknown or read-only object in PUT DATA |
6A81 |
RSA key generation unavailable in this build |
6A82 |
data object not found |
6A84 |
not enough memory (certificate > 2048 B, object cap, 10 KiB PIV budget) |
6A86 |
wrong P1/P2 (algorithm mismatch, invalid key reference) |
6A88 |
key reference not found (empty slot, unsupported PIN reference) |
6D00 |
instruction not supported (including key import) |
6E00 |
class not supported |
8. Usage examples¶
The device must be unlocked; confirm each private-key operation on its screen. Reader names below are examples.
8.1 OpenSC¶
opensc-tool --list-readers
opensc-tool -s 00A4040005A00000030800 -s 00CB3FFF035C017E00 # raw SELECT + discovery
pkcs15-tool --list-certificates --list-public-keys
pkcs11-tool --module opensc-pkcs11.so --list-objects
# generate a key in 9A with the default AES-192 administration key
piv-tool -A M:9B:0A -G 9A:11 -o 9a.pub
# (piv-tool reads the administration key from the file named by
# $PIV_EXT_AUTH_KEY; algorithm 0A = AES-192, 03 = 3DES)
# load a certificate obtained for that key
piv-tool -A M:9B:0A -O 9A -i cert.der
# sign with 9C (PIN asked by pkcs11-tool, prompt on the device)
pkcs11-tool --module opensc-pkcs11.so --login --sign --mechanism ECDSA \
--id 02 -i digest.bin -o sig.bin
# TLS client authentication / SSH via PKCS#11
ssh -I /usr/lib/opensc-pkcs11.so user@host
8.2 yubico-piv-tool¶
yubico-piv-tool only lists readers whose name contains "Yubikey" unless
-r is given: pass the reader name explicitly (-r '' matches any).
yubico-piv-tool -r '' -a status
yubico-piv-tool -r '' -a change-pin -P 123456 -N 24681357
yubico-piv-tool -r '' -a change-puk -P 12345678 -N 87654321
yubico-piv-tool -r '' -k 010203040506070801020304050607080102030405060708 \
-a generate -s 9c -A ECCP256 -o 9c.pub
yubico-piv-tool -r '' -a verify-pin -P 24681357 -a selfsign-certificate -s 9c \
-S '/CN=alice/' -i 9c.pub -o 9c.crt
yubico-piv-tool -r '' -k … -a import-certificate -s 9c -i 9c.crt
yubico-piv-tool -r '' -a verify-pin -P 24681357 -a test-signature -s 9c -i 9c.crt
yubico-piv-tool -r '' -k … -a set-mgm-key -m AES256 -n <64 hex digits>
-a import-key fails with 6D00 by design; --pin-policy=never on 9A/9C
fails with 6A80 (only stricter policies are honoured); --touch-policy=never
fails because every operation is confirmed on the device.
9. Device menus (local management)¶
"Cryptographie → PIV" (apps/card/piv/localmgmt.py): list the four slots
with status, algorithm, fingerprint and PIN policy; generate a key (P-256 or
RSA 2048) in a slot; delete a slot (key + certificate); show a certificate
summary (subject CN, issuer CN, validity, serial — display-only parser);
set PIN / PUK; generate or reset the administration key; make a slot's PIN
policy stricter; reset PIV; export a slot identity as an encrypted QR backup
(docs/protocols/backup-piv.md).
10. Limitations¶
- No retired key slots, no secure messaging / VCI, no pairing code, no
biometric objects, no attestation (
F9). - No issuer-signed CHUID / security object: relying parties that require FIPS 201 card authentication of the CHUID signature will reject it.
- RSA 2048 key generation takes seconds on the device (keep-alive time
extensions are sent); it requires
feuristic.core.rsa. - Private keys are exportable through the device's encrypted QR backup (spec §8.2); the device never claims them non-exportable. They are never readable over USB.
GET CHALLENGEis not part of PIV; use the AES/RNG profile (docs/protocols/aes-gcm-iso7816-v1.md§9).