diff options
| author | J08nY | 2018-11-28 01:04:31 +0100 |
|---|---|---|
| committer | J08nY | 2018-11-28 01:04:31 +0100 |
| commit | ebe40e2fdd5e28cdabe05250422f3149e188641a (patch) | |
| tree | fbf29423e8053c6a7267d600d1630fefb1bf1a1b /src/cz/crcs/ectester/reader/test | |
| parent | 7e9917742785a9fd532a52231e95ddad5775555f (diff) | |
| parent | 12845c8c41eff5f598dc8e843920f5bb4638775d (diff) | |
| download | ECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.tar.gz ECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.tar.zst ECTester-ebe40e2fdd5e28cdabe05250422f3149e188641a.zip | |
Merge branch 'devel'
Diffstat (limited to 'src/cz/crcs/ectester/reader/test')
11 files changed, 205 insertions, 57 deletions
diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java index 710b704..172c8af 100644 --- a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java @@ -31,8 +31,8 @@ public class CardCofactorSuite extends CardTestSuite { @Override protected void runTests() throws Exception { Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "cofactor"); - List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) { + Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); @@ -46,7 +46,7 @@ public class CardCofactorSuite extends CardTestSuite { for (EC_Key.Public pub : keys) { Test setPub = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE); Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE); - Test objectEcdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with degenerate pubkey.", setPub, ecdh); + Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with degenerate pubkey.", setPub, ecdh); Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); Test rawEcdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on non-generator subgroup.", "Card incorrectly accepted point on non-generator subgroup."); ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", objectEcdh, rawEcdh)); diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java index 336b371..4bf9290 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java @@ -37,8 +37,8 @@ public class CardCompositeSuite extends CardTestSuite { * is revealed. */ Map<String, EC_Key> keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite"); - List<Map.Entry<EC_Curve, List<EC_Key>>> mappedKeys = EC_Store.mapKeyToCurve(keys.values()); - for (Map.Entry<EC_Curve, List<EC_Key>> curveKeys : mappedKeys) { + Map<EC_Curve, List<EC_Key>> mappedKeys = EC_Store.mapKeyToCurve(keys.values()); + for (Map.Entry<EC_Curve, List<EC_Key>> curveKeys : mappedKeys.entrySet()) { EC_Curve curve = curveKeys.getKey(); List<Test> tests = new LinkedList<>(); Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); @@ -59,35 +59,35 @@ public class CardCompositeSuite extends CardTestSuite { Map<String, EC_Curve> results = EC_Store.getInstance().getObjects(EC_Curve.class, "composite"); - List<Map.Entry<String, List<EC_Curve>>> groupList = EC_Store.mapToPrefix(results.values()); + Map<String, List<EC_Curve>> groups = EC_Store.mapToPrefix(results.values()); /* Test the whole curves with both keypairs generated on card(no small-order public points provided). */ - List<EC_Curve> wholeCurves = groupList.stream().filter((e) -> e.getKey().equals("whole")).findFirst().get().getValue(); + List<EC_Curve> wholeCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("whole")).findFirst().get().getValue(); testGroup(wholeCurves, "Composite generator order", ExpectedValue.FAILURE, "Card rejected to do ECDH with composite order generator.", "Card did not reject to do ECDH with composite order generator."); /* Also test having a G of small order, so small R. */ - List<EC_Curve> smallRCurves = groupList.stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); + List<EC_Curve> smallRCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator."); /* Test increasingly larger prime R, to determine where/if card behavior changes. */ - List<EC_Curve> varyingCurves = groupList.stream().filter((e) -> e.getKey().equals("varying")).findFirst().get().getValue(); + List<EC_Curve> varyingCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("varying")).findFirst().get().getValue(); testGroup(varyingCurves, null, ExpectedValue.ANY, "", ""); /* Also test having a G of large but composite order, R = p * q, */ - List<EC_Curve> pqCurves = groupList.stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); + List<EC_Curve> pqCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); /* Also test having G or large order being a Carmichael pseudoprime, R = p * q * r, */ - List<EC_Curve> ppCurves = groupList.stream().filter((e) -> e.getKey().equals("pp")).findFirst().get().getValue(); + List<EC_Curve> ppCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("pp")).findFirst().get().getValue(); testGroup(ppCurves, "Generator order = Carmichael pseudoprime", ExpectedValue.ANY, "", ""); /* Also test rg0 curves. */ - List<EC_Curve> rg0Curves = groupList.stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); + List<EC_Curve> rg0Curves = groups.entrySet().stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); testGroup(rg0Curves, null, ExpectedValue.ANY, "", ""); } diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java index ae25bf1..291cc04 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java @@ -2,6 +2,8 @@ package cz.crcs.ectester.reader.test; import cz.crcs.ectester.applet.ECTesterApplet; import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.ec.EC_Curve; +import cz.crcs.ectester.common.ec.EC_Key; import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.test.CompoundTest; import cz.crcs.ectester.common.test.Result; @@ -9,6 +11,7 @@ import cz.crcs.ectester.common.test.Test; 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; @@ -18,6 +21,7 @@ import javacard.security.KeyPair; import java.security.spec.ECPoint; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * @author Jan Jancar johny@neuromancer.sk @@ -51,6 +55,10 @@ public class CardCompressionSuite extends CardTestSuite { if (cfg.binaryField) { runCompression(KeyPair.ALG_EC_F2M); } + + // Now, do ECDH over SECG curves and give the implementation a compressed key that is not a quadratic residue in + // decompression. + runNonResidue(); } private void runCompression(byte field) throws Exception { @@ -59,27 +67,28 @@ public class CardCompressionSuite extends CardTestSuite { for (short keyLength : keySizes) { String spec = keyLength + "b " + CardUtil.getKeyTypeString(field); + byte curveId = EC_Consts.getCurve(keyLength, field); Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), Result.ExpectedValue.SUCCESS)); if (!allocateFirst.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + spec + ".", allocateFirst)); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for compression test on " + spec + ".", allocateFirst)); continue; } List<Test> compressionTests = new LinkedList<>(); compressionTests.add(allocateFirst); - Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.getCurve(keyLength, field), domain, null), Result.ExpectedValue.SUCCESS)); + Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curveId, domain, null), Result.ExpectedValue.SUCCESS)); Test genCustom = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS)); compressionTests.add(setCustom); compressionTests.add(genCustom); Response.Export key = new Command.Export(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send(); byte[] pubkey = key.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC); + EC_Curve secgCurve = EC_Store.getInstance().getObject(EC_Curve.class, "secg", CardUtil.getCurveName(curveId)); ECPoint pub; try { - pub = ECUtil.fromX962(pubkey, null); + pub = ECUtil.fromX962(pubkey, secgCurve.toCurve()); } catch (IllegalArgumentException iae) { - // TODO: use external SECG curves so we have them here. doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "", compressionTests.toArray(new Test[0]))); continue; } @@ -119,4 +128,26 @@ public class CardCompressionSuite extends CardTestSuite { doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Compression test of " + spec + ".", compressionTests.toArray(new Test[0]))); } } + + private void runNonResidue() { + Map<String, EC_Key.Public> otherKeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "misc"); + List<EC_Key.Public> compressionKeys = EC_Store.mapToPrefix(otherKeys.values()).get("compression"); + + for (EC_Key.Public key : compressionKeys) { + EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve()); + List<Test> tests = new LinkedList<>(); + Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); + if (!allocate.ok()) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for non-residue test on " + curve.getBits() + "b " + curve.getId() + ".", allocate)); + continue; + } + tests.add(allocate); + tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS)); + tests.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS)); + byte[] pointData = ECUtil.toX962Compressed(key.getParam(EC_Consts.PARAMETER_W)); + byte[] pointDataEncoded = ByteUtil.prependLength(pointData); + tests.add(CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pointDataEncoded), Result.ExpectedValue.FAILURE)); + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Non-residue test of " + curve.getId() + ".", tests.toArray(new Test[0]))); + } + } } diff --git a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java index e495b00..91f9ef6 100644 --- a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java @@ -10,6 +10,7 @@ import cz.crcs.ectester.common.util.CardUtil; 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 java.util.LinkedList; diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java index c926a4d..f434d4d 100644 --- a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java @@ -31,8 +31,8 @@ public class CardDegenerateSuite extends CardTestSuite { @Override protected void runTests() throws Exception { Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate"); - List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) { + Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); diff --git a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java index b68b2ec..ccec401 100644 --- a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java @@ -39,8 +39,8 @@ public class CardEdgeCasesSuite extends CardTestSuite { @Override protected void runTests() throws Exception { Map<String, EC_KAResult> results = EC_Store.getInstance().getObjects(EC_KAResult.class, "wycheproof"); - List<Map.Entry<String, List<EC_KAResult>>> groupList = EC_Store.mapToPrefix(results.values()); - for (Map.Entry<String, List<EC_KAResult>> e : groupList) { + Map<String, List<EC_KAResult>> groups = EC_Store.mapToPrefix(results.values()); + for (Map.Entry<String, List<EC_KAResult>> e : groups.entrySet()) { String description = null; switch (e.getKey()) { case "addsub": @@ -55,8 +55,8 @@ public class CardEdgeCasesSuite extends CardTestSuite { } List<Test> groupTests = new LinkedList<>(); - List<Map.Entry<EC_Curve, List<EC_KAResult>>> curveList = EC_Store.mapResultToCurve(e.getValue()); - for (Map.Entry<EC_Curve, List<EC_KAResult>> c : curveList) { + Map<EC_Curve, List<EC_KAResult>> curveList = EC_Store.mapResultToCurve(e.getValue()); + for (Map.Entry<EC_Curve, List<EC_KAResult>> c : curveList.entrySet()) { EC_Curve curve = c.getKey(); List<Test> curveTests = new LinkedList<>(); @@ -111,7 +111,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { } { - EC_KAResult openssl_bug = EC_Store.getInstance().getObject(EC_KAResult.class, "other", "openssl-bug"); + EC_KAResult openssl_bug = EC_Store.getInstance().getObject(EC_KAResult.class, "misc", "openssl-bug"); EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, openssl_bug.getCurve()); EC_Key.Private skey = EC_Store.getInstance().getObject(EC_Key.Private.class, openssl_bug.getOtherKey()); EC_Key.Public pkey = EC_Store.getInstance().getObject(EC_Key.Public.class, openssl_bug.getOneKey()); @@ -145,7 +145,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { for (EC_Curve curve : curves) { Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS)); if (!key.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b ALG_EC_FP.", key)); + doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + curve.getId() + ".", key)); continue; } Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); @@ -238,7 +238,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, secp160r1.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS)); if (!key.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + secp160r1.getBits() + "b ALG_EC_FP.", key)); + doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + secp160r1.getBits() + "b secp160r1.", key)); return; } Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, secp160r1.getParams(), secp160r1.flatten()), Result.ExpectedValue.SUCCESS); diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java index 17c5d4b..3b9e0e5 100644 --- a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java @@ -35,8 +35,8 @@ public class CardInvalidSuite extends CardTestSuite { * Try ECDH with invalid public keys of increasing order. */ Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid"); - List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) { + Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java index 8623e36..a2ce2ce 100644 --- a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java @@ -7,12 +7,14 @@ import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.test.CompoundTest; import cz.crcs.ectester.common.test.Result; import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; 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 java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Map; /** @@ -21,7 +23,9 @@ import java.util.Map; public class CardMiscSuite extends CardTestSuite { public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves and some Barreto-Naehrig curves with small embedding degree and CM discriminant."); + super(writer, cfg, cardManager, "miscellaneous", "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves,", + "Barreto-Naehrig curves with small embedding degree and CM discriminant, MNT curves,", + "some Montgomery curves transformed to short Weierstrass form and Curve25519 transformed to short Weierstrass form."); } @Override @@ -29,32 +33,45 @@ public class CardMiscSuite extends CardTestSuite { Map<String, EC_Curve> anCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "anomalous"); Map<String, EC_Curve> ssCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "supersingular"); Map<String, EC_Curve> bnCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "Barreto-Naehrig"); + Map<String, EC_Curve> mntCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "MNT"); + List<EC_Curve> mCurves = new ArrayList<>(); + mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-221")); + mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-383")); + mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-511")); + EC_Curve curve25519 = EC_Store.getInstance().getObject(EC_Curve.class, "other", "Curve25519"); - testCurves(anCurves, "anomalous", Result.ExpectedValue.FAILURE); - testCurves(ssCurves, "supersingular", Result.ExpectedValue.FAILURE); - testCurves(bnCurves, "Barreto-Naehrig", Result.ExpectedValue.ANY); + testCurves(anCurves.values(), "anomalous", Result.ExpectedValue.FAILURE); + testCurves(ssCurves.values(), "supersingular", Result.ExpectedValue.FAILURE); + testCurves(bnCurves.values(), "Barreto-Naehrig", Result.ExpectedValue.SUCCESS); + testCurves(mntCurves.values(), "MNT", Result.ExpectedValue.SUCCESS); + testCurves(mCurves, "Montgomery", Result.ExpectedValue.SUCCESS); + testCurve(curve25519, "Montgomery", Result.ExpectedValue.SUCCESS); } - private void testCurves(Map<String, EC_Curve> curves, String catName, Result.ExpectedValue expected) throws Exception { - for (EC_Curve curve : curves.values()) { - Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); - if (!allocateFirst.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocateFirst)); - continue; - } + private void testCurve(EC_Curve curve, String catName, Result.ExpectedValue expected) { + Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); + if (!allocateFirst.ok()) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst)); + return; + } + + Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); + Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.ANY); + Test ka = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), expected); + Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), expected); + Test perform = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH and ECDSA.", ka, sig); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.ANY); - Test ka = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), expected); - Test sig = CommandTest.expect(new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), expected); - Test perform = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH and ECDSA", ka, sig); + if (cfg.cleanup) { + Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform, cleanup)); + } else { + doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform)); + } + } - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform, cleanup)); - } else { - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + " " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform)); - } + private void testCurves(Collection<EC_Curve> curves, String catName, Result.ExpectedValue expected) { + for (EC_Curve curve : curves) { + testCurve(curve, catName, expected); } } } diff --git a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java b/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java index 59def74..20546c8 100644 --- a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java @@ -28,16 +28,16 @@ public class CardSignatureSuite extends CardTestSuite { @Override protected void runTests() throws Exception { Map<String, EC_SigResult> results = EC_Store.getInstance().getObjects(EC_SigResult.class, "wrong"); - List<Map.Entry<String, List<EC_SigResult>>> groupList = EC_Store.mapToPrefix(results.values()); + Map<String, List<EC_SigResult>> groups = EC_Store.mapToPrefix(results.values()); - List<EC_SigResult> nok = groupList.stream().filter((e) -> e.getKey().equals("nok")).findFirst().get().getValue(); + List<EC_SigResult> nok = groups.entrySet().stream().filter((e) -> e.getKey().equals("nok")).findFirst().get().getValue(); byte[] data = "Some stuff that is not the actual data".getBytes(); for (EC_SigResult sig : nok) { ecdsaTest(sig, Result.ExpectedValue.FAILURE, data); } - List<EC_SigResult> ok = groupList.stream().filter((e) -> e.getKey().equals("ok")).findFirst().get().getValue(); + List<EC_SigResult> ok = groups.entrySet().stream().filter((e) -> e.getKey().equals("ok")).findFirst().get().getValue(); for (EC_SigResult sig : ok) { ecdsaTest(sig, Result.ExpectedValue.SUCCESS, null); } 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]))); } } } diff --git a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java index 6ad4ce6..3df4c65 100644 --- a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java @@ -29,8 +29,8 @@ public class CardTwistSuite extends CardTestSuite { @Override protected void runTests() throws Exception { Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist"); - List<Map.Entry<EC_Curve, List<EC_Key.Public>>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList) { + Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); + for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); |
