JavaCardSpot-dev / KeepassNFCApplet

The Unlicense
0 stars 1 forks source link

KeepassNFC Build Status Coverage Status

IMPORTANT

This repository is used for class PV204 Security Technologies at Masaryk University. All meaningful improvements will be attempted to be pushed to upstream repository in June 2018.

Overview

KeePass Password Safe is an open source password manager that aims to store passwords securely.

KeepassNFC is an applet that can protect the secret key of the KeePass database.

This applet was based on the project smartcard_crypto_applet and can be run on javacard platform with JCRE version 2.2.x or above. It is meant to be used in a card supporting NFC (Near Field Communication) technology.

Compiling the project

This project has two different build systems that can be used. JCIDE is the one originally used, while the Gradle integration has been added later using the template from @crocs-muni.

JCIDE

A project file (KeepassNFC.jcproj) has been created for the users of JCIDE. If you have already installed the JCIDE, only a simple double-clicking on this file is needed to start the development environment. You can view, edit, build or debug the code with JCIDE, a powerful Javacard Integrated Development Environment. You can use pyApdutool to download and install the applet, please reference the topic in the JavaCardOS for the operation detail.

Support for this configuration is guaranteed until commit 701cdfc.

Gradle

This configuration gives the ability to easily compile and convert the applet to cap files, it has support for easy tests creation, including test coverage. Also, it provides integration with Travis CI platform (and easily with any other CI platform). It additionally provides the means to execute on both real cards and JCardSim.org simulator.

This build configuration can be used with all the IDEs that provide integration (native or by plugins) with Gradle (IntelliJ, NetBeans, Eclipse...).

After recursively cloning the repository (to gather all the JavaCard SKDs),

git clone --recurse-submodules git@github.com:JavaCardSpot-dev/KeepassNFCApplet.git 

you can choose the desired JavaCard SDK to use by setting the JCSDK environment variable (by default it is empty, and the minimum required SDK version will be used). Then simply run

./gradlew buildJavaCard --info
JCSDK=jc304 ./gradlew buildJavaCard --info

to get the .cap file. It will be located under bin/net/lardcave/keepassnfcapplet/{JCSDK}/keepassnfcapplet.cap

Usage

Here, the user is intended as both you and the client application.

Also, when talking about APDU headers, the length will be always omitted, just like P1 and P2, except when needed.

General functionality

Actually, the applet is able to decrypt the user-supplied database using AES-256. Future development will include also its encryption, and possibly support for more algorithms (Twofish/ChaCha20).

The applet uses three classes of commands:

PIN management

Authentication is provided by the means of two PIN verifications. Both PINs initial values are actually hardcoded.

Both PINs are recommended to be changed by the final user using commands under the 0xA0 class.

Both PIN verifications are kept valid until the card is extracted (or the applet is deselected).

Applet configuration

For applet configuration, all commands are of class 0xB0, and as such require verify User PIN (A082) to have been called successfully.

  1. As first one-time-only step, the user will let the card generate an internal key pair (2048b RSA)(B075).
  2. After generation, the user will be able to get the public key by means of exponent and modulus (B070).
  3. Then, the user will send its Password Key to the applet, encrypted with the card's public key (B076, B071).

After calling these commands, the applet is configured to actually decrypt the KeePass database.

Applet usage

For applet usage, all commands are of class 0xB0, and as such require verify User PIN (A082) to have been called successfully. Also, the configuration is considered to be done.

Each usage is identified by a transaction, with related transaction key (AES-128). The user is required to:

  1. generate a AES-128 transaction key, encrypt it with card's public key and send it to card using write to scratch (B076).
  2. send to card IVs to initialize password and transaction ciphers (B072).
  3. send to card the password-encrypted database split in blocks, getting the same transaction-encrypted (B073).
  4. decrypt each block with transaction key, obtaining plaintext database.

Infomative commands

The user can obtain two different information pieces about the status of the applet, without changing its state and without any authentication:

APDU formats

Header Name Payload (plaintext) Functionality Authenticated Requirements Response format
9072 lock reason/PIN trials empty Return number of trials remaining for both PINs. In future can contain more information mmuu, with mm remaining trials for Master PIN and uu for User PIN
9074
B074*
get version empty Return applet version 01vv, with vv the actual version.
A080 verify Master PIN Master PIN Verify given Master PIN against the stored one
  • if successful 01
  • if wrong PIN SW=0x99nn, with nn as number of trials remaining
A081 set Master PIN New Master PIN Set Master PIN to given data Master (A080)
A082 verify User PIN User PIN Verify given User PIN against the stored one
  • if successful 01
  • if wrong PIN SW=0x99nn, with nn as number of trials remaining
A083 set User PIN New User PIN Set User PIN to given data Master (A080)
B070 get public key 010000 Get public key's exponent User (A082) B075 successfully called 01ssssk..., with ssss a short for exponent length, and k... the actual exponent
B070 get public key 02oooo Get public key's modulus from offset oooo User (A082) B075 successfully called 01ssssSSSSk..., with ssss a short for the bytes sent, SSSS a short for the missing bytes after the sent ones, and k... the actual modulus part
B070 get public key xxoooo --- User (A082) 02 (failure) when xx different from 01 or 02
B071 set password key empty Decrypt first bytes in scratch area as password key (AES-256, saved also after disconnection) User (A082) B075 successfully called and B076 used to store encrypted password key in scratch area 01 if successful
B072 prepare decryption password & transaction IVs (16+16 bytes) Decrypt first bytes in scratch area as transaction key (AES-128, saved only for the session). Initialize password cipher for decryption and transaction cipher for encryption. User (A082) B076 used to store encrypted transaction key in scratch area 01 if successful
B073
P1=80
decrypt block encrypted block Decrypts given data with password cipher expecting more data. Then encrypts the result with transaction cipher. User (A082) B072 successfully called 01b..., with b... actual block
B073
P1!=80
decrypt block encrypted block Same as above, but as last block. This will also reset ciphers. User (A082) B072 successfully called 01b..., with b... actual block
B075 generate key pair empty Generate card's key pair. User (A082) 01ssss, with ssss a short for key length.
B076 write to scratch oodd... Store data (dd...) in internal scratch area at offset oo User (A082) 01ssss, with ssss a short for free space after saved data.

B074 instruction to get version is maintained only for compatibility reasons, and it's deprecated. Nevertheless, since it's a B0-class instruction, it still needs correct User PIN verification.

Error codes

Apart from standard exception codes, the following specific SW codes are used:

SW Meaning ISO7816 equivalence
97nn Action requires Master PIN verification, but A080 wasn't successfully called. nn contains remaining numebr of trials.
98nn Action requires User PIN verification, but A082 wasn't successfully called. nn contains remaining number of trials.
99nn The verification of Master/User PIN gone wrong. nn contains remaining number of trials.
6700 Input data has wrong length compared to expected one. SW_WRONG_LENGTH
6A80 Input data has different values than expected. SW_WRONG_DATA
6982 In case of error caused by supposed tampering. SW_SECURITY_STATUS_NOT_SATISFIED
F1tt A crypto-related exception occurred. tt from 01 to 05 are standard CryptoException reasons, while 09 is used for rare situation when evaluating a number too big. This only happened if skipping some commands while setting password/trasaction keys.

Future work

Help is always appreciated! Please read these suggestions for what to do, and always follow the contibution rules!

This applet can be improved in several ways:

Also the repository can be improved:

Known compatibilities

Until 701cdfc it should work on JC30M48, the downloading and installation have been tested on this card.

Until June 2018 it was successfully tested with NXP J2E 081 (NXP JCOP v2.4.x).

Timings

Some profiling has been performed for all the commands (timings are in ms, average over 20 trials, smartcard NXP J2E 081):

Header Avg timing Timing range Notes
9072 7 7 - 8 (get lock reason/remaining PINs), direct read
9074 7 7 - 9 (get version), direct read
A080 37 37 - 39 (verify Master PIN)
A081 33 33 - 34 (set Master PIN)
A082 37 37 - 38 (verify User PIN)
A083 33 32 - 34 (set User PIN)
B070
010000
13 13 - 14 (get Card Key exponent) Supposed one execution every usage.
B070
020000
44 44 - 45 (get Card Key modulus - first part) Supposed one execution every usage.
B071 714 714 - 716 (set password key) Supposed one execution every long time.
B072 699 698 - 700 (set transaction key) Supposed one execution every usage.
B073
P1!=80
96 95 - 97 (decrypt one block) Decrypting 128 bytes unique block.
B075 21660 5557 - 54592 (generate card key) Supposed one execution every long time.
B076 14 14 - 15 (write to scratch) Writing 16 bytes to scratch ~encrypted transaction key.
B076 18 18 (write to scratch) Writing 32 bytes to scratch ~encrypted password key.
B076 26 26 - 27 (write to scratch) Writing 64 bytes to scratch, more than needed by keys.

About the B073 command (block decryption): a fully populated KeePass database can be long around 200 KiB, that corresponds to 1600 executions of given command. These result in a total execution time of around 150 seconds, or 2.5 minutes. This should be improved.

Maintainers

The original creator of the project is the JavaCardOS community.

As the initial notice explains, this project will be maintained by students of the Masaryk University about until June 2018.