status-keycard/CLIENT_NOTES.md

140 lines
11 KiB
Markdown
Raw Normal View History

2017-12-05 14:02:30 +00:00
# Notes for client implementation
2018-12-04 07:20:43 +00:00
This document should help client application developers to integrate support for the Status Keycard in their applications.
2017-12-05 14:02:30 +00:00
## Low-level communication
2018-12-04 07:20:43 +00:00
The Status Keycard is a JavaCard application and as such is deployed on ISO7816 compatible SmartCards. Communication
2017-12-05 14:02:30 +00:00
will happen exchanging APDUs using either the T=0 or preferably the T=1 protocol. Most operating systems use an
implementation of [this Microsoft API](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx#smart_card_functions)
like [PCSC lite](http://pcsclite.alioth.debian.org/pcsclite.html). Your language of choice might provide bindings for
this library or an higher-level API built on top of it.
A few things to keep in mind when communicating with SmartCards
1. The card can never initiate communication. The card only responds to commands sent from the client.
2. When connecting to the card using SCardConnect, always use the SCARD_SHARE_EXCLUSIVE mode to avoid OS services
messing with the card while you are using it.
3. A SmartCard can have multiple applications installed. If using only the basic channel (recommended for our use-case)
only a single application can be selected at the time. This must be done explicitly on each reset by issuing the
2018-12-04 07:20:43 +00:00
SELECT command with the AID of the keycard application.
2017-12-05 14:02:30 +00:00
4. Since we are not using extended APDUs, the maximum size of the data field of the APDU is 255 bytes.
## Wallet management and security
2018-12-04 07:20:43 +00:00
Before thinking about the application-specific communication (i.e: actually using the Keycard applet to derive keys and
2017-12-05 14:02:30 +00:00
sign transactions) the client must be able to actually talk with the card using its [Secure Channel protocol](SECURE_CHANNEL.MD).
2018-12-04 07:20:43 +00:00
The first step, after an APDU channel is available is to [SELECT](APPLICATION.MD) the Keycard application on the card.
The Keycard will return its Instance UID and public key for Secure Channel establishment. Although both values are unique,
only use the Instance UID to identify the Keycard since only this value is guaranteed not to change over the lifetime of
the card. If your application has already performed pairing with the Keycard with this Instance UID, you can establish
2017-12-05 14:02:30 +00:00
a Secure Channel session (described later). Otherwise you should proceed with pairing.
2018-07-18 10:48:00 +00:00
For pairing, the client must show that it knows the pairing code. For this reason the user must be prompted
2017-12-05 14:02:30 +00:00
to insert said code. The result of pairing is a secret value shared by both parties which is used during the session key
generation on establishment of a Secure Channel. The client must permanently store the association of the Instance UID,
the secret generated during pairing and the index which the card assigned to this client. Said index must be provided
when opening a Secure Channel so that the card knows with which client it is speaking. Since the pairing secret is
sensitive data, it should be stored as securely as possible, eventually with password protection. Losing this secret
2018-11-14 12:28:41 +00:00
allows an attacker to pose either as the client to the card or as the card to the client. It does not allow however
decrypting older communication and perform passive attacks.
2017-12-05 14:02:30 +00:00
Note that the card can only pair with a limited number of clients (currently 5). Unpairing allows to replace old clients
with new ones.
When a card and a client are paired, they can establish a Secure Channel session. The Secure Channel provides the
authentication, confidentiality and integrity guarantees which the plain APDU channel does not provide. This phase is
divided in 2 steps:
1. Sending an OPEN SECURE CHANNEL APDU to generate session keys
2. Sending a MUTUALLY AUTHENTICATE command to verify that both parties have the same keys.
After this happens, all further communication will be encrypted and with a MAC providing integrity and authentication
for each APDU.
The card and client must abort the Secure Channel session at any time if MAC verification fails, since this means that
the APDU has been corrupted, possibly as a result of an attack attempt. The card also resets the session when the
application is (re-)selected or the card is reset (or on power loss).
Note that while pairing requires user input, opening a secure channel session does not.
## User authentication
Aside from the Secure Channel-related APDUs, the application also provides commands to authenticate the user (as opposed
as authenticating the client) and to manage the user's authentication credentials. These are the VERIFY PIN, CHANGE PIN
and UNBLOCK PIN commands. The client is not supposed to store the PIN and verification should always require user input.
After verifying the PIN the card considers to the user to be authenticated for the entire application session. The
application session ends on card reset, power loss or application re-selection. The client should keep track of whether
the user has been authenticated or not in order to avoid repeatedly asking for the PIN. The card will respond with an
error to any APDU requiring user authentication if the user has not been authenticated in the current application
session.
2018-12-04 07:20:43 +00:00
## Keycard features and workflow
2017-12-05 14:02:30 +00:00
Now that the client can finally talk with the applet and provide user authentication facilities, it is time to look on
2018-12-04 07:20:43 +00:00
how to actually use the Keycard. The Keycard applet allows management of a single HD wallet as described in the
2018-11-14 12:28:41 +00:00
[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) specifications. It provides the following features
2017-12-05 14:02:30 +00:00
1. Source of entropy to generate master seeds (GENERATE MNEMONIC). No PIN required (has no effect on card state).
2. Loading of master key (LOAD KEY). PIN required. The same command can be used to replace the loaded master key.
3. Set the key to be used for signing by deriving from the master key (DERIVE KEY). PIN required unless a PIN-less path
is set.
4. Sign hashes (SIGN). PIN required unless the current key path is set as PIN-less. Note that the Keccak-256 hash of the
transaction is signed and must be generate off-card. The actual transaction data are not sent to the card.
5. Setting/Unsetting a PIN-less path (SET PINLESS PATH). PIN required. It allows disabling PIN authentication for a
specific key path.
2018-11-14 12:28:41 +00:00
6. Exporting keys (EXPORT KEY). PIN required. Exporting the private key is only allowed for specific keys.
2017-12-05 14:02:30 +00:00
Additionally the GET STATUS command (no PIN required) allows retrieving information about the card status and the
current key path.
The card is shipped with no keys on-board. In this state the SIGN and DERIVE KEY commands will not work. The client can
detect when a card has no keys by issuing a GET STATUS command. In this case it could prompt the user to either enter a
mnemonic passphrase or allow the card to generate a new one (GENERATE MNEMONIC is issued). In both cases, the mnemonic
must be converted to a master key from the client and loaded to the card using the LOAD KEY command.
The card stores the master key permanently, until replaced. Additionally the card has the concept of current key and
current key path. The current key is the one used during the SIGN command. The current key equals the master key when
new keys are loaded and the current key path is empty. Using the DERIVE KEY command however, the client can move through
the tree of the HD wallet. This command derives the key as described in BIP32 and sets both the current key and current
key path according to its arguments and the results of key derivation. Using the GET STATUS command the client can
always know the current key path and thus decide if further derivation is needed or not before issuing a SIGN command.
The current key persists across application sessions (including in case of power loss). A flag in the DERIVE KEY command
decides whether derivations restarts from the master key or is performed on the current key, extending the current path.
The current maximum key path depth is 10 levels under the master key.
The SIGN command signs the Keccak-256 hash provided in the APDU's data field using the current key. The client must
calculate the hash of the transaction off-card. The signature (r,s) and the public key used to verify it are both
returned. The client must use this to calculate 'v' and format the signature as required by Ethereum (v,r,s) if it
wishes to submit the transaction to the network.
Another feature is the ability to define a key path which requires no PIN authentication for signing. When a PIN-less
path is set the DERIVE KEY command never requires a PIN (because there must be a PIN-less way to reach that path). Note
that setting the PIN-less key path does not automatically set the current key path to the PIN-less one. You still need
to use DERIVE KEY to get there. Only when the current key path matches the PIN-less one the SIGN command will not require
PIN authentication. The master key can never be used without PIN.
2018-11-14 12:28:41 +00:00
Finally, some keys can be exported (after PIN authentication). The public key can be exported for any key, while the
private one only for specific keys. The EXPORT KEY command does not automatically do key derivation. This means that you
must use DERIVE KEY before exporting the desired key.
2017-12-05 14:02:30 +00:00
## Additional notes
1. The SIGN command also allows signing data directly instead of a precomputed hash (if P1 is 0x00 instead of 0x01),
transmitted over several blocks if needed. This feature is never used because this signature uses SHA-256 instead of
Keccak-256 (which is not available) making it useless. This mode of operation has been implemented before the current
one with precomputed hashes. It remains because if we get hold of a hardware platform implementing Keccak-256, or we
decide to implement it in software, we might want to operate this way.
2018-11-14 12:28:41 +00:00
2. Communication has less overhead when using the T=1 protocol. However the card/reader/os combination I have seems to
2017-12-05 14:02:30 +00:00
only work with T=0 (although all claim to support T=1). Contactless readers always emulate T=1 when operated through
the PC/SC interface.
2018-11-14 12:28:41 +00:00
3. You can refer to the tests for examples of communication with the card. The manual-only signTransactionTest test in
2017-12-05 14:02:30 +00:00
particular generates a real transaction, signs it and submits it to the network.
2018-11-14 12:28:41 +00:00
4. If you test your client against our fork of jCardSim instead of a real card, keep in mind that it supports unassisted
2017-12-05 14:02:30 +00:00
key derivation, but you shouldn't use it because, as explained above, it wouldn't work on the card.
2018-11-14 12:28:41 +00:00
5. If using jCardSim, only use our fork, since some of the needed algorithms are unsupported in the upstream version.
6. The pairing code is a randomly generated password (using whatever password generation algorithm is desired). This
2018-12-04 13:13:27 +00:00
password must be converted to a 256-bit key using PBKDF2 with the salt "Keycard Pairing Password Salt" and 50000 iterations.
2017-12-05 14:02:30 +00:00