diff options
| author | J08nY | 2017-03-24 17:11:44 +0100 |
|---|---|---|
| committer | J08nY | 2017-03-24 17:11:44 +0100 |
| commit | a50b554fbc577df6873705738b379fa15980d2b7 (patch) | |
| tree | 68f5fcaa4eec1ceabcc40d5a1fc63eecb052a419 /src | |
| parent | dd0947b2dd33baa882279a50876806cc1f0471c4 (diff) | |
| download | ECTester-a50b554fbc577df6873705738b379fa15980d2b7.tar.gz ECTester-a50b554fbc577df6873705738b379fa15980d2b7.tar.zst ECTester-a50b554fbc577df6873705738b379fa15980d2b7.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECKeyTester.java | 3 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECTesterApplet.java | 23 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/EC_Consts.java | 21 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Command.java | 9 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTester.java | 27 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/Response.java | 29 |
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); } } |
