aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2016-12-10 23:32:41 +0100
committerJ08nY2016-12-10 23:37:51 +0100
commit5f0ec2706a9dbb6aa72ea3c7eb798cd83045e867 (patch)
tree36df89a0253469d4cca2de53eb12314ccc58f4cb
parent31a9da5493cb5085354dbfa034cea4b1d45df3cb (diff)
downloadECTester-5f0ec2706a9dbb6aa72ea3c7eb798cd83045e867.tar.gz
ECTester-5f0ec2706a9dbb6aa72ea3c7eb798cd83045e867.tar.zst
ECTester-5f0ec2706a9dbb6aa72ea3c7eb798cd83045e867.zip
-rw-r--r--!uploader/simpleECC.capbin18215 -> 18296 bytes
-rw-r--r--README.md39
-rw-r--r--dist/SimpleAPDU.jarbin3078963 -> 470966 bytes
-rw-r--r--lib/commons-cli-1.3.1-javadoc.jarbin0 -> 169756 bytes
-rw-r--r--lib/commons-cli-1.3.1.jarbin0 -> 52988 bytes
-rw-r--r--src/applets/ECKeyGenerator.java5
-rw-r--r--src/applets/SimpleECCApplet.java23
-rw-r--r--src/simpleapdu/CardMngr.java7
-rw-r--r--src/simpleapdu/DirtyLogger.java12
-rw-r--r--src/simpleapdu/SimpleAPDU.java413
10 files changed, 282 insertions, 217 deletions
diff --git a/!uploader/simpleECC.cap b/!uploader/simpleECC.cap
index e76168c..52fef17 100644
--- a/!uploader/simpleECC.cap
+++ b/!uploader/simpleECC.cap
Binary files differ
diff --git a/README.md b/README.md
index df80750..ad76fc1 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Tests support and behavior of smartcards with JavaCard platform with focus on El
Usage
------
1. Upload simpleECC.cap using your favorite tool (e.g., [GlobalPlatformPro tool](https://github.com/martinpaljak/GlobalPlatform))
-2. Run java -jar SimpleAPDU.jar
+2. Run `java -jar SimpleAPDU.jar`
3. Inspect output log with annotated results
Following operations are tested:
@@ -14,24 +14,33 @@ Following operations are tested:
- Generation of keypair with default curve
- Setting of custom curve and keypair generation
- Generation of shared secret via ECDH
-- Behavior of card when invalid curves/points are provided (shoudl fail)
+- Signature via ECDSA
+- Behavior of card when invalid curves/points are provided (should fail)
+
+See `java -jar SimpleAPDU.jar -h` for more.
Example output
--------------
- EC type: ALG_EC_FP
- EC key length (bits): 224 bits
- KeyPair object allocation: OK (0x9000)
- Generate key with def curve (fails if no def): fail (ILLEGAL_VALUE, 0x1)
- Set valid custom curve: OK (0x9000)
- Generate key with valid curve: OK (0x9000)
- !!ECDH agreement with valid point: fail (0x6f00)
- ECDH agreement with invalid point (fail is good): fail (unknown, 0x6f00)
- Set invalid custom curve (fail is good): fail (ILLEGAL_VALUE, 0x1)
- Generate key with invalid curve (fail is good): fail (skipped, 0xee1)
-
-
-*Explanation: ALG_EC_FP with 224b curve was tested. Is supported by card (KeyPair object allocation: OK), don't have preset default curve (Generate key with def curve: fail), custom curve can be set (Set valid custom curve: OK), new keypair can be generated (Generate key with valid curve: OK), ECDH key agreement failed to execute (ECDH agreement with valid point: fail) altough it was supposed to suceed (log line is therefore marked with !!), ECDH wil fail (expected behavior) if invalid point is provided (ECDH agreement with invalid point: fail), invalid custom curve cannot be set (expected behavior) (Set invalid custom curve: fail) and new keypair cannot be generated with invalid curve (Generate key with invalid curve: skipped) - last test was skipped as invalid curve canot be set.*
+ ### Test for support and with valid and invalid EC curves
+ EC type: ALG_EC_FP
+ EC key length (bits): 256 bits
+ KeyPair object allocation: OK (0x9000)
+ Generate key with def curve (fails if no def): OK (0x9000)
+ Set valid custom curve: OK (0x9000)
+ Generate key with valid curve: OK (0x9000)
+ !! ECDH agreement with valid point: fail (unknown, 0x6f00)
+ ECDH agreement with invalid point (fail is good): fail (ILLEGAL_VALUE, 0x 1)
+ ECDSA signature on random data: OK (0x9000)
+ Set anomalous custom curve (may fail): OK (0x9000)
+ Generate key with anomalous curve (may fail): fail (unknown, 0x6f00)
+ ECDH agreement with small order point (fail is good):fail (skipped, 0x ee1)
+ Set invalid custom curve (may fail): OK (0x9000)
+ Generate key with invalid curve (fail is good): fail (unknown, 0x6f00)
+ Set invalid field (may fail): OK (0x9000)
+ Generate key with invalid field (fail si good): fail (unknown, 0x6f00)
+
+*Explanation: ALG_EC_FP with 256b curve was tested. Is supported by card (KeyPair object allocation: OK), don't have preset default curve (Generate key with def curve: fail), custom curve can be set (Set valid custom curve: OK), new keypair can be generated (Generate key with valid curve: OK), ECDH key agreement failed to execute (ECDH agreement with valid point: fail) although it was supposed to succeed (log line is therefore marked with !!), ECDH wil fail (expected behavior) if invalid point is provided (ECDH agreement with invalid point: fail), ECDSA signature worked and verified correctly (ECDSA signature on random data: OK), anomalous curve can be set (Set anomalous custom curve: OK), however generating a key on it will fail (Generate key with anomalous curve: fail), ECDH with small-order public key provided will fail as intended (ECDH agreement with small order point: fail), invalid custom curve could be set (Set invalid custom curve: OK), new keypair cannot be generated with invalid curve (Generate key with invalid curve: fail), invalid field (non-prime) could be set (Set invalid field: OK), however a key could not be generated (Generate key with invalid field: fail).*
If you are interested in testing support for other JavaCard algorithms, please visit JCAlgTester project: https://github.com/crocs-muni/JCAlgTest
diff --git a/dist/SimpleAPDU.jar b/dist/SimpleAPDU.jar
index 09b7e73..1e96259 100644
--- a/dist/SimpleAPDU.jar
+++ b/dist/SimpleAPDU.jar
Binary files differ
diff --git a/lib/commons-cli-1.3.1-javadoc.jar b/lib/commons-cli-1.3.1-javadoc.jar
new file mode 100644
index 0000000..c741ec4
--- /dev/null
+++ b/lib/commons-cli-1.3.1-javadoc.jar
Binary files differ
diff --git a/lib/commons-cli-1.3.1.jar b/lib/commons-cli-1.3.1.jar
new file mode 100644
index 0000000..c3e7a1f
--- /dev/null
+++ b/lib/commons-cli-1.3.1.jar
Binary files differ
diff --git a/src/applets/ECKeyGenerator.java b/src/applets/ECKeyGenerator.java
index c4b71c0..491cd86 100644
--- a/src/applets/ECKeyGenerator.java
+++ b/src/applets/ECKeyGenerator.java
@@ -22,7 +22,6 @@ public class ECKeyGenerator {
public static final byte KEY_BOTH = KEY_PUBLIC | KEY_PRIVATE;
- //TODO: add something like allocateGenerate, or modify allocate to auto-generate a key-pair if it returns null key references after allocating
public short allocatePair(byte keyClass, short keyLength) {
short result = ISO7816.SW_NO_ERROR;
try {
@@ -105,6 +104,10 @@ public class ECKeyGenerator {
return sw;
}
+ public short setCustomAnomalousCurve(short keyClass, short keyLength, byte[] buffer, short offset) {
+ return setCustomCurve(EC_Consts.getAnomalousCurve(keyClass, keyLength), buffer, offset);
+ }
+
public short setParameter(byte key, short param, byte[] data, short offset, short length) {
short result = ISO7816.SW_NO_ERROR;
try {
diff --git a/src/applets/SimpleECCApplet.java b/src/applets/SimpleECCApplet.java
index e63bcf2..ecdfa4e 100644
--- a/src/applets/SimpleECCApplet.java
+++ b/src/applets/SimpleECCApplet.java
@@ -359,7 +359,7 @@ public class SimpleECCApplet extends Applet {
sw = SW_SKIPPED;
if ((testFlags & FLAG_ECTEST_SET_ANOMALOUSCURVE) != (short) 0) {
if (keyClass == KeyPair.ALG_EC_FP) { //Only FP supported at the moment
- sw = ecKeyGenerator.setCustomCurve(EC_Consts.getAnomalousCurve(keyClass, keyLen), m_ramArray, (short) 0);
+ sw = ecKeyGenerator.setCustomAnomalousCurve(keyClass, keyLen, m_ramArray, (short) 0);
}
if (sw != ISO7816.SW_NO_ERROR) {
testFlags &= ~FLAG_ECTEST_GENERATE_KEYPAIR_ANOMALOUSCUVE;
@@ -915,21 +915,30 @@ public class SimpleECCApplet extends Applet {
void GenerateAndReturnKey(APDU apdu) {
byte[] apdubuf = apdu.getBuffer();
apdu.setIncomingAndReceive();
+
+ short offset = ISO7816.OFFSET_CDATA;
+ byte keyClass = apdubuf[offset];
+ offset++;
- short bitLen = Util.getShort(apdubuf, ISO7816.OFFSET_CDATA);
+ short keyLength = Util.getShort(apdubuf, offset);
+ offset+=2;
- short offset = 0;
+ byte anomalous = apdubuf[offset];
+
+ offset = 0;
switch (apdubuf[ISO7816.OFFSET_P1]) {
case P1_SETCURVE: {
- ecKeyGenerator.allocatePair(KeyPair.ALG_EC_FP, bitLen);
+ ecKeyGenerator.allocatePair(keyClass, keyLength);
+ if(anomalous != 0) {
+ ecKeyGenerator.setCustomAnomalousCurve(keyClass, keyLength, m_ramArray, (short) 0);
+ } else {
+ ecKeyGenerator.setCustomCurve(keyClass, keyLength, m_ramArray, (short) 0);
+ }
ecKeyGenerator.generatePair();
ecPubKey = ecKeyGenerator.getPublicKey();
ecPrivKey = ecKeyGenerator.getPrivateKey();
-
- // If required, initialize curve parameters first
- ecKeyGenerator.setCustomCurve(KeyPair.ALG_EC_FP, bitLen, m_ramArray, (short) 0);
break;
}
case P1_GENERATEKEYPAIR: {
diff --git a/src/simpleapdu/CardMngr.java b/src/simpleapdu/CardMngr.java
index d778bc8..ae8bd55 100644
--- a/src/simpleapdu/CardMngr.java
+++ b/src/simpleapdu/CardMngr.java
@@ -105,7 +105,10 @@ public class CardMngr {
return true;
}
-
+
+ public boolean isConnected() {
+ return m_card != null;
+ }
public void DisconnectFromCard() throws Exception {
if (m_card != null) {
@@ -191,7 +194,7 @@ public class CardMngr {
if (responseAPDU.getSW1() == (byte) 0x61) {
CommandAPDU apduToSend = new CommandAPDU((byte) 0x00,
(byte) 0xC0, (byte) 0x00, (byte) 0x00,
- (int) responseAPDU.getSW1());
+ responseAPDU.getSW1());
responseAPDU = m_channel.transmit(apduToSend);
System.out.println(bytesToHex(responseAPDU.getBytes()));
diff --git a/src/simpleapdu/DirtyLogger.java b/src/simpleapdu/DirtyLogger.java
index 69e5e65..c06571b 100644
--- a/src/simpleapdu/DirtyLogger.java
+++ b/src/simpleapdu/DirtyLogger.java
@@ -1,14 +1,7 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
package simpleapdu;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
/**
*
@@ -17,6 +10,7 @@ import java.util.logging.Logger;
public class DirtyLogger {
FileOutputStream m_logFile;
boolean m_bOutputSystemOut = true;
+
public DirtyLogger(FileOutputStream logFile, boolean bOutputSystemOut) {
m_logFile = logFile;
m_bOutputSystemOut = bOutputSystemOut;
@@ -47,4 +41,8 @@ public class DirtyLogger {
} catch (IOException ex) {
}
}
+
+ void close() throws IOException {
+ m_logFile.close();
+ }
}
diff --git a/src/simpleapdu/SimpleAPDU.java b/src/simpleapdu/SimpleAPDU.java
index 44bf302..241ef4c 100644
--- a/src/simpleapdu/SimpleAPDU.java
+++ b/src/simpleapdu/SimpleAPDU.java
@@ -5,7 +5,13 @@ import applets.SimpleECCApplet;
import javacard.framework.ISO7816;
import javacard.security.CryptoException;
import javacard.security.KeyPair;
-import sun.java2d.pipe.SpanShapeRenderer;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
import javax.smartcardio.ResponseAPDU;
import java.io.FileNotFoundException;
@@ -18,13 +24,17 @@ import java.util.Arrays;
* @author Petr Svenda petr@svenda.com
*/
public class SimpleAPDU {
- static CardMngr cardManager = new CardMngr();
+ private CardMngr cardManager = new CardMngr();
+ private DirtyLogger systemOutLogger = null;
+
+ private CommandLineParser cliParser = new DefaultParser();
+ private Options opts = new Options();
+ private static final String cliHeader = "";
+ private static final String cliFooter = "";
private final static byte SELECT_ECTESTERAPPLET[] = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0a,
(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31};
- static DirtyLogger m_SystemOutLogger = null;
-
private static final byte TESTECSUPPORTALL_FP[] = {(byte) 0xB0, (byte) 0x5E, (byte) 0x00, (byte) 0x00, (byte) 0x00};
private static final byte TESTECSUPPORTALL_F2M[] = {(byte) 0xB0, (byte) 0x5F, (byte) 0x00, (byte) 0x00, (byte) 0x00};
private static final byte TESTECSUPPORT_GIVENALG[] = {(byte) 0xB0, (byte) 0x71, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00};
@@ -38,8 +48,104 @@ public class SimpleAPDU {
private static final short INVALIDCURVEB_CORRUPTIONTYPE_OFFSET = 7;
private static final short INVALIDCURVEB_REWINDONSUCCESS_OFFSET = 9;
- private static final byte TESTECSUPPORT_GENERATEECCKEY[] = {(byte) 0xB0, (byte) 0x5a, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00};
+ private static final byte TESTECSUPPORT_GENERATEECCKEY[] = {(byte) 0xB0, (byte) 0x5a, (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
+ private static final short GENERATEECKEY_ALG_OFFSET = 5;
+ private static final short GENERATEECKEY_KEYLENGTH_OFFSET = 6;
+ private static final short GENERATEECKEY_ANOMALOUS_OFFSET = 8;
+
+
+ public void run(String[] args) {
+ try {
+ //parse cmd args
+ CommandLine cli = parseArgs(args);
+
+ //byte[] installData = new byte[10];
+ //byte[] AID = {(byte) 0x4C, (byte) 0x61, (byte) 0x62, (byte) 0x61, (byte) 0x6B, (byte) 0x41, (byte) 0x70, (byte) 0x70, (byte) 0x6C, (byte) 0x65, (byte) 0x74};
+ //cardManager.prepareLocalSimulatorApplet(AID, installData, SimpleECCApplet.class);
+
+ //do stuff
+ if (cli.hasOption("help")) {
+ HelpFormatter help = new HelpFormatter();
+ help.printHelp("SimpleAPDU", cliHeader, opts, cliFooter);
+ } else {
+ //open log(only when actually doing something)
+ String logFileName = cli.getOptionValue("output-file", String.format("ECTESTER_log_%d.log", System.currentTimeMillis()));
+ FileOutputStream stdoutStream = new FileOutputStream(logFileName);
+ systemOutLogger = new DirtyLogger(stdoutStream, true);
+
+ boolean fp = cli.hasOption("fp");
+ boolean f2m = cli.hasOption("f2m");
+ if (!fp && !f2m) {
+ fp = true;
+ f2m = true;
+ }
+ int genAmount = Integer.parseInt(cli.getOptionValue("generate", "0"));
+ int keyLength = Integer.parseInt(cli.getOptionValue("b", "192"));
+
+ if (cli.hasOption("generate")) {
+ //generate EC keys
+ if (fp) {
+ generateECKeys(genAmount, KeyPair.ALG_EC_FP, (short) keyLength, cli.hasOption("anomalous"));
+ }
+ if (f2m) {
+ generateECKeys(genAmount, KeyPair.ALG_EC_F2M, (short) keyLength, cli.hasOption("anomalous"));
+ }
+ } else if (cli.hasOption("test")) {
+ if (cli.hasOption("bit-length")) {
+ //test only one bitsize
+ if (fp) {
+ testSupportECFp((short) keyLength);
+ }
+ if (f2m) {
+ testSupportECFp((short) keyLength);
+ }
+ } else {
+ //test default bit sizes
+ testSupportECAll(fp, f2m);
+ testFPkeyGen((short) 10, EC_Consts.CORRUPTION_ONEBYTERANDOM, true);
+ }
+ } else {
+ systemOutLogger.println("You need to specify one of -t / -g [num] commands.");
+ }
+
+ //close log
+ systemOutLogger.close();
+ }
+ //disconnect
+ cardManager.DisconnectFromCard();
+ } catch (Exception ex) {
+ if (systemOutLogger != null) {
+ systemOutLogger.println("Exception : " + ex);
+ }
+ }
+ }
+
+ private CommandLine parseArgs(String[] args) throws ParseException {
+
+ opts.addOption("h", "help", false, "show this help");
+ opts.addOption(Option.builder("g")
+ .longOpt("generate")
+ .hasArg()
+ .optionalArg(true)
+ .argName("num")
+ .desc("generate EC keys").build());
+ opts.addOption("t", "test", false, "test EC support (default)");
+ opts.addOption(Option.builder("b")
+ .longOpt("bit-length")
+ .hasArg()
+ .argName("bits")
+ .desc("set EC bit size").build());
+ opts.addOption("f2m", "use EC over binary-fields");
+ opts.addOption("fp", "user EC over prime-fields (default)");
+ opts.addOption("s", "anomalous", false, "generate anomalous (non-prime order, small pubkey order) curves");
+ opts.addOption(Option.builder("o")
+ .longOpt("output-file")
+ .hasArg()
+ .argName("file")
+ .desc("output file to log to").build());
+ return cliParser.parse(opts, args);
+ }
static short getShort(byte[] array, int offset) {
return (short) (((array[offset] & 0xFF) << 8) | (array[offset + 1] & 0xFF));
@@ -50,190 +156,125 @@ public class SimpleAPDU {
array[offset] = (byte) ((value >> 8) & 0xFF);
}
- static void testFPkeyGen_setNumRepeats(byte[] apduArray, short numRepeats) {
- setShort(apduArray, INVALIDCURVEB_NUMREPEATS_OFFSET, numRepeats);
- }
-
- static void testFPkeyGen_setCorruptionType(byte[] apduArray, short corruptionType) {
- setShort(apduArray, INVALIDCURVEB_CORRUPTIONTYPE_OFFSET, corruptionType);
- }
-
- static void testFPkeyGen_rewindOnSuccess(byte[] apduArray, boolean bRewind) {
- apduArray[INVALIDCURVEB_REWINDONSUCCESS_OFFSET] = bRewind ? (byte) 1 : (byte) 0;
- }
+ private boolean ReconnnectToCard() throws Exception {
+ if (cardManager.isConnected()) {
+ cardManager.DisconnectFromCard();
+ }
- static CardMngr ReconnnectToCard() throws Exception {
- cardManager.DisconnectFromCard();
- if (cardManager.ConnectToCard()) {
+ boolean result = cardManager.ConnectToCard();
+ if (result) {
// Select our application on card
cardManager.sendAPDU(SELECT_ECTESTERAPPLET);
}
- return cardManager;
+ return result;
+ }
+
+ private void testFPkeyGen(short numRepeats, short corruptionType, boolean bRewind) throws Exception {
+ byte[] apdu = Arrays.copyOf(TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB, TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB.length);
+ setShort(apdu, INVALIDCURVEB_NUMREPEATS_OFFSET, numRepeats);
+ setShort(apdu, INVALIDCURVEB_CORRUPTIONTYPE_OFFSET, corruptionType);
+ apdu[INVALIDCURVEB_REWINDONSUCCESS_OFFSET] = bRewind ? (byte) 1 : (byte) 0;
+
+ ReconnnectToCard();
+ ResponseAPDU resp_fp_keygen = cardManager.sendAPDU(apdu);
+ ResponseAPDU resp_keygen_params = cardManager.sendAPDU(TESTECSUPPORTALL_LASTUSEDPARAMS);
+ PrintECKeyGenInvalidCurveB(resp_fp_keygen);
+ PrintECKeyGenInvalidCurveB_lastUserParams(resp_keygen_params);
}
- static void testSupportECGivenAlg(byte[] apdu, CardMngr cardManager) throws Exception {
+ private void testSupportECGivenAlg(short keyLength, byte keyClass) throws Exception {
+ byte[] apdu = Arrays.copyOf(TESTECSUPPORT_GIVENALG, TESTECSUPPORT_GIVENALG.length);
+ apdu[TESTECSUPPORT_ALG_OFFSET] = keyClass;
+ setShort(apdu, TESTECSUPPORT_KEYLENGTH_OFFSET, keyLength);
+
ReconnnectToCard();
ResponseAPDU resp = cardManager.sendAPDU(apdu);
//byte[] resp = cardManager.sendAPDUSimulator(apdu);
PrintECSupport(resp);
}
- static void testSupportECAll(CardMngr cardManager) throws Exception {
- byte[] testAPDU = Arrays.copyOf(TESTECSUPPORT_GIVENALG, TESTECSUPPORT_GIVENALG.length);
-
- testAPDU[TESTECSUPPORT_ALG_OFFSET] = KeyPair.ALG_EC_FP;
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 128);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 160);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 192);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 224);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 256);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 384);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 521);
- testSupportECGivenAlg(testAPDU, cardManager);
-
- testAPDU[TESTECSUPPORT_ALG_OFFSET] = KeyPair.ALG_EC_F2M;
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 113);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 131);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 163);
- testSupportECGivenAlg(testAPDU, cardManager);
- setShort(testAPDU, TESTECSUPPORT_KEYLENGTH_OFFSET, (short) 193);
- testSupportECGivenAlg(testAPDU, cardManager);
-
+ private void testSupportECFp(short keyLength) throws Exception {
+ testSupportECGivenAlg(keyLength, KeyPair.ALG_EC_FP);
}
- public static void main(String[] args) throws FileNotFoundException, IOException {
- //parse cli args. Should be replaced with some cli parsing library code in the future.
- boolean genKeys = false;
- int genAmount = 0;
- boolean testAll = false;
- if (args.length > 0) {
- for (int i = 0; i < args.length; i++) {
- if (args[i].equals("-g")) {
- genKeys = true;
- if (args.length >= i + 1) {
- try {
- genAmount = Integer.parseInt(args[i + 1]);
- }catch (NumberFormatException ignored) {
- //is another param, genAmount = 0 by default
- genAmount = 0;
- }
+ private void testSupportECF2m(short keyLength) throws Exception {
+ testSupportECGivenAlg(keyLength, KeyPair.ALG_EC_F2M);
+ }
- }
- } else if (args[i].equals("-a")) {
- testAll = true;
- }
- }
+ private void testSupportECAll(boolean testFp, boolean testF2m) throws Exception {
+ if (testFp) {
+ testSupportECFp((short) 128);
+ testSupportECFp((short) 192);
+ testSupportECFp((short) 224);
+ testSupportECFp((short) 256);
+ testSupportECFp((short) 384);
+ testSupportECFp((short) 521);
}
- //by default do the test
- if (!genKeys && !testAll) {
- testAll = true;
+ if (testF2m) {
+ testSupportECF2m((short) 113);
+ testSupportECF2m((short) 131);
+ testSupportECF2m((short) 163);
+ testSupportECF2m((short) 193);
}
+ }
+ private void generateECKeys(int amount, byte keyClass, short keyLength, boolean anomalous) throws Exception {
+ if (cardManager.ConnectToCardSelect()) {
+ cardManager.sendAPDU(SELECT_ECTESTERAPPLET);
- String logFileName = String.format("ECTESTER_log_%d.log", System.currentTimeMillis());
- FileOutputStream systemOutLogger = new FileOutputStream(logFileName);
- m_SystemOutLogger = new DirtyLogger(systemOutLogger, true);
-
- try {
- if (testAll) {
- //byte[] installData = new byte[10];
- //byte[] AID = {(byte) 0x4C, (byte) 0x61, (byte) 0x62, (byte) 0x61, (byte) 0x6B, (byte) 0x41, (byte) 0x70, (byte) 0x70, (byte) 0x6C, (byte) 0x65, (byte) 0x74};
- //cardManager.prepareLocalSimulatorApplet(AID, installData, SimpleECCApplet.class);
- if (cardManager.ConnectToCard()) {
-
- // Test all default curves for both fields
- testSupportECAll(cardManager);
+ String keyFileName = String.format("ECKEYS_%s_%d.log", keyClass == KeyPair.ALG_EC_FP ? "fp" : "f2m", System.currentTimeMillis());
+ FileOutputStream keysFile = new FileOutputStream(keyFileName);
- // Test setting invalid parameter B of curve
- byte[] testAPDU = Arrays.copyOf(TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB, TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB.length);
- testFPkeyGen_setCorruptionType(testAPDU, EC_Consts.CORRUPTION_ONEBYTERANDOM);
- testFPkeyGen_setNumRepeats(testAPDU, (short) 10);
- testFPkeyGen_rewindOnSuccess(testAPDU, true);
+ String message = "index;time;pubW;privS\n";
+ keysFile.write(message.getBytes());
+ byte[] gatherKeyAPDU = Arrays.copyOf(TESTECSUPPORT_GENERATEECCKEY, TESTECSUPPORT_GENERATEECCKEY.length);
+ // Prepare keypair object
+ gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_SETCURVE;
+ gatherKeyAPDU[GENERATEECKEY_ALG_OFFSET] = keyClass;
+ setShort(gatherKeyAPDU, GENERATEECKEY_KEYLENGTH_OFFSET, keyLength);
+ gatherKeyAPDU[GENERATEECKEY_ANOMALOUS_OFFSET] = anomalous ? (byte) 1 : (byte) 0;
+ ResponseAPDU respGather = cardManager.sendAPDU(gatherKeyAPDU);
- ReconnnectToCard();
- ResponseAPDU resp_fp_keygen = cardManager.sendAPDU(testAPDU);
- ResponseAPDU resp_keygen_params = cardManager.sendAPDU(TESTECSUPPORTALL_LASTUSEDPARAMS);
- PrintECKeyGenInvalidCurveB(resp_fp_keygen);
- PrintECKeyGenInvalidCurveB_lastUserParams(resp_keygen_params);
+ // Generate new keypair
+ gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_GENERATEKEYPAIR;
+ int counter = 0;
+ while (true) {
+ counter++;
+ long elapsed = -System.nanoTime();
+ respGather = cardManager.sendAPDU(gatherKeyAPDU);
+ elapsed += System.nanoTime();
- cardManager.DisconnectFromCard();
- } else {
- m_SystemOutLogger.println("Failed to connect to card");
+ byte[] data = respGather.getData();
+ int offset = 0;
+ String pubKeyW = "";
+ String privKeyS = "";
+ if (data[offset] == EC_Consts.TAG_ECPUBKEY) {
+ offset++;
+ short len = getShort(data, offset);
+ offset += 2;
+ pubKeyW = CardMngr.bytesToHex(data, offset, len, false);
+ offset += len;
+ }
+ if (data[offset] == EC_Consts.TAG_ECPRIVKEY) {
+ offset++;
+ short len = getShort(data, offset);
+ offset += 2;
+ privKeyS = CardMngr.bytesToHex(data, offset, len, false);
+ offset += len;
}
- }
-
- if (genKeys) {
- // Gather large number of ECC keypairs
- if (cardManager.ConnectToCardSelect()) {
- cardManager.sendAPDU(SELECT_ECTESTERAPPLET);
-
- String keyFileName = String.format("ECKEYS_%d.log", System.currentTimeMillis());
- FileOutputStream keysFile = new FileOutputStream(keyFileName);
-
- String message = "index;time;pubW;privS\n";
- keysFile.write(message.getBytes());
- byte[] gatherKeyAPDU = Arrays.copyOf(TESTECSUPPORT_GENERATEECCKEY, TESTECSUPPORT_GENERATEECCKEY.length);
- // Prepare keypair object
- gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_SETCURVE;
- setShort(gatherKeyAPDU, (short) 5, (short) 192); // ecc length
- ResponseAPDU respGather = cardManager.sendAPDU(gatherKeyAPDU);
-
- // Generate new keypair
- gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_GENERATEKEYPAIR;
- int counter = 0;
- while (true) {
- counter++;
- long elapsed = -System.nanoTime();
- respGather = cardManager.sendAPDU(gatherKeyAPDU);
- elapsed += System.nanoTime();
-
- byte[] data = respGather.getData();
- int offset = 0;
- String pubKeyW = "";
- String privKeyS = "";
- if (data[offset] == EC_Consts.TAG_ECPUBKEY) {
- offset++;
- short len = getShort(data, offset);
- offset += 2;
- pubKeyW = CardMngr.bytesToHex(data, offset, len, false);
- offset += len;
- }
- if (data[offset] == EC_Consts.TAG_ECPRIVKEY) {
- offset++;
- short len = getShort(data, offset);
- offset += 2;
- privKeyS = CardMngr.bytesToHex(data, offset, len, false);
- offset += len;
- }
- message = String.format("%d;%d;%s;%s\n", counter, elapsed / 1000000, pubKeyW, privKeyS);
- keysFile.write(message.getBytes());
+ message = String.format("%d;%d;%s;%s\n", counter, elapsed / 1000000, pubKeyW, privKeyS);
+ keysFile.write(message.getBytes());
- m_SystemOutLogger.flush();
- keysFile.flush();
+ this.systemOutLogger.flush();
+ keysFile.flush();
- //stop when we have enough keys, go on forever with 0
- if (counter >= genAmount && genAmount != 0)
- break;
- }
- }
+ //stop when we have enough keys, go on forever with 0
+ if (counter >= amount && amount != 0)
+ break;
}
-
-
- } catch (Exception ex) {
- m_SystemOutLogger.println("Exception : " + ex);
}
-
- systemOutLogger.close();
}
static String getPrintError(short code) {
@@ -278,12 +319,12 @@ public class SimpleAPDU {
MUST_FAIL
}
- static int VerifyPrintResult(String message, byte expectedTag, byte[] buffer, int bufferOffset, ExpResult expRes) {
+ private int VerifyPrintResult(String message, byte expectedTag, byte[] buffer, int bufferOffset, ExpResult expRes) {
if (bufferOffset >= buffer.length) {
- m_SystemOutLogger.println(" No more data returned");
+ systemOutLogger.println(" No more data returned");
} else {
if (buffer[bufferOffset] != expectedTag) {
- m_SystemOutLogger.println(" ERROR: mismatched tag");
+ systemOutLogger.println(" ERROR: mismatched tag");
assert (buffer[bufferOffset] == expectedTag);
}
bufferOffset++;
@@ -298,22 +339,21 @@ public class SimpleAPDU {
bHiglight = true;
}
if (bHiglight) {
- m_SystemOutLogger.println(String.format("!! %-50s%s", message, getPrintError(resCode)));
+ systemOutLogger.println(String.format("!! %-53s%s", message, getPrintError(resCode)));
} else {
- m_SystemOutLogger.println(String.format(" %-50s%s", message, getPrintError(resCode)));
+ systemOutLogger.println(String.format(" %-53s%s", message, getPrintError(resCode)));
}
}
return bufferOffset;
}
- static void PrintECSupport(ResponseAPDU resp) {
+ private void PrintECSupport(ResponseAPDU resp) {
PrintECSupport(resp.getData());
}
- static void PrintECSupport(byte[] buffer) {
-
- m_SystemOutLogger.println();
- m_SystemOutLogger.println("### Test for support and with valid and invalid EC curves");
+ private void PrintECSupport(byte[] buffer) {
+ systemOutLogger.println();
+ systemOutLogger.println("### Test for support and with valid and invalid EC curves");
int bufferOffset = 0;
while (bufferOffset < buffer.length) {
assert (buffer[bufferOffset] == SimpleECCApplet.ECTEST_SEPARATOR);
@@ -325,10 +365,10 @@ public class SimpleAPDU {
if (buffer[bufferOffset] == KeyPair.ALG_EC_F2M) {
ecType = "ALG_EC_F2M";
}
- m_SystemOutLogger.println(String.format("%-53s%s", "EC type:", ecType));
+ systemOutLogger.println(String.format("%-56s%s", "EC type:", ecType));
bufferOffset++;
short keyLen = getShort(buffer, bufferOffset);
- m_SystemOutLogger.println(String.format("%-53s%d bits", "EC key length (bits):", keyLen));
+ systemOutLogger.println(String.format("%-56s%d bits", "EC key length (bits):", keyLen));
bufferOffset += 2;
bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED);
@@ -346,18 +386,17 @@ public class SimpleAPDU {
bufferOffset = VerifyPrintResult("Set invalid field (may fail):", SimpleECCApplet.ECTEST_SET_INVALIDFIELD, buffer, bufferOffset, ExpResult.MAY_FAIL);
bufferOffset = VerifyPrintResult("Generate key with invalid field (fail si good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDFIELD, buffer, bufferOffset, ExpResult.MUST_FAIL);
- m_SystemOutLogger.println();
+ systemOutLogger.println();
}
}
- static void PrintECKeyGenInvalidCurveB(ResponseAPDU resp) {
+ private void PrintECKeyGenInvalidCurveB(ResponseAPDU resp) {
PrintECKeyGenInvalidCurveB(resp.getData());
}
- static void PrintECKeyGenInvalidCurveB(byte[] buffer) {
-
- m_SystemOutLogger.println();
- m_SystemOutLogger.println("### Test for computation with invalid parameter B for EC curve");
+ private void PrintECKeyGenInvalidCurveB(byte[] buffer) {
+ systemOutLogger.println();
+ systemOutLogger.println("### Test for computation with invalid parameter B for EC curve");
int bufferOffset = 0;
while (bufferOffset < buffer.length) {
assert (buffer[bufferOffset] == SimpleECCApplet.ECTEST_SEPARATOR);
@@ -369,15 +408,15 @@ public class SimpleAPDU {
if (buffer[bufferOffset] == KeyPair.ALG_EC_F2M) {
ecType = "ALG_EC_F2M";
}
- m_SystemOutLogger.println(String.format("%-53s%s", "EC type:", ecType));
+ systemOutLogger.println(String.format("%-53s%s", "EC type:", ecType));
bufferOffset++;
short keyLen = getShort(buffer, bufferOffset);
- m_SystemOutLogger.println(String.format("%-53s%d bits", "EC key length (bits):", keyLen));
+ systemOutLogger.println(String.format("%-53s%d bits", "EC key length (bits):", keyLen));
bufferOffset += 2;
short numRepeats = getShort(buffer, bufferOffset);
bufferOffset += 2;
- m_SystemOutLogger.println(String.format("%-53s%d times", "Executed repeats before unexpected error: ", numRepeats));
+ systemOutLogger.println(String.format("%-53s%d times", "Executed repeats before unexpected error: ", numRepeats));
bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED);
while (bufferOffset < buffer.length) {
@@ -390,18 +429,22 @@ public class SimpleAPDU {
bufferOffset = VerifyPrintResult("Generate key with valid curve:", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED);
}
- m_SystemOutLogger.println();
+ systemOutLogger.println();
}
}
- static void PrintECKeyGenInvalidCurveB_lastUserParams(ResponseAPDU resp) {
+ private void PrintECKeyGenInvalidCurveB_lastUserParams(ResponseAPDU resp) {
byte[] buffer = resp.getData();
short offset = 0;
- m_SystemOutLogger.print("Last used value of B: ");
+ systemOutLogger.print("Last used value of B: ");
while (offset < buffer.length) {
- m_SystemOutLogger.print(String.format("%x ", buffer[offset]));
+ systemOutLogger.print(String.format("%x ", buffer[offset]));
offset++;
}
+ }
+ public static void main(String[] args) throws FileNotFoundException, IOException {
+ SimpleAPDU app = new SimpleAPDU();
+ app.run(args);
}
}