diff options
3 files changed, 78 insertions, 12 deletions
diff --git a/common/src/main/java/cz/crcs/ectester/common/ec/EC_Params.java b/common/src/main/java/cz/crcs/ectester/common/ec/EC_Params.java index 8d15437..24e9d56 100644 --- a/common/src/main/java/cz/crcs/ectester/common/ec/EC_Params.java +++ b/common/src/main/java/cz/crcs/ectester/common/ec/EC_Params.java @@ -5,6 +5,7 @@ import cz.crcs.ectester.common.util.CardUtil; import java.io.ByteArrayOutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -265,6 +266,29 @@ public class EC_Params extends EC_Data { return p; } + public static EC_Params merge(EC_Params p1, EC_Params p2) { + if ((p1.params & p2.params) != 0) { + throw new IllegalArgumentException("Cannot merge EC_Params with overlapping parameters."); + } + short params = (short) (p1.params | p2.params); + List<byte[]> dataList = new ArrayList<>(); + short paramMask = EC_Consts.PARAMETER_FP; + while (paramMask <= EC_Consts.PARAMETER_S) { + byte[][] paramData; + if ((p1.params & paramMask) != 0) { + paramData = p1.getParam(paramMask); + } else if ((p2.params & paramMask) != 0) { + paramData = p2.getParam(paramMask); + } else { + throw new IllegalArgumentException("Cannot merge EC_Params with overlapping parameters."); + } + dataList.addAll(Arrays.asList(paramData)); + paramMask = (short) (paramMask << 1); + } + + return new EC_Params(params, dataList.toArray(new byte[dataList.size()][])); + } + @Override public String[] expand() { List<String> out = new ArrayList<>(); diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java index 6eb0b1a..677075b 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java @@ -71,6 +71,13 @@ public class ECUtil { return toX962Compressed(point, spec.getCurve().getField().getFieldSize()); } + public static byte[] toX962Uncompressed(byte[][] point) { + if (point.length != 2) { + return null; + } + return ByteUtil.concatenate(new byte[]{(byte) (0x04)}, point[0], point[1]); + } + public static byte[] toX962Uncompressed(ECPoint point, int bits) { if (point.equals(ECPoint.POINT_INFINITY)) { return new byte[]{0}; diff --git a/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java b/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java index 1fa937e..bb11484 100644 --- a/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java +++ b/reader/src/main/java/cz/crcs/ectester/reader/ECTesterReader.java @@ -28,6 +28,7 @@ import cz.crcs.ectester.common.cli.CLITools; import cz.crcs.ectester.common.cli.Colors; import cz.crcs.ectester.common.ec.EC_Curve; import cz.crcs.ectester.common.ec.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Params; import cz.crcs.ectester.common.output.OutputLogger; import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.util.*; @@ -333,6 +334,7 @@ public class ECTesterReader { opts.addOption(Option.builder("v").longOpt("verbose").desc("Turn on verbose logging.").build()); opts.addOption(Option.builder().longOpt("format").desc("Output format to use. One of: text,yml,xml.").hasArg().argName("format").build()); + opts.addOption(Option.builder().longOpt("external").desc("Use external key in ECDH.").build()); opts.addOption(Option.builder().longOpt("alloc-keypair").desc("Use KeyPair allocation method, one of: keypair, keybuilder, any.").hasArg().argName("method").build()); opts.addOption(Option.builder().longOpt("fixed").desc("Generate key(s) only once, keep them for later operations.").build()); opts.addOption(Option.builder().longOpt("fixed-private").desc("Generate private key only once, keep it for later ECDH.").build()); @@ -600,10 +602,23 @@ public class ECTesterReader { Response gen = new Command.Generate(cardManager, CardConsts.KEYPAIR_BOTH).send(); respWriter.outputResponse(gen); - if (cfg.anyPublicKey || cfg.anyKey) { - Response prep = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, CardConsts.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W).send(); - respWriter.outputResponse(prep); + EC_Params keypair = null; + if (!cfg.external) { + if (cfg.anyPublicKey || cfg.anyKey) { + Response prep = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, CardConsts.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W).send(); + respWriter.outputResponse(prep); + } + } else { + if (cfg.key != null || cfg.namedKey != null) { + keypair = ECUtil.loadParams(EC_Consts.PARAMETERS_KEYPAIR, cfg.namedKey, cfg.key); + } else if (cfg.publicKey != null || cfg.namedPublicKey != null) { + keypair = ECUtil.loadParams(EC_Consts.PARAMETER_W, cfg.namedPublicKey, cfg.publicKey); + } else { + System.err.println(Colors.error("No key provided for external ECDH.")); + return; + } } + if (cfg.anyPrivateKey || cfg.anyKey) { Response prep = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, CardConsts.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S).send(); respWriter.outputResponse(prep); @@ -633,21 +648,34 @@ public class ECTesterReader { respWriter.outputResponse(regen); } - Response.Export exportRemote = new Command.Export(cardManager, CardConsts.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send(); - respWriter.outputResponse(exportRemote); - Response.Export exportLocal = new Command.Export(cardManager, CardConsts.KEYPAIR_LOCAL, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S).send(); - respWriter.outputResponse(exportLocal); - byte[] pubkey_bytes = exportRemote.getParameter(CardConsts.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W); - byte[] privkey_bytes = exportLocal.getParameter(CardConsts.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S); + byte[] privkey_bytes; + byte[] pubkey_bytes; + Command perform; + if (cfg.external) { + Response.Export exportLocal = new Command.Export(cardManager, CardConsts.KEYPAIR_LOCAL, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S).send(); + respWriter.outputResponse(exportLocal); + privkey_bytes = exportLocal.getParameter(CardConsts.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S); + pubkey_bytes = ECUtil.toX962Uncompressed(keypair.getParam(EC_Consts.PARAMETER_W)); + + perform = new Command.ECDH_direct(cardManager, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, cfg.ECKAType, pubkey_bytes); + } else { + Response.Export exportRemote = new Command.Export(cardManager, CardConsts.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send(); + respWriter.outputResponse(exportRemote); + Response.Export exportLocal = new Command.Export(cardManager, CardConsts.KEYPAIR_LOCAL, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S).send(); + respWriter.outputResponse(exportLocal); + pubkey_bytes = exportRemote.getParameter(CardConsts.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W); + privkey_bytes = exportLocal.getParameter(CardConsts.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S); + + perform = new Command.ECDH(cardManager, CardConsts.KEYPAIR_REMOTE, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, cfg.ECKAType); + } - Command.ECDH perform = new Command.ECDH(cardManager, CardConsts.KEYPAIR_REMOTE, CardConsts.KEYPAIR_LOCAL, CardConsts.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, cfg.ECKAType); long time = 0; if (cfg.time) { time = -Command.dryRunTime(cardManager, perform, 2, respWriter); } - Response.ECDH result = perform.send(); + Response.ECDH result = (Response.ECDH) perform.send(); respWriter.outputResponse(result); if (!result.successful() || !result.hasSecret()) { @@ -842,7 +870,7 @@ public class ECTesterReader { public boolean fixedKey = false; public boolean fixedPrivate = false; public boolean fixedPublic = false; - public byte keyBuilder; + public byte keyBuilder = CardConsts.BUILD_KEYBUILDER | CardConsts.BUILD_KEYPAIR; public String log; @@ -859,6 +887,7 @@ public class ECTesterReader { public boolean color; //Action-related options + public boolean external; public String listNamed; public String testSuite; public int testFrom; @@ -1080,6 +1109,12 @@ public class ECTesterReader { } } else if (cli.hasOption("ecdh")) { + external = cli.hasOption("external"); + if (external && !(anyPublicKey || anyKey)) { + System.err.print(Colors.error("Need to specify public key with -pub or -named-public (or key with -key or -named-key) when specifying --external.")); + return false; + } + if (primeField == binaryField) { System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)")); return false; |
