diff options
| author | J08nY | 2017-04-19 01:10:17 +0200 |
|---|---|---|
| committer | J08nY | 2017-04-19 01:10:17 +0200 |
| commit | a7eef06134bef0861e43261640d61153ebb2a6e5 (patch) | |
| tree | 2ef308843b4e8b1770be6681c15b98dcd78d40ff /src/cz/crcs/ectester/reader/ECTester.java | |
| parent | f4a66768ed6dfcfd7156ad0c8c364cdbf6e45e9c (diff) | |
| download | ECTester-a7eef06134bef0861e43261640d61153ebb2a6e5.tar.gz ECTester-a7eef06134bef0861e43261640d61153ebb2a6e5.tar.zst ECTester-a7eef06134bef0861e43261640d61153ebb2a6e5.zip | |
Diffstat (limited to 'src/cz/crcs/ectester/reader/ECTester.java')
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTester.java | 666 |
1 files changed, 310 insertions, 356 deletions
diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java index 6965d14..8afda17 100644 --- a/src/cz/crcs/ectester/reader/ECTester.java +++ b/src/cz/crcs/ectester/reader/ECTester.java @@ -44,47 +44,7 @@ public class ECTester { private CardMngr cardManager; private DirtyLogger systemOutLogger; private EC_Store dataStore; - - //Options - private int optBits; - private boolean optAll; - private boolean optPrimeField = false; - private boolean optBinaryField = false; - - private String optNamedCurve = null; - private String optCurveFile = null; - private boolean optCustomCurve = false; - - private boolean optAnyPublic = false; - private String optNamedPublic = null; - private String optPublic = null; - - private boolean optAnyPrivate = false; - private String optNamedPrivate = null; - private String optPrivate = null; - - private boolean optAnyKey = false; - private String optNamedKey = null; - private String optKey = null; - - private boolean optAnyKeypart = false; - - private String optLog = null; - - private boolean optVerbose = false; - private String optInput = null; - private String optOutput = null; - private boolean optFresh = false; - private boolean optSimulate = false; - - //Action-related options - private String optListNamed; - private String optTestSuite; - private int optGenerateAmount; - private int optECDHCount; - private byte optECDHKA; - private int optECDSACount; - + private Config cfg; private Options opts = new Options(); private static final String CLI_HEADER = "\nECTester, a javacard Elliptic Curve Cryptograhy support tester/utility.\n\n"; @@ -104,8 +64,10 @@ public class ECTester { help(); return; } + cfg = new Config(); + //if not, read other options first, into attributes, then do action - if (!readOptions(cli)) { + if (!cfg.readOptions(cli)) { return; } @@ -117,10 +79,10 @@ public class ECTester { } //init CardManager - cardManager = new CardMngr(optVerbose, optSimulate); + cardManager = new CardMngr(cfg.verbose, cfg.simulate); //connect or simulate connection - if (optSimulate) { + if (cfg.simulate) { if (!cardManager.prepareLocalSimulatorApplet(AID, INSTALL_DATA, ECTesterApplet.class)) { System.err.println("Failed to establish a simulator."); System.exit(1); @@ -133,7 +95,7 @@ public class ECTester { cardManager.send(SELECT_ECTESTERAPPLET); } - systemOutLogger = new DirtyLogger(optLog, true); + systemOutLogger = new DirtyLogger(cfg.log, true); //do action if (cli.hasOption("export")) { @@ -208,7 +170,7 @@ public class ECTester { * -dh / --ecdh [count] * -dhc / --ecdhc [count] * -dsa / --ecdsa [count] - * -ln / --list-named + * -ln / --list-named [obj] * * Options: * -b / --bit-size <b> // -a / --all @@ -292,193 +254,25 @@ public class ECTester { } /** - * Reads and validates options, also sets defaults. - * - * @param cli cli object, with parsed args - * @return whether the options are valid. - */ - private boolean readOptions(CommandLine cli) { - optBits = Integer.parseInt(cli.getOptionValue("bit-size", "0")); - optAll = cli.hasOption("all"); - optPrimeField = cli.hasOption("fp"); - optBinaryField = cli.hasOption("f2m"); - - optNamedCurve = cli.getOptionValue("named-curve"); - optCustomCurve = cli.hasOption("custom"); - optCurveFile = cli.getOptionValue("curve"); - - optNamedPublic = cli.getOptionValue("named-public"); - optPublic = cli.getOptionValue("public"); - optAnyPublic = (optPublic != null) || (optNamedPublic != null); - - optNamedPrivate = cli.getOptionValue("named-private"); - optPrivate = cli.getOptionValue("private"); - optAnyPrivate = (optPrivate != null) || (optNamedPrivate != null); - - optNamedKey = cli.getOptionValue("named-key"); - optKey = cli.getOptionValue("key"); - optAnyKey = (optKey != null) || (optNamedKey != null); - optAnyKeypart = optAnyKey || optAnyPublic || optAnyPrivate; - - if (cli.hasOption("log")) { - optLog = cli.getOptionValue("log", String.format("ECTESTER_log_%d.log", System.currentTimeMillis() / 1000)); - } - - optVerbose = cli.hasOption("verbose"); - optInput = cli.getOptionValue("input"); - optOutput = cli.getOptionValue("output"); - optFresh = cli.hasOption("fresh"); - optSimulate = cli.hasOption("simulate"); - - if (cli.hasOption("list-named")) { - optListNamed = cli.getOptionValue("list-named"); - return true; - } - - if ((optKey != null || optNamedKey != null) && (optPublic != null || optPrivate != null || optNamedPublic != null || optNamedPrivate != null)) { - System.err.print("Can only specify the whole key with --key/--named-key or pubkey and privkey with --public/--named-public and --private/--named-private."); - return false; - } - if (optBits < 0) { - System.err.println("Bit-size must not be negative."); - return false; - } - if (optBits == 0 && !optAll) { - System.err.println("You must specify either bit-size with -b or all bit-sizes with -a."); - return false; - } - - if (optKey != null && optNamedKey != null || optPublic != null && optNamedPublic != null || optPrivate != null && optNamedPrivate != null) { - System.err.println("You cannot specify both a named key and a key file."); - return false; - } - - if (cli.hasOption("export")) { - if (optPrimeField == optBinaryField) { - System.err.print("Need to specify field with -fp or -f2m. (not both)"); - return false; - } - if (optAnyKeypart) { - System.err.println("Keys should not be specified when exporting curve params."); - return false; - } - if (optNamedCurve != null || optCustomCurve || optCurveFile != null) { - System.err.println("Specifying a curve for curve export makes no sense."); - return false; - } - if (optOutput == null) { - System.err.println("You have to specify an output file for curve parameter export."); - return false; - } - if (optAll) { - System.err.println("You have to specify curve bit-size with -b"); - return false; - } - - } else if (cli.hasOption("generate")) { - if (optPrimeField == optBinaryField) { - System.err.print("Need to specify field with -fp or -f2m. (not both)"); - return false; - } - if (optAnyKeypart) { - System.err.println("Keys should not be specified when generating keys."); - return false; - } - if (optOutput == null) { - System.err.println("You have to specify an output file for the key generation process."); - return false; - } - if (optAll) { - System.err.println("You have to specify curve bit-size with -b"); - return false; - } - - optGenerateAmount = Integer.parseInt(cli.getOptionValue("generate", "0")); - if (optGenerateAmount < 0) { - System.err.println("Amount of keys generated cant be negative."); - return false; - } - } else if (cli.hasOption("test")) { - if (!optBinaryField && !optPrimeField) { - optBinaryField = true; - optPrimeField = true; - } - - optTestSuite = cli.getOptionValue("test", "default").toLowerCase(); - String[] tests = new String[]{"default", "nonprime", "invalid", "test-vectors", "wrong"}; - List<String> testsList = Arrays.asList(tests); - if (!testsList.contains(optTestSuite)) { - System.err.println("Unknown test case. Should be one of: " + Arrays.toString(tests)); - return false; - } - - } else if (cli.hasOption("ecdh") || cli.hasOption("ecdhc")) { - if (optPrimeField == optBinaryField) { - System.err.print("Need to specify field with -fp or -f2m. (not both)"); - return false; - } - if (optAll) { - System.err.println("You have to specify curve bit-size with -b"); - return false; - } - - if (cli.hasOption("ecdh")) { - optECDHCount = Integer.parseInt(cli.getOptionValue("ecdh", "1")); - optECDHKA = EC_Consts.KA_ECDH; - } else if (cli.hasOption("ecdhc")) { - optECDHCount = Integer.parseInt(cli.getOptionValue("ecdhc", "1")); - optECDHKA = EC_Consts.KA_ECDHC; - } - if (optECDHCount <= 0) { - System.err.println("ECDH count cannot be <= 0."); - return false; - } - - } else if (cli.hasOption("ecdsa")) { - if (optPrimeField == optBinaryField) { - System.err.print("Need to specify field with -fp or -f2m. (but not both)"); - return false; - } - if (optAll) { - System.err.println("You have to specify curve bit-size with -b"); - return false; - } - - if ((optAnyPublic) != (optAnyPrivate) && !optAnyKey) { - System.err.println("You cannot only specify a part of a keypair."); - return false; - } - - optECDSACount = Integer.parseInt(cli.getOptionValue("ecdsa", "1")); - if (optECDSACount <= 0) { - System.err.println("ECDSA count cannot be <= 0."); - return false; - } - } - - return true; - } - - /** * List categories and named curves. */ private void list() { Map<String, EC_Category> categories = dataStore.getCategories(); - if (optListNamed == null) { + if (cfg.listNamed == null) { // print all categories, briefly for (EC_Category cat : categories.values()) { System.out.println(cat); } - } else if (categories.containsKey(optListNamed)) { + } else if (categories.containsKey(cfg.listNamed)) { // print given category - System.out.println(categories.get(optListNamed)); + System.out.println(categories.get(cfg.listNamed)); } else { // print given object - EC_Data object = dataStore.getObject(EC_Data.class, optListNamed); + EC_Data object = dataStore.getObject(EC_Data.class, cfg.listNamed); if (object != null) { System.out.println(object); } else { - System.err.println("Named object " + optListNamed + " not found!"); + System.err.println("Named object " + cfg.listNamed + " not found!"); } } } @@ -499,17 +293,17 @@ public class ECTester { * @throws IOException if an IO error occurs when writing to key file. */ private void export() throws CardException, IOException { - byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; + byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; List<Response> sent = new LinkedList<>(); - sent.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass).send()); + sent.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send()); sent.add(new Command.Clear(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send()); sent.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send()); // Cofactor generally isn't set on the default curve parameters on cards, // since its not necessary for ECDH, only ECDHC which not many cards implement // TODO: check if its assumend to be == 1? - short domainAll = optPrimeField ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; + short domainAll = cfg.primeField ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; short domain = (short) (domainAll ^ EC_Consts.PARAMETER_K); Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domainAll).send(); if (!export.successful()) { @@ -521,7 +315,7 @@ public class ECTester { EC_Params exported = new EC_Params(domain, export.getParams()); - FileOutputStream out = new FileOutputStream(optOutput); + FileOutputStream out = new FileOutputStream(cfg.output); exported.writeCSV(out); out.close(); } @@ -533,18 +327,18 @@ public class ECTester { * @throws IOException if an IO error occurs when writing to key file. */ private void generate() throws CardException, IOException { - byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; + byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass).send(); - List<Command> curve = prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass); + new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass).send(); + List<Command> curve = prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) cfg.bits, keyClass); - FileWriter keysFile = new FileWriter(optOutput); + FileWriter keysFile = new FileWriter(cfg.output); keysFile.write("index;time;pubW;privS\n"); int generated = 0; int retry = 0; - while (generated < optGenerateAmount || optGenerateAmount == 0) { - if (optFresh || generated == 0) { + while (generated < cfg.generateAmount || cfg.generateAmount == 0) { + if (cfg.fresh || generated == 0) { Command.sendAll(curve); } @@ -583,19 +377,20 @@ public class ECTester { */ private void test() throws IOException, CardException { List<Command> commands = new LinkedList<>(); + TestSuite suite = null; - if (optTestSuite.equals("default")) { + if (cfg.testSuite.equals("default")) { commands.add(new Command.Support(cardManager)); - if (optNamedCurve != null) { - if (optPrimeField) { - commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_FP)); + if (cfg.namedCurve != null) { + if (cfg.primeField) { + commands.addAll(testCurves(cfg.namedCurve, KeyPair.ALG_EC_FP)); } - if (optBinaryField) { - commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_F2M)); + if (cfg.binaryField) { + commands.addAll(testCurves(cfg.namedCurve, KeyPair.ALG_EC_F2M)); } } else { - if (optAll) { - if (optPrimeField) { + 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)); @@ -604,7 +399,7 @@ public class ECTester { commands.add(new Command.Cleanup(cardManager)); } } - if (optBinaryField) { + 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)); @@ -614,60 +409,31 @@ public class ECTester { } } } else { - if (optPrimeField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); + 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 (optBinaryField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); + 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 (optTestSuite.equals("test-vectors")) { + } 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. * */ - 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()); - if (optNamedCurve != null && !(result.getCurve().startsWith(optNamedCurve) || result.getCurve().equals(optNamedCurve))) { - continue; - } - if (curve.getBits() != optBits && !optAll) { - continue; - } - EC_Params onekey = dataStore.getObject(EC_Keypair.class, result.getOneKey()); - if (onekey == null) { - onekey = dataStore.getObject(EC_Key.Private.class, result.getOneKey()); - } - EC_Params otherkey = dataStore.getObject(EC_Keypair.class, result.getOtherKey()); - if (otherkey == null) { - otherkey = dataStore.getObject(EC_Key.Public.class, result.getOtherKey()); - } - if (onekey == null || otherkey == null) { - throw new IOException("Test vector keys not located"); - } - - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField())); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten())); - commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, onekey.flatten(EC_Consts.PARAMETER_S))); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_W, otherkey.flatten(EC_Consts.PARAMETER_W))); - commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, result.getKA())); - //TODO add compare with result.getParam(0); - commands.add(new Command.Cleanup(cardManager)); - } + suite = new TestSuite.TestVectors(dataStore, cfg); } else { // These tests are dangerous, prompt before them. - System.out.println("The test you selected (" + optTestSuite + ") is potentially dangerous."); + 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); @@ -677,62 +443,40 @@ public class ECTester { } in.close(); - if (optTestSuite.equals("wrong")) { + if (cfg.testSuite.equals("wrong")) { /* Just do the default tests on the wrong curves. * These should generally fail, the curves aren't safe. */ - if (optPrimeField) { - commands.addAll(testCurves(optTestSuite, KeyPair.ALG_EC_FP)); + if (cfg.primeField) { + commands.addAll(testCurves(cfg.testSuite, KeyPair.ALG_EC_FP)); } - if (optBinaryField) { - commands.addAll(testCurves(optTestSuite, KeyPair.ALG_EC_F2M)); + if (cfg.binaryField) { + commands.addAll(testCurves(cfg.testSuite, KeyPair.ALG_EC_F2M)); } - } else if (optTestSuite.equals("nonprime")) { + } 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. */ - 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()); - if ((curve.getBits() == optBits || optAll)) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField())); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten())); - commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL)); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, key.getParams(), key.flatten())); - commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDH)); - commands.add(new Command.Cleanup(cardManager)); - } - } - } else if (optTestSuite.equals("invalid")) { + 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. */ - 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()); - if (optNamedCurve != null && !(key.getCurve().startsWith(optNamedCurve) || key.getCurve().equals(optNamedCurve))) { - continue; - } - if (curve.getBits() != optBits && !optAll) { - continue; - } - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField())); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten())); - commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL)); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, key.getParams(), key.flatten())); - commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_BOTH)); - //commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_NONE, EC_Consts.KA_ECDHC)); - commands.add(new Command.Cleanup(cardManager)); - - } + suite = new TestSuite.Invalid(dataStore, cfg); } } List<Response> test = Command.sendAll(commands); - systemOutLogger.println(Response.toString(test, optTestSuite)); + if (suite != null) { + List<Test> tests = suite.run(cardManager); + for (Test t : tests) { + System.out.println(t); + } + } + systemOutLogger.println(Response.toString(test, cfg.testSuite)); } @@ -743,34 +487,34 @@ public class ECTester { * @throws IOException if an IO error occurs when writing to key file. */ private void ecdh() throws IOException, CardException { - byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; + 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) optBits, keyClass).send()); - prepare.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass))); + 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))); systemOutLogger.println(Response.toString(prepare)); - byte pubkey = (optAnyPublic || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; - byte privkey = (optAnyPrivate || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + byte pubkey = (cfg.anyPublicKey || cfg.anyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + byte privkey = (cfg.anyPrivateKey || cfg.anyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; List<Command> generate = new LinkedList<>(); generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); - if (optAnyPublic || optAnyPrivate || optAnyKey) { + if (cfg.anyPublicKey || cfg.anyPrivateKey || cfg.anyKey) { generate.add(prepareKey(ECTesterApplet.KEYPAIR_REMOTE)); } FileWriter out = null; - if (optOutput != null) { - out = new FileWriter(optOutput); + if (cfg.output != null) { + out = new FileWriter(cfg.output); out.write("index;time;secret\n"); } int retry = 0; int done = 0; - while (done < optECDHCount) { + while (done < cfg.ECDHCount) { List<Response> ecdh = Command.sendAll(generate); - Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, optECDHKA).send(); + Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, cfg.ECDHKA).send(); ecdh.add(perform); systemOutLogger.println(Response.toString(ecdh)); @@ -804,38 +548,38 @@ public class ECTester { private void ecdsa() throws CardException, IOException { //read file, if asked to sign byte[] data = null; - if (optInput != null) { - File in = new File(optInput); + if (cfg.input != null) { + File in = new File(cfg.input); long len = in.length(); if (len == 0) { - throw new FileNotFoundException(optInput); + throw new FileNotFoundException(cfg.input); } data = Files.readAllBytes(in.toPath()); } Command generate; - if (optAnyKeypart) { + if (cfg.anyKeypart) { generate = prepareKey(ECTesterApplet.KEYPAIR_LOCAL); } else { generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL); } - byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; + 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) optBits, keyClass).send()); - prepare.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass))); + 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))); systemOutLogger.println(Response.toString(prepare)); FileWriter out = null; - if (optOutput != null) { - out = new FileWriter(optOutput); + if (cfg.output != null) { + out = new FileWriter(cfg.output); out.write("index;time;signature\n"); } int retry = 0; int done = 0; - while (done < optECDSACount) { + while (done < cfg.ECDSACount) { List<Response> ecdsa = new LinkedList<>(); ecdsa.add(generate.send()); @@ -873,14 +617,14 @@ public class ECTester { private List<Command> prepareCurve(byte keyPair, short keyLength, byte keyClass) throws IOException { List<Command> commands = new ArrayList<>(); - if (optCustomCurve) { + 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 (optNamedCurve != null) { + } else if (cfg.namedCurve != null) { // Set a named curve. - // parse optNamedCurve -> cat / id | cat | id - EC_Curve curve = dataStore.getObject(EC_Curve.class, optNamedCurve); + // 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."); } @@ -893,11 +637,11 @@ public class ECTester { 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 (optCurveFile != null) { + } else if (cfg.curveFile != null) { // Set curve loaded from a file - EC_Curve curve = new EC_Curve(keyLength, keyClass); + EC_Curve curve = new EC_Curve(null, keyLength, keyClass); - FileInputStream in = new FileInputStream(optCurveFile); + FileInputStream in = new FileInputStream(cfg.curveFile); curve.readCSV(in); in.close(); @@ -927,17 +671,17 @@ public class ECTester { short params = EC_Consts.PARAMETERS_NONE; byte[] data = null; - if (optKey != null || optNamedKey != null) { + if (cfg.key != null || cfg.namedKey != null) { params |= EC_Consts.PARAMETERS_KEYPAIR; EC_Params keypair; - if (optKey != null) { + if (cfg.key != null) { keypair = new EC_Params(EC_Consts.PARAMETERS_KEYPAIR); - FileInputStream in = new FileInputStream(optKey); + FileInputStream in = new FileInputStream(cfg.key); keypair.readCSV(in); in.close(); } else { - keypair = dataStore.getObject(EC_Keypair.class, optNamedKey); + keypair = dataStore.getObject(EC_Keypair.class, cfg.namedKey); } data = keypair.flatten(); @@ -946,19 +690,19 @@ public class ECTester { } } - if (optPublic != null || optNamedPublic != null) { + if (cfg.publicKey != null || cfg.namedPublicKey != null) { params |= EC_Consts.PARAMETER_W; EC_Params pub; - if (optPublic != null) { + if (cfg.publicKey != null) { pub = new EC_Params(EC_Consts.PARAMETER_W); - FileInputStream in = new FileInputStream(optPublic); + FileInputStream in = new FileInputStream(cfg.publicKey); pub.readCSV(in); in.close(); } else { - pub = dataStore.getObject(EC_Key.Public.class, optNamedPublic); + pub = dataStore.getObject(EC_Key.Public.class, cfg.namedPublicKey); if (pub == null) { - pub = dataStore.getObject(EC_Keypair.class, optNamedPublic); + pub = dataStore.getObject(EC_Keypair.class, cfg.namedPublicKey); } } @@ -968,19 +712,19 @@ public class ECTester { } data = pubkey; } - if (optPrivate != null || optNamedPrivate != null) { + if (cfg.privateKey != null || cfg.namedPrivateKey != null) { params |= EC_Consts.PARAMETER_S; EC_Params priv; - if (optPrivate != null) { + if (cfg.privateKey != null) { priv = new EC_Params(EC_Consts.PARAMETER_S); - FileInputStream in = new FileInputStream(optPrivate); + FileInputStream in = new FileInputStream(cfg.privateKey); priv.readCSV(in); in.close(); } else { - priv = dataStore.getObject(EC_Key.Public.class, optNamedPrivate); + priv = dataStore.getObject(EC_Key.Public.class, cfg.namedPrivateKey); if (priv == null) { - priv = dataStore.getObject(EC_Keypair.class, optNamedPrivate); + priv = dataStore.getObject(EC_Keypair.class, cfg.namedPrivateKey); } } @@ -1022,7 +766,7 @@ public class ECTester { return commands; for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) { EC_Curve curve = entry.getValue(); - if (curve.getField() == field && (curve.getBits() == optBits || optAll)) { + 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()); @@ -1037,4 +781,214 @@ public class ECTester { ECTester app = new ECTester(); app.run(args); } + + public static class Config { + + //Options + public int bits; + public boolean all; + public boolean primeField = false; + public boolean binaryField = false; + + public String namedCurve; + public String curveFile; + public boolean customCurve = false; + + public boolean anyPublicKey = false; + public String namedPublicKey; + public String publicKey; + + public boolean anyPrivateKey = false; + public String namedPrivateKey; + public String privateKey; + + public boolean anyKey = false; + public String namedKey; + public String key; + + public boolean anyKeypart = false; + + public String log; + + public boolean verbose = false; + public String input; + public String output; + public boolean fresh = false; + public boolean simulate = false; + + //Action-related ions + public String listNamed; + public String testSuite; + public int generateAmount; + public int ECDHCount; + public byte ECDHKA; + public int ECDSACount; + + /** + * Reads and validates options, also sets defaults. + * + * @param cli cli object, with parsed args + * @return whether the options are valid. + */ + public boolean readOptions(CommandLine cli) { + bits = Integer.parseInt(cli.getOptionValue("bit-size", "0")); + all = cli.hasOption("all"); + primeField = cli.hasOption("fp"); + binaryField = cli.hasOption("f2m"); + + namedCurve = cli.getOptionValue("named-curve"); + customCurve = cli.hasOption("custom"); + curveFile = cli.getOptionValue("curve"); + + namedPublicKey = cli.getOptionValue("named-public"); + publicKey = cli.getOptionValue("public"); + anyPublicKey = (publicKey != null) || (namedPublicKey != null); + + namedPrivateKey = cli.getOptionValue("named-private"); + privateKey = cli.getOptionValue("private"); + anyPrivateKey = (privateKey != null) || (namedPrivateKey != null); + + namedKey = cli.getOptionValue("named-key"); + key = cli.getOptionValue("key"); + anyKey = (key != null) || (namedKey != null); + anyKeypart = anyKey || anyPublicKey || anyPrivateKey; + + if (cli.hasOption("log")) { + log = cli.getOptionValue("log", String.format("ECTESTER_log_%d.log", System.currentTimeMillis() / 1000)); + } + + verbose = cli.hasOption("verbose"); + input = cli.getOptionValue("input"); + output = cli.getOptionValue("output"); + fresh = cli.hasOption("fresh"); + simulate = cli.hasOption("simulate"); + + if (cli.hasOption("list-named")) { + listNamed = cli.getOptionValue("list-named"); + return true; + } + + if ((key != null || namedKey != null) && (anyPublicKey || anyPrivateKey)) { + System.err.print("Can only specify the whole key with --key/--named-key or pubkey and privkey with --public/--named-public and --private/--named-private."); + return false; + } + if (bits < 0) { + System.err.println("Bit-size must not be negative."); + return false; + } + if (bits == 0 && !all) { + System.err.println("You must specify either bit-size with -b or all bit-sizes with -a."); + return false; + } + + if (key != null && namedKey != null || publicKey != null && namedPublicKey != null || privateKey != null && namedPrivateKey != null) { + System.err.println("You cannot specify both a named key and a key file."); + return false; + } + + if (cli.hasOption("export")) { + if (primeField == binaryField) { + System.err.print("Need to specify field with -fp or -f2m. (not both)"); + return false; + } + if (anyKeypart) { + System.err.println("Keys should not be specified when exporting curve params."); + return false; + } + if (namedCurve != null || customCurve || curveFile != null) { + System.err.println("Specifying a curve for curve export makes no sense."); + return false; + } + if (output == null) { + System.err.println("You have to specify an output file for curve parameter export."); + return false; + } + if (all) { + System.err.println("You have to specify curve bit-size with -b"); + return false; + } + + } else if (cli.hasOption("generate")) { + if (primeField == binaryField) { + System.err.print("Need to specify field with -fp or -f2m. (not both)"); + return false; + } + if (anyKeypart) { + System.err.println("Keys should not be specified when generating keys."); + return false; + } + if (output == null) { + System.err.println("You have to specify an output file for the key generation process."); + return false; + } + if (all) { + System.err.println("You have to specify curve bit-size with -b"); + return false; + } + + generateAmount = Integer.parseInt(cli.getOptionValue("generate", "0")); + if (generateAmount < 0) { + System.err.println("Amount of keys generated cant be negative."); + return false; + } + } else if (cli.hasOption("test")) { + if (!binaryField && primeField) { + binaryField = true; + primeField = true; + } + + testSuite = cli.getOptionValue("test", "default").toLowerCase(); + String[] tests = new String[]{"default", "nonprime", "invalid", "test-vectors", "wrong"}; + List<String> testsList = Arrays.asList(tests); + if (!testsList.contains(testSuite)) { + System.err.println("Unknown test case. Should be one of: " + Arrays.toString(tests)); + return false; + } + + } else if (cli.hasOption("ecdh") || cli.hasOption("ecdhc")) { + if (primeField == binaryField) { + System.err.print("Need to specify field with -fp or -f2m. (not both)"); + return false; + } + if (all) { + System.err.println("You have to specify curve bit-size with -b"); + return false; + } + + if (cli.hasOption("ecdh")) { + ECDHCount = Integer.parseInt(cli.getOptionValue("ecdh", "1")); + ECDHKA = EC_Consts.KA_ECDH; + } else if (cli.hasOption("ecdhc")) { + ECDHCount = Integer.parseInt(cli.getOptionValue("ecdhc", "1")); + ECDHKA = EC_Consts.KA_ECDHC; + } + if (ECDHCount <= 0) { + System.err.println("ECDH count cannot be <= 0."); + return false; + } + + } else if (cli.hasOption("ecdsa")) { + if (primeField == binaryField) { + System.err.print("Need to specify field with -fp or -f2m. (but not both)"); + return false; + } + if (all) { + System.err.println("You have to specify curve bit-size with -b"); + return false; + } + + if ((anyPublicKey) != (anyPrivateKey) && !anyKey) { + System.err.println("You cannot only specify a part of a keypair."); + return false; + } + + ECDSACount = Integer.parseInt(cli.getOptionValue("ecdsa", "1")); + if (ECDSACount <= 0) { + System.err.println("ECDSA count cannot be <= 0."); + return false; + } + } + return true; + } + } } |
