summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2017-03-24 17:11:44 +0100
committerJ08nY2017-03-24 17:11:44 +0100
commita50b554fbc577df6873705738b379fa15980d2b7 (patch)
tree68f5fcaa4eec1ceabcc40d5a1fc63eecb052a419 /src
parentdd0947b2dd33baa882279a50876806cc1f0471c4 (diff)
downloadECTester-a50b554fbc577df6873705738b379fa15980d2b7.tar.gz
ECTester-a50b554fbc577df6873705738b379fa15980d2b7.tar.zst
ECTester-a50b554fbc577df6873705738b379fa15980d2b7.zip
Diffstat (limited to 'src')
-rw-r--r--src/cz/crcs/ectester/applet/ECKeyTester.java3
-rw-r--r--src/cz/crcs/ectester/applet/ECTesterApplet.java23
-rw-r--r--src/cz/crcs/ectester/applet/EC_Consts.java21
-rw-r--r--src/cz/crcs/ectester/reader/Command.java9
-rw-r--r--src/cz/crcs/ectester/reader/ECTester.java27
-rw-r--r--src/cz/crcs/ectester/reader/Response.java29
6 files changed, 84 insertions, 28 deletions
diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java
index 89fd617..057d357 100644
--- a/src/cz/crcs/ectester/applet/ECKeyTester.java
+++ b/src/cz/crcs/ectester/applet/ECKeyTester.java
@@ -93,8 +93,7 @@ public class ECKeyTester {
* @param outputBuffer
* @param outputOffset
* @param corruption
- * @return ISO7816.SW_NO_ERROR on correct operation,
- * exception reason otherwise
+ * @return derived secret length
*/
public short testECDHC(ECPrivateKey privateKey, ECPublicKey publicKey, byte[] pubkeyBuffer, short pubkeyOffset, byte[] outputBuffer, short outputOffset, byte corruption) {
short length = publicKey.getW(pubkeyBuffer, pubkeyOffset);
diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java
index 4dafd21..e17d102 100644
--- a/src/cz/crcs/ectester/applet/ECTesterApplet.java
+++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -329,6 +329,7 @@ public class ECTesterApplet extends Applet {
* P2 = byte privkey (KEYPAIR_*)
* DATA = byte export (EXPORT_TRUE || EXPORT_FALSE)
* byte corruption (00 = valid, !00 = invalid)
+ * byte type (EC_Consts.KA_* | ...)
*/
private void insECDH(APDU apdu) {
apdu.setIncomingAndReceive();
@@ -338,8 +339,9 @@ public class ECTesterApplet extends Applet {
byte privkey = apdubuf[ISO7816.OFFSET_P2];
byte export = apdubuf[ISO7816.OFFSET_CDATA];
byte corruption = apdubuf[(short) (ISO7816.OFFSET_CDATA + 1)];
+ byte type = apdubuf[(short) (ISO7816.OFFSET_CDATA + 2)];
- short len = ecdh(pubkey, privkey, export, corruption, apdubuf, (short) 0);
+ short len = ecdh(pubkey, privkey, export, corruption, type, apdubuf, (short) 0);
apdu.setOutgoingAndSend((short) 0, len);
}
@@ -513,17 +515,31 @@ public class ECTesterApplet extends Applet {
* @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param export whether to export ECDH secret
* @param corruption whether to invalidate the pubkey before ECDH
+ * @param type
* @param buffer buffer to write sw to, and export ECDH secret {@code if(export == EXPORT_TRUE)}
* @param offset output offset in buffer
* @return length of data written to the buffer
*/
- private short ecdh(byte pubkey, byte privkey, byte export, byte corruption, byte[] buffer, short offset) {
+ private short ecdh(byte pubkey, byte privkey, byte export, byte corruption, byte type, byte[] buffer, short offset) {
short length = 0;
KeyPair pub = ((pubkey & KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
KeyPair priv = ((privkey & KEYPAIR_LOCAL) != 0) ? localKeypair : remoteKeypair;
- short secretLength = keyTester.testECDH((ECPrivateKey) priv.getPrivate(), (ECPublicKey) pub.getPublic(), ramArray, (short) 0, ramArray2, (short) 0, corruption);
+ short secretLength = 0;
+ switch (type) {
+ case EC_Consts.KA_ECDH:
+ secretLength = keyTester.testECDH((ECPrivateKey) priv.getPrivate(), (ECPublicKey) pub.getPublic(), ramArray, (short) 0, ramArray2, (short) 0, corruption);
+ break;
+ case EC_Consts.KA_ECDHC:
+ secretLength = keyTester.testECDHC((ECPrivateKey) priv.getPrivate(), (ECPublicKey) pub.getPublic(), ramArray, (short) 0, ramArray2, (short) 0, corruption);
+ break;
+ case EC_Consts.KA_BOTH:
+ // TODO
+ break;
+ default:
+ ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
+ }
Util.setShort(buffer, offset, keyTester.getSW());
length += 2;
@@ -574,7 +590,6 @@ public class ECTesterApplet extends Applet {
}
/**
- *
* @param buffer
* @param offset
* @return
diff --git a/src/cz/crcs/ectester/applet/EC_Consts.java b/src/cz/crcs/ectester/applet/EC_Consts.java
index 64f8dca..cac5d79 100644
--- a/src/cz/crcs/ectester/applet/EC_Consts.java
+++ b/src/cz/crcs/ectester/applet/EC_Consts.java
@@ -26,7 +26,7 @@ public class EC_Consts {
private static byte[] EC_F2M_F2M = null; //[short i1, short i2, short i3], f = x^m + x^i1 + x^i2 + x^i3 + 1
-
+ // EC domain parameter identifiers (bit flags)
public static final short PARAMETER_FP = 0x0001;
public static final short PARAMETER_F2M = 0x0002;
@@ -53,10 +53,18 @@ public class EC_Consts {
public static final short PARAMETERS_KEYPAIR = 0x0180;
public static final short PARAMETERS_ALL = 0x01ff;
+
+ // EC key identifiers
public static final byte KEY_PUBLIC = 0x01;
public static final byte KEY_PRIVATE = 0x02;
public static final byte KEY_BOTH = KEY_PUBLIC | KEY_PRIVATE;
+
+ // Key Agreement test identifiers
+ public static final byte KA_ECDH = 0x01;
+ public static final byte KA_ECDHC = 0x02;
+ public static final byte KA_BOTH = KA_ECDH | KA_ECDHC;
+
public static RandomData randomData = null;
@@ -1298,21 +1306,22 @@ public class EC_Consts {
size += xLength;
short offset = outputOffset;
+ outputBuffer[offset] = 0;
switch (form) {
case X962_UNCOMPRESSED:
- outputBuffer[offset] = 0x04;
+ outputBuffer[offset] = 4;
break;
+ case X962_HYBRID:
+ outputBuffer[offset] = 4;
case X962_COMPRESSED:
byte yLSB = yBuffer[(short) (yOffset + yLength)];
byte yBit = (byte) (yLSB & 0x01);
if (yBit == 1) {
- outputBuffer[offset] = 3;
+ outputBuffer[offset] += 3;
} else {
- outputBuffer[offset] = 2;
+ outputBuffer[offset] += 2;
}
- case X962_HYBRID:
- outputBuffer[offset] += 4;
break;
default:
ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED);
diff --git a/src/cz/crcs/ectester/reader/Command.java b/src/cz/crcs/ectester/reader/Command.java
index c5cef00..92d9da1 100644
--- a/src/cz/crcs/ectester/reader/Command.java
+++ b/src/cz/crcs/ectester/reader/Command.java
@@ -251,6 +251,7 @@ public abstract class Command {
private byte privkey;
private byte export;
private byte corruption;
+ private byte type;
/**
* Creates the INS_ECDH instruction.
@@ -260,15 +261,17 @@ public abstract class Command {
* @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE)
* @param export whether to export ECDH secret
* @param corruption whether to invalidate the pubkey before ECDH (EC_Consts.CORRUPTION_* || ...)
+ * @param type
*/
- public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, byte corruption) {
+ public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, byte corruption, byte type) {
super(cardManager);
this.pubkey = pubkey;
this.privkey = privkey;
this.export = export;
this.corruption = corruption;
+ this.type = type;
- byte[] data = new byte[]{export, corruption};
+ byte[] data = new byte[]{export, corruption, type};
this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH, pubkey, privkey, data);
}
@@ -278,7 +281,7 @@ public abstract class Command {
long elapsed = -System.nanoTime();
ResponseAPDU response = cardManager.send(cmd);
elapsed += System.nanoTime();
- return new Response.ECDH(response, elapsed, pubkey, privkey, export, corruption);
+ return new Response.ECDH(response, elapsed, pubkey, privkey, export, corruption, type);
}
}
diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java
index e14bb38..ef35b2d 100644
--- a/src/cz/crcs/ectester/reader/ECTester.java
+++ b/src/cz/crcs/ectester/reader/ECTester.java
@@ -85,6 +85,7 @@ public class ECTester {
private String optTestCase;
private int optGenerateAmount;
private int optECDHCount;
+ private byte optECDHKA;
private int optECDSACount;
@@ -145,7 +146,7 @@ public class ECTester {
generate();
} else if (cli.hasOption("test")) {
test();
- } else if (cli.hasOption("ecdh")) {
+ } else if (cli.hasOption("ecdh") || cli.hasOption("ecdhc")) {
ecdh();
} else if (cli.hasOption("ecdsa")) {
ecdsa();
@@ -209,6 +210,7 @@ public class ECTester {
* -g / --generate [amount]
* -t / --test [test_case]
* -dh / --ecdh [count]
+ * -dhc / --ecdhc [count]
* -dsa / --ecdsa [count]
* -ln / --list-named
*
@@ -248,6 +250,7 @@ public class ECTester {
actions.addOption(Option.builder("g").longOpt("generate").desc("Generate [amount] of EC keys.").hasArg().argName("amount").optionalArg(true).build());
actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support.").hasArg().argName("test_case").optionalArg(true).build());
actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do ECDH, [count] times.").hasArg().argName("count").optionalArg(true).build());
+ actions.addOption(Option.builder("dhc").longOpt("ecdhc").desc("Do ECDHC, [count] times.").hasArg().argName("count").optionalArg(true).build());
actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build());
opts.addOptionGroup(actions);
@@ -408,7 +411,7 @@ public class ECTester {
return false;
}
- } else if (cli.hasOption("ecdh")) {
+ } 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;
@@ -418,7 +421,13 @@ public class ECTester {
return false;
}
- optECDHCount = Integer.parseInt(cli.getOptionValue("ecdh", "1"));
+ 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;
@@ -697,7 +706,7 @@ public class ECTester {
while (done < optECDHCount) {
List<Response> ecdh = Command.sendAll(generate);
- Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, (byte) 0).send();
+ Response.ECDH perform = new Command.ECDH(cardManager, pubkey, privkey, ECTesterApplet.EXPORT_TRUE, EC_Consts.CORRUPTION_NONE, optECDHKA).send();
ecdh.add(perform);
systemOutLogger.println(Response.toString(ecdh));
@@ -921,11 +930,11 @@ public class ECTester {
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));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ONE));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_ZERO));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_MAX));
- commands.add(new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.CORRUPTION_FULLRANDOM));
+ 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;
}
diff --git a/src/cz/crcs/ectester/reader/Response.java b/src/cz/crcs/ectester/reader/Response.java
index 691bc5a..92d1b9f 100644
--- a/src/cz/crcs/ectester/reader/Response.java
+++ b/src/cz/crcs/ectester/reader/Response.java
@@ -118,6 +118,10 @@ public abstract class Response {
public abstract String toString();
public static String toString(List<Response> responses) {
+ return toString(responses, null);
+ }
+
+ public static String toString(List<Response> responses, String prefix) {
StringBuilder out = new StringBuilder();
for (int i = 0; i < responses.size(); ++i) {
Response r = responses.get(i);
@@ -129,6 +133,10 @@ public abstract class Response {
} else {
suffix = String.format("%s %s", Util.getSWString(r.getSW1()), Util.getSWString(r.getSW2()));
}
+
+ if (prefix != null)
+ out.append(prefix);
+
out.append(String.format("%-58s:%4d ms : %s", message, r.time / 1000000, suffix));
if (i < responses.size() - 1) {
out.append("\n");
@@ -423,13 +431,15 @@ public abstract class Response {
private byte privkey;
private byte export;
private byte corruption;
+ private byte type;
- protected ECDH(ResponseAPDU response, long time, byte pubkey, byte privkey, byte export, byte corruption) {
+ protected ECDH(ResponseAPDU response, long time, byte pubkey, byte privkey, byte export, byte corruption, byte type) {
super(response, time);
this.pubkey = pubkey;
this.privkey = privkey;
this.export = export;
this.corruption = corruption;
+ this.type = type;
parse(1, (export == ECTesterApplet.EXPORT_TRUE) ? 1 : 0);
}
@@ -444,16 +454,27 @@ public abstract class Response {
@Override
public String toString() {
+ String algo = "";
+ if ((type & EC_Consts.KA_ECDH) != 0) {
+ algo += "ECDH";
+ }
+ if (type == EC_Consts.KA_BOTH) {
+ algo += "+";
+ }
+ if ((type & EC_Consts.KA_ECDHC) != 0) {
+ algo += "ECDHC";
+ }
+
String pub = pubkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote";
- String validity;
+ String validity;
if (corruption == EC_Consts.CORRUPTION_NONE) {
- validity = "valid";
+ validity = "unchanged";
} else {
validity = Util.getCorruption(corruption);
}
- return String.format("ECDH of %s pubkey and %s privkey(%s point)", pub, priv, validity);
+ return String.format("%s of %s pubkey and %s privkey(%s point)", algo, pub, priv, validity);
}
}