Setup & channel commands
SELECT
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
|
AID |
Request Data
Field |
Size |
Description |
|---|---|---|
AID |
7B |
Application identifier: |
The SELECT command is documented in the ISO 7816-4 specifications and is used to select
the application on the card, making it the active one. The data field is the AID of the
application.
After receiving the ATR from the card, this must be the first command sent. It provides basic information about the card applet status and flags, which the client should use to determine the card’s current state and capabilities before proceeding with further operations.
Response Data — 24 bytes
Field |
Size |
Description |
|---|---|---|
Applet type |
1B |
|
Applet version |
3B |
Major.Middle.Minor (e.g. |
Status flags |
2B |
Big-endian short, see below |
PubKey flags |
2B |
Big-endian short, see below |
Custom bytes |
16B |
User-defined, written by |
Status flag bits (bit 15 = MSB, bit 0 = LSB):
Bit |
Meaning |
|---|---|
7 |
Reset is disabled |
6 |
Initialized |
5 |
Seed (master seed or EC pair loaded) |
4 |
Pin Auth possible |
3 |
Pinless enabled |
2 |
xpub output enabled |
1 |
Clear read of current public key enabled |
PubKey flag bits:
Bit |
Meaning |
|---|---|
0 |
User Public Key #1 (ECDSA 256r1) active |
1 |
User Public Key #2 (RSA 2048) active |
2 |
User Public Key #3 (FIDO2) active |
4 |
User Public Key #4 (ECDSA 256r1) active |
5 |
User Public Key #5 (ECDSA 256r1) active |
The custom bytes can be used to provide personal hints about how to authenticate with the card, or what’s stored inside the card. Note that whoever has the card can freely and easily read this data.
The card serial ID can be read with the GET MANUFACTURER CERTIFICATE command which provides
the card certificate signed by the manufacturer. The card serial is the serial of the provided
X509 certificate.
Status Words
SW |
Description |
|---|---|
|
Success |
GET CARD PUBKEY
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
— |
None |
Response Data — 65 bytes
Field |
Size |
Description |
|---|---|---|
Card public key |
65B |
EC R1 uncompressed point ( |
This command reads the card’s static EC R1 public key. During the installation of the applet, the card initializes its own EC R1 key pair. This command is only useful for the manufacturer at factory to send the Cryptnox certificate in the card, which contains this card public key, thus authenticating the genuineness of the card.
GET MANUFACTURER CERTIFICATE
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
Page |
— |
None |
P2 values
P2 |
Description |
|---|---|
|
First 253 bytes of certificate + 2 bytes length prefix |
|
Remaining pages, 255 bytes each |
Response Data
Field |
Size |
Description |
|---|---|---|
Certificate length |
2B |
Big-endian short (P2=0 only) |
Certificate data |
up to 253B/255B |
X509 certificate fragment |
This command reads the Cryptnox card X509 certificate. This command should be used after each
SELECT and before the OPEN SECURE CHANNEL command in order to:
Read the Card Serial Number. This is useful to get the right pairing key associated with the card, especially when the user client communicates with several cards and needs to associate the PairingKey with the instance SN.
Read the card public key, to further check the ECDH card public key authenticity during the secure channel setup.
Check if the card is genuine by verifying the certificate against the Cryptnox public key.
The answer is limited to 255 bytes per page. P2=0 returns the first 253 bytes of the
certificate prepended with 2 bytes of its total length. P2>0 returns the remaining parts,
paginated by 255 bytes.
Status Words
SW |
Description |
|---|---|
|
Success |
GET CARD CERTIFICATE
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
|
Nonce |
Request Data
Field |
Size |
Description |
|---|---|---|
Nonce |
8B |
Random nonce for certificate freshness |
This command generates and provides the card basic certificate. It should be used after each
GET MANUFACTURER CERTIFICATE and before the OPEN SECURE CHANNEL command in order to
securely get the card ephemeral public key for the channel encryption key exchange.
The nonce is provided by the command query, so the certificate can only be refreshed and live generated by the card. This ensures that the session public key is fresh and has not been replayed from a previous session.
Response Data — variable (~138-140 bytes)
The basic card certificate is a special compact format:
Field |
Size |
Description |
|---|---|---|
Tag |
1B |
|
Nonce |
8B |
Echo of the provided nonce |
Session public key |
65B |
Ephemeral EC 256r1 card key for ECDH |
Signature |
70-72B |
ASN1-DER ECDSA signature over the above fields, signed with the card private key |
The session public key is the ephemeral EC 256r1 card key for the ECDH secure channel establishment. The signature is made from the concatenation of the tag, nonce and session public key, signed with the card’s static private key (whose public key is in the Cryptnox certificate). This allows the client to verify the session key authenticity.
Status Words
SW |
Description |
|---|---|
|
Success |
|
Nonce length is not 8 bytes |
INIT
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
var |
PubKey(LV) | IV | Encrypted payload |
Preconditions: Card must be in pre-initialized state.
This command is only available when the applet is in pre-initialized state and successful execution brings the applet into the initialized state. This command is needed to allow securely storing secrets on the applet. Currently these are the PIN, PUK and pairing password. The user can also enter personal info (name and email).
The client must take the public key received after the GET CARD CERTIFICATE command,
generate a random keypair and perform R1 EC-DH to generate an AES key. It must then generate
a random IV and encrypt the payload using AES-CBC with ISO/IEC 9797-1 Method 2 padding.
This scheme guarantees protection against passive MITM attacks. Since the applet has no “owner” before the execution of this command, protection against active MITM cannot be provided at this stage. However since the communication happens locally (either through NFC or contacted interface) the realization of such an attack at this point is unrealistic.
Request Data (wire format)
Field |
Size |
Description |
|---|---|---|
PubKey length |
1B |
Length of the EC public key (65) |
PubKey |
65B |
Client ephemeral EC R1 uncompressed point for ECDH |
IV |
16B |
AES-CBC initialization vector |
Encrypted payload |
var |
AES-CBC encrypted parameters (ISO 9797-1 M2 padded) |
Decrypted payload content
The payload is the concatenation of the User data, PIN, PUK and the Secure Channel first
pairing secret. The User data consists of the User Name and the User Email, each prepended
with a byte indicating their length. For example: 0x07 | 'Cryptnox' | 0x14 | 'contact@cryptnox.com'.
These user fields can carry whatever information the user wants to input in the card: their name, an ID number, a key identifier, etc.
Field |
Size |
Description |
|---|---|---|
Name length |
1B |
Length of owner name (0-20) |
Name |
0-20B |
Owner name |
Email length |
1B |
Length of owner email (0-60) |
0-60B |
Owner email |
|
PIN |
9B |
4-9 digit PIN, right-padded with |
PUK |
12B |
PUK code |
Pairing secret |
32B |
First secure channel pairing key |
The PIN must be 4 to 9 figure number characters ('0'-'9'). If the PIN is less than 9
bytes, it must be filled with 0x00 until 9 chars long.
After successful execution, this command cannot be executed anymore (except after a full reset with PUK). The regular SecureChannel (with pairing) is active and PIN and PUK are initialized and validated.
Status Words
SW |
Description |
|---|---|
|
Success |
|
Applet already initialized |
|
Invalid data (bad pubkey, non-digits in PIN, wrong decrypted length) |
|
Decryption invalid (wrong encryption key or bad padding) |
OPEN SECURE CHANNEL
Request APDU
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
Key idx |
|
|
Client session public key |
This APDU command is the first step to establish a Secure Channel session. A session is aborted when the application is deselected, either directly or because of a card power off or tear away.
In a standard use of the applet, just after selecting the applet, the client opens a secure channel using their PairingKey for this card. The user generates an EC key pair for the session and provides the public key part in this command.
P1 values
P1 |
Description |
|---|---|
|
Pairing key slot 0 |
|
Use |
When P1=0xFF, the PUK can be used as a pairing key. This is useful when the user has lost
their pairing info: the PUK hashed 32 times with SHA256 can always be used as a pairing key.
Request Data
Field |
Size |
Description |
|---|---|---|
Client session public key |
65B |
EC 256r1 uncompressed point ( |
Response Data — 32 bytes
The card generates a random 256-bit salt which is sent to the client.
Field |
Size |
Description |
|---|---|---|
Session salt |
32B |
Random salt for key derivation |
Key derivation — performed identically by both card and client:
ECDHsecret = PrivateKey . CounterpartPublicKey (x-coordinate)
For the card: ECDHsecret = SessionCardPrivateKey . SessionUserPublicKey (x)
For the user: ECDHsecret = SessionUserPrivateKey . SessionCardPublicKey (x)
AESkey | MACkey = SHA512( ECDHsecret | PairingKey | Salt )
[0..31] = AESkey (256-bit encryption key)
[32..63] = MACkey (256-bit MAC key)
The SessionCardPublicKey is received in the GET CARD CERTIFICATE response. The
SessionUserPublicKey is transmitted to the card in this command.
For the mutual authentication, any IV can be used for the first encrypted message. Then the IV to use is the latest MAC field received from the counterpart.
Status Words
SW |
Description |
|---|---|
|
Success |
|
Invalid P1 (unknown pairing key index) |
|
Data is not a valid public key |
MUTUALLY AUTHENTICATE
Request APDU (encrypted)
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
var |
MAC | Encrypted random |
This APDU command allows both parties to verify that the keys generated in the
OPEN SECURE CHANNEL step are matching and thus guarantee authentication of the counterpart.
The data sent by both parties is a 256-bit random number. The APDU data is sent encrypted
with the keys generated in the OPEN SECURE CHANNEL step. Each party must verify the MAC
of the received APDU. If the MAC and padding can be verified, it means that both parties are
using the same keys.
Only after this step has been executed can the secure channel be considered to be opened and other commands sent.
Request Data (plaintext before encryption)
Field |
Size |
Description |
|---|---|---|
Random |
32B |
256-bit random number |
Response Data (plaintext after decryption) — 32 bytes
Field |
Size |
Description |
|---|---|---|
Random |
32B |
256-bit random number from the card |
If the authentication fails the card responds with 0x6982. In this case the
OPEN SECURE CHANNEL command must be repeated to generate new keys.
Note
Once the secure channel is opened, for commands requiring a secure channel, the status
error codes are sent back as encrypted data through the tunnel. The last 2 bytes of the
decoded data are the command status word, and the “outer plain” data are always 0x9000.
The real status word is the one being encrypted in the secure channel inner data payload.
Status Words
SW |
Description |
|---|---|
|
Success |
|
Previous APDU was not |
|
Authentication failed or data is not 256-bit |
CHANGE PAIRING KEY
Request APDU (encrypted)
CLA |
INS |
P1 |
P2 |
LC |
Data |
|---|---|---|---|---|---|
|
|
|
|
var |
MAC | Encrypted data |
Preconditions: Secure Channel must be opened.
Update the SecureChannel PairingKey for a new one. The PUK is required for authorization.
In case the current pairing key was lost, preventing the opening of any secure channel (needed
to change it), one has to use the PUK derived key as the pairing key (key index 0xFF in
OPEN SECURE CHANNEL). The PUK pairing slot can’t be changed this way, but it is
automatically updated when the PUK is changed.
Request Data (plaintext)
Field |
Size |
Description |
|---|---|---|
New PairingKey |
32B |
New pairing secret |
PUK |
12B |
Current PUK for authorization |
Total plaintext: 44 bytes.
Status Words
SW |
Description |
|---|---|
|
Success |
|
Data is not 44 bytes |
|
Wrong PUK (x = remaining tries before power cycle) |
|
P1 is not 0 |