aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/reader/ECTester.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cz/crcs/ectester/reader/ECTester.java')
-rw-r--r--src/cz/crcs/ectester/reader/ECTester.java121
1 files changed, 85 insertions, 36 deletions
diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java
index e5a2b70..4cb63f7 100644
--- a/src/cz/crcs/ectester/reader/ECTester.java
+++ b/src/cz/crcs/ectester/reader/ECTester.java
@@ -33,6 +33,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -58,6 +59,7 @@ public class ECTester {
private String optKey = null;
private String optLog = null;
private String optOutput = null;
+ private boolean optFresh = false;
private boolean optSimulate = false;
private int optGenerateAmount;
@@ -244,11 +246,15 @@ public class ECTester {
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());
+
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());
+
+ opts.addOption(Option.builder("f").longOpt("fresh").desc("Generate fresh keys(set domain parameters before every generation).").build());
opts.addOption(Option.builder("s").longOpt("simulate").desc("Simulate a card with jcardsim instead of using a terminal.").build());
CommandLineParser parser = new DefaultParser();
@@ -275,6 +281,7 @@ public class ECTester {
optLog = cli.getOptionValue("log", String.format("ECTESTER_log_%d.log", System.currentTimeMillis() / 1000));
}
optOutput = cli.getOptionValue("output");
+ optFresh = cli.hasOption("fresh");
optSimulate = cli.hasOption("simulate");
if (optKey != null && (optPublic != null || optPrivate != null)) {
@@ -365,7 +372,8 @@ public class ECTester {
*/
private void generate() throws CardException, IOException {
byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
- List<Response> prepare = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass));
+ List<Response> prepare = Command.sendAll(prepareKeyPair(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass));
+ prepare.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass)));
FileWriter keysFile = new FileWriter(optOutput);
keysFile.write("index;time;pubW;privS\n");
@@ -373,6 +381,10 @@ public class ECTester {
int generated = 0;
int retry = 0;
while (generated < optGenerateAmount || optGenerateAmount == 0) {
+ if (optFresh) {
+ Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass));
+ }
+
Command.Generate generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, (byte) (ECTesterApplet.EXPORT_BOTH | ECTesterApplet.KEYPAIR_LOCAL));
Response.Generate response = generate.send();
long elapsed = response.getDuration();
@@ -400,47 +412,36 @@ public class ECTester {
/**
* Tests Elliptic curve support for a given curve/curves.
+ *
+ * @throws IOException
+ * @throws CardException
*/
- private void test() {
- //TODO
+ private void test() throws IOException, CardException {
+ List<Command> commands = new LinkedList<>();
if (optAll) {
if (optPrimeField) {
//iterate over prime curve sizes used: EC_Consts.FP_SIZES
for (short keyLength : EC_Consts.FP_SIZES) {
- //prepareCurve(KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP);
- //insGenerate(KEYPAIR_BOTH, EXPORT_NONE);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 00);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 01);
- //insECDSA(KEYPAIR_LOCAL, EXPORT_NONE, null);
+ commands.addAll(testCurve(keyLength, KeyPair.ALG_EC_FP));
}
}
if (optBinaryField) {
//iterate over binary curve sizes used: EC_Consts.F2M_SIZES
for (short keyLength : EC_Consts.F2M_SIZES) {
- //prepareCurve(KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M);
- //insGenerate(KEYPAIR_BOTH, EXPORT_NONE);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 00);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 01);
- //insECDSA(KEYPAIR_LOCAL, EXPORT_NONE, null);
+ commands.addAll(testCurve(keyLength, KeyPair.ALG_EC_F2M));
}
}
} else {
if (optPrimeField) {
- //test with prepareCurve(KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)
- //insGenerate(KEYPAIR_BOTH, EXPORT_NONE);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 00);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 01);
- //insECDSA(KEYPAIR_LOCAL, EXPORT_NONE, null);
+ commands.addAll(testCurve((short) optBits, KeyPair.ALG_EC_FP));
}
if (optBinaryField) {
- //test with prepareCurve(KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)
- //insGenerate(KEYPAIR_BOTH, EXPORT_NONE);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 00);
- //insECDH(KEYPAIR_LOCAL, KEYPAIR_REMOTE, EXPORT_NONE, 01);
- //insECDSA(KEYPAIR_LOCAL, EXPORT_NONE, null);
+ commands.addAll(testCurve((short) optBits, KeyPair.ALG_EC_F2M));
}
}
+ List<Response> test = Command.sendAll(commands);
+ systemOutLogger.println(Response.toString(test));
}
/**
@@ -451,7 +452,8 @@ public class ECTester {
*/
private void ecdh() throws IOException, CardException {
byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
- List<Response> ecdh = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass));
+ List<Response> ecdh = Command.sendAll(prepareKeyPair(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass));
+ ecdh.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, keyClass)));
if (optPublic != null || optPrivate != null || optKey != null) {
Response local = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE).send();
@@ -465,10 +467,17 @@ public class ECTester {
Response.ECDH perform = new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_ECDH, (byte) 0).send();
ecdh.add(perform);
- for (Response r : ecdh) {
- systemOutLogger.println(r.toString());
+ systemOutLogger.println(Response.toString(ecdh));
+
+ if (!perform.hasSecret()) {
+ System.err.println("Couldn't obtain ECDH secret from card response.");
+ } else {
+ if (optOutput != null) {
+ FileWriter out = new FileWriter(optOutput);
+ out.write(Util.bytesToHex(perform.getSecret(), false));
+ out.close();
+ }
}
- //TODO check perform.hasSecret(), write perform.getSecret to file if -o
}
/**
@@ -479,7 +488,8 @@ public class ECTester {
*/
private void ecdsa() throws CardException, IOException {
byte keyClass = optPrimeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M;
- List<Response> ecdsa = Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass));
+ List<Response> ecdsa = Command.sendAll(prepareKeyPair(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass));
+ ecdsa.addAll(Command.sendAll(prepareCurve(ECTesterApplet.KEYPAIR_LOCAL, (short) optBits, keyClass)));
Response keys;
if (optKey != null || (optPublic != null && optPrivate != null)) {
@@ -502,33 +512,55 @@ public class ECTester {
Response.ECDSA perform = new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_SIG, data).send();
ecdsa.add(perform);
- for (Response r : ecdsa) {
- systemOutLogger.println(r.toString());
+ systemOutLogger.println(Response.toString(ecdsa));
+
+ if (!perform.hasSignature()) {
+ System.err.println("Couldn't obtain ECDSA signature from card response.");
+ } else {
+ if (optOutput != null) {
+ FileWriter out = new FileWriter(optOutput);
+ out.write(Util.bytesToHex(perform.getSignature(), false));
+ out.close();
+ }
}
- //TODO output to file
}
/**
- * @param keyPair which keyPair/s (local/remote) to set curve domain parameters on
+ * @param keyPair which keyPair/s (local/remote) to allocate
* @param keyLength key length to allocate
* @param keyClass key class to allocate
- * @return an array of CommandAPDUs to send in order to prepare the keypair/s.
+ * @return a list of Commands to send in order to prepare the keyPair.
+ */
+ private List<Command> prepareKeyPair(byte keyPair, short keyLength, byte keyClass) {
+ List<Command> commands = new ArrayList<>();
+ commands.add(new Command.Allocate(cardManager, keyPair, keyLength, keyClass));
+ return commands;
+ }
+
+ /**
+ * @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<>();
- commands.add(new Command.Allocate(cardManager, keyPair, keyLength, keyClass));
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)
commands.add(new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.getCurve(keyLength, keyClass), domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, null));
- }
- if (optCurve != null) {
+ } else if (optCurve != null) {
+ // Set curve loaded from a file
byte[] external = ParamReader.flatten(domainParams, ParamReader.readFile(optCurve));
if (external == null) {
throw new IOException("Couldn't read the curve file correctly.");
}
commands.add(new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, domainParams, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, external));
+ } else {
+ // Set default curve
+ commands.add(new Command.Clear(cardManager, keyPair));
}
return commands;
@@ -566,6 +598,23 @@ public class ECTester {
return new Command.Set(cardManager, keyPair, ECTesterApplet.EXPORT_NONE, EC_Consts.CURVE_external, params, EC_Consts.PARAMETERS_NONE, EC_Consts.CORRUPTION_NONE, data);
}
+ /**
+ * @param keyLength
+ * @param keyClass
+ * @return
+ * @throws IOException
+ */
+ private List<Command> testCurve(short keyLength, byte keyClass) throws IOException {
+ List<Command> commands = new LinkedList<>();
+ commands.addAll(prepareKeyPair(ECTesterApplet.KEYPAIR_BOTH, keyLength, keyClass));
+ commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, keyLength, keyClass));
+ commands.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH, ECTesterApplet.EXPORT_NONE));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_NONE, (byte) 0));
+ commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_NONE, (byte) 1));
+ commands.add(new Command.ECDSA(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_NONE, null));
+ return commands;
+ }
+
public static void main(String[] args) {
ECTester app = new ECTester();
app.run(args);