diff options
| author | J08nY | 2017-04-27 15:13:55 +0200 |
|---|---|---|
| committer | J08nY | 2017-04-27 15:13:55 +0200 |
| commit | 6238d40a1fa44bfbaa251620eb83c3aa803d626e (patch) | |
| tree | eac84abf044e72eaa593556ec826c3f1899d3e9f /src | |
| parent | 3aaead661e2b23b5e5811a3a06daed61db638a72 (diff) | |
| download | ECTester-6238d40a1fa44bfbaa251620eb83c3aa803d626e.tar.gz ECTester-6238d40a1fa44bfbaa251620eb83c3aa803d626e.tar.zst ECTester-6238d40a1fa44bfbaa251620eb83c3aa803d626e.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/cz/crcs/ectester/reader/Command.java | 144 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTester.java | 334 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/TestSuite.java | 131 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Util.java | 12 |
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; |
