2017-09-22 09:14:15 +00:00
# Status Wallet Application
2018-11-07 12:17:17 +00:00
## Version
Version numbers are in the form major.minor. An major revision increment indicates the presence of breaking changes as
compared to the previous released version. This is version 2.0 of the specs (unreleased).
### Changes since 1.2
* **BREAKING** Removed assisted key derivation
2018-11-07 13:02:21 +00:00
* **BREAKING** Removed plain data signing, now only 32-byte long hashes can be signed
2018-11-12 08:09:36 +00:00
* Added internal key generation (GENERATE KEY)
* Added the ability to customize the NDEF response (SET NDEF)
2018-11-07 12:17:17 +00:00
2017-09-22 09:14:15 +00:00
## Overview
This application allows signing of transactions using ECDSA with a keyset stored on card. The keys are defined on the
SECP256k1 curve. Signing is available only after PIN authentication.
The keyset used for signing is generated externally and loaded on card. This is also only available after PIN
authentication.
Before any application command is processed, a Secure Channel session must be established as specified in the
[SECURE_CHANNEL.MD](SECURE_CHANNEL.MD) document.
2018-10-10 08:39:51 +00:00
## INITIALIZATION
After installation, the applet is not ready to operate and is in a pre-initializaed state. In this state the applet can
only process the SELECT and INIT command. The INIT command is used to personalize the PIN, PUK and pairing secret, which
must be generated off-card.
2017-09-22 09:14:15 +00:00
## PIN
2018-10-10 08:39:51 +00:00
The PIN length is fixed at 6 digits. After 3 failed authentication attempts the PIN is blocked and authentication is not
possible anymore. A blocked PIN can be replaced and unblocked using a PUK. The PUK is a 12-digit number. After 5 failed
attempts to unblock the applet using the PUK, the PUK is blocked, meaning the wallet is lost.
2017-09-22 09:14:15 +00:00
After authentication, the user remains authenticated until the application is either deselected or the card is reset.
2017-10-26 09:11:49 +00:00
Authentication with PIN is a requirement for most commands to succeed.
2017-09-22 09:14:15 +00:00
2018-10-10 08:39:51 +00:00
The PIN and PUK can be changed by the user after authentication.
2017-09-22 09:14:15 +00:00
## Keys & Signature
2018-01-23 11:31:05 +00:00
The application allows loading and replacing of a single EC keyset, defined on the SECP256k1 curve. The keyset can contain
2017-10-19 13:37:14 +00:00
a 32-byte chain code to further derive keys according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
specifications. This keyset is used to sign transactions. When the applet is first installed, no keyset is available so
signing will fail. It is necessary to first load the keyset in order for the application to be fully operational.
2017-09-22 09:14:15 +00:00
Signing of transactions is done by uploading the data in blocks no larger than 255 bytes (including the overhead caused
2017-10-26 09:11:49 +00:00
by the Secure Channel). Segmentation must be handled at the application protocol. Another option is to sign the hash
of the transaction, with the hash being calculated off-card. Signing generally requires the PIN to be authenticated,
however the user can set a special key path which requires no authentication.
2017-09-22 09:14:15 +00:00
2017-10-09 12:06:59 +00:00
## APDUs
2017-09-22 09:14:15 +00:00
These are the commands supported by the application. When a command has a precondition clause and these are not met the
2017-10-09 12:06:59 +00:00
SW 0x6985 is returned. All tagged data structures are encoded in the [BER-TLV format](http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-d.aspx)
2017-09-22 09:14:15 +00:00
### SELECT
* CLA = 0x00
* INS = 0xA4
* P1 = 0x04
* P2 = 0x00
* Data = 53746174757357616C6C6574417070 (hex)
2018-10-10 08:39:51 +00:00
* Response = Application Info Template or ECC public key.
2017-11-15 09:55:41 +00:00
Response Data format:
- Tag 0xA4 = Application Info Template
2018-04-22 10:39:10 +00:00
- Tag 0x8F = Instance UID (16 bytes)
2017-11-15 09:55:41 +00:00
- Tag 0x80 = ECC public Key
2018-04-22 10:39:10 +00:00
- Tag 0x02 = Application Version (2 bytes)
2018-06-25 09:13:06 +00:00
- Tag 0x02 = Number of remaining pairing slots (1 byte)
2018-10-01 13:41:19 +00:00
- Tag 0x8E = Key UID (0 or 32 bytes)
2017-09-22 09:14:15 +00:00
The SELECT command is documented in the ISO 7816-4 specifications and is used to select the application on the card,
2017-11-15 09:55:41 +00:00
making it the active one. The data field is the AID of the application. The response is the Application Info template
which contains the instance UID (which can be used by the client to keep track of multiple cards) and the public key
2018-04-22 10:39:10 +00:00
which must be used by the client to establish the Secure Channel. Additionally it contains the version number of the
application, formatted on two bytes. The first byte is the major version and the second is the minor version
2018-06-25 09:13:06 +00:00
(e.g: version 1.1 is formatted as 0x0101). The number of remaining pairing slots is also included in the response.
2017-09-22 09:14:15 +00:00
2018-10-01 13:41:19 +00:00
The Key UID can be either empty (when no key is loaded on card) or the SHA-256 hash of the master public key.
2018-10-10 08:39:51 +00:00
When the applet is in pre-initializated state, it only returns the ECC public key, BER-TLV encoded with tag 0x80.
### INIT
* CLA = 0x80
* INS = 0xFE
* P1 = 0x00
* P2 = 0x00
* Data = EC public key (LV encoded) | IV | encrypted payload
2018-11-07 13:02:21 +00:00
* Response SW = 0x9000 on success, 0x6D00 if the applet is already initialized, 0x6A80 if the data is invalid
2018-10-10 08:39:51 +00:00
This command is only available when the applet is in pre-initialized state and successful execution brings the applet in
the initialized state. This command is needed to allow securely storing secrets on the applet at a different moment and
place than installation is taking place. Currently these are the PIN, PUK and pairing password.
The client must take the public key received after the SELECT command, generate a random keypair and perform 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.
They payload is the concatenation of the PIN (6 digits/bytes), PUK (12 digits/bytes) and pairing secret (32 bytes).
2018-10-10 10:42:34 +00:00
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.
After successful execution, this command cannot be executed anymore. The regular SecureChannel (with pairing) is active
and PIN and PUK are initialized.
2017-09-22 09:14:15 +00:00
### OPEN SECURE CHANNEL
The OPEN SECURE CHANNEL command is as specified in the [SECURE_CHANNEL.MD](SECURE_CHANNEL.MD).
2017-11-17 13:12:28 +00:00
### MUTUALLY AUTHENTICATE
The MUTUALLY AUTHENTICATE command is as specified in the [SECURE_CHANNEL.MD](SECURE_CHANNEL.MD).
2017-11-14 12:50:07 +00:00
### PAIR
2018-06-25 09:13:06 +00:00
The PAIR command is as specified in the [SECURE_CHANNEL.MD](SECURE_CHANNEL.MD). The shared secret is 32 bytes long. The
way the secret is generated is not within the scope of this document because the applet accepts the already generated
secret as an installation parameter. However the card issuer and clients must agree on the way it is generated for
interoperability reasons.
If the code is meant to be input manually, a random, variable length alphanumeric password to be used in conjuction with
an algorithm such as scrypt or PBKDF2 is suggested. If another input mechanism is foreseen (such as QR-code scanning),
then the sequence should be composed of random bytes from a secure source of randomness.
2017-11-14 12:50:07 +00:00
### UNPAIR
The UNPAIR command is as specified in the [SECURE_CHANNEL.MD](SECURE_CHANNEL.MD). The user PIN must be verified for the
command to work.
2017-10-09 14:12:21 +00:00
### GET STATUS
2017-10-26 09:11:49 +00:00
2017-10-09 14:12:21 +00:00
* CLA = 0x80
* INS = 0xF2
2017-10-25 11:29:13 +00:00
* P1 = 0x00 for application status, 0x01 for key path status
2017-10-09 14:12:21 +00:00
* P2 = 0x00
2017-10-25 11:29:13 +00:00
* Response SW = 0x9000 on success, 0x6A86 on undefined P1
* Response Data = Application Status Template or Key Path
2018-11-07 12:17:17 +00:00
* Preconditions: Secure Channel must be opened
2017-10-09 14:12:21 +00:00
Response Data format:
2017-10-25 11:29:13 +00:00
if P1 = 0x00:
2017-10-09 14:12:21 +00:00
- Tag 0xA3 = Application Status Template
2018-01-17 13:29:38 +00:00
- Tag 0x02 = PIN retry count (1 byte)
- Tag 0x02 = PUK retry count (1 byte)
2018-10-01 08:58:44 +00:00
- Tag 0x01 = 0xff if key is initialized, 0 otherwise
2017-10-09 14:12:21 +00:00
2017-10-25 11:29:13 +00:00
if P1 = 0x01
- a sequence of 32-bit numbers indicating the current key path. Empty if master key is selected.
2018-11-12 08:09:36 +00:00
### SET NDEF
* CLA = 0x80
* INS = 0xF3
* P1 = 0x00
* P2 = 0x00
* Data = the data to store
* Response SW = 0x9000 on success, 0x6A80 on invalid data
* Preconditions: Secure Channel must be opened, PIN must be verified
Used to set the content of the data file owned by the NDEF applet. This allows changing the behavior of Android and other
clients when tapping the card with no open client. As an example, it could be used to launch a specific wallet software.
The data is stored as is. A check is made that the first 2 bytes, read as a MSB first short, are equal to the Lc field
minus 2 (the length of the field itself). This does not ensure that the NDEF record is valid, but ensures that no out
of bound access happens.
2017-09-22 09:14:15 +00:00
### VERIFY PIN
* CLA = 0x80
* INS = 0x20
* P1 = 0x00
* P2 = 0x00
* Data = the PIN to be verified
* Response SW = 0x9000 on success, 0x63CX on failure, where X is the number of attempt remaining
* Preconditions: Secure Channel must be opened
Used to verify the user PIN. On correct PIN entry the card returns 0x9000, the retry counter is reset and the PIN is
marked as authenticated for the entire session (until the application is deselected or the card reset/teared). On
error, the number of remaining retries is decreased and the SW 0x63CX, where X is the number of available retries is
returned. When the number of remaining retries reaches 0 the PIN is blocked. When the PIN is blocked this command
always returns 0x63C0, even if the PIN is inserted correctly.
### CHANGE PIN
* CLA = 0x80
* INS = 0x21
2018-10-10 10:42:34 +00:00
* P1 = PIN identifier
2017-09-22 09:14:15 +00:00
* P2 = 0x00
* Data = the new PIN
2018-10-10 10:42:34 +00:00
* Response SW = 0x9000 on success, 0x6A80 if the PIN format is invalid, 0x6A86 if P1 is invalid
2017-09-22 09:14:15 +00:00
* Preconditions: Secure Channel must be opened, user PIN must be verified
2018-10-10 10:42:34 +00:00
Used to change a PIN or secret. In case of invalid format, the code 0x6A80 is returned. If the conditions match, the PIN
or secret is updated. The no-error SW 0x9000 is returned.
P1:
* 0x00: User PIN. Must be 6-digits. The updated PIN is authenticated for the rest of the session.
* 0x01: Applet PUK. Must be 12-digits.
* 0x02: Pairing secret. Must be 32-bytes long. Existing pairings are not broken, but new pairings will need to use the
new secret.
2017-09-22 09:14:15 +00:00
### UNBLOCK PIN
* CLA = 0x80
* INS = 0x22
* P1 = 0x00
* P2 = 0x00
* Data = the PUK followed by the new PIN
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid
* Preconditions: Secure Channel must be opened, user PIN must be blocked
2017-10-09 12:06:59 +00:00
Used to unblock the user PIN. The data field must contain exactly 18 numeric digits, otherwise SW 0x6A80 is returned.
The first 12 digits are the PUK and the last 6 are the new PIN. If the PUK is correct the PIN is changed to the supplied
one, it is unblocked and authenticated for the rest of the session. The status code 0x9000 is returned. When the PUK is
wrong, the number of remaining retries is decreased and the SW 0x63CX, where X is the number of available retries is
2017-09-22 09:14:15 +00:00
returned. When the number of remaining retries reaches 0 the PUK is blocked. When the PUK is blocked this command
always returns 0x63C0, even if the PUK is inserted correctly. In this case the wallet is effectively lost.
2017-09-22 09:41:43 +00:00
2017-09-25 08:27:55 +00:00
### LOAD KEY
2017-09-22 09:41:43 +00:00
* CLA = 0x80
* INS = 0xD0
2017-10-09 12:06:59 +00:00
* P1 = key type
2017-09-25 08:27:55 +00:00
* P2 = 0x00
2017-09-22 09:41:43 +00:00
* Data = the key data
2018-11-07 12:17:17 +00:00
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid, 0x6A86 if P1 is invalid
2018-10-01 13:41:19 +00:00
* Response Data = the key UID, defined as the SHA-256 of the public key
2017-09-22 09:41:43 +00:00
* Preconditions: Secure Channel must be opened, user PIN must be verified
2017-10-09 12:06:59 +00:00
P1:
* 0x01 = ECC SECP256k1 keypair
* 0x02 = ECC SECP256k1 extended keypair
2017-10-11 07:55:04 +00:00
* 0x03 = Binary seed as defined in [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
2017-09-25 07:53:20 +00:00
2017-10-09 12:06:59 +00:00
Data:
If P1 is 0x01 or 0x02
2017-09-25 08:27:55 +00:00
- Tag 0xA1 = keypair template
2018-11-07 12:17:17 +00:00
- Tag 0x80 = ECC public key component (can be omitted)
2017-10-06 12:08:07 +00:00
- Tag 0x81 = ECC private key component
2017-10-09 12:06:59 +00:00
- Tag 0x82 = chain code (if P1=0x02)
If P1 is 0x03 a 64 byte sequence generated according to the BIP39 specifications is expected. The master key will be
2017-10-19 13:37:14 +00:00
generated according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) specifications. This
is only supported if the hardware supports public key derivation.
2017-09-25 07:53:20 +00:00
This command is used to load or replace the keypair used for signing on the card. This command always aborts open
2017-10-09 12:06:59 +00:00
signing sessions, if any. Unless a DERIVE KEY is sent, a subsequent SIGN command will use this keypair for signature.
### DERIVE KEY
* CLA = 0x80
* INS = 0xD1
2017-10-19 13:37:14 +00:00
* P1 = derivation options
2018-11-07 12:17:17 +00:00
* P2 = 0x00
2017-10-19 13:37:14 +00:00
* Data = a sequence of 32-bit integers (most significant byte first). Empty if the master key must be used. On assisted
derivation contains a public key when P2 = 0x02.
2018-11-07 12:17:17 +00:00
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid, 0x6984 if one of the components in the path
2018-01-23 10:41:30 +00:00
generates an invalid key, 0x6B00 if derivation from parent keys is selected but no valid parent key is cached.
2017-11-20 14:42:12 +00:00
* Preconditions: Secure Channel must be opened, user PIN must be verified (if no PIN-less key is defined), an extended
keyset must be loaded
2017-10-09 12:06:59 +00:00
2017-10-18 11:30:56 +00:00
This command is used before a signing session to generate a private key according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
2017-10-19 13:37:14 +00:00
specifications. This command always aborts open signing sessions, if any. The generated key is used for all subsequent
2018-11-07 12:17:17 +00:00
SIGN sessions. The maximum depth of derivation from the master key is 10. Any attempt to get deeper results in 0x6A80
being returned. The BIP32 specifications define a few checks which must be performed on the derived keys. If these fail,
the 0x6984 is returned and the invalid key is discarded. A client should perform a GET STATUS command to get the actual
current key path and resume derivation using a different path.
2017-10-19 13:37:14 +00:00
2018-01-23 10:41:30 +00:00
The ability to start derivation from the parent keys allows to more efficiently switch between children of the same key.
Note however that only the immediate parent of the current key is cached so you cannot use this to go back in the
hierarchy. If no valid parent key is available the status code 0x6B00 will be returned.
2017-10-19 13:37:14 +00:00
P1:
2018-11-07 12:17:17 +00:00
* bit 0-5 = reserved
2018-01-23 10:41:30 +00:00
* bit 7-6:
- 00 derive from master keys
- 01 derive from parent keys
- 10 derive from current keys
- 11 reserved
2017-10-19 13:37:14 +00:00
2017-10-09 12:06:59 +00:00
### GENERATE MNEMONIC
* CLA = 0x80
* INS = 0xD2
* P1 = checksum size (between 4 and 8)
* P2 = 0x00
* Response SW = 0x9000 on success. 0x6A86 if P1 is invalid.
* Response Data = a sequence of 16-bit integers (most significant byte first).
* Preconditions: Secure Channel must be opened
Used to generate a mnemonic according to the algorithm specified in [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).
The returned data is a list of 16-byte integers which should be used as indexes in a wordlist to generate the
human-readable mnemonic. Each integer can have a value from 0 to 2047.
2017-09-25 07:53:20 +00:00
2018-10-01 08:58:44 +00:00
### REMOVE KEY
* CLA = 0x80
* INS = 0xD3
* P1 = 0x00
* P2 = 0x00
* Response SW = 0x9000 on success.
* Preconditions: Secure Channel must be opened, user PIN must be verified
Removes the key from the card, bringing it back to an uninitialized state. No signing operation is possible after this
command until a new LOAD KEY command is performed.
2018-11-07 10:56:06 +00:00
### GENERATE KEY
* CLA = 0x80
* INS = 0xD4
* P1 = 0x00
* P2 = 0x00
* Response SW = 0x9000 on success.
* Response Data = the key UID, defined as the SHA-256 of the public key
* Preconditions: Secure Channel must be opened, user PIN must be verified
Generates and stores keys completely on card. The state of the card after execution is the same as if a LOAD KEY command
had been performed.
2017-09-25 07:53:20 +00:00
### SIGN
* CLA = 0x80
* INS = 0xC0
2018-11-07 13:02:21 +00:00
* P1 = 0x00
* P2 = 0x00
* Data = the hash to sign
* Response = public key and the signature
* Response SW = 0x9000 on success, 0x6A80 if the data is not 32-byte long
2017-11-20 14:42:12 +00:00
* Preconditions: Secure Channel must be opened, user PIN must be verified (or a PIN-less key must be active), a valid
keypair must be loaded
2017-09-25 07:53:20 +00:00
2017-10-06 12:08:07 +00:00
Response Data format:
- Tag 0xA0 = signature template
- Tag 0x80 = ECC public key component
- Tag 0x30 = ECDSA Signature
- Tag 0x02 = R value
- Tag 0x02 = S value
2018-11-07 13:02:21 +00:00
Returns the ECDSA signature of the hash. The hash can be calculated using any algorithm, but must be 32-bytes long. The
signature is returned in a signature template, containing the public key associated to the signature and the signature
itself. For usage on the blockchain, you will need to calculate the recovery ID in addition to extracting R and S.
To calculate the recovery ID you need to apply the same algorithm used for public key recovery from a transaction starting
with a recovery ID of 0. If the public key matches the one returned in the template, then you have found the recovery ID,
otherwise you try again by incrementing the recovery ID.
2017-10-26 09:11:49 +00:00
### SET PINLESS PATH
* CLA = 0x80
* INS = 0xC1
* P1 = 0x00
* P2 = 0x00
* Data = a sequence of 32-bit integers
* Response SW = 0x9000 on success, 0x6A80 if data is invalid
* Preconditions: Secure Channel must be opened, user PIN must be verified
Sets the given sequence of 32-bit integers as a PIN-less path. When the current derived key matches this path, SIGN
2017-10-26 11:15:40 +00:00
will work even if no PIN authentication has been performed. An empty sequence means that no PIN-less path is defined.
### EXPORT KEY
* CLA = 0x80
* INS = 0xC2
2018-01-19 09:04:55 +00:00
* P1 = key path index
* P2 = export options
* Response SW = 0x9000 on success, 0x6A86 if P1 or P2 are wrong
2017-10-26 11:15:40 +00:00
* Response Data = key pair template
* Preconditions: Secure Channel must be opened, user PIN must be verified, the current key path must match the one of
the key selected through P1
2018-01-19 09:04:55 +00:00
P1:
0x00 = Any key
2018-09-18 08:26:24 +00:00
0x01 = Non-wallet key
2018-01-19 09:04:55 +00:00
P2:
0x00 = private and public key
0x01 = public key only
2017-10-26 11:15:40 +00:00
Response Data format:
- Tag 0xA1 = keypair template
- Tag 0x80 = ECC public key component
2018-01-19 09:04:55 +00:00
- Tag 0x81 = ECC private key component (if P2=0x00)
2017-10-26 11:15:40 +00:00
2018-09-18 08:26:24 +00:00
This command exports the current public and private key if and only if the current key path matches the conditions
dictated by the given P1 parameter. This currently allows exporting any key whose last path component has a key index
with the two most significant bits set (that is, matches the 0xc0000000 mask). No key in this range should be used for
wallet accounts, even as intermediate path component. These keys are meant for client-specific use such as the Whisper key.
2018-01-19 09:04:55 +00:00
The special index 0x00 indicates any path, which means the current key will always be exported regardless of its actual
path. This works however only in combination with P2=0x01, so only the public key will be exported.