This section describes the development environment and architecture of the OpenFIPS201 applet.
1 Contents
Table of Contents | ||||||
---|---|---|---|---|---|---|
|
2 Overview
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 Building OpenFIPS201
Setting Up The Build Environment
First, you'll need to grab the latest OpenFIPS201 master branch:
Code Block |
---|
git clone https://github.com/makinako/OpenFIPS201.git |
To simplify the build process, the following third-party tools are already included in the repository under the tools directory:
Apache Ant (Apache Software Foundation, https://ant.apache.org/ )
ant-javacard (Martin Paljak, https://github.com/martinpaljak/ant-javacard )
Javacard SDK 3.0.4 (Oracle, http://www.oracle.com/technetwork/java/embedded/javacard/overview/index.html )
In addition, the Oracle Java SE JDK and JRE must be installed (JDK v9 is not recommended). (http://www.oracle.com/technetwork/java/javase/downloads/index.html )
3.1 Build Process
From the root repository folder:
Go to the build folder
Edit the build.cmd and set the 'JDK' environment variable to the version you have installed.
Optionally, edit the build.xml ant configuration file, overriding any default build properties at the top (this is where you can change the target Javacard or GlobalPlatform version in particular).
Run build.cmd, which will build the CAP file to the ./bin folder and the intrinsic documentation to the ./doc folder.
3.2 Applet Configuration
The OpenFIPS201 source contains a file Config.java, which drives the advanced behaviour of the applet. Each feature / parameter is described below, along with the requirement for compliance with NIST SP800-73-4.
3.2.1.1 Features
Feature | Description | Default Value | ||
---|---|---|---|---|
PIV TEST VECTORS | This must only be enabled for protocol debugging and analysis, as this forces the applet to use FIXED values for cryptographic nonces and will cripple security.
| False | ||
RESTRICT SCP TO CONTACT | If set to true, an authentication to GlobalPlatform will fail on the contactless interface. | True | ||
ERROR ON EMPTY DATA OBJECT | If set to true, a call to GET DATA for an object that exists in the file system, but which has not been initialised with data will result in SW_FILE_NOT_FOUND. If set to false, it will return an empty data field with SW OK. | False | ||
DISCOVERY OBJECT DEFAULT | If set to true, when the discovery object is created it will automatically be populated with a default value based on the configured parameters (specifically the PIN policy element dynamic elements). | True | ||
PIN CARD ENABLED | Indicates that the mandatory PIV Card Application PIN satisfies the PIV Access Control Rules (ACRs) for command execution and data object access. | False | ||
PIN GLOBAL ENABLED | Indicates that the optional 'Global PIN' feature of PIV is enabled. | False | ||
PIN GLOBAL PREFERRED | Indicates that the Global PIN is the primary PIN used to satisfy the PIV ACRs for command execution and object access. | False | ||
PIN GLOBAL CHANGE | Indicates that the Global PIN may be updated by the PIV applet. | False | ||
PIN INIT RANDOM | Indicates that the PIN will be set to a random value at applet instantiation. If this is set to False, it will be set to a default value defined in the same Config file (DEFAULT PIN). | True | ||
PUK CHANGE | Indicates that the PUK may be updated by the PIV applet. | True | ||
PUK INIT RANDOM | Indicates that the PUK will be set to a random value at applet instantiation. If this is set to False, it will be set to a default value defined in the same Config file (DEFAULT PUK). | True | ||
PIN OVER CONTACTLESS | Permits the PIN or Global PIN to be used over contactless without the need for the VCI condition. | False | ||
PUK OVER CONTACTLESS | Permits the PUK to be used over contactless without the need for the VCI condition. | False |
3.2.1.2 PIN and PUK Settings
Parameter | Description | Default Value |
---|---|---|
PIN RETRIES | The number of retries before the PIN object is blocked. | 6 |
PIN RETRIES INTERMEDIATE | The number of retries remaining before the PIN object is blocked on the contactless interface only. | 1 |
PUK RETRIES | The number of retries before the PUK object is blocked. | 6 |
PUK RETRIES INTERMEDIATE | The number of retries before the PIN object is blocked on the contactless interface only. | 1 |
PIN LENGTH MIN | The minimum length of the PIN value (SP800-73-4 default is '6' - NOTE: Changing this value from its default will break PIV compliance). | 6 |
PIN LENGTH MAX | The maximum length of the PIN value (SP800-73-4 default is '8' - NOTE: Changing this value from its default will break PIV compliance). | 8 |
4 Applet Architecture
Component | Description | ||
---|---|---|---|
OpenFIPS201 Facade | This is the derived implementation of the Javacard It implements the following functionality:
| ||
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:
| ||
PIV Security Provider | This class is the entry point for all cryptographic operations. It performs the following:
| ||
Key Object | The base class from which all PIV dynamic Keys derive. It extends
| ||
PKI Key | The base class for asymmetric keys. It extends the
| ||
RSA Key | A concrete implementation of the
| ||
ECC Key | A concrete implementation of the
| ||
Symmetric Key | A concrete implementation of the
| ||
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. |
4.1.1 Key Role
The following key roles are defined:
Role | Description | ||
---|---|---|---|
01 - ROLE_AUTHENTICATE | This key can be used for card/host authentication
| ||
02 - ROLE_SIGN | This key can be used for digital signature generation.
| ||
04 - ROLE_VERIFY | This key can be used for digital signature verification.
| ||
08 - ROLE_KEY_ESTABLISH | This key can be used for key establishment schemes.
| ||
10 - ROLE_SECURE_MESSAGING | This key can be used for secure messaging establishment.
|
Info |
---|
The Key Role parameter is a control bitmap, meaning multiple values can be combined. |
4.1.2 Key Attributes
The following key attributes are defined:
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.
|
Info |
---|
The Key Attribute parameter is a control bitmap, meaning multiple values can be combined. |
4.1 Applet Lifecycle
OpenFIPS201 supports the following lifecycle states:
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:
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.
|
4.2 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.
Note |
---|
It is extremely important that the underlying Hardware, OS and Javacard runtime environment is considered in terms of the overall assurance level required, since OpenFIPS201 relies on these for all cryptographic functions and secure storage of critical security parameters. |
4.2.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.
Code Block | ||
---|---|---|
| ||
// BAD
public class MyClass {
}
// GOOD
class MyClass {
} |
4.2.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.
4.2.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.
4.2.4 Early Initialisation - Critical Data
OpenFIPS201 ensures that all critical objects and buffers are defined at applet installation. This has a number of impacts:
It eliminates the chance of undefined behaviour due to allocation failures on memory-constrained devices.
The card issuance system is immediately aware of any memory allocation failures, which prevents installation and renders the applet unable to be selected.
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
4.2.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
Info |
---|
For Data Objects:
|
Info |
---|
For Key Objects:
|
4.2.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
4.2.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.
4.2.8 Approved Algorithms
OpenFIPS201 makes use of only cryptographic mechanisms which are approved by:
4.2.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
4.2.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.
Note |
---|
In order to continue to support Java Card 3.0.4, OpenFIPS201 has implemented |
5 Environment - Java Card
Anchor | ||||
---|---|---|---|---|
|
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()
andsetInitialDigest()
, 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.
5.1.1 Java Card API
The following Java Card API objects are required for OpenFIPS201 to install:
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 |
5.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 |
---|
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 |
Note |
---|
If any of the following primitives are not supported, this will implicitly disable Secure Messaging functionality.
|
6 Environment - Global Platform
OpenFIPS201 makes use of functionality in the GlobalPlatform API for version 2.1.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 |
---|
org.globalplatform.GPSystem |
org.globalplatform.CVM |
org.globalplatform.SecureChannel |
7 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:
PIV Card Application and Middleware Interface Test Guidelines (SP 800-73-4 Compliance)
(Requires a password, which can be obtained from NIST with instructions provided on their web site)
7.1.1.1 Installation Requirements
PIV Test Runner requires the following:
Microsoft Windows XP or above
At least 40MB disk space
Oracle Java Runtime Environment (JRE) version 1.8 (Java 8) or later
"The Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6.0" (http://www.oracle.com/technetwork/java/embedded/embedded-se/downloads/jce-7-download-432124.html )
1 x contact (ISO-7816) PC/SC compliant reader
1 x contactless (ISO-14443) PC/SC compliant reader
2 x Javacard / GlobalPlatform smartcards
7.1.1.2 Installation and Configuration
Download and install the PIV Test Runner (from the above link) to a writable folder
Execute startTestRunner_SP800_73_4.bat in the install directory
Open the OPENFIPS201.xml configuration file
Customise the following configuration settings to your test readers
Configuration / Connectivity / Contact Reader Name
Configuration / Connectivity / Contactless Reader Name
7.1.1.3 Test Preparation
If you do not already have a compile OpenFIPS201 applet
Configure the OpenFIPS201 project (See Development)
Compile the OpenFIPS201 project
Load and install the OpenFIPS201 applet onto each target Javacard with the Default Applet privilege!
Perform pre-personalisation by executing the NIST Compliant Profile on each card
Execute the Test Personalisation on each card
7.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.
7.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.