Skip to content
This repository has been archived by the owner on Feb 14, 2024. It is now read-only.

Add tests #7

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.gradle/
build/
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "libs-sdks"]
path = libs-sdks
url = https://github.com/martinpaljak/oracle_javacard_sdks.git
[submodule "libs"]
path = libs
url = https://github.com/J08nY/javacard-libs
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ It uses no proprietary vendor API and is freely available on [Ledger Unplugged](

# Building

- Set the environment variable `JC_HOME` to the folder containg the [Java Card Development Kit 3.0.2](http://www.oracle.com/technetwork/java/embedded/javacard/downloads/index.html)
- Run `gradlew convertJavacard`
- Run `gradlew buildJavaCard`

# Installing

Expand Down
85 changes: 70 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,27 +1,82 @@
apply plugin: 'javacard'
group 'ledger-u2f-javacard'
version '1.0-SNAPSHOT'

// Buildscript configuration for the javacard-gradle plugin.
// Do not modify this particular block. Dependencies for the project are lower.
buildscript {
repositories {
maven { url 'http://snapshots.marmeladburk.fidesmo.com/' }
mavenCentral()
}

dependencies {
classpath 'com.fidesmo:gradle-javacard:0.2.7-SNAPSHOT'
classpath 'com.klinec:gradle-javacard:1.5.5'
}
}

apply plugin: 'javacard'
apply plugin: 'jacoco'
sourceCompatibility = 1.8

// Common settings, definitions
final def rootPath = rootDir.absolutePath
final def libs = rootPath + '/libs'
final def libsSdk = rootPath + '/libs-sdks'

// Repositories for your project
repositories {
mavenCentral()
// mavenLocal() // for local maven repository if needed
flatDir {
dirs libs
}
}

// Dependencies for your project
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'

jcardsim name: 'jcardsim-3_0_5/jcardsim-3.0.5-SNAPSHOT'
}

test {
jvmArgs '-noverify'
}

// JavaCard SDKs and libraries
final def JC212 = libsSdk + '/jc212_kit'
final def JC221 = libsSdk + '/jc221_kit'
final def JC222 = libsSdk + '/jc222_kit'
final def JC303 = libsSdk + '/jc303_kit'
final def JC304 = libsSdk + '/jc304_kit'
final def JC305 = libsSdk + '/jc305u1_kit'

// Which JavaCard SDK to use - select
final def JC_SELECTED = JC305

javacard {

sdkVersion = '3.0.2'

cap {
aid = '0xa0:0x00:0x00:0x06:0x17:0x00:0x4f:0x97:0xa2:0xe9:0x50:0x01'
packageName = 'com.ledger.u2f'
applet {
aid = '0xa0:0x00:0x00:0x06:0x17:0x00:0x4f:0x97:0xa2:0xe9:0x49:0x01'
className = 'U2FApplet'
}
version = '1.1'
}
//noinspection GroovyAssignabilityCheck
config {
jckit JC_SELECTED

// JCardSim automatically added by the javacard-gradle plugin
addSurrogateJcardSimRepo false
addImplicitJcardSim false
addImplicitJcardSimJunit false

//noinspection GroovyAssignabilityCheck
cap {
packageName 'com.ledger.u2f'
version '1.1'
aid '0xa0:0x00:0x00:0x06:0x17:0x00:0x4f:0x97:0xa2:0xe9:0x50:0x01'
output 'ledger-u2f.cap'

//noinspection GroovyAssignabilityCheck
applet {
className 'com.ledger.u2f.U2FApplet'
aid '0xa0:0x00:0x00:0x06:0x17:0x00:0x4f:0x97:0xa2:0xe9:0x49:0x01'
}
}
}
}

12 changes: 0 additions & 12 deletions build.xml

This file was deleted.

Binary file removed cap/ledger-u2f.cap
Binary file not shown.
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Wed Aug 13 13:45:49 CEST 2014
#Sun Dec 10 20:07:32 CET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
1 change: 1 addition & 0 deletions libs
Submodule libs added at adb960
1 change: 1 addition & 0 deletions libs-sdks
Submodule libs-sdks added at 2b3694
12 changes: 3 additions & 9 deletions src/main/java/com/ledger/u2f/FIDOStandalone.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,10 @@

package com.ledger.u2f;

import javacard.security.KeyBuilder;
import javacard.security.*;
import javacard.security.KeyPair;
import javacard.security.ECKey;
import javacard.security.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.KeyPair;
import javacard.security.AESKey;
import javacardx.crypto.Cipher;
import javacard.framework.JCSystem;
import javacard.security.RandomData;
import javacard.framework.Util;

public class FIDOStandalone implements FIDOAPI {
Expand All @@ -49,10 +43,10 @@ public FIDOStandalone() {
(ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false));
Secp256r1.setCommonCurveParameters((ECKey)keyPair.getPrivate());
Secp256r1.setCommonCurveParameters((ECKey)keyPair.getPublic());
random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
random = RandomData.getInstance(RandomData.ALG_KEYGENERATION);
// Initialize the unique wrapping key
chipKey = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
random.generateData(scratch, (short)0, (short)32);
random.nextBytes(scratch, (short)0, (short)32);
chipKey.setKey(scratch, (short)0);
cipherEncrypt = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
cipherEncrypt.init(chipKey, Cipher.MODE_ENCRYPT, IV_ZERO_AES, (short)0, (short)IV_ZERO_AES.length);
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/ledger/u2f/U2FApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import javacard.security.KeyBuilder;
import javacardx.apdu.ExtendedLength;
import javacard.security.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.Signature;
import javacard.security.CryptoException;

Expand Down
120 changes: 120 additions & 0 deletions src/test/java/com/ledger/u2f/SimulatorTestBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package com.ledger.u2f;

import apdu4j.ISO7816;
import com.licel.jcardsim.io.JavaxSmartCardInterface;
import javacard.framework.AID;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import java.util.LinkedList;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class SimulatorTestBase {
static JavaxSmartCardInterface sim;
static final byte[] AIDArray = {(byte) 0xa0, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x17, (byte) 0x00, (byte) 0x4f, (byte) 0x97, (byte) 0xa2, (byte) 0xe9, (byte) 0x49, (byte) 0x01};
static final AID aid = new AID(AIDArray, (short) 0, (byte) AIDArray.length);

static final byte FIDO_CLA = (byte) 0x00;
static final byte FIDO_INS_ENROLL = (byte) 0x01;
static final byte FIDO_INS_SIGN = (byte) 0x02;
static final byte FIDO_INS_VERSION = (byte) 0x03;
static final byte PROPRIETARY_CLA = (byte) 0xF0;
static final byte ISO_INS_GET_DATA = (byte) 0xC0;
static final byte FIDO_ADM_SET_ATTESTATION_CERT = (byte) 0x01;
static final byte P1_SIGN_OPERATION = (byte) 0x03;
static final byte P1_SIGN_CHECK_ONLY = (byte) 0x07;
static final int FIDO_SW_TEST_OF_PRESENCE_REQUIRED = 0x6985;
static final int FIDO_SW_INVALID_KEY_HANDLE = ISO7816.SW_WRONG_DATA;
static final byte INSTALL_FLAG_ENABLE_USER_PRESENCE = (byte) 0;
static final byte INSTALL_FLAG_DISABLE_USER_PRESENCE = (byte) 0x01;


@BeforeClass
public static void setUpClass() {
sim = new JavaxSmartCardInterface();
}

@Before
public void setUp() {
}

public void prepareApplet(byte[] installData) {
// Setup the GlobalPlatform install data format.
byte[] fullData = new byte[2 + AIDArray.length + 1 + installData.length + 1];
int offset = 0;
fullData[offset++] = (byte) AIDArray.length;
System.arraycopy(AIDArray, 0, fullData, offset, AIDArray.length);
offset += AIDArray.length;
fullData[offset++] = 0;
fullData[offset++] = (byte) installData.length;
System.arraycopy(installData, 0, fullData, offset, installData.length);

sim.installApplet(aid, U2FApplet.class, fullData, (short) 0, (byte) fullData.length);
sim.selectApplet(aid);
}

public void prepareApplet(byte flags, int attestationCertLength, byte[] attestationPrivKey) {
byte[] installData = new byte[35];
installData[0] = flags;
installData[1] = (byte) ((attestationCertLength & 0xff00) >> 8);
installData[2] = (byte) (attestationCertLength & 0xff);
System.arraycopy(attestationPrivKey, 0, installData, 3, 32);

prepareApplet(installData);
}

public byte[] sendGetData(int ne) {
List<byte[]> responses = new LinkedList<>();
CommandAPDU cmd = new CommandAPDU(FIDO_CLA, ISO_INS_GET_DATA, 0, 0, ne);
do {
ResponseAPDU getDataAPDU = sim.transmitCommand(cmd);
responses.add(getDataAPDU.getData());
int nr = getDataAPDU.getNr();

assertThat(nr, lessThanOrEqualTo(ne));
int sw = getDataAPDU.getSW();
if (sw == ISO7816.SW_NO_ERROR) {
break;
}

if (ne == 256) {
assertThat(sw, allOf(greaterThanOrEqualTo(ISO7816.SW_BYTES_REMAINING_00), lessThanOrEqualTo(ISO7816.SW_BYTES_REMAINING_00 + 256)));
} else {
assertThat(sw, is(ISO7816.SW_NO_ERROR));
break;
}

if (getDataAPDU.getSW() != ISO7816.SW_BYTES_REMAINING_00) {
ne = getDataAPDU.getSW() - ISO7816.SW_BYTES_REMAINING_00;
}

} while (true);

return responses.stream().reduce((a, b) -> {
byte[] result = new byte[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}).get();
}

public byte[] sendGetData() {
return sendGetData(256);
}

@After
public void tearDown() {
sim.resetRuntime();
}

@AfterClass
public static void tearDownClass() {
}
}
Loading