aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
diff options
context:
space:
mode:
authorJ08nY2018-11-28 01:04:31 +0100
committerJ08nY2018-11-28 01:04:31 +0100
commitebe40e2fdd5e28cdabe05250422f3149e188641a (patch)
treefbf29423e8053c6a7267d600d1630fefb1bf1a1b /src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
parent7e9917742785a9fd532a52231e95ddad5775555f (diff)
parent12845c8c41eff5f598dc8e843920f5bb4638775d (diff)
downloadECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.tar.gz
ECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.tar.zst
ECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.zip
Diffstat (limited to 'src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java')
-rw-r--r--src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java103
1 files changed, 101 insertions, 2 deletions
diff --git a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
index fbdf103..3abcebb 100644
--- a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
+++ b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java
@@ -9,16 +9,28 @@ import cz.crcs.ectester.common.test.Result;
import cz.crcs.ectester.common.test.Test;
import cz.crcs.ectester.common.test.TestCallback;
import cz.crcs.ectester.common.util.ByteUtil;
+import cz.crcs.ectester.common.util.CardUtil;
+import cz.crcs.ectester.common.util.ECUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.reader.CardMngr;
import cz.crcs.ectester.reader.ECTesterReader;
import cz.crcs.ectester.reader.command.Command;
import cz.crcs.ectester.reader.response.Response;
+import javacard.security.KeyPair;
+import javax.crypto.KeyAgreement;
import java.io.IOException;
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import static cz.crcs.ectester.common.test.Result.ExpectedValue;
import static cz.crcs.ectester.common.test.Result.Value;
@@ -52,8 +64,13 @@ public class CardTestVectorSuite extends CardTestSuite {
throw new IOException("Test vector keys couldn't be located.");
}
List<Test> testVector = new LinkedList<>();
+ Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
+ if (!allocate.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate));
+ continue;
+ }
- testVector.add(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
+ testVector.add(allocate);
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS));
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, onekey.flatten(EC_Consts.PARAMETER_S)), ExpectedValue.SUCCESS));
testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_W, otherkey.flatten(EC_Consts.PARAMETER_W)), ExpectedValue.SUCCESS));
@@ -75,7 +92,89 @@ public class CardTestVectorSuite extends CardTestSuite {
if (cfg.cleanup) {
testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY));
}
- doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Test vector " + result.getId(), testVector.toArray(new Test[0])));
+ doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Test vector " + result.getId() + ".", testVector.toArray(new Test[0])));
+ }
+
+ KeyAgreement ka;
+ KeyFactory kf;
+ MessageDigest md;
+ try {
+ ka = KeyAgreement.getInstance("ECDH", "BC");
+ kf = KeyFactory.getInstance("ECDH", "BC");
+ md = MessageDigest.getInstance("SHA1", "BC");
+ } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
+ return;
+ }
+
+ List<EC_Curve> testCurves = new ArrayList<>();
+ testCurves.addAll(EC_Store.getInstance().getObjects(EC_Curve.class, "secg").values().stream().filter((curve) -> curve.getField() == KeyPair.ALG_EC_FP).collect(Collectors.toList()));
+ testCurves.addAll(EC_Store.getInstance().getObjects(EC_Curve.class, "brainpool").values().stream().filter((curve) -> curve.getField() == KeyPair.ALG_EC_FP).collect(Collectors.toList()));
+ for (EC_Curve curve : testCurves) {
+ List<Test> testVector = new LinkedList<>();
+ Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS));
+ if (!allocate.ok()) {
+ doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate));
+ continue;
+ }
+ testVector.add(allocate);
+ testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS));
+ testVector.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS));
+ CommandTest export = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR), ExpectedValue.ANY);
+ testVector.add(export);
+ TestCallback<CommandTestable> kaCallback = new TestCallback<CommandTestable>() {
+ @Override
+ public Result apply(CommandTestable testable) {
+ Response.ECDH ecdhData = (Response.ECDH) testable.getResponse();
+ if (!ecdhData.successful())
+ return new Result(Value.FAILURE, "ECDH was unsuccessful.");
+ if (!ecdhData.hasSecret()) {
+ return new Result(Value.FAILURE, "ECDH response did not contain the derived secret.");
+ }
+ byte[] secret = ecdhData.getSecret();
+ Response.Export keyData = (Response.Export) export.getResponse();
+ byte[] pkey = keyData.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W);
+ byte[] skey = keyData.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.PARAMETER_S);
+ ECParameterSpec spec = curve.toSpec();
+ ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger(1, skey), spec);
+ ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(ECUtil.fromX962(pkey, curve.toCurve()), spec);
+ PrivateKey privKey;
+ PublicKey pubkey;
+ try {
+ privKey = kf.generatePrivate(privKeySpec);
+ pubkey = kf.generatePublic(pubKeySpec);
+ ka.init(privKey);
+ ka.doPhase(pubkey, true);
+ byte[] rawDerived = ka.generateSecret();
+ int fieldSize = (curve.getBits() + 7) / 8;
+ if (rawDerived.length < fieldSize) {
+ byte[] padded = new byte[fieldSize];
+ System.arraycopy(rawDerived, 0, padded, fieldSize - rawDerived.length, rawDerived.length);
+ rawDerived = padded;
+ }
+ byte[] derived = md.digest(rawDerived);
+ if (secret.length != derived.length) {
+ if (secret.length < derived.length) {
+ return new Result(Value.FAILURE, String.format("Derived secret was shorter than expected: %d vs %d (expected).", secret.length, derived.length));
+ } else {
+ return new Result(Value.FAILURE, String.format("Derived secret was longer than expected: %d vs %d (expected).", secret.length, derived.length));
+ }
+ }
+ int diff = ByteUtil.diffBytes(derived, 0, secret, 0, secret.length);
+ if (diff == secret.length) {
+ return new Result(Value.SUCCESS, "Derived secret matched expected value.");
+ } else {
+ return new Result(Value.FAILURE, "Derived secret does not match expected value, first difference was at byte " + String.valueOf(diff) + ".");
+ }
+ } catch (InvalidKeySpecException | InvalidKeyException ex) {
+ return new Result(Value.SUCCESS, "Result could not be verified. " + ex.getMessage());
+ }
+ }
+ };
+ testVector.add(CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), kaCallback));
+ if (cfg.cleanup) {
+ testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY));
+ }
+ doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Validation test on " + curve.getId() + ".", testVector.toArray(new Test[0])));
}
}
}