closes #32
This commit is contained in:
parent
73b73ffa3c
commit
a33aae5ed5
24
README.md
24
README.md
|
@ -4,17 +4,6 @@ The project is built using Gradle with the [Fidesmo Javacard Gradle plugin](http
|
||||||
You can set the JavaCard HOME not only through the environment but also creating a gradle.properties file with the
|
You can set the JavaCard HOME not only through the environment but also creating a gradle.properties file with the
|
||||||
property "com.fidesmo.gradle.javacard.home" set to the correct path.
|
property "com.fidesmo.gradle.javacard.home" set to the correct path.
|
||||||
|
|
||||||
Loading and installing the applet requires [gpshell](https://sourceforge.net/p/globalplatform/wiki/GPShell/) to be
|
|
||||||
installed on the system. The gradle.properties file must contain the following properties
|
|
||||||
|
|
||||||
* im.status.gradle.gpshell = the path to the gpshell executable
|
|
||||||
* im.status.gradle.gpshell.isd = the AID of the issuer security domain
|
|
||||||
* im.status.gradle.gpshell.mac_key = the MAC key for the ISD
|
|
||||||
* im.status.gradle.gpshell.enc_key = the ENC key for the ISD
|
|
||||||
* im.status.gradle.gpshell.kek_key = the KEK key for the ISD
|
|
||||||
* im.status.gradle.gpshell.kvn = the Key Version Number for the ISD
|
|
||||||
* im.status.keycard.test.simulated = true if the test should run on the simulator, false (or anything else) otherwise
|
|
||||||
|
|
||||||
Testing is done with JUnit and performed either on a real card or on [jCardSim](https://github.com/status-im/jcardsim).
|
Testing is done with JUnit and performed either on a real card or on [jCardSim](https://github.com/status-im/jcardsim).
|
||||||
Although the tests are comprehensive, debugging on the real card is not easy because raw APDUs are not shown in the test
|
Although the tests are comprehensive, debugging on the real card is not easy because raw APDUs are not shown in the test
|
||||||
log and there is no way to set breakpoints in the applet.
|
log and there is no way to set breakpoints in the applet.
|
||||||
|
@ -40,19 +29,6 @@ In order to test with the simulator with an IDE, you need to pass these addition
|
||||||
installed. For more information check [here](https://stackoverflow.com/questions/41580489/how-to-install-unlimited-strength-jurisdiction-policy-files).
|
installed. For more information check [here](https://stackoverflow.com/questions/41580489/how-to-install-unlimited-strength-jurisdiction-policy-files).
|
||||||
3. Run `./gradlew test`
|
3. Run `./gradlew test`
|
||||||
|
|
||||||
## Example gradle.properties file
|
|
||||||
|
|
||||||
```
|
|
||||||
com.fidesmo.gradle.javacard.home=/home/username/javacard-3_0_4
|
|
||||||
im.status.gradle.gpshell=/usr/local/bin/gpshell
|
|
||||||
im.status.gradle.gpshell.isd=A000000151000000
|
|
||||||
im.status.gradle.gpshell.mac_key=404142434445464748494a4b4c4d4e4f
|
|
||||||
im.status.gradle.gpshell.enc_key=404142434445464748494a4b4c4d4e4f
|
|
||||||
im.status.gradle.gpshell.kek_key=404142434445464748494a4b4c4d4e4f
|
|
||||||
im.status.gradle.gpshell.kvn=0
|
|
||||||
im.status.keycard.test.simulated=false
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementation notes
|
## Implementation notes
|
||||||
|
|
||||||
* The applet requires JavaCard 3.0.4 (with the addition of KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY
|
* The applet requires JavaCard 3.0.4 (with the addition of KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY
|
||||||
|
|
23
build.gradle
23
build.gradle
|
@ -5,11 +5,13 @@ buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
maven { url 'http://releases.marmeladburk.fidesmo.com/' }
|
maven { url 'http://releases.marmeladburk.fidesmo.com/' }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.fidesmo:gradle-javacard:0.2.7'
|
classpath 'com.fidesmo:gradle-javacard:0.2.7'
|
||||||
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.1.1'
|
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.1.1'
|
||||||
|
classpath 'com.github.status-im.status-keycard-java:desktop:2.0rc1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,26 +61,7 @@ task wrapper(type: Wrapper) {
|
||||||
gradleVersion = '4.7'
|
gradleVersion = '4.7'
|
||||||
}
|
}
|
||||||
|
|
||||||
task install(type: Exec) {
|
task install (type: im.status.keycard.build.InstallTask)
|
||||||
def gpShellScript = """
|
|
||||||
mode_211
|
|
||||||
enable_trace
|
|
||||||
establish_context
|
|
||||||
card_connect
|
|
||||||
select -AID ${project.properties['im.status.gradle.gpshell.isd']}
|
|
||||||
open_sc -security 1 -keyind 0 -keyver ${project.properties['im.status.gradle.gpshell.kvn']} -mac_key ${project.properties['im.status.gradle.gpshell.mac_key']} -enc_key ${project.properties['im.status.gradle.gpshell.enc_key']} -kek_key ${project.properties['im.status.gradle.gpshell.kek_key']}
|
|
||||||
send_apdu_nostop -sc 1 -APDU 80E400800E4F0C53746174757357616C6C6574
|
|
||||||
install_for_load -pkgAID 53746174757357616C6C6574
|
|
||||||
load -file build/javacard/im/status/keycard/javacard/keycard.cap
|
|
||||||
install_for_install -AID 53746174757357616C6C6574417070 -pkgAID 53746174757357616C6C6574 -instAID 53746174757357616C6C6574417070
|
|
||||||
install_for_install -AID 53746174757357616C6C65744e4643 -pkgAID 53746174757357616C6C6574 -instAID D2760000850101
|
|
||||||
card_disconnect
|
|
||||||
release_context
|
|
||||||
"""
|
|
||||||
|
|
||||||
executable project.properties['im.status.gradle.gpshell']
|
|
||||||
standardInput new ByteArrayInputStream(gpShellScript.getBytes("UTF-8"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (project.properties['im.status.keycard.test.simulated'] != 'true') {
|
if (project.properties['im.status.keycard.test.simulated'] != 'true') {
|
||||||
tasks.install.dependsOn(convertJavacard)
|
tasks.install.dependsOn(convertJavacard)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile 'com.github.status-im.status-keycard-java:desktop:2.0rc1'
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package im.status.keycard.build;
|
||||||
|
|
||||||
|
import im.status.keycard.desktop.PCSCCardChannel;
|
||||||
|
import im.status.keycard.globalplatform.GlobalPlatformCommandSet;
|
||||||
|
import im.status.keycard.globalplatform.LoadCallback;
|
||||||
|
import im.status.keycard.io.APDUException;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import javax.smartcardio.*;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class InstallTask extends DefaultTask {
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void install() {
|
||||||
|
Logger logger = getLogger();
|
||||||
|
|
||||||
|
TerminalFactory tf = TerminalFactory.getDefault();
|
||||||
|
CardTerminal cardTerminal = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (CardTerminal t : tf.terminals().list()) {
|
||||||
|
if (t.isCardPresent()) {
|
||||||
|
cardTerminal = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(CardException e) {
|
||||||
|
throw new GradleException("Error listing card terminals", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cardTerminal == null) {
|
||||||
|
throw new GradleException("No available PC/SC terminal");
|
||||||
|
}
|
||||||
|
|
||||||
|
Card apduCard;
|
||||||
|
|
||||||
|
try {
|
||||||
|
apduCard = cardTerminal.connect("*");
|
||||||
|
} catch(CardException e) {
|
||||||
|
throw new GradleException("Couldn't connect to the card", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Connected to " + cardTerminal.getName());
|
||||||
|
PCSCCardChannel sdkChannel = new PCSCCardChannel(apduCard.getBasicChannel());
|
||||||
|
GlobalPlatformCommandSet cmdSet = new GlobalPlatformCommandSet(sdkChannel);
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.info("Selecting the ISD");
|
||||||
|
cmdSet.select().checkOK();
|
||||||
|
logger.info("Opening a SecureChannel");
|
||||||
|
cmdSet.openSecureChannel();
|
||||||
|
logger.info("Deleting the old instances and package (if present)");
|
||||||
|
cmdSet.deleteKeycardInstancesAndPackage();
|
||||||
|
logger.info("Loading the new package");
|
||||||
|
cmdSet.loadKeycardPackage(new FileInputStream("build/javacard/im/status/keycard/javacard/keycard.cap"), new LoadCallback() {
|
||||||
|
@Override
|
||||||
|
public void blockLoaded(int loadedBlock, int blockCount) {
|
||||||
|
logger.info("Loaded block " + loadedBlock + "/" + blockCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logger.info("Installing the Keycard Applet");
|
||||||
|
cmdSet.installKeycardApplet();
|
||||||
|
logger.info("Installing the NDEF Applet");
|
||||||
|
cmdSet.installNDEFApplet(new byte[0]);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new GradleException("I/O error", e);
|
||||||
|
} catch (APDUException e) {
|
||||||
|
throw new GradleException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue