Keycard is an open-source hardware wallet for managing private keys and signing transactions. It takes the form-factor of a credit-card and uses NFC technology for a contactless experience with the Status mobile app.
The previous article gave an overview of the Keycard technology and touched briefly upon the security aspects. This article takes a deeper-dive specifically into the various underlying security features.
The threat model considered is quite broad. The confidentiality, integrity and availability of Status app user’s wallet assets and chat messages should be preserved even if the attacker has physical possession of the user’s phone, Keycard or both. The attacker may also have access to one or more of the authentication tokens required with the Keycard.
Therefore, every aspect of Keycard has been designed with the highest security in mind. We describe them in the below six categories of cryptography, access control, smart card security, communication security, applet security and transparency.
The primary use case for Keycard is a hardware crypto wallet for which it implements a BIP-32 Hierarchical Deterministic (HD) wallet. The foundation of such a wallet is what is known as a seed phrase.
This is typically a 12-24 worded BIP-39 phrase which is randomly chosen from a list of 2048 words. This provides the entropy required to obtain a binary seed which is generated using the PBKDF2 function. The binary seed is then used to generate the asymmetric key pairs for the BIP-32 wallet. The user is expected to write down the seed phrase somewhere safe because it could be required later for restoring the keys on another card or phone or wallet.
In the current Status implementation, the seed phrase consists of 12 words generated on the Status mobile app and so provides 128-bits of entropy (each choice of word provides 11-bits, because 2^11 = 2048; 12 * 11 = 132; 128-bits of entropy + 4-bits for checksum = 132). It is on the Keycard roadmap to provide an option for a 24-word seed phrase which gives an increased entropy of 256-bits.
The current implementation generates the seed phrase on the Status app and loads the corresponding binary seed into Keycard for generating the BIP-32 master key. In a future release, it is planned to generate this seed phrase on the Keycard itself (using GENERATE-MNEMONIC API). In either case, the seed phrase has to be accessible by the Status app during setup so it can be displayed to the user for backing it up. Once the user backs up the seed phrase, it is deleted from the Status app and can never be accessed again. The user is encouraged to do this right at the setup phase itself so that an attacker cannot access the seed phrase from the Status app.
Wallet and Chat Keys
The wallet key pair is generated on the standard BIP-44 m/44’/60’/0’/0/0 path. The chat key pair is created on m/43’/60’/1581’/0/0 path as per EIP-1581 and is exported from the Keycard to the Status app so that the app can automatically encrypt and decrypt every chat message without requiring the user to enter passcode (see next section) each time which would be cumbersome.
The chat messages are saved in the Status app database by encrypting with a key derived from the key pair at m/43’/60’/1581’/1/0. This happens only if the user uses Keycard with their Status app. Otherwise, the chat messages database is encrypted using a key derived from the password.
This has an implication on recovery of keys. Currently, the Status app doesn’t support changing of the password because it requires the re-encryption of the database. So, forgetting the password means one can only recover the wallet assets from the seed phrase but loses the chat history.
However, when Keycard is used with Status app, the key recovery upon the user losing the Keycard can recover both wallet assets and chat history because the chat database is encrypted with a key derived from the seed phrase (as there is no password). This will be an additional benefit to using Keycard with Status app. Note that recovery is currently not implemented but is planned for a future release.
The access to Keycard is protected with a passcode and a Personal-Unlocking-Key code (PUK code). Keycard itself can be used for authenticating to the Status app.
Passcode: Passcode is a 6-digit numeric code which is created during setup. The user is required to enter this code to authorise every wallet transaction. Entering the incorrect passcode three times freezes the Keycard which then requires the user to enter the PUK code to unfreeze the card and reset the passcode. This prevents an attacker who has both the user's phone and Keycard from executing unauthorised transactions without knowing the passcode.
PUK code: PUK code is a 12-digit numeric code which is displayed only once during setup. The user is expected to write this down somewhere safe. This is required to reset the passcode when the Keycard freezes on entering the incorrect passcode three times. This prevents an attacker from brute-forcing the passcode beyond three attempts. Entering the incorrect PUK code five times blocks the card permanently.
Two-Factor Authentication (2FA): With Keycard, users can sign-in to the Status app using the Keycard instead of a password. The Keycard has to be tapped on the phone and then the 6-digit passcode entered to get into the Status app. This effectively brings in two-factor authentication to Status app by combining what-you-have, i.e. Keycard, with what-you-know, i.e. associated passcode.
With the use of Keycard, one no longer has the option of using a password like earlier. If one wants to use Keycard only for signing transactions but not for 2FA login to Status app, one has to rely on the phone's biometric Touch ID to get into the Status app.
Smart Card Security
Keycard is a Javacard based on ISO standards (7810, 7816 and 14443) and is Common Criteria EAL5+ certified. This is similar to the ones trusted for contactless payment credit/debit cards around the world. Smart cards are widely considered to be very secure for various financial use cases. This is the primary motivation for Keycard being based on smart card technology. The security guarantees of smart cards come from the tamper-resistant Secure Element (SE) used in them.
One often-cited concern with SE or Trusted Execution Environment (TEE) is the potential for a class of attacks known as side-channel attacks, where the attacker relies on observing program execution side-effects such as power, timing or electromagnetic signals to infer execution semantics.
Side-channels can be dangerous if the attacker is able to deduce, for example, the keys being generated or used. But in the case of smart cards, such attacks typically rely on physical access to the card and expensive hardware to infer power or timing characteristics. We are not aware of any documented cases of practical side-channel attacks on the latest generation of smart cards, such as the JCOP4 cards used for Keycard.
Nevertheless, there are software techniques to mitigate side-channels based on timing and power. Given that such attacks typically rely on inferring the (conditional) branches taken by an executing program based on observed time taken or power used by the instructions along those paths, the mitigation technique is to balance the two branch paths for these metrics by using different instructions or buffer/dummy instructions. While this adds a bit of computational overhead, it does not leak the branch taken information. With Keycard, we strive to follow such best practices to reduce the risk of potential side-channel attacks.
Communication between the Keycard and the mobile app on the client/user device happens over Near-field Communications (NFC). NFC is a standards-based short-range wireless connectivity technology which is widely used today in mobile devices and consumer electronics. Most smartphones ship with NFC where it is used for payments along with contactless credit/debit cards. Technologies using NFC can leverage numerous security features.
As explained here, this communication between Keycard and Status app happens over a secure channel to protect transmitted sensitive information from man-in-the-middle (MITM) attacks. The creation of this secure channel relies on a pairing mechanism for mutual authentication. So clients wishing to communicate with the card need to pair with it first. To establish the pairing, the client needs to know the pairing code.
Pairing code is a 16-character alphanumeric code which is generated and displayed only once during card setup. This, along with the passcode, is required anytime the user wants to pair the Keycard to a different phone. This prevents an attacker from pairing the user's Keycard to the attacker's app on a different phone without knowing the pairing code.
Currently, five clients can be paired with a Keycard at any time. And it is possible to unpair previously paired clients.
As described in the earlier article, all the current Keycard functionality is implemented in three Java applets which run on the Keycard:
- Wallet: This applet implements a BIP-32 HD wallet with features of generation/loading of a 12-word BIP-39 seed phrase, loading a key pair, BIP-32 key derivation and key signatures all based on ECDSA secp256k1. The private keys never leave the applet and all communication with the applet is over a secure channel based on a shared secret i.e. pairing code. All interactions with this applet require a passcode.
- Cash: This applet implements the generation of one key pair (which cannot be changed, exported or used for derivation) and signing of transactions with it but without requiring the setup of a secure channel or the passcode with every transaction. This is supposed to be used for lower-security applications because the security here depends on the physical possession of the Keycard.
- NDEF: This applet implements NFC tag emulation where the SDK APIs can be used to set the NFC Data Exchange Format (NDEF) record for storing a link or QR code. This applet is used to implement the download of an app or opening a dApp link on the device of choice.
GlobalPlatform Issuer Security Domain
To load new applets or delete installed applets, one needs access to the GlobalPlatform (GP) Issuer Security Domain (ISD) used with Keycard. For now, this GP-ISD used by Status with Keycard is published online to allow developers to test with their own applets on Keycards.
But an attacker can potentially abuse this in certain scenarios. For e.g., if the Keycard wallet applet or any other applet implementing a BIP-32 wallet were to generate the seed phrase itself (instead of on the corresponding mobile app), an attacker could intercept the physical Keycard before it has been initialised by user(s) and load a malicious applet using the publicly advertised GP-ISD key. This malicious applet could fake the generation of a random seed phrase by modifying the GENERATE-MNEMONIC implementation such that it always provides the pre-determined attacker-known seed phrase(s). This will allow the attacker to drain the funds from all such Keycards. This is an example of what is known as "supply-chain" attack or "evil-maid" attack.
This hypothetical attack is possible because currently anyone can load any applet into the Keycard using the published GP-ISD key. There are at least three ways to mitigate this:
- Make the GP-ISD key private so that no one else can load/delete applets on Keycard.
- Have the mobile app verify the integrity of corresponding Keycard applets before communicating with them.
- Have the mobile app install the correct applets instead of Keycard shipping with pre-installed applets.
There are pros/cons of these mitigations which have to be considered while designing the solution for the relevant threat model.
The Keycard applets, Java/Go/Swift SDKs and command-line tools are all open source, for anyone to review, modify and adapt them. Keycard is based on technology that is Common Criteria EAL5+ certified. There is no reliance on security through obscurity.
The vision behind Keycard is to create an open framework for crypto smart cards. Developers are encouraged to create new app integrations with Keycard applets or develop entirely new applets using the open SDKs. Businesses are encouraged to white-label Keycards or source the design and manufacturing of cards.
Keycard has been designed with the highest security in mind. This article gives an overview of the various security features considered under the categories of cryptography, access control, smart card security, communication security, applet security and transparency.
The security features, current implementation, potential exploit scenarios and corresponding mitigations described hopefully give a good idea of Keycard’s security considerations. The next article in this series will go into the different security flows and scenarios.
Status team strives to continually improve the security posture of Keycard as we explore more features and applications for it. If you have any suggestions or questions, please feel free to reach out to us at [email protected].
(Thanks to Guy-Louis Grau, Michele Balistreri and Tobias Heldt for reviewing drafts of this article and providing helpful feedback. Thanks to Alex Howell for the thoughtful illustrations.)