diff options
| author | J08nY | 2017-02-20 20:46:59 +0100 |
|---|---|---|
| committer | J08nY | 2017-02-21 15:25:19 +0100 |
| commit | 66bd8469e56cbe7c6bed823b376229a02ecdd37d (patch) | |
| tree | 58854c07799445dc998c951a464897089e62a80f /src/cz/crcs/ectester/reader | |
| parent | abe9f00e15993d55a71b8b328f430421f2f2f151 (diff) | |
| download | ECTester-66bd8469e56cbe7c6bed823b376229a02ecdd37d.tar.gz ECTester-66bd8469e56cbe7c6bed823b376229a02ecdd37d.tar.zst ECTester-66bd8469e56cbe7c6bed823b376229a02ecdd37d.zip | |
removed newlines, changed f2m format, removed old SimpleAPDU
data:
- now truly csv
- f2m format now:
m,e_1,e_2,e_3,a,b,gx,gy,r,k,wx,wy,s
reader:
- removed SimpleAPDU
- changed f2m format
applet:
- changed f2m format
Diffstat (limited to 'src/cz/crcs/ectester/reader')
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECParams.java | 34 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTester.java | 86 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Response.java | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/SimpleAPDU.java | 459 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Util.java | 24 |
5 files changed, 102 insertions, 502 deletions
diff --git a/src/cz/crcs/ectester/reader/ECParams.java b/src/cz/crcs/ectester/reader/ECParams.java index c19640e..76347b1 100644 --- a/src/cz/crcs/ectester/reader/ECParams.java +++ b/src/cz/crcs/ectester/reader/ECParams.java @@ -13,7 +13,7 @@ import java.util.regex.Pattern; * @author Jan Jancar johny@neuromancer.sk */ public class ECParams { - private static final Pattern hex = Pattern.compile("[a-fA-F\\d]+"); + private static final Pattern hex = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); /** * Flattens params read from String[] data into a byte[] with their lengths prepended as short entries. @@ -34,12 +34,12 @@ public class ECParams { short masked = (short) (params & paramMask); if (masked != 0) { byte[] param = parse(data[i]); - if (masked == EC_Consts.PARAMETER_F2M && data.length == 9) { - //read and pad and append e_2, e_3 - param = Util.concatenate(param, parse(data[i + 1]), parse(data[i + 2])); - i += 2; - if (param.length != 6) - throw new RuntimeException("PARAMETER_F2M length is not 6.(should be)"); + if (masked == EC_Consts.PARAMETER_F2M) { + //add m, e_1, e_2, e_3 + param = Util.concatenate(param, parse(data[i + 1]), parse(data[i + 2]), parse(data[i + 3])); + i += 3; + if (param.length != 8) + throw new RuntimeException("PARAMETER_F2M length is not 8.(should be)"); } if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { //read another param (the y coord) and put into X962 format. @@ -80,12 +80,13 @@ public class ECParams { byte[] param = data[index]; if (masked == EC_Consts.PARAMETER_F2M) { - //split into three shorts - if (param.length != 6) { - throw new RuntimeException("PARAMETER_F2M length is not 6.(should be)"); + //split into m, e1, [e2, e3] + if (!((param.length == 4) || (param.length == 8))) { + throw new RuntimeException("PARAMETER_F2M length is not 4 or 8.(should be)"); } - for (int i = 0; i < 3; ++i) { - out.add(String.format("%04x", Util.getShort(param, i*2))); + int max = param.length == 4 ? 2 : 4; + for (int i = 0; i < max; ++i) { + out.add(String.format("%04x", Util.getShort(param, i * 2))); } } else if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { @@ -171,8 +172,13 @@ public class ECParams { return true; } - private static byte[] parse(String hex) { - byte[] data = Util.hexToBytes(hex); + private static byte[] parse(String param) { + byte[] data; + if (param.startsWith("0x") || param.startsWith("0X")) { + data = Util.hexToBytes(param.substring(2)); + } else { + data = Util.hexToBytes(param); + } if (data == null) return new byte[0]; if (data.length < 2) diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java index b359e16..f55e943 100644 --- a/src/cz/crcs/ectester/reader/ECTester.java +++ b/src/cz/crcs/ectester/reader/ECTester.java @@ -52,11 +52,20 @@ public class ECTester { private boolean optAll; private boolean optPrimeField = false; private boolean optBinaryField = false; - private boolean optNamed = false; - private String optCurve = null; + + private String optNamedCurve = null; + private String optCurveFile = null; + private boolean optCustomCurve = false; + + private String optNamedPublic = null; private String optPublic = null; + + private String optNamedPrivate = null; private String optPrivate = null; + + private String optNamedKey = null; private String optKey = null; + private String optLog = null; private String optOutput = null; private boolean optFresh = false; @@ -77,6 +86,7 @@ public class ECTester { private void run(String[] args) { try { + CommandLine cli = parseArgs(args); //if help, print and quit @@ -138,7 +148,6 @@ public class ECTester { System.err.println("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName()); } catch (NumberFormatException nfex) { System.err.println("Not a number. " + nfex.getMessage()); - nfex.printStackTrace(System.err); } catch (FileNotFoundException fnfe) { System.err.println("File " + fnfe.getMessage() + " not found."); } catch (ParseException | IOException | CardException ex) { @@ -165,12 +174,18 @@ public class ECTester { * * Options: * -b / --bit-size [b] // -a / --all + * * -fp / --prime-field * -f2m / --binary-field - * -n / --named // -c / --curve [curve_file] field,a,b,gx,gy,r,k - * --public [pubkey_file] wx,wy - * --private [privkey_file] s + * + * -u / --custom + * -n / --named [cat/id|id|cat] + * -c / --curve [curve_file] field,a,b,gx,gy,r,k + * + * -pub / --public [pubkey_file] wx,wy + * -priv / --private [privkey_file] s * -k / --key [key_file] wx,wy,s + * * -o / --output [output_file] * -s / --simulate */ @@ -190,16 +205,28 @@ public class ECTester { opts.addOptionGroup(size); OptionGroup curve = new OptionGroup(); - curve.addOption(Option.builder("n").longOpt("named").desc("Use a named curve.").build()); + curve.addOption(Option.builder("n").longOpt("named").desc("Use a named curve.").hasArg().argName("[cat/id|id|cat]").build()); curve.addOption(Option.builder("c").longOpt("curve").desc("Use curve from file [curve_file] (field,a,b,gx,gy,r,k).").hasArg().argName("curve_file").build()); + curve.addOption(Option.builder("u").longOpt("custom").desc("Use a custom curve(applet-side embedded, SECG curves).").build()); opts.addOptionGroup(curve); opts.addOption(Option.builder("fp").longOpt("prime-field").desc("Use prime field curve.").build()); opts.addOption(Option.builder("f2m").longOpt("binary-field").desc("Use binary field curve.").build()); - opts.addOption(Option.builder("pub").longOpt("public").desc("Use public key from file [pubkey_file] (wx,wy).").hasArg().argName("pubkey_file").build()); - opts.addOption(Option.builder("priv").longOpt("private").desc("Use private key from file [privkey_file] (s).").hasArg().argName("privkey_file").build()); - opts.addOption(Option.builder("k").longOpt("key").desc("Use keyPair from fileĀ [key_file] (wx,wy,s).").hasArg().argName("key_file").build()); + OptionGroup pub = new OptionGroup(); + pub.addOption(Option.builder("npub").longOpt("named-public").desc("Use public key from KeyDB: [cat/id|cat|id]").hasArg().argName("[cat/id|id|cat]").build()); + pub.addOption(Option.builder("pub").longOpt("public").desc("Use public key from file [pubkey_file] (wx,wy).").hasArg().argName("pubkey_file").build()); + opts.addOptionGroup(pub); + + OptionGroup priv = new OptionGroup(); + priv.addOption(Option.builder("npriv").longOpt("named-private").desc("Use private key from KeyDB: [cat/id|id|cat]").hasArg().argName("[cat/id|id|cat]").build()); + priv.addOption(Option.builder("priv").longOpt("private").desc("Use private key from file [privkey_file] (s).").hasArg().argName("privkey_file").build()); + opts.addOptionGroup(priv); + + OptionGroup key = new OptionGroup(); + key.addOption(Option.builder("nk").longOpt("named-key").desc("Use keyPair from KeyDB: [cat/id|id|cat]").hasArg().argName("[cat/id|id|cat]").build()); + key.addOption(Option.builder("k").longOpt("key").desc("Use keyPair from fileĀ [key_file] (wx,wy,s).").hasArg().argName("key_file").build()); + opts.addOptionGroup(key); opts.addOption(Option.builder("o").longOpt("output").desc("Output into file [output_file].").hasArg().argName("output_file").build()); opts.addOption(Option.builder("l").longOpt("log").desc("Log output into file [log_file].").hasArg().argName("log_file").optionalArg(true).build()); @@ -222,10 +249,18 @@ public class ECTester { optAll = cli.hasOption("all"); optPrimeField = cli.hasOption("fp"); optBinaryField = cli.hasOption("f2m"); - optNamed = cli.hasOption("named"); - optCurve = cli.getOptionValue("curve"); + + optNamedCurve = cli.getOptionValue("named"); + optCustomCurve = cli.hasOption("custom"); + optCurveFile = cli.getOptionValue("curve"); + + optNamedPublic = cli.getOptionValue("named-public"); optPublic = cli.getOptionValue("public"); + + optNamedPrivate = cli.getOptionValue("named-private"); optPrivate = cli.getOptionValue("private"); + + optNamedKey = cli.getOptionValue("named-key"); optKey = cli.getOptionValue("key"); if (cli.hasOption("log")) { optLog = cli.getOptionValue("log", String.format("ECTESTER_log_%d.log", System.currentTimeMillis() / 1000)); @@ -234,8 +269,8 @@ public class ECTester { optFresh = cli.hasOption("fresh"); optSimulate = cli.hasOption("simulate"); - if (optKey != null && (optPublic != null || optPrivate != null)) { - System.err.print("Can only specify the whole key with --key or pubkey and privkey with --public and --private."); + 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) { @@ -253,8 +288,8 @@ public class ECTester { System.err.print("Need to specify field with -fp or -f2m. (not both)"); return false; } - if (optKey != null || optPublic != null || optPrivate != null) { - System.err.println("Keys should not be specified when generating keys."); + if (optKey != null || optPublic != null || optPrivate != null || optNamedKey != null || optNamedPublic != null || optNamedPrivate != null) { + System.err.println("Keys should not be specified when exporting curve params."); return false; } if (optOutput == null) { @@ -271,7 +306,7 @@ public class ECTester { System.err.print("Need to specify field with -fp or -f2m. (not both)"); return false; } - if (optKey != null || optPublic != null || optPrivate != null) { + if (optKey != null || optPublic != null || optPrivate != null || optNamedKey != null || optNamedPublic != null || optNamedPrivate != null) { System.err.println("Keys should not be specified when generating keys."); return false; } @@ -314,7 +349,11 @@ public class ECTester { System.err.println("You have to specify curve bit-size with -b"); return false; } - if ((optPublic == null) != (optPrivate == null)) { + + boolean hasPublic = (optPublic != null) || (optNamedPublic != null); + boolean hasPrivate = (optPrivate != null) || (optNamedPrivate != null); + boolean hasKey = (optKey != null) || (optNamedKey != null); + if ((hasPublic) != (hasPrivate) && !hasKey) { System.err.println("You have cannot only specify a part of a keypair."); return false; } @@ -541,12 +580,15 @@ public class ECTester { List<Command> commands = new ArrayList<>(); short domainParams = keyClass == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; - if (optNamed) { - // Set named curve (one of the SECG curves embedded applet-side) + if (optCustomCurve) { + // Set custom curve (one of the SECG curves embedded applet-side) commands.add(new Command.Set(cardManager, keyPair, EC_Consts.getCurve(keyLength, keyClass), domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, null)); - } else if (optCurve != null) { + } else if (optNamedCurve != null) { + // Set a named curve. + // parse optNamedCurve -> cat / id | cat | id + } else if (optCurveFile != null) { // Set curve loaded from a file - byte[] external = ECParams.flatten(domainParams, ECParams.readFile(optCurve)); + byte[] external = ECParams.flatten(domainParams, ECParams.readFile(optCurveFile)); if (external == null) { throw new IOException("Couldn't read the curve file correctly."); } diff --git a/src/cz/crcs/ectester/reader/Response.java b/src/cz/crcs/ectester/reader/Response.java index 368a8ef..d1925b8 100644 --- a/src/cz/crcs/ectester/reader/Response.java +++ b/src/cz/crcs/ectester/reader/Response.java @@ -117,7 +117,6 @@ public abstract class Response { @Override public abstract String toString(); - public static String toString(List<Response> responses) { StringBuilder out = new StringBuilder(); for (Response r : responses) { diff --git a/src/cz/crcs/ectester/reader/SimpleAPDU.java b/src/cz/crcs/ectester/reader/SimpleAPDU.java deleted file mode 100644 index f120608..0000000 --- a/src/cz/crcs/ectester/reader/SimpleAPDU.java +++ /dev/null @@ -1,459 +0,0 @@ -package cz.crcs.ectester.reader; - -import cz.crcs.ectester.applet.EC_Consts; -import javacard.framework.ISO7816; -import javacard.security.CryptoException; -import javacard.security.KeyPair; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; - -import javax.smartcardio.ResponseAPDU; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Arrays; - - -/** - * @author Petr Svenda petr@svenda.com - */ -public class SimpleAPDU { - private CardMngr cardManager = new CardMngr(); - private DirtyLogger systemOutLogger = null; - - private CommandLineParser cliParser = new DefaultParser(); - private Options opts = new Options(); - private static final String cliHeader = ""; - private static final String cliFooter = ""; - - private final static byte SELECT_ECTESTERAPPLET[] = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0a, - (byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31}; - - private static final byte TESTECSUPPORTALL_FP[] = {(byte) 0xB0, (byte) 0x5E, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final byte TESTECSUPPORTALL_F2M[] = {(byte) 0xB0, (byte) 0x5F, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final byte TESTECSUPPORT_GIVENALG[] = {(byte) 0xB0, (byte) 0x71, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final short TESTECSUPPORT_ALG_OFFSET = 5; - private static final short TESTECSUPPORT_KEYLENGTH_OFFSET = 6; - - private static final byte TESTECSUPPORTALL_LASTUSEDPARAMS[] = {(byte) 0xB0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - - private static final byte TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB[] = {(byte) 0xB0, (byte) 0x70, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final short INVALIDCURVEB_NUMREPEATS_OFFSET = 5; - private static final short INVALIDCURVEB_CORRUPTIONTYPE_OFFSET = 7; - private static final short INVALIDCURVEB_REWINDONSUCCESS_OFFSET = 9; - - private static final byte TESTECSUPPORT_GENERATEECCKEY[] = {(byte) 0xB0, (byte) 0x5a, (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; - private static final short GENERATEECKEY_ALG_OFFSET = 5; - private static final short GENERATEECKEY_KEYLENGTH_OFFSET = 6; - private static final short GENERATEECKEY_ANOMALOUS_OFFSET = 8; - - - private void run(String[] args) { - try { - //parse cmd args - CommandLine cli = parseArgs(args); - - //byte[] installData = new byte[10]; - //byte[] AID = {(byte) 0x4C, (byte) 0x61, (byte) 0x62, (byte) 0x61, (byte) 0x6B, (byte) 0x41, (byte) 0x70, (byte) 0x70, (byte) 0x6C, (byte) 0x65, (byte) 0x74}; - //cardManager.prepareLocalSimulatorApplet(AID, installData, SimpleECCApplet.class); - - //do stuff - if (cli.hasOption("help")) { - HelpFormatter help = new HelpFormatter(); - help.printHelp("SimpleAPDU", cliHeader, opts, cliFooter); - } else { - //open log(only when actually doing something) - String logFileName = cli.getOptionValue("output-file", String.format("ECTESTER_log_%d.log", System.currentTimeMillis())); - FileOutputStream stdoutStream = new FileOutputStream(logFileName); - systemOutLogger = new DirtyLogger(stdoutStream, true); - - boolean fp = cli.hasOption("fp"); - boolean f2m = cli.hasOption("f2m"); - if (!fp && !f2m) { - fp = true; - f2m = true; - } - int genAmount = Integer.parseInt(cli.getOptionValue("generate", "0")); - int keyLength = Integer.parseInt(cli.getOptionValue("b", "192")); - - if (cli.hasOption("generate")) { - //generate EC keys - if (fp) { - generateECKeys(genAmount, KeyPair.ALG_EC_FP, (short) keyLength, cli.hasOption("anomalous")); - } - if (f2m) { - generateECKeys(genAmount, KeyPair.ALG_EC_F2M, (short) keyLength, cli.hasOption("anomalous")); - } - } else if (cli.hasOption("test")) { - if (cli.hasOption("bit-size")) { - //test only one bitsize - if (fp) { - testSupportECFp((short) keyLength); - } - if (f2m) { - testSupportECFp((short) keyLength); - } - } else { - //test default bit sizes - testSupportECAll(fp, f2m); - testFPkeyGen((short) 10, EC_Consts.CORRUPTION_ONEBYTERANDOM, true); - } - } else { - systemOutLogger.println("You need to specify one of -t / -g [num] commands."); - } - - //close log - systemOutLogger.close(); - } - - //disconnect - cardManager.disconnectFromCard(); - } catch (Exception ex) { - if (systemOutLogger != null) { - systemOutLogger.println("Exception : " + ex); - } - } - } - - private CommandLine parseArgs(String[] args) throws ParseException { - - opts.addOption("h", "help", false, "show this help"); - opts.addOption(Option.builder("g") - .longOpt("generate") - .hasArg() - .optionalArg(true) - .argName("num") - .desc("generate EC keys").build()); - opts.addOption("t", "test", false, "test EC support (default)"); - opts.addOption(Option.builder("b") - .longOpt("bit-size") - .hasArg() - .argName("bits") - .desc("set EC bit size").build()); - opts.addOption("f2m", "use EC over binary-fields"); - opts.addOption("fp", "user EC over prime-fields (default)"); - opts.addOption("s", "anomalous", false, "generate anomalous (non-prime order, small pubkey order) curves"); - opts.addOption(Option.builder("o") - .longOpt("output-file") - .hasArg() - .argName("file") - .desc("output file to log to").build()); - return cliParser.parse(opts, args); - } - - static short getShort(byte[] array, int offset) { - return (short) (((array[offset] & 0xFF) << 8) | (array[offset + 1] & 0xFF)); - } - - static void setShort(byte[] array, int offset, short value) { - array[offset + 1] = (byte) (value & 0xFF); - array[offset] = (byte) ((value >> 8) & 0xFF); - } - - private boolean ReconnnectToCard() throws Exception { - if (cardManager.connected()) { - cardManager.disconnectFromCard(); - } - - boolean result = cardManager.connectToCard(); - if (result) { - // Select our application on card - cardManager.sendAPDU(SELECT_ECTESTERAPPLET); - } - return result; - } - - private void testFPkeyGen(short numRepeats, short corruptionType, boolean bRewind) throws Exception { - byte[] apdu = Arrays.copyOf(TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB, TESTECSUPPORTALL_FP_KEYGEN_INVALIDCURVEB.length); - setShort(apdu, INVALIDCURVEB_NUMREPEATS_OFFSET, numRepeats); - setShort(apdu, INVALIDCURVEB_CORRUPTIONTYPE_OFFSET, corruptionType); - apdu[INVALIDCURVEB_REWINDONSUCCESS_OFFSET] = bRewind ? (byte) 1 : (byte) 0; - - ReconnnectToCard(); - ResponseAPDU resp_fp_keygen = cardManager.sendAPDU(apdu); - ResponseAPDU resp_keygen_params = cardManager.sendAPDU(TESTECSUPPORTALL_LASTUSEDPARAMS); - PrintECKeyGenInvalidCurveB(resp_fp_keygen); - PrintECKeyGenInvalidCurveB_lastUserParams(resp_keygen_params); - } - - private void testSupportECGivenAlg(short keyLength, byte keyClass) throws Exception { - byte[] apdu = Arrays.copyOf(TESTECSUPPORT_GIVENALG, TESTECSUPPORT_GIVENALG.length); - apdu[TESTECSUPPORT_ALG_OFFSET] = keyClass; - setShort(apdu, TESTECSUPPORT_KEYLENGTH_OFFSET, keyLength); - - ReconnnectToCard(); - ResponseAPDU resp = cardManager.sendAPDU(apdu); - //byte[] resp = cardManager.sendAPDUSimulator(apdu); - PrintECSupport(resp); - } - - private void testSupportECFp(short keyLength) throws Exception { - testSupportECGivenAlg(keyLength, KeyPair.ALG_EC_FP); - } - - private void testSupportECF2m(short keyLength) throws Exception { - testSupportECGivenAlg(keyLength, KeyPair.ALG_EC_F2M); - } - - private void testSupportECAll(boolean testFp, boolean testF2m) throws Exception { - if (testFp) { - testSupportECFp((short) 128); - testSupportECFp((short) 192); - testSupportECFp((short) 224); - testSupportECFp((short) 256); - testSupportECFp((short) 384); - testSupportECFp((short) 521); - } - - if (testF2m) { - testSupportECF2m((short) 113); - testSupportECF2m((short) 131); - testSupportECF2m((short) 163); - testSupportECF2m((short) 193); - } - } - - private void generateECKeys(int amount, byte keyClass, short keyLength, boolean anomalous) throws Exception { - if (cardManager.connectToCardSelect()) { - cardManager.sendAPDU(SELECT_ECTESTERAPPLET); - - String keyFileName = String.format("ECKEYS_%s_%d.log", keyClass == KeyPair.ALG_EC_FP ? "fp" : "f2m", System.currentTimeMillis()); - FileOutputStream keysFile = new FileOutputStream(keyFileName); - - String message = "index;time;pubW;privS\n"; - keysFile.write(message.getBytes()); - byte[] gatherKeyAPDU = Arrays.copyOf(TESTECSUPPORT_GENERATEECCKEY, TESTECSUPPORT_GENERATEECCKEY.length); - // Prepare keypair object - gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_SETCURVE; - gatherKeyAPDU[GENERATEECKEY_ALG_OFFSET] = keyClass; - setShort(gatherKeyAPDU, GENERATEECKEY_KEYLENGTH_OFFSET, keyLength); - gatherKeyAPDU[GENERATEECKEY_ANOMALOUS_OFFSET] = anomalous ? (byte) 1 : (byte) 0; - - ResponseAPDU respGather = cardManager.sendAPDU(gatherKeyAPDU); - if (respGather.getSW() != ISO7816.SW_NO_ERROR) { - systemOutLogger.println(String.format("Card error: %x", respGather.getSW())); - keysFile.close(); - return; - } - - // Generate new keypair - gatherKeyAPDU[ISO7816.OFFSET_P1] = SimpleECCApplet.P1_GENERATEKEYPAIR; - int counter = 0; - while (true) { - counter++; - long elapsed = -System.nanoTime(); - respGather = cardManager.sendAPDU(gatherKeyAPDU); - elapsed += System.nanoTime(); - - if (respGather.getSW() != ISO7816.SW_NO_ERROR) { - systemOutLogger.println(String.format("Card error: %x", respGather.getSW())); - break; - } - byte[] data = respGather.getData(); - int offset = 0; - String pubKeyW = ""; - String privKeyS = ""; - if (data[offset] == EC_Consts.TAG_ECPUBKEY) { - offset++; - short len = getShort(data, offset); - offset += 2; - pubKeyW = Util.bytesToHex(data, offset, len, false); - offset += len; - } - if (data[offset] == EC_Consts.TAG_ECPRIVKEY) { - offset++; - short len = getShort(data, offset); - offset += 2; - privKeyS = Util.bytesToHex(data, offset, len, false); - offset += len; - } - - message = String.format("%d;%d;%s;%s\n", counter, elapsed / 1000000, pubKeyW, privKeyS); - keysFile.write(message.getBytes()); - - this.systemOutLogger.flush(); - keysFile.flush(); - - //stop when we have enough keys, go on forever with 0 - if (counter >= amount && amount != 0) - break; - } - keysFile.close(); - } - } - - private static String getPrintError(short code) { - if (code == ISO7816.SW_NO_ERROR) { - return "OK\t(0x9000)"; - } else { - String codeStr = "unknown"; - if (code == CryptoException.ILLEGAL_VALUE) { - codeStr = "ILLEGAL_VALUE"; - } - if (code == CryptoException.UNINITIALIZED_KEY) { - codeStr = "UNINITIALIZED_KEY"; - } - if (code == CryptoException.NO_SUCH_ALGORITHM) { - codeStr = "NO_SUCH_ALG"; - } - if (code == CryptoException.INVALID_INIT) { - codeStr = "INVALID_INIT"; - } - if (code == CryptoException.ILLEGAL_USE) { - codeStr = "ILLEGAL_USE"; - } - if (code == SimpleECCApplet.SW_SKIPPED) { - codeStr = "skipped"; - } - if (code == SimpleECCApplet.SW_KEYPAIR_GENERATED_INVALID) { - codeStr = "SW_KEYPAIR_GENERATED_INVALID"; - } - if (code == SimpleECCApplet.SW_INVALID_CORRUPTION_TYPE) { - codeStr = "SW_INVALID_CORRUPTION_TYPE"; - } - if (code == SimpleECCApplet.SW_SIG_VERIFY_FAIL) { - codeStr = "SW_SIG_VERIFY_FAIL"; - } - return String.format("fail\t(%s,\t0x%4x)", codeStr, code); - } - } - - enum ExpResult { - SHOULD_SUCCEED, - MAY_FAIL, - MUST_FAIL - } - - private int VerifyPrintResult(String message, byte expectedTag, byte[] buffer, int bufferOffset, ExpResult expRes) { - if (bufferOffset >= buffer.length) { - systemOutLogger.println(" No more data returned"); - } else { - if (buffer[bufferOffset] != expectedTag) { - systemOutLogger.println(" ERROR: mismatched tag"); - assert (buffer[bufferOffset] == expectedTag); - } - bufferOffset++; - short resCode = getShort(buffer, bufferOffset); - bufferOffset += 2; - - boolean bHiglight = false; - if ((expRes == ExpResult.MUST_FAIL) && (resCode == ISO7816.SW_NO_ERROR)) { - bHiglight = true; - } - if ((expRes == ExpResult.SHOULD_SUCCEED) && (resCode != ISO7816.SW_NO_ERROR)) { - bHiglight = true; - } - if (bHiglight) { - systemOutLogger.println(String.format("!! %-53s%s", message, getPrintError(resCode))); - } else { - systemOutLogger.println(String.format(" %-53s%s", message, getPrintError(resCode))); - } - } - return bufferOffset; - } - - private void PrintECSupport(ResponseAPDU resp) { - PrintECSupport(resp.getData()); - } - - private void PrintECSupport(byte[] buffer) { - systemOutLogger.println(); - systemOutLogger.println("### Test for support and with valid and invalid EC curves"); - int bufferOffset = 0; - while (bufferOffset < buffer.length) { - assert (buffer[bufferOffset] == SimpleECCApplet.ECTEST_SEPARATOR); - bufferOffset++; - String ecType = "unknown"; - if (buffer[bufferOffset] == KeyPair.ALG_EC_FP) { - ecType = "ALG_EC_FP"; - } - if (buffer[bufferOffset] == KeyPair.ALG_EC_F2M) { - ecType = "ALG_EC_F2M"; - } - systemOutLogger.println(String.format("%-56s%s", "EC type:", ecType)); - bufferOffset++; - short keyLen = getShort(buffer, bufferOffset); - systemOutLogger.println(String.format("%-56s%d bits", "EC key length (bits):", keyLen)); - bufferOffset += 2; - - bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("Generate key with def curve (fails if no def):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_DEFCURVE, buffer, bufferOffset, ExpResult.MAY_FAIL); - bufferOffset = VerifyPrintResult("Set valid custom curve:", SimpleECCApplet.ECTEST_SET_VALIDCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("Generate key with valid curve:", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("ECDH agreement with valid point:", SimpleECCApplet.ECTEST_ECDH_AGREEMENT_VALID_POINT, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("ECDH agreement with invalid point (fail is good):", SimpleECCApplet.ECTEST_ECDH_AGREEMENT_INVALID_POINT, buffer, bufferOffset, ExpResult.MUST_FAIL); - bufferOffset = VerifyPrintResult("ECDSA signature on random data:", SimpleECCApplet.ECTEST_ECDSA_SIGNATURE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("Set anomalous custom curve (may fail):", SimpleECCApplet.ECTEST_SET_ANOMALOUSCURVE, buffer, bufferOffset, ExpResult.MAY_FAIL); - bufferOffset = VerifyPrintResult("Generate key with anomalous curve (may fail):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_ANOMALOUSCURVE, buffer, bufferOffset, ExpResult.MAY_FAIL); - bufferOffset = VerifyPrintResult("ECDH agreement with small order point (fail is good):", SimpleECCApplet.ECTEST_ECDH_AGREEMENT_SMALL_DEGREE_POINT, buffer, bufferOffset, ExpResult.MUST_FAIL); - bufferOffset = VerifyPrintResult("Set invalid custom curve (may fail):", SimpleECCApplet.ECTEST_SET_INVALIDCURVE, buffer, bufferOffset, ExpResult.MAY_FAIL); - bufferOffset = VerifyPrintResult("Generate key with invalid curve (fail is good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE, buffer, bufferOffset, ExpResult.MUST_FAIL); - bufferOffset = VerifyPrintResult("Set invalid field (may fail):", SimpleECCApplet.ECTEST_SET_INVALIDFIELD, buffer, bufferOffset, ExpResult.MAY_FAIL); - bufferOffset = VerifyPrintResult("Generate key with invalid field (fail si good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDFIELD, buffer, bufferOffset, ExpResult.MUST_FAIL); - - systemOutLogger.println(); - } - } - - private void PrintECKeyGenInvalidCurveB(ResponseAPDU resp) { - PrintECKeyGenInvalidCurveB(resp.getData()); - } - - private void PrintECKeyGenInvalidCurveB(byte[] buffer) { - systemOutLogger.println(); - systemOutLogger.println("### Test for computation with invalid parameter B for EC curve"); - int bufferOffset = 0; - while (bufferOffset < buffer.length) { - assert (buffer[bufferOffset] == SimpleECCApplet.ECTEST_SEPARATOR); - bufferOffset++; - String ecType = "unknown"; - if (buffer[bufferOffset] == KeyPair.ALG_EC_FP) { - ecType = "ALG_EC_FP"; - } - if (buffer[bufferOffset] == KeyPair.ALG_EC_F2M) { - ecType = "ALG_EC_F2M"; - } - systemOutLogger.println(String.format("%-53s%s", "EC type:", ecType)); - bufferOffset++; - short keyLen = getShort(buffer, bufferOffset); - systemOutLogger.println(String.format("%-53s%d bits", "EC key length (bits):", keyLen)); - bufferOffset += 2; - - short numRepeats = getShort(buffer, bufferOffset); - bufferOffset += 2; - systemOutLogger.println(String.format("%-53s%d times", "Executed repeats before unexpected error: ", numRepeats)); - - bufferOffset = VerifyPrintResult("KeyPair object allocation:", SimpleECCApplet.ECTEST_ALLOCATE_KEYPAIR, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - while (bufferOffset < buffer.length) { - bufferOffset = VerifyPrintResult("Set invalid custom curve:", SimpleECCApplet.ECTEST_SET_INVALIDCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("Generate key with invalid curve (fail is good):", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_INVALIDCUSTOMCURVE, buffer, bufferOffset, ExpResult.MUST_FAIL); - if (buffer[bufferOffset] == SimpleECCApplet.ECTEST_DH_GENERATESECRET) { - bufferOffset = VerifyPrintResult("ECDH agreement with invalid point (fail is good):", SimpleECCApplet.ECTEST_DH_GENERATESECRET, buffer, bufferOffset, ExpResult.MUST_FAIL); - } - bufferOffset = VerifyPrintResult("Set valid custom curve:", SimpleECCApplet.ECTEST_SET_VALIDCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - bufferOffset = VerifyPrintResult("Generate key with valid curve:", SimpleECCApplet.ECTEST_GENERATE_KEYPAIR_CUSTOMCURVE, buffer, bufferOffset, ExpResult.SHOULD_SUCCEED); - } - - systemOutLogger.println(); - } - } - - private void PrintECKeyGenInvalidCurveB_lastUserParams(ResponseAPDU resp) { - byte[] buffer = resp.getData(); - short offset = 0; - systemOutLogger.print("Last used value of B: "); - while (offset < buffer.length) { - systemOutLogger.print(String.format("%x ", buffer[offset])); - offset++; - } - } - - public static void main(String[] args) throws IOException { - SimpleAPDU app = new SimpleAPDU(); - app.run(args); - } -} diff --git a/src/cz/crcs/ectester/reader/Util.java b/src/cz/crcs/ectester/reader/Util.java index f876fe4..e297ab1 100644 --- a/src/cz/crcs/ectester/reader/Util.java +++ b/src/cz/crcs/ectester/reader/Util.java @@ -26,16 +26,28 @@ public class Util { } public static byte[] hexToBytes(String hex, boolean bigEndian) { - StringBuilder sb = new StringBuilder(hex.replace(" ", "")); - if (!bigEndian) { - sb.reverse(); - } - int len = sb.length(); + hex = hex.replace(" ", ""); + int len = hex.length(); + StringBuilder sb = new StringBuilder(); + if (len % 2 == 1) { - sb.insert(0, "0"); + sb.append("0"); ++len; } + if (bigEndian) { + sb.append(hex); + } else { + for (int i = 0; i < len / 2; ++i) { + if (sb.length() >= 2) { + sb.insert(sb.length() - 2, hex.substring(2 * i, 2 * i + 2)); + } else { + sb.append(hex.substring(2 * i, 2 * i + 2)); + } + + } + } + String data = sb.toString(); byte[] result = new byte[len / 2]; for (int i = 0; i < len; i += 2) { |
