aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/reader/ECTester.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz/crcs/ectester/reader/ECTester.java')
-rw-r--r--src/cz/crcs/ectester/reader/ECTester.java334
1 files changed, 53 insertions, 281 deletions
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;
}