Document toolboxDocument toolbox

Applet Development

This section describes the development environment and architecture of the OpenFIPS201 applet.

1 Contents

2 Building OpenFIPS201

2.1 Setting Up The Build Environment

OpenFIPS201 has been build tested on Windows 10 and 11, but there’s no reason to believe it won’t build on most major operating systems.

  1. Make sure you have a suitable Java Development Kit (JDK) installed. For OpenFIPS201, the most appropriate version is Java SE 11 LTS, which can be downloaded from here:
    https://www.oracle.com/au/java/technologies/javase/jdk11-archive-downloads.html

  2. Make sure you set the environment variable JAVA_HOME to the full path to the SDK.
    For example: JAVA_HOME=C:\Program Files\Java\jdk-11.0.13

  3. To simplify the build process, the following third-party tools are already included in the repository under the tools directory:

    1. Apache Ant (Apache Software Foundation, Apache Ant ) for the build processor

    2. Ant-Javacard (Martin Paljak, GitHub - martinpaljak/ant-javacard ) for the Javacard build tasks

    3. Javacard SDK 3.0.4 (Oracle, Java Archive Downloads) for the Target SDK

    4. Javacard SDK 3.1.0 (Oracle, Java Card SDK Downloads) for the Build SDK

  4. Next, you'll need to grab the latest OpenFIPS201 master branch:

    git clone https://github.com/makinako/OpenFIPS201.git

     

  5. Drop to a command / terminal prompt and navigate to the build directory where you just cloned the repository.

  6. Run the build.cmd (Windows) or build.sh (Linux) script

  7. You are done!
    The CAP file has now been created in the bin directory and the Javadoc HTML has been generated in the doc directory.

It can be tempting to install the latest JDK, however all but the latest Java Card development kits (JC 3.1.0) are targeted to specific, older Java target versions that are not supported on newer JDK’s.
OpenFIPS201 targets JC 3.0.4 currently, which means it must be compiled to target 1.7.

 

 

 

 

OpenFIPS201 targets JC 3.0.4, but uses the latest 3.1.0 compiler. This is the recommended approach by Oracle.

 

 

 

 

3 Applet Architecture

OpenFIPS201 is built with the following high-level design goals in mind:

  • Simplicity and Readability - The code is designed to be a clean interpretation of the [SP 800-73] Part 2 document, using the standard terms wherever possible.

  • Flexibility - The file system, access control rules and applet behaviour are all configured from a single class before compilation, allowing for strict compliance to PIV or to allow for additional data objects or security requirements (PIV-I or CIV for example).

  • Production Quality - The project aims to be of a quality that can be used directly in a production environment and submitted for certification.

  • Low Memory Footprint - Although the file system itself is capable of taking up enormous amounts of EEPROM, the applet itself is designed to minimise its EEPROM and RAM footprint. Data Object arrays are only allocated when first written to and the APDU buffer is used where possible for intermediate operations.

 

3.1 Component Hierarchy

 

OpenFIPS201 Component Hierarchy

 

Component

Description

Component

Description

OpenFIPS201 Facade

This is the derived implementation of the Javacard Applet class and provides the entry point for all communications to the applet.

It implements the following functionality:

  • Applet installation and memory allocation

  • Applet selection and deselection

  • APDU processing

  • GP Secure Channel processing

PIV

The implementation of all [SP800-73-4] commands and functionality.

PIV Object

The base class from which all PIV dynamic objects derive. It contains the identification and access control information associated with all PIV objects.

It defines the following attributes:

  • Object Identifier

  • Access Mode - Contact Interface

  • Access Mode - Contactless Interface

This class is abstract and cannot be instantiated.

PIV Security Provider

This class is the entry point for all cryptographic operations. It performs the following:

  1. Manages the cryptographic key store.

  2. Permits querying of available keys.

  3. Maintains card verification data and state.

  4. Permits querying of PIV Object access conditions against the current verification and authentication state.

Key Object

The base class from which all PIV dynamic Keys derive. It extends PIV Object to include additional attributes.

  • Cryptographic Mechanism

  • Key Role

  • Key Attributes

PKI Key

The base class for asymmetric keys. It extends the Key Object to include additional functionality:

  • Signing operation

  • Key Agreement operation

  • Key Generation operation

RSA Key

A concrete implementation of the PKI Key class, which provides RSA cryptographic operations.

ECC Key

A concrete implementation of the PKI Key class, which provides Elliptic Curve cryptographic operations.

Symmetric Key

A concrete implementation of the Key Object class, which provides AES and TripleDES cryptographic operations.

Data Object

Represents a single PIV Data Object, which is accessed via the GET DATA and PUT DATA commands.

TLV Reader

Implements ASN.1 BER and DER-TLV object validation and querying.

TLV Writer

Implements ASN.1 BER and DER-TLV object validation and querying.

Chain Buffer

Implements [ISO 7816] command chaining to a temporary command buffer so that other components need not consider the existence of chaining.

CMVPIN

Extends the Java Card PIN interface to implement access to the GlobalPlatform Global PIN in a consistent manner.

 

3.1.1 Key Role

The following key roles are defined:

Role

Description

Role

Description

01 - ROLE_AUTHENTICATE

This key can be used for card/host authentication

  • Symmetric Keys - Permit Internal, External and Mutual Authentication.

  • RSA - Not supported (RSA authentication is just a Digital Signature of a challenge)

  • ECC - Not supported (ECC authentication is just a Digital Signature of a challenge)

02 - ROLE_SIGN

This key can be used for digital signature generation.

  • Symmetric Keys - Not supported (Could be used for MAC generation)

  • RSA - RSA Digital Signature

  • ECC - ECDSA

04 - ROLE_VERIFY

This key can be used for digital signature verification.

  • Symmetric Keys - Not supported (Could be used for MAC verification)

  • RSA - RSA Digital Signature

  • ECC - Elliptic Curve Digital Signature Algorithm (ECDSA)

08 - ROLE_KEY_ESTABLISH

This key can be used for key establishment schemes.

  • Symmetric Keys - Not supported

  • RSA - RSA Key Transport

  • ECC - Elliptic Curve Diffie Hellman (ECDH)

10 - ROLE_SECURE_MESSAGING

This key can be used for secure messaging establishment.

  • Symmetric Keys - Not supported

  • RSA - Not supported

  • ECC - Opacity ZKM

3.1.2 Key Attributes

The following key attributes are defined:

Attribute

Description

Attribute

Description

01 - ATTR_ADMIN

This key can be used for administrative authentication

02 - ATTR_GENERATE_ONLY

This key can only be generated on-card (i.e. injection is blocked).

04 - ATTR_MUTUAL_ONLY

This key is limited to MUTUAL (host/card) authentication only. Setting this disables EXTERNAL and INTERNAL authentication for symmetric keys.

 

3.2 Applet Lifecycle

 

OpenFIPS201 supports the following lifecycle states:

OpenFIPS201 Applet Lifecycle

 

State

Description

State

Description

Installed

OpenFIPS201 is installed on the Card (in the appropriate GlobalPlatform Security Domain) and all memory has been allocated. The applet is inactive and an attempt to select it via its Application Identifier (AID) will fail.

Selectable

OpenFIPS201 has been activated in the Card Manager and is now able to receive commands from a Terminal. By default the applet does not yet define any Configuration, Data Objects or Key values

Personalised

The applet is now operational and able to perform cryptographic operations.

Locked

The applet has been temporarily locked and is no longer selectable. This state can have a number of causes:

  • The Card Manager has determined that the applet should be locked

  • OpenFIPS201 has determined that the applet should be locked

  • An authorised Card Administrator has requested the applet be locked explicitly

Once the applet is Locked, only the GlobalPlatform Security Domain is able to unlock it.

Terminated

The applet has been irreversibly locked and can no longer be used. The following steps occur in order.

  1. The applet internally sets a flag to indicate that it is now in the Terminated state.

  2. All authentication and verification states are reset

  3. All key values are cleared

  4. All verification values are cleared

  5. All data objects are cleared

  6. Garbage collection is requested from the card manager, if available.

  7. The applet is locked by the card manager and is no longer selectable.

 

3.3 Development Principles

OpenFIPS201 follows a number of design principles to ensure that undefined or unintended behaviour does not occur, whether through the fault of development (bugs), fault of use or malicious act.

 

3.3.1 Private-Package Class Declarations

All classes in the OpenFIPS201 package shall be declared ‘Private-Package', with the intention that they are non-accessible outside the main package. This is intended to reduce attack surface related to static members.

// BAD public class MyClass { } // GOOD class MyClass { }

3.3.2 Exception-based Error Handling

All functions generate errors via the Java Card exceptions paradigm, which causes the applet to stop functioning unless the exception is explicitly handled.

Return values are only ever informational or functional, they are never used to express the failure of a function to operate normally. Conversely, exceptions are never used to convey information or drive application flow.

This is done to prevent calling code from unintentionally ignoring error conditions, which may then lead to unintended behaviours or exposure to attackers.

3.3.3 Object Locking

Utility and Cryptographic objects make use of a simple Acquire and Release locking mechanism, which ensures that any unintended or malicious attempts to execute functionality are caught.

Before a call to any protected object is made, the caller must Acquire a lock. If a lock already exists, the object will throw an exception. Once a lock is requested, the caller must then explicitly release the object.

3.3.4 Early Initialisation - Critical Data

OpenFIPS201 ensures that all critical objects and buffers are defined at applet installation. This has a number of impacts:

  1. It eliminates the chance of undefined behaviour due to allocation failures on memory-constrained devices.

  2. The card issuance system is immediately aware of any memory allocation failures, which prevents installation and renders the applet unable to be selected.

  3. It provides early visibility of how much memory the base installation of OpenFIPS201 uses

The following elements are instantiated at applet install:

  • All functional modules (classes)

  • The primary transient (RAM-based) temporary buffer (called the Scratch space)

  • The dedicated transient authentication state

  • The [ISO-7816] communications command-chain handler (Chain Buffer)

  • The PIV Implementation

  • The PIV Security Provider including all Java Card cryptographic primitive instances

  • TLV Parsing and Construction Utilities

3.3.5 Lazy Initialisation - Filesystem and Key Store

In contrast to critical data, OpenFIPS201 deliberately avoids allocating memory for dynamic objects until they are populated with data. This is because a PIV filesystem has the potential to consume large amounts of memory and data object lengths are not always known, so early instantiation would need to take into account worst-case memory usage which would further impact the applet footprint.

In any typical PIV deployment, many objects will remain unpopulated for the entire life-time of the applet. Lazy initialisation optimises this by only allocating memory for these resources until they are first used and the requested size is known.

This includes:

  • File System Descriptors

  • Data Objects

  • Key Objects

 

3.3.6 Defined Cryptographic Boundary

All cryptographic operations occur inside specific classes and internal Java Card implementations are not accessible outside of these objects. This reduces the chances of sensitive cryptographic functions being used in an unintended or malicious way.

The classes that contain references to cryptographic primitive instances are:

  • PIV Security Provider

  • PIV Crypto

3.3.7 Optimised File Allocation Table

All Data Object and Key records are held by a simple linked list. Since it is possible that many data objects and keys will not be populated, OpenFIPS201 optimises this linked list by moving objects to the top of the list as they are allocated. This ensures that the lookup time is minimised as empty objects are never hit in normal operational circumstances.

3.3.8 Approved Algorithms

OpenFIPS201 makes use of only cryptographic mechanisms which are approved by:

 

3.3.9 Critical Security Parameter (CSP) Management

All CSPs are carefully managed to ensure that the potential for exposure or misuse is limited. Some of the ways in which this is implemented are:

  • All cryptographic keys are only ever stored in Java Card Key objects, which are protected by the JCRE / JCVM.

  • All PIN and PUK values are stored in Java Card OwnerPin objects, which are protected by the JCRE / JCVM.

  • Keys and cryptographic primitives are kept within defined classes and access to them is only permitted through abstracted operations.

  • Transport of cryptographic keys is only ever permitted over a secure channel with command Encryption and MAC, never in plaintext.

  • Asymmetric Keys are able to be decorated with a 'Generate Only' attribute, which prevents key injection. This provides assurance of key ownership and guards against repudiation.

  • All temporary and intermediate values are zeroised immediately after they are no longer needed

 

3.3.10 No ‘Roll Your Own’ Crypto

OpenFIPS201 does not make use of any cryptographic primitives that are defined in software, but rather makes use of the existing primitives provided by the Java Card API.

4 Environment - Java Card

OpenFIPS201 avoids the use of any platform-specific API outside of Java Card and GlobalPlatform namespaces, to ensure maximum compatibility with commercially available cards.

The minimum Java Card Runtime Environment (JCRE) version is targeted at v3.0.4 and as such, does not make use of functionality in later versions. There are several reasons for this:

  • A number of cryptographic primitives are not supported by JC22, especially in the Elliptic Curve domain. This makes it impossible to fully implement SP800-73-4 without resorting to a soft-crypto implementation.

  • The PIV requirement to format signature input blocks off-card, which is not supported by JC22 resulted in the need to implement a hack to encrypt using the private key. Moving to JC30 will allow the use of Signature with signPreComputedHash() and setInitialDigest(), which are both specifically intended for off-card signature block formatting.

  • JC22 does not support the Applet.reselectingApplet() feature, which again is a breaking point for PIV. NIST have indicated they will permit certification exceptions to support JC22 cards, however this hasn't been tested to our knowledge.

4.1.1 Java Card API

The following Java Card API objects are required for OpenFIPS201 to install:

Class / Namespace

Requirement

Class / Namespace

Requirement

javacard.framework.APDU

Mandatory

javacard.framework.Applet

Mandatory

javacard.framework.CardRuntimeException

Mandatory

javacard.framework.ISO7816

Mandatory

javacard.framework.ISOException

Mandatory

javacard.framework.JCSystem

Mandatory

javacard.framework.OwnerPIN

Mandatory

javacard.framework.PIN

Mandatory

javacard.framework.PINException

Mandatory

javacard.framework.Util

Mandatory

javacard.security.AESKey

Optional

javacard.security.CryptoException

Mandatory

javacard.security.DESKey

Optional

javacard.security.ECPrivateKey

Optional

javacard.security.ECPublicKey

Optional

javacard.security.KeyAgreement

Mandatory

javacard.security.KeyBuilder

Mandatory

javacard.security.KeyPair

Mandatory

javacard.security.MessageDigest

Mandatory

javacard.security.PrivateKey

Mandatory

javacard.security.PublicKey

Mandatory

javacard.security.RandomData

Mandatory

javacard.security.RSAPrivateKey

Optional

javacard.security.RSAPublicKey

Optional

javacard.security.SecretKey

Mandatory

javacard.security.Signature

Mandatory

javacardx.crypto.Cipher

Mandatory

 

4.1.2 Cryptographic Primitives

OpenFIPS201 dynamically checks which cryptographic primitives are available on the target card during installation. If one or more are not available (cannot be instantiated), the applet will disable that mechanism and prevent keys of those types from being added to the file system during pre-personalisation.

The following primitives are used if available:

Class / Namespace

Class / Namespace

Cipher.ALG_AES_BLOCK_128_CBC_NOPAD

Cipher.ALG_AES_BLOCK_128_ECB_NOPAD

Cipher.ALG_DES_ECB_NOPAD

Cipher.ALG_RSA_NOPAD

KeyAgreement.ALG_EC_SVDP_DH_PLAIN

MessageDigest.ALG_SHA_256

MessageDigest.ALG_SHA_384

Signature.ALG_ECDSA_SHA

Signature.ALG_ECDSA_SHA_256

Signature.ALG_ECDSA_SHA_384

Signature.ALG_ECDSA_SHA_512

Signature.ALG_RSA_SHA_PKCS1

5 Environment - Global Platform

  • OpenFIPS201 makes use of functionality in the GlobalPlatform API for version 2.2.1 or higher

  • OpenFIPS201 avoids the use of any platform-specific API outside of Java Card and GlobalPlatform namespaces, to ensure maximum compatibility with commercially available cards.

  • OpenFIPS201 makes use of the Global Platform Secure Channel Protocol 03 functionality, specifically to mutually authenticate the card and the issuer (or card manager). For an administrative status to be considered valid, both the C-ENC and C-MAC protocol options must be set.

  • The following Global Platform API objects are required at a minimum:

Class / Namespace

Class / Namespace

org.globalplatform.GPSystem

org.globalplatform.CVM

org.globalplatform.SecureChannel

 

6 Applet Interoperability Testing

NIST has supplied testing documentation and software that is used to perform black-box testing of a PIV applet and/or middleware component.

OpenFIPS201 has been tested using this software, excluding tests that fall into a number of categories:

  • Unsupported features (Biometric On-Card Comparison)

  • Inapplicable (i.e. Middleware tests)

  • Data Format Validation (It tests the contents of a data object, which is outside the scope of the Card Application to enforce)

The document and software links can be found here:

6.1.1.1 Installation Requirements

PIV Test Runner requires the following:

6.1.1.2 Installation and Configuration

  1. Download and install the PIV Test Runner (from the above link) to a writable folder

  2. Execute startTestRunner_SP800_73_4.bat in the install directory

  3. Open the OPENFIPS201.xml configuration file

  4. Customise the following configuration settings to your test readers

    • Configuration / Connectivity / Contact Reader Name

    • Configuration / Connectivity / Contactless Reader Name

6.1.1.3 Test Preparation

  1. If you do not already have a compile OpenFIPS201 applet

    • Configure the OpenFIPS201 project (See Development)

    • Compile the OpenFIPS201 project

  2. Load and install the OpenFIPS201 applet onto each target Javacard with the Default Applet privilege!

  3. Perform pre-personalisation by executing the NIST Compliant Profile on each card

  4. Execute the Test Personalisation on each card

6.1.1.4 Test Execution

Unless you are testing a comprehensive PIV setup (i.e. Middleware and Personalisation system), it is not recommended to use the 'Run All' functionality. Instead, only selected tests should be executed from the list below.

  • ChangeReferenceDataCommand

  • GeneralAuthenticateCommand

  • GenerateAsymmetricKeyPairCommand

  • GetDataCommand

  • PutDataCommand

  • ResetRetryCounterCommand

  • ChangeReferenceDataCommand

  • SelectCommand

  • VerifyCommand

These can be executed either individually, or all selected. PIV Test Runner does not appear to provide a mechanism to generate a 'test profile' file.

6.1.1.5 Test Results

PIV Test Runner provides summary test results by clicking on the parent Test item. Each test category will show either PASS, FAIL or blank if they were not executed.

Inside each test sub-category you have the option to select the Log tab, which will give detailed diagnostic output for the execution of each test with a summary of each step outcome at the end of the log.

Note that all test numbering maps back to the NIST test documentation described at the start of this page.