aboutsummaryrefslogtreecommitdiff
path: root/src/cz
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz')
-rw-r--r--src/cz/crcs/ectester/reader/Command.java144
-rw-r--r--src/cz/crcs/ectester/reader/ECTester.java334
-rw-r--r--src/cz/crcs/ectester/reader/TestSuite.java131
-rw-r--r--src/cz/crcs/ectester/reader/Util.java12
4 files changed, 335 insertions, 286 deletions
diff --git a/src/cz/crcs/ectester/reader/Command.java b/src/cz/crcs/ectester/reader/Command.java
index 73f4987..b65159a 100644
--- a/src/cz/crcs/ectester/reader/Command.java
+++ b/src/cz/crcs/ectester/reader/Command.java
@@ -1,10 +1,19 @@
package cz.crcs.ectester.reader;
import cz.crcs.ectester.applet.ECTesterApplet;
+import cz.crcs.ectester.applet.EC_Consts;
+import cz.crcs.ectester.data.EC_Store;
+import cz.crcs.ectester.reader.ec.EC_Curve;
+import cz.crcs.ectester.reader.ec.EC_Key;
+import cz.crcs.ectester.reader.ec.EC_Keypair;
+import cz.crcs.ectester.reader.ec.EC_Params;
+import javacard.security.KeyPair;
import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -33,6 +42,139 @@ public abstract class Command {
return result;
}
+
+ /**
+ * @param keyPair which keyPair/s (local/remote) to set curve domain parameters on
+ * @param keyLength key length to choose
+ * @param keyClass key class to choose
+ * @return a list of Commands to send in order to prepare the curve on the keypairs.
+ * @throws IOException if curve file cannot be found/opened
+ */
+ public static List<Command> prepareCurve(CardMngr cardManager, EC_Store dataStore, ECTester.Config cfg, byte keyPair, short keyLength, byte keyClass) throws IOException {
+ List<Command> commands = new ArrayList<>();
+
+ if (cfg.customCurve) {
+ // Set custom curve (one of the SECG curves embedded applet-side)
+ short domainParams = keyClass == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
+ commands.add(new Command.Set(cardManager, keyPair, EC_Consts.getCurve(keyLength, keyClass), domainParams, null));
+ } else if (cfg.namedCurve != null) {
+ // Set a named curve.
+ // parse cfg.namedCurve -> cat / id | cat | id
+ EC_Curve curve = dataStore.getObject(EC_Curve.class, cfg.namedCurve);
+ if (curve == null) {
+ throw new IOException("Curve could no be found.");
+ }
+ if (curve.getBits() != keyLength) {
+ throw new IOException("Curve bits mismatch: " + curve.getBits() + " vs " + keyLength + " entered.");
+ }
+
+ byte[] external = curve.flatten();
+ if (external == null) {
+ throw new IOException("Couldn't read named curve data.");
+ }
+ commands.add(new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, curve.getParams(), external));
+ } else if (cfg.curveFile != null) {
+ // Set curve loaded from a file
+ EC_Curve curve = new EC_Curve(null, keyLength, keyClass);
+
+ FileInputStream in = new FileInputStream(cfg.curveFile);
+ curve.readCSV(in);
+ in.close();
+
+ byte[] external = curve.flatten();
+ if (external == null) {
+ throw new IOException("Couldn't read the curve file correctly.");
+ }
+ commands.add(new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, curve.getParams(), external));
+ } else {
+ // Set default curve
+ /* This command was generally causing problems for simulating on jcardsim.
+ * Since there, .clearKey() resets all the keys values, even the domain.
+ * This might break some other stuff.. But should not.
+ */
+ //commands.add(new Command.Clear(cardManager, keyPair));
+ }
+
+ return commands;
+ }
+
+
+ /**
+ * @param keyPair which keyPair/s to set the key params on
+ * @return a CommandAPDU setting params loaded on the keyPair/s
+ * @throws IOException if any of the key files cannot be found/opened
+ */
+ public static Command prepareKey(CardMngr cardManager, EC_Store dataStore, ECTester.Config cfg, byte keyPair) throws IOException {
+ short params = EC_Consts.PARAMETERS_NONE;
+ byte[] data = null;
+
+ if (cfg.key != null || cfg.namedKey != null) {
+ params |= EC_Consts.PARAMETERS_KEYPAIR;
+ EC_Params keypair;
+ if (cfg.key != null) {
+ keypair = new EC_Params(EC_Consts.PARAMETERS_KEYPAIR);
+
+ FileInputStream in = new FileInputStream(cfg.key);
+ keypair.readCSV(in);
+ in.close();
+ } else {
+ keypair = dataStore.getObject(EC_Keypair.class, cfg.namedKey);
+ }
+
+ data = keypair.flatten();
+ if (data == null) {
+ throw new IOException("Couldn't read the key file correctly.");
+ }
+ }
+
+ if (cfg.publicKey != null || cfg.namedPublicKey != null) {
+ params |= EC_Consts.PARAMETER_W;
+ EC_Params pub;
+ if (cfg.publicKey != null) {
+ pub = new EC_Params(EC_Consts.PARAMETER_W);
+
+ FileInputStream in = new FileInputStream(cfg.publicKey);
+ pub.readCSV(in);
+ in.close();
+ } else {
+ pub = dataStore.getObject(EC_Key.Public.class, cfg.namedPublicKey);
+ if (pub == null) {
+ pub = dataStore.getObject(EC_Keypair.class, cfg.namedPublicKey);
+ }
+ }
+
+ byte[] pubkey = pub.flatten(EC_Consts.PARAMETER_W);
+ if (pubkey == null) {
+ throw new IOException("Couldn't read the public key file correctly.");
+ }
+ data = pubkey;
+ }
+ if (cfg.privateKey != null || cfg.namedPrivateKey != null) {
+ params |= EC_Consts.PARAMETER_S;
+ EC_Params priv;
+ if (cfg.privateKey != null) {
+ priv = new EC_Params(EC_Consts.PARAMETER_S);
+
+ FileInputStream in = new FileInputStream(cfg.privateKey);
+ priv.readCSV(in);
+ in.close();
+ } else {
+ priv = dataStore.getObject(EC_Key.Public.class, cfg.namedPrivateKey);
+ if (priv == null) {
+ priv = dataStore.getObject(EC_Keypair.class, cfg.namedPrivateKey);
+ }
+ }
+
+ byte[] privkey = priv.flatten(EC_Consts.PARAMETER_S);
+ if (privkey == null) {
+ throw new IOException("Couldn't read the private key file correctly.");
+ }
+ data = Util.concatenate(data, privkey);
+ }
+ return new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, params, data);
+ }
+
+
/**
*
*/
@@ -329,7 +471,6 @@ public abstract class Command {
public static class Cleanup extends Command {
/**
- *
* @param cardManager cardManager to send APDU through
*/
protected Cleanup(CardMngr cardManager) {
@@ -353,7 +494,6 @@ public abstract class Command {
public static class Support extends Command {
/**
- *
* @param cardManager cardManager to send APDU through
*/
protected Support(CardMngr cardManager) {
diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java
index 9191b70..33d1b7f 100644
--- a/src/cz/crcs/ectester/reader/ECTester.java
+++ b/src/cz/crcs/ectester/reader/ECTester.java
@@ -24,7 +24,9 @@ package cz.crcs.ectester.reader;
import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.data.EC_Store;
-import cz.crcs.ectester.reader.ec.*;
+import cz.crcs.ectester.reader.ec.EC_Category;
+import cz.crcs.ectester.reader.ec.EC_Data;
+import cz.crcs.ectester.reader.ec.EC_Params;
import javacard.security.KeyPair;
import org.apache.commons.cli.*;
@@ -45,6 +47,7 @@ public class ECTester {
private DirtyLogger systemOutLogger;
private EC_Store dataStore;
private Config cfg;
+ private TestSuite[] testSuites;
private Options opts = new Options();
private static final String CLI_HEADER = "\nECTester, a javacard Elliptic Curve Cryptograhy support tester/utility.\n\n";
@@ -254,6 +257,15 @@ public class ECTester {
}
/**
+ * Prints help.
+ */
+ private void help() {
+ HelpFormatter help = new HelpFormatter();
+ help.setOptionComparator(null);
+ help.printHelp("ECTester.jar", CLI_HEADER, opts, CLI_FOOTER, true);
+ }
+
+ /**
* List categories and named curves.
*/
private void list() {
@@ -278,15 +290,6 @@ public class ECTester {
}
/**
- * Prints help.
- */
- private void help() {
- HelpFormatter help = new HelpFormatter();
- help.setOptionComparator(null);
- help.printHelp("ECTester.jar", CLI_HEADER, opts, CLI_FOOTER, true);
- }
-
- /**
* Exports default card/simulation EC domain parameters to output file.
*
* @throws CardException if APDU transmission fails
@@ -330,7 +333,7 @@ public class ECTester {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send();
- List<Command> curve = prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass);
+ List<Command> curve = Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass);
FileWriter keysFile = new FileWriter(cfg.output);
keysFile.write("index;time;pubW;privS\n");
@@ -376,105 +379,44 @@ public class ECTester {
* @throws IOException if an IO error occurs when writing to key file.
*/
private void test() throws IOException, CardException {
- List<Command> commands = new LinkedList<>();
- TestSuite suite = null;
+ TestSuite suite;
- if (cfg.testSuite.equals("default")) {
- commands.add(new Command.Support(cardManager));
- if (cfg.namedCurve != null) {
- if (cfg.primeField) {
- commands.addAll(testCurves(cfg.namedCurve, KeyPair.ALG_EC_FP));
- }
- if (cfg.binaryField) {
- commands.addAll(testCurves(cfg.namedCurve, KeyPair.ALG_EC_F2M));
+ switch (cfg.testSuite) {
+ case "default":
+ suite = new TestSuite.Default(dataStore, cfg);
+ break;
+ case "test-vectors":
+ suite = new TestSuite.TestVectors(dataStore, cfg);
+ break;
+ default:
+ // These tests are dangerous, prompt before them.
+ System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous.");
+ System.out.println("Some of these tests have caused temporary DoS of some cards.");
+ System.out.print("Do you want to proceed? (y/n): ");
+ Scanner in = new Scanner(System.in);
+ String confirmation = in.nextLine();
+ if (!Arrays.asList("yes", "YES", "y", "Y").contains(confirmation)) {
+ return;
}
- } else {
- if (cfg.all) {
- if (cfg.primeField) {
- //iterate over prime curve sizes used: EC_Consts.FP_SIZES
- for (short keyLength : EC_Consts.FP_SIZES) {
- commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP));
- commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP));
- commands.addAll(testCurve());
- commands.add(new Command.Cleanup(cardManager));
- }
- }
- if (cfg.binaryField) {
- //iterate over binary curve sizes used: EC_Consts.F2M_SIZES
- for (short keyLength : EC_Consts.F2M_SIZES) {
- commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M));
- commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M));
- commands.addAll(testCurve());
- commands.add(new Command.Cleanup(cardManager));
- }
- }
- } else {
- if (cfg.primeField) {
- commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_FP));
- commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_FP));
- commands.addAll(testCurve());
- commands.add(new Command.Cleanup(cardManager));
- }
-
- if (cfg.binaryField) {
- commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_F2M));
- commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_F2M));
- commands.addAll(testCurve());
- commands.add(new Command.Cleanup(cardManager));
- }
- }
- }
- } else if (cfg.testSuite.equals("test-vectors")) {
- /* Set original curves (secg/nist/brainpool). Set keypairs from test vectors.
- * Do ECDH both ways, export and verify that the result is correct.
- *
- */
- suite = new TestSuite.TestVectors(dataStore, cfg);
-
- } else {
- // These tests are dangerous, prompt before them.
- System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous.");
- System.out.println("Some of these tests have caused temporary DoS of some cards.");
- System.out.print("Do you want to proceed? (y/n): ");
- Scanner in = new Scanner(System.in);
- String confirmation = in.nextLine();
- if (!Arrays.asList("yes", "y", "Y").contains(confirmation)) {
- return;
- }
- in.close();
+ in.close();
- if (cfg.testSuite.equals("wrong")) {
- /* Just do the default tests on the wrong curves.
- * These should generally fail, the curves aren't safe.
- */
- if (cfg.primeField) {
- commands.addAll(testCurves(cfg.testSuite, KeyPair.ALG_EC_FP));
- }
- if (cfg.binaryField) {
- commands.addAll(testCurves(cfg.testSuite, KeyPair.ALG_EC_F2M));
+ switch (cfg.testSuite) {
+ case "wrong":
+ suite = new TestSuite.Wrong(dataStore, cfg);
+ break;
+ case "nonprime":
+ suite = new TestSuite.NonPrime(dataStore, cfg);
+ break;
+ case "invalid":
+ suite = new TestSuite.Invalid(dataStore, cfg);
+ break;
+ default:
+ System.err.println("Unknown test suite.");
+ return;
}
- } else if (cfg.testSuite.equals("nonprime")) {
- /* Do the default tests with the public keys set to provided nonprime keys.
- * These should fail, the curves aren't safe so that if the computation with
- * a small order public key succeeds the private key modulo the public key order
- * is revealed.
- */
- suite = new TestSuite.NonPrime(dataStore, cfg);
- } else if (cfg.testSuite.equals("invalid")) {
- /* Set original curves (secg/nist/brainpool). Generate local.
- * Try ECDH with invalid public keys of increasing (or decreasing) order.
- */
- suite = new TestSuite.Invalid(dataStore, cfg);
- }
+ break;
}
-
-
- List<Response> test = Command.sendAll(commands);
- if (suite != null) {
- suite.run(cardManager);
- }
- systemOutLogger.println(Response.toString(test, cfg.testSuite));
-
+ suite.run(cardManager);
}
/**
@@ -487,7 +429,7 @@ public class ECTester {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
List<Response> prepare = new LinkedList<>();
prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, keyClass).send());
- prepare.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, keyClass)));
+ prepare.addAll(Command.sendAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, keyClass)));
systemOutLogger.println(Response.toString(prepare));
@@ -497,7 +439,7 @@ public class ECTester {
List<Command> generate = new LinkedList<>();
generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH));
if (cfg.anyPublicKey || cfg.anyPrivateKey || cfg.anyKey) {
- generate.add(prepareKey(ECTesterApplet.KEYPAIR_REMOTE));
+ generate.add(Command.prepareKey(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_REMOTE));
}
FileWriter out = null;
@@ -556,7 +498,7 @@ public class ECTester {
Command generate;
if (cfg.anyKeypart) {
- generate = prepareKey(ECTesterApplet.KEYPAIR_LOCAL);
+ generate = Command.prepareKey(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_LOCAL);
} else {
generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL);
}
@@ -564,7 +506,7 @@ public class ECTester {
byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
List<Response> prepare = new LinkedList<>();
prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send());
- prepare.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass)));
+ prepare.addAll(Command.sendAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass)));
systemOutLogger.println(Response.toString(prepare));
@@ -604,176 +546,6 @@ public class ECTester {
out.close();
}
- /**
- * @param keyPair which keyPair/s (local/remote) to set curve domain parameters on
- * @param keyLength key length to choose
- * @param keyClass key class to choose
- * @return a list of Commands to send in order to prepare the curve on the keypairs.
- * @throws IOException if curve file cannot be found/opened
- */
- private List<Command> prepareCurve(byte keyPair, short keyLength, byte keyClass) throws IOException {
- List<Command> commands = new ArrayList<>();
-
- if (cfg.customCurve) {
- // Set custom curve (one of the SECG curves embedded applet-side)
- short domainParams = keyClass == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M;
- commands.add(new Command.Set(cardManager, keyPair, EC_Consts.getCurve(keyLength, keyClass), domainParams, null));
- } else if (cfg.namedCurve != null) {
- // Set a named curve.
- // parse cfg.namedCurve -> cat / id | cat | id
- EC_Curve curve = dataStore.getObject(EC_Curve.class, cfg.namedCurve);
- if (curve == null) {
- throw new IOException("Curve could no be found.");
- }
- if (curve.getBits() != keyLength) {
- throw new IOException("Curve bits mismatch: " + curve.getBits() + " vs " + keyLength + " entered.");
- }
-
- byte[] external = curve.flatten();
- if (external == null) {
- throw new IOException("Couldn't read named curve data.");
- }
- commands.add(new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, curve.getParams(), external));
- } else if (cfg.curveFile != null) {
- // Set curve loaded from a file
- EC_Curve curve = new EC_Curve(null, keyLength, keyClass);
-
- FileInputStream in = new FileInputStream(cfg.curveFile);
- curve.readCSV(in);
- in.close();
-
- byte[] external = curve.flatten();
- if (external == null) {
- throw new IOException("Couldn't read the curve file correctly.");
- }
- commands.add(new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, curve.getParams(), external));
- } else {
- // Set default curve
- /* This command was generally causing problems for simulating on jcardsim.
- * Since there, .clearKey() resets all the keys values, even the domain.
- * This might break some other stuff.. But should not.
- */
- //commands.add(new Command.Clear(cardManager, keyPair));
- }
-
- return commands;
- }
-
- /**
- * @param keyPair which keyPair/s to set the key params on
- * @return a CommandAPDU setting params loaded on the keyPair/s
- * @throws IOException if any of the key files cannot be found/opened
- */
- private Command prepareKey(byte keyPair) throws IOException {
- short params = EC_Consts.PARAMETERS_NONE;
- byte[] data = null;
-
- if (cfg.key != null || cfg.namedKey != null) {
- params |= EC_Consts.PARAMETERS_KEYPAIR;
- EC_Params keypair;
- if (cfg.key != null) {
- keypair = new EC_Params(EC_Consts.PARAMETERS_KEYPAIR);
-
- FileInputStream in = new FileInputStream(cfg.key);
- keypair.readCSV(in);
- in.close();
- } else {
- keypair = dataStore.getObject(EC_Keypair.class, cfg.namedKey);
- }
-
- data = keypair.flatten();
- if (data == null) {
- throw new IOException("Couldn't read the key file correctly.");
- }
- }
-
- if (cfg.publicKey != null || cfg.namedPublicKey != null) {
- params |= EC_Consts.PARAMETER_W;
- EC_Params pub;
- if (cfg.publicKey != null) {
- pub = new EC_Params(EC_Consts.PARAMETER_W);
-
- FileInputStream in = new FileInputStream(cfg.publicKey);
- pub.readCSV(in);
- in.close();
- } else {
- pub = dataStore.getObject(EC_Key.Public.class, cfg.namedPublicKey);
- if (pub == null) {
- pub = dataStore.getObject(EC_Keypair.class, cfg.namedPublicKey);
- }
- }
-
- byte[] pubkey = pub.flatten(EC_Consts.PARAMETER_W);
- if (pubkey == null) {
- throw new IOException("Couldn't read the public key file correctly.");
- }
- data = pubkey;
- }
- if (cfg.privateKey != null || cfg.namedPrivateKey != null) {
- params |= EC_Consts.PARAMETER_S;
- EC_Params priv;
- if (cfg.privateKey != null) {
- priv = new EC_Params(EC_Consts.PARAMETER_S);
-
- FileInputStream in = new FileInputStream(cfg.privateKey);
- priv.readCSV(in);
- in.close();
- } else {
- priv = dataStore.getObject(EC_Key.Public.class, cfg.namedPrivateKey);
- if (priv == null) {
- priv = dataStore.getObject(EC_Keypair.class, cfg.namedPrivateKey);
- }
- }
-
- byte[] privkey = priv.flatten(EC_Consts.PARAMETER_S);
- if (privkey == null) {
- throw new IOException("Couldn't read the private key file correctly.");
- }
- data = Util.concatenate(data, privkey);
- }
- return new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, params, data);
- }
-
- /**
- * @return
- * @throws IOException if an IO error occurs when writing to key file.
- */
- private List<Command> testCurve() throws IOException {
- List<Command> commands = new LinkedList<>();
- commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ONE, EC_Consts.KA_ECDH));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ZERO, EC_Consts.KA_ECDH));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_MAX, EC_Consts.KA_ECDH));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_FULLRANDOM, EC_Consts.KA_ECDH));
- commands.add(new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, null));
- return commands;
- }
-
- /**
- * @param category
- * @param field
- * @return
- * @throws IOException if an IO error occurs when writing to key file.
- */
- private List<Command> testCurves(String category, byte field) throws IOException {
- List<Command> commands = new LinkedList<>();
- Map<String, EC_Curve> curves = dataStore.getObjects(EC_Curve.class, category);
- if (curves == null)
- return commands;
- for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) {
- EC_Curve curve = entry.getValue();
- if (curve.getField() == field && (curve.getBits() == cfg.bits || cfg.all)) {
- commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), field));
- commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()));
- commands.addAll(testCurve());
- commands.add(new Command.Cleanup(cardManager));
- }
- }
-
- return commands;
- }
-
public static void main(String[] args) {
ECTester app = new ECTester();
app.run(args);
@@ -827,7 +599,7 @@ public class ECTester {
* @param cli cli object, with parsed args
* @return whether the options are valid.
*/
- public boolean readOptions(CommandLine cli) {
+ boolean readOptions(CommandLine cli) {
bits = Integer.parseInt(cli.getOptionValue("bit-size", "0"));
all = cli.hasOption("all");
primeField = cli.hasOption("fp");
@@ -929,7 +701,7 @@ public class ECTester {
return false;
}
} else if (cli.hasOption("test")) {
- if (!binaryField && primeField) {
+ if (!(binaryField || primeField)) {
binaryField = true;
primeField = true;
}
diff --git a/src/cz/crcs/ectester/reader/TestSuite.java b/src/cz/crcs/ectester/reader/TestSuite.java
index 56e0a4a..047b7f6 100644
--- a/src/cz/crcs/ectester/reader/TestSuite.java
+++ b/src/cz/crcs/ectester/reader/TestSuite.java
@@ -4,6 +4,7 @@ import cz.crcs.ectester.applet.ECTesterApplet;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.ec.*;
+import javacard.security.KeyPair;
import javax.smartcardio.CardException;
import java.io.IOException;
@@ -23,7 +24,7 @@ public abstract class TestSuite {
boolean hasRun;
List<Test> tests = new LinkedList<>();
- public TestSuite(EC_Store dataStore, ECTester.Config cfg, String name) {
+ TestSuite(EC_Store dataStore, ECTester.Config cfg, String name) {
this.dataStore = dataStore;
this.cfg = cfg;
this.name = name;
@@ -50,6 +51,46 @@ public abstract class TestSuite {
return name;
}
+ /**
+ * @return
+ * @throws IOException if an IO error occurs when writing to key file.
+ */
+ List<Command> testCurve(CardMngr cardManager) throws IOException {
+ List<Command> commands = new LinkedList<>();
+ commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ONE, EC_Consts.KA_ECDH));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ZERO, EC_Consts.KA_ECDH));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_MAX, EC_Consts.KA_ECDH));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_FULLRANDOM, EC_Consts.KA_ECDH));
+ commands.add(new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, null));
+ return commands;
+ }
+
+ /**
+ * @param category
+ * @param field
+ * @return
+ * @throws IOException if an IO error occurs when writing to key file.
+ */
+ List<Command> testCurves(CardMngr cardManager, String category, byte field) throws IOException {
+ List<Command> commands = new LinkedList<>();
+ Map<String, EC_Curve> curves = dataStore.getObjects(EC_Curve.class, category);
+ if (curves == null)
+ return commands;
+ for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) {
+ EC_Curve curve = entry.getValue();
+ if (curve.getField() == field && (curve.getBits() == cfg.bits || cfg.all)) {
+ commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), field));
+ commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()));
+ commands.addAll(testCurve(cardManager));
+ commands.add(new Command.Cleanup(cardManager));
+ }
+ }
+
+ return commands;
+ }
+
public static class Default extends TestSuite {
public Default(EC_Store dataStore, ECTester.Config cfg) {
@@ -57,7 +98,55 @@ public abstract class TestSuite {
}
@Override
- public List<Test> run(CardMngr cardManager) {
+ public List<Test> run(CardMngr cardManager) throws IOException, CardException {
+ //TODO: Convert TestSuire.Default to Tests
+ List<Command> commands = new LinkedList<>();
+ commands.add(new Command.Support(cardManager));
+ if (cfg.namedCurve != null) {
+ if (cfg.primeField) {
+ commands.addAll(testCurves(cardManager, cfg.namedCurve, KeyPair.ALG_EC_FP));
+ }
+ if (cfg.binaryField) {
+ commands.addAll(testCurves(cardManager, cfg.namedCurve, KeyPair.ALG_EC_F2M));
+ }
+ } else {
+ if (cfg.all) {
+ if (cfg.primeField) {
+ //iterate over prime curve sizes used: EC_Consts.FP_SIZES
+ for (short keyLength : EC_Consts.FP_SIZES) {
+ commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP));
+ commands.addAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP));
+ commands.addAll(testCurve(cardManager));
+ commands.add(new Command.Cleanup(cardManager));
+ }
+ }
+ if (cfg.binaryField) {
+ //iterate over binary curve sizes used: EC_Consts.F2M_SIZES
+ for (short keyLength : EC_Consts.F2M_SIZES) {
+ commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M));
+ commands.addAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M));
+ commands.addAll(testCurve(cardManager));
+ commands.add(new Command.Cleanup(cardManager));
+ }
+ }
+ } else {
+ if (cfg.primeField) {
+ commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_FP));
+ commands.addAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_FP));
+ commands.addAll(testCurve(cardManager));
+ commands.add(new Command.Cleanup(cardManager));
+ }
+
+ if (cfg.binaryField) {
+ commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_F2M));
+ commands.addAll(Command.prepareCurve(cardManager, dataStore, cfg, ECTesterApplet.KEYPAIR_BOTH, (short) cfg.bits, KeyPair.ALG_EC_F2M));
+ commands.addAll(testCurve(cardManager));
+ commands.add(new Command.Cleanup(cardManager));
+ }
+ }
+ }
+ List<Response> test = Command.sendAll(commands);
+ System.out.println(Response.toString(test));
return null;
}
}
@@ -70,7 +159,9 @@ public abstract class TestSuite {
@Override
public List<Test> run(CardMngr cardManager) throws IOException, CardException {
-
+ /* Set original curves (secg/nist/brainpool). Set keypairs from test vectors.
+ * Do ECDH both ways, export and verify that the result is correct.
+ */
Map<String, EC_KAResult> results = dataStore.getObjects(EC_KAResult.class, "test");
for (EC_KAResult result : results.values()) {
EC_Curve curve = dataStore.getObject(EC_Curve.class, result.getCurve());
@@ -122,6 +213,12 @@ public abstract class TestSuite {
@Override
public List<Test> run(CardMngr cardManager) throws IOException, CardException {
+ /* Do the default tests with the public keys set to provided smallorder keys
+ * over non-prime order curves. Essentially small subgroup attacks.
+ * These should fail, the curves aren't safe so that if the computation with
+ * a small order public key succeeds the private key modulo the public key order
+ * is revealed.
+ */
Map<String, EC_Key> keys = dataStore.getObjects(EC_Key.class, "nonprime");
for (EC_Key key : keys.values()) {
EC_Curve curve = dataStore.getObject(EC_Curve.class, key.getCurve());
@@ -146,6 +243,9 @@ public abstract class TestSuite {
@Override
public List<Test> run(CardMngr cardManager) throws IOException, CardException {
+ /* Set original curves (secg/nist/brainpool). Generate local.
+ * Try ECDH with invalid public keys of increasing (or decreasing) order.
+ */
Map<String, EC_Key.Public> pubkeys = dataStore.getObjects(EC_Key.Public.class, "invalid");
for (EC_Key.Public key : pubkeys.values()) {
EC_Curve curve = dataStore.getObject(EC_Curve.class, key.getCurve());
@@ -165,4 +265,29 @@ public abstract class TestSuite {
return super.run(cardManager);
}
}
+
+ public static class Wrong extends TestSuite {
+
+ public Wrong(EC_Store dataStore, ECTester.Config cfg) {
+ super(dataStore, cfg, "wrong");
+ }
+
+ @Override
+ public List<Test> run(CardMngr cardManager) throws IOException, CardException {
+ /* Just do the default tests on the wrong curves.
+ * These should generally fail, the curves aren't curves.
+ */
+ //TODO: Convert TestSuire.Wrong to Tests
+ List<Command> commands = new LinkedList<>();
+ if (cfg.primeField) {
+ commands.addAll(testCurves(cardManager, cfg.testSuite, KeyPair.ALG_EC_FP));
+ }
+ if (cfg.binaryField) {
+ commands.addAll(testCurves(cardManager, cfg.testSuite, KeyPair.ALG_EC_F2M));
+ }
+ List<Response> test = Command.sendAll(commands);
+ System.out.println(Response.toString(test));
+ return null;
+ }
+ }
}
diff --git a/src/cz/crcs/ectester/reader/Util.java b/src/cz/crcs/ectester/reader/Util.java
index 6fe3b8e..21d4992 100644
--- a/src/cz/crcs/ectester/reader/Util.java
+++ b/src/cz/crcs/ectester/reader/Util.java
@@ -306,6 +306,18 @@ public class Util {
case EC_Consts.CORRUPTION_INFINITY:
corrupt = "INFINITY";
break;
+ case EC_Consts.CORRUPTION_PREFIX_COMPRESSED:
+ corrupt = "COMPRESSED";
+ break;
+ case EC_Consts.CORRUPTION_PREFIX_HYBRID:
+ corrupt = "HYBRID";
+ break;
+ case EC_Consts.CORRUPTION_PREFIX_UNCOMPRESSED:
+ corrupt = "UNCOMPRESSED";
+ break;
+ case EC_Consts.CORRUPTION_MAX:
+ corrupt = "MAX";
+ break;
default:
corrupt = "unknown";
break;