diff options
Diffstat (limited to 'src/cz/crcs/ectester/reader/test')
14 files changed, 237 insertions, 67 deletions
diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java index 172c8af..982e07a 100644 --- a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java @@ -25,7 +25,8 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue; */ public class CardCofactorSuite extends CardTestSuite { public CardCofactorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "cofactor", "The cofactor test suite tests whether the card correctly rejects points on the curve but not in the subgroup generated by the generator during ECDH."); + super(writer, cfg, cardManager, "cofactor", "The cofactor test suite tests whether the card correctly rejects points on the curve", + "but not in the subgroup generated by the generator(so of small order, dividing the cofactor) during ECDH."); } @Override @@ -38,7 +39,7 @@ public class CardCofactorSuite extends CardTestSuite { Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS); Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS); + Test generate = genOrPreset(curve, ExpectedValue.SUCCESS); Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java index 4bf9290..93d50e8 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java @@ -25,7 +25,8 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue; public class CardCompositeSuite extends CardTestSuite { public CardCompositeSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order. This should generally fail, as using such a curve is unsafe."); + super(writer, cfg, cardManager, "composite", "The composite suite runs ECDH over curves with composite order.", + "Various types of compositeness is tested: smooth numbers, Carmichael pseudoprime, prime square, product of two large primes."); } @Override @@ -48,11 +49,18 @@ public class CardCompositeSuite extends CardTestSuite { } tests.add(allocate); tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY)); - tests.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.ANY)); + + String name; + if (cfg.testOptions.contains("preset")) { + name = "preset semi-random key"; + } else { + name = "generated key"; + } + tests.add(genOrPreset(curve, ExpectedValue.ANY)); for (EC_Key key : curveKeys.getValue()) { 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, key.flatten()); Test ecdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a composite order curve.", "Card incorrectly does ECDH over a composite order curve, leaks bits of private key."); - tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", " + key.getDesc(), ecdh)); + tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with " + name + ", " + key.getDesc(), ecdh)); } doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0]))); } diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java index 291cc04..c86c0b1 100644 --- a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java @@ -29,7 +29,9 @@ import java.util.Map; public class CardCompressionSuite extends CardTestSuite { public CardCompressionSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { super(writer, cfg, cardManager, "compression", "The compression test suite tests cards support for compressed points in ECDH (as per ANSI X9.62).", - "It also tests for handling of bogus input by using the point at infinity and a hybrid point with the y coordinate corrupted."); + "It also tests for handling of bogus input in ECDH by using the point at infinity and a hybrid point with the y coordinate corrupted.", + "It also tests handling of compressed point in ECDH, where the x coordinate is invalid and therefore", + "a quadratic non-residue will be computed and (square root-ed) during decompression."); } @Override diff --git a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java index 91f9ef6..ebece61 100644 --- a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java @@ -10,7 +10,6 @@ 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; @@ -29,7 +28,7 @@ import static cz.crcs.ectester.common.test.Result.Value; public class CardDefaultSuite extends CardTestSuite { public CardDefaultSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "default", "The default test suite tests basic support of ECDH and ECDSA."); + super(writer, cfg, cardManager, "default", "The default test suite tests basic support and performance of ECDH and ECDSA."); } @Override @@ -83,7 +82,7 @@ public class CardDefaultSuite extends CardTestSuite { Test compound; if (ka.ok()) { - Test perfTest = runTest(PerformanceTest.repeat(ecdh, 10)); + Test perfTest = runTest(PerformanceTest.repeat(this.card, ecdh, 10)); compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed, perfTest)); } else { compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed)); @@ -114,10 +113,10 @@ public class CardDefaultSuite extends CardTestSuite { Test compound; if (expect.ok()) { Command ecdsaSign = new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_TRUE, sigData); - PerformanceTest signTest = runTest(PerformanceTest.repeat("Sign", ecdsaSign, 10)); + PerformanceTest signTest = runTest(PerformanceTest.repeat(this.card, "Sign", ecdsaSign, 10)); byte[] signature = signTest.getResponses()[0].getParam(0); Command ecdsaVerify = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, sigData, signature); - PerformanceTest verifyTest = runTest(PerformanceTest.repeat("Verify", ecdsaVerify, 10)); + PerformanceTest verifyTest = runTest(PerformanceTest.repeat(this.card, "Verify", ecdsaVerify, 10)); compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect, signTest, verifyTest)); } else { compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect)); diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java index f434d4d..730c70b 100644 --- a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java @@ -25,7 +25,7 @@ public class CardDegenerateSuite extends CardTestSuite { public CardDegenerateSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { super(writer, cfg, cardManager, "degenerate", "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.", - "The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas work."); + "The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas degenerate into exponentiation in the base finite field."); } @Override @@ -36,27 +36,32 @@ public class CardDegenerateSuite extends CardTestSuite { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); + Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); + if (!allocate.ok()) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); + continue; + } 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_LOCAL), Result.ExpectedValue.SUCCESS); - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); List<Test> ecdhTests = new LinkedList<>(); 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 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, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve."); 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, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve."); ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " degenerate key test.", objectEcdh, rawEcdh)); + //TODO: actually get the result of ECDH here, as well as export privkey and compare to exponentiation in Fp^*. } - Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points", ecdhTests.toArray(new Test[0])); + Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points.", ecdhTests.toArray(new Test[0])); if (cfg.cleanup) { Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh, cleanup)); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", prepare, ecdh, cleanup)); } else { - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId(), prepare, ecdh)); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", prepare, ecdh)); } } diff --git a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java index ccec401..53f3b6b 100644 --- a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java @@ -33,6 +33,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { public CardEdgeCasesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { super(writer, cfg, cardManager, "edge-cases", "The edge-cases test suite tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during it.", "Some of the data is from the google/Wycheproof project. Tests include CVE-2017-10176 and CVE-2017-8932.", + "Also tests values of the private key and public key that would trigger the OpenSSL modualr multiplication bug on the P-256 curve.", "Various edge private key values are also tested."); } @@ -91,7 +92,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { int firstDiff = ByteUtil.diffBytes(dh.getSecret(), 0, value.getData(0), 0, dh.secretLength()); System.err.println(ByteUtil.bytesToHex(dh.getSecret())); System.err.println(ByteUtil.bytesToHex(value.getData(0))); - return new Result(Result.Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + String.valueOf(firstDiff) + "."); + return new Result(Result.Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + firstDiff + "."); } return new Result(Result.Value.SUCCESS); } @@ -104,6 +105,10 @@ public class CardEdgeCasesSuite extends CardTestSuite { curveTests.add(one); } + if (cfg.cleanup) { + curveTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY)); + } + Test curveTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests", curveTests.toArray(new Test[0])); groupTests.add(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Tests on " + curve.getId() + ".", prepareCurve, curveTest)); } @@ -149,8 +154,22 @@ public class CardEdgeCasesSuite extends CardTestSuite { continue; } 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_LOCAL), Result.ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate); + Test generate = genOrPreset(curve, Result.ExpectedValue.SUCCESS); + CommandTest export = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W), Result.ExpectedValue.SUCCESS); + Test setup = runTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate, export)); + + byte[] pParam = curve.getParam(EC_Consts.PARAMETER_FP)[0]; + BigInteger p = new BigInteger(1, pParam); + byte[] wParam = ((Response.Export) export.getResponse()).getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W); + byte[] yValue = new byte[(wParam.length - 1) / 2]; + System.arraycopy(wParam, (wParam.length / 2) + 1, yValue, 0, yValue.length); + BigInteger y = new BigInteger(1, yValue); + BigInteger negY = p.subtract(y); + byte[] newY = ECUtil.toByteArray(negY, curve.getBits()); + System.arraycopy(newY, 0, wParam, (wParam.length / 2) + 1, newY.length); + + EC_Params negYParams = makeParams(newY); + Test negYTest = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, negYParams.getParams(), negYParams.flatten()), "ECDH with pubkey negated.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); Test zeroS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ZERO), "ECDH with S = 0.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); Test oneS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ONE), "ECDH with S = 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); @@ -164,8 +183,21 @@ public class CardEdgeCasesSuite extends CardTestSuite { BigInteger full = BigInteger.valueOf(1).shiftLeft(R.bitLength() - 1).subtract(BigInteger.ONE); + BigInteger alternate = full; + for (int i = 0; i < R.bitLength(); i += 2) { + alternate = alternate.clearBit(i); + } + + BigInteger alternateOther = alternate.xor(full); + + EC_Params alternateParams = makeParams(alternate); + Test alternateS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, alternateParams.getParams(), alternateParams.flatten()), "ECDH with S = 101010101...01010.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); + + EC_Params alternateOtherParams = makeParams(alternateOther); + Test alternateOtherS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, alternateOtherParams.getParams(), alternateOtherParams.flatten()), "ECDH with S = 010101010...10101.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); + EC_Params fullParams = makeParams(full); - Test fullS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, fullParams.getParams(), fullParams.flatten()), "ECDH with S = 2^((log2 r) - 1) - 1.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); + Test fullS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, fullParams.getParams(), fullParams.flatten()), "ECDH with S = 111111111...11111 (but < r).", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); EC_Params smallerParams = makeParams(smaller); Test smallerS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, smallerParams.getParams(), smallerParams.flatten()), "ECDH with S < r.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); @@ -191,20 +223,22 @@ public class CardEdgeCasesSuite extends CardTestSuite { BigInteger krm1 = kr.subtract(BigInteger.ONE); BigInteger krp1 = kr.add(BigInteger.ONE); + Result.ExpectedValue kExpected = K.equals(BigInteger.ONE) ? Result.ExpectedValue.SUCCESS : Result.ExpectedValue.FAILURE; + EC_Params krParams = makeParams(kr); Test krS /*ONE!*/ = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krParams.getParams(), krParams.flatten()), "ECDH with S = k * r.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); EC_Params krm1Params = makeParams(krm1); - Test krm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krm1Params.getParams(), krm1Params.flatten()), "ECDH with S = (k * r) - 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); + Test krm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krm1Params.getParams(), krm1Params.flatten()), "ECDH with S = (k * r) - 1.", kExpected, kExpected); EC_Params krp1Params = makeParams(krp1); - Test krp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krp1Params.getParams(), krp1Params.flatten()), "ECDH with S = (k * r) + 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); + Test krp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krp1Params.getParams(), krp1Params.flatten()), "ECDH with S = (k * r) + 1.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); if (cfg.cleanup) { Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, zeroS, oneS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S, cleanup)); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, negYTest, zeroS, oneS, alternateS, alternateOtherS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S, cleanup)); } else { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, zeroS, oneS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S)); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, negYTest, zeroS, oneS, alternateS, alternateOtherS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S)); } } @@ -249,7 +283,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { int i = 0; for (BigInteger nearZero : zeros) { EC_Params params = makeParams(nearZero); - zeroTests[i++] = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearZero.toString(16), Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); + zeroTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearZero.toString(16), Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); } Test zeroTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near zero.", zeroTests); @@ -257,7 +291,7 @@ public class CardEdgeCasesSuite extends CardTestSuite { i = 0; for (BigInteger nearP : ps) { EC_Params params = makeParams(nearP); - pTests[i++] = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearP.toString(16) + (nearP.compareTo(p) > 0 ? " (>p)" : " (<=p)"), Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); + pTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearP.toString(16) + (nearP.compareTo(p) > 0 ? " (>p)" : " (<=p)"), Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); } Test pTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near p.", pTests); @@ -265,12 +299,23 @@ public class CardEdgeCasesSuite extends CardTestSuite { i = 0; for (BigInteger nearR : rs) { EC_Params params = makeParams(nearR); - rTests[i++] = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearR.toString(16) + (nearR.compareTo(r) > 0 ? " (>r)" : " (<=r)"), Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); + if (nearR.compareTo(r) >= 0) { + rTests[i++] = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearR.toString(16) + " (>=r)", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); + } else { + rTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearR.toString(16) + " (<r)", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); + } } Test rTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near r.", rTests); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test private key values near zero, near p and near/larger than the order.", setup, zeroTest, pTest, rTest)); } + private Test ecdhTestBoth(Command setPriv, String desc, Result.ExpectedValue setExpect, Result.ExpectedValue ecdhExpect) { + Test set = CommandTest.expect(setPriv, setExpect); + Test ecdh = CommandTest.expect(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), ecdhExpect); + + return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, set, ecdh); + } + private Test ecdhTest(Command setPriv, String desc, Result.ExpectedValue setExpect, Result.ExpectedValue ecdhExpect) { Test set = CommandTest.expect(setPriv, setExpect); Test ecdh = CommandTest.expect(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), ecdhExpect); diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java index 3b9e0e5..9c4b54c 100644 --- a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java @@ -40,11 +40,15 @@ public class CardInvalidSuite extends CardTestSuite { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS); + 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(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); + continue; + } Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS); Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS); - Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); List<Test> ecdhTests = new LinkedList<>(); for (EC_Key.Public pub : keys) { @@ -55,13 +59,13 @@ public class CardInvalidSuite extends CardTestSuite { Test rawEcdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on invalid curve.", "Card incorrectly accepted point on invalid curve."); ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", objectEcdh, rawEcdh)); } - Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with invalid public points", ecdhTests.toArray(new Test[0])); + Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with invalid public points.", ecdhTests.toArray(new Test[0])); if (cfg.cleanup) { Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, ecdh, cleanup)); + doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", prepare, ecdh, cleanup)); } else { - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId(), prepare, ecdh)); + doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", prepare, ecdh)); } } } diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java index a2ce2ce..b1163c3 100644 --- a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java @@ -56,7 +56,7 @@ public class CardMiscSuite extends CardTestSuite { } 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 generate = genOrPreset(curve, 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); diff --git a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java b/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java index 20546c8..0fa58d3 100644 --- a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java @@ -22,7 +22,7 @@ import java.util.Map; */ public class CardSignatureSuite extends CardTestSuite { public CardSignatureSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "signature", "Test verifying various wrong ECDSA values."); + super(writer, cfg, cardManager, "signature", "The signature test suite tests verifying various malformed and well-formed but invalid ECDSA signatures."); } @Override diff --git a/src/cz/crcs/ectester/reader/test/CardTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTestSuite.java index 3578f9c..73acbe7 100644 --- a/src/cz/crcs/ectester/reader/test/CardTestSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardTestSuite.java @@ -1,9 +1,17 @@ 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_Params; import cz.crcs.ectester.common.output.TestWriter; +import cz.crcs.ectester.common.test.Result; +import cz.crcs.ectester.common.test.Test; import cz.crcs.ectester.common.test.TestSuite; +import cz.crcs.ectester.common.util.ECUtil; import cz.crcs.ectester.reader.CardMngr; import cz.crcs.ectester.reader.ECTesterReader; +import cz.crcs.ectester.reader.command.Command; /** * @author Jan Jancar johny@neuromancer.sk @@ -21,4 +29,18 @@ public abstract class CardTestSuite extends TestSuite { public CardMngr getCard() { return card; } + + public ECTesterReader.Config getCfg() { + return cfg; + } + + public Test genOrPreset(EC_Curve curve, Result.ExpectedValue expected) { + if (cfg.testOptions.contains("preset")) { + byte[] presetPriv = ECUtil.semiRandomKey(curve); + EC_Params privParms = new EC_Params(EC_Consts.PARAMETER_S, new byte[][]{presetPriv}); + return CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, privParms.getParams(), privParms.flatten()), expected); + } else { + return CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), expected); + } + } } diff --git a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java index 3abcebb..b6dc904 100644 --- a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.function.BiFunction; import java.util.stream.Collectors; import static cz.crcs.ectester.common.test.Result.ExpectedValue; @@ -84,7 +85,7 @@ public class CardTestVectorSuite extends CardTestSuite { return new Result(Value.FAILURE, "ECDH response did not contain the derived secret."); if (!ByteUtil.compareBytes(dh.getSecret(), 0, result.getData(0), 0, dh.secretLength())) { int firstDiff = ByteUtil.diffBytes(dh.getSecret(), 0, result.getData(0), 0, dh.secretLength()); - return new Result(Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + String.valueOf(firstDiff) + "."); + return new Result(Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + firstDiff + "."); } return new Result(Value.SUCCESS); } @@ -96,10 +97,12 @@ public class CardTestVectorSuite extends CardTestSuite { } KeyAgreement ka; + Signature sig; KeyFactory kf; MessageDigest md; try { ka = KeyAgreement.getInstance("ECDH", "BC"); + sig = Signature.getInstance("ECDSAwithSHA1", "BC"); kf = KeyFactory.getInstance("ECDH", "BC"); md = MessageDigest.getInstance("SHA1", "BC"); } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { @@ -119,8 +122,26 @@ public class CardTestVectorSuite extends CardTestSuite { 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); + CommandTest exportLocal = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W), ExpectedValue.ANY); + CommandTest exportRemote = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S), ExpectedValue.ANY); + testVector.add(exportLocal); + testVector.add(exportRemote); + BiFunction<Response.Export, Response.Export, Key[]> getKeys = (localData, remoteData) -> { + byte[] pkey = localData.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W); + byte[] skey = remoteData.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); + } catch (InvalidKeySpecException ex) { + return null; + } + return new Key[]{privKey, pubKey}; + }; TestCallback<CommandTestable> kaCallback = new TestCallback<CommandTestable>() { @Override public Result apply(CommandTestable testable) { @@ -131,19 +152,17 @@ public class CardTestVectorSuite extends CardTestSuite { 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; + Response.Export localData = (Response.Export) exportLocal.getResponse(); + Response.Export remoteData = (Response.Export) exportRemote.getResponse(); + Key[] keys = getKeys.apply(localData, remoteData); + if (keys == null) { + return new Result(Value.SUCCESS, "Result could not be verified. keyData unavailable."); + } + PrivateKey privKey = (PrivateKey) keys[0]; + PublicKey pubKey = (PublicKey) keys[1]; try { - privKey = kf.generatePrivate(privKeySpec); - pubkey = kf.generatePublic(pubKeySpec); ka.init(privKey); - ka.doPhase(pubkey, true); + ka.doPhase(pubKey, true); byte[] rawDerived = ka.generateSecret(); int fieldSize = (curve.getBits() + 7) / 8; if (rawDerived.length < fieldSize) { @@ -163,14 +182,47 @@ public class CardTestVectorSuite extends CardTestSuite { 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) + "."); + return new Result(Value.FAILURE, "Derived secret does not match expected value, first difference was at byte " + diff + "."); + } + } catch (InvalidKeyException ex) { + return new Result(Value.SUCCESS, "Result could not be verified. " + ex.getMessage()); + } + } + }; + Test ecdhTest = 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); + byte[] data = new byte[32]; + TestCallback<CommandTestable> sigCallback = new TestCallback<CommandTestable>() { + @Override + public Result apply(CommandTestable testable) { + Response.ECDSA ecdsaData = (Response.ECDSA) testable.getResponse(); + if (!ecdsaData.successful()) + return new Result(Value.FAILURE, "ECDSA was unsuccessful."); + if (!ecdsaData.hasSignature()) { + return new Result(Value.FAILURE, "ECDSA response did not contain the signature."); + } + byte[] signature = ecdsaData.getSignature(); + Response.Export localData = (Response.Export) exportLocal.getResponse(); + Response.Export remoteData = (Response.Export) exportRemote.getResponse(); + Key[] keys = getKeys.apply(localData, remoteData); + if (keys == null) { + return new Result(Value.SUCCESS, "Result could not be verified. keyData unavailable."); + } + PublicKey pubKey = (PublicKey) keys[1]; + try { + sig.initVerify(pubKey); + sig.update(data); + if (sig.verify(signature)) { + return new Result(Value.SUCCESS, "Signature verified."); + } else { + return new Result(Value.FAILURE, "Signature failed to verify."); } - } catch (InvalidKeySpecException | InvalidKeyException ex) { + } catch (InvalidKeyException | SignatureException 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)); + Test ecdsaTest = CommandTest.function(new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_TRUE, data), sigCallback); + testVector.add(CompoundTest.all(ExpectedValue.SUCCESS, "", ecdhTest, ecdsaTest)); if (cfg.cleanup) { testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY)); } diff --git a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java index 3df4c65..4929d52 100644 --- a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java @@ -34,29 +34,33 @@ public class CardTwistSuite extends CardTestSuite { EC_Curve curve = e.getKey(); List<EC_Key.Public> keys = e.getValue(); - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); + Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); + if (!allocate.ok()) { + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); + continue; + } 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_LOCAL), Result.ExpectedValue.SUCCESS); - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId(), allocate, set, generate); + Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); List<Test> ecdhTests = new LinkedList<>(); 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 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, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."); Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with twist 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, Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."); ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " twist key test.", objectEcdh, rawEcdh)); } - Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on twist", ecdhTests.toArray(new Test[0])); + Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on twist.", ecdhTests.toArray(new Test[0])); Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", ecdh); if (cfg.cleanup) { Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests, cleanup)); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", prepare, tests, cleanup)); } else { - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId(), prepare, tests)); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", prepare, tests)); } } } diff --git a/src/cz/crcs/ectester/reader/test/CommandTest.java b/src/cz/crcs/ectester/reader/test/CommandTest.java index adad191..b05d3e4 100644 --- a/src/cz/crcs/ectester/reader/test/CommandTest.java +++ b/src/cz/crcs/ectester/reader/test/CommandTest.java @@ -32,7 +32,7 @@ public class CommandTest extends SimpleTest<CommandTestable> { @Override public Result apply(CommandTestable commandTestable) { Result.Value resultValue = Result.Value.fromExpected(expected, commandTestable.ok(), commandTestable.error()); - return new Result(resultValue, resultValue.ok() ? ok : nok); + return new Result(resultValue, commandTestable.error() ? commandTestable.errorCause() : (resultValue.ok() ? ok : nok)); } }); } diff --git a/src/cz/crcs/ectester/reader/test/PerformanceTest.java b/src/cz/crcs/ectester/reader/test/PerformanceTest.java index f9a4472..f9cba46 100644 --- a/src/cz/crcs/ectester/reader/test/PerformanceTest.java +++ b/src/cz/crcs/ectester/reader/test/PerformanceTest.java @@ -1,18 +1,24 @@ package cz.crcs.ectester.reader.test; +import cz.crcs.ectester.applet.ECTesterApplet; import cz.crcs.ectester.common.test.Result; import cz.crcs.ectester.common.test.SimpleTest; import cz.crcs.ectester.common.test.TestCallback; +import cz.crcs.ectester.common.test.TestException; +import cz.crcs.ectester.reader.CardMngr; import cz.crcs.ectester.reader.command.Command; import cz.crcs.ectester.reader.response.Response; +import javax.smartcardio.CardException; import java.util.Arrays; /** * @author Jan Jancar johny@neuromancer.sk */ public class PerformanceTest extends SimpleTest<CommandTestable> { + private CardMngr cardManager; private long[] times; + private long[] reducedTimes; private Response[] responses; private long mean; private long median; @@ -20,23 +26,24 @@ public class PerformanceTest extends SimpleTest<CommandTestable> { private int count; private String desc; - private PerformanceTest(CommandTestable testable, int count, String desc) { + private PerformanceTest(CardMngr cardManager, CommandTestable testable, int count, String desc) { super(testable, new TestCallback<CommandTestable>() { @Override public Result apply(CommandTestable testable) { return new Result(Result.Value.SUCCESS); } }); + this.cardManager = cardManager; this.count = count; this.desc = desc; } - public static PerformanceTest repeat(Command cmd, int count) { - return new PerformanceTest(new CommandTestable(cmd), count, null); + public static PerformanceTest repeat(CardMngr cardManager, Command cmd, int count) { + return new PerformanceTest(cardManager, new CommandTestable(cmd), count, null); } - public static PerformanceTest repeat(String desc, Command cmd, int count) { - return new PerformanceTest(new CommandTestable(cmd), count, desc); + public static PerformanceTest repeat(CardMngr cardManager, String desc, Command cmd, int count) { + return new PerformanceTest(cardManager, new CommandTestable(cmd), count, desc); } @Override @@ -47,18 +54,35 @@ public class PerformanceTest extends SimpleTest<CommandTestable> { @Override protected void runSelf() { + long baseTime; + try { + new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_DRY_RUN).send(); + testable.run(); + baseTime = testable.getResponse().getDuration(); + testable.reset(); + testable.run(); + baseTime += testable.getResponse().getDuration(); + testable.reset(); + baseTime /= 2; + new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_NORMAL).send(); + } catch (CardException ce) { + throw new TestException(ce); + } + times = new long[count]; + reducedTimes = new long[count]; responses = new Response[count]; for (int i = 0; i < count; ++i) { testable.run(); responses[i] = testable.getResponse(); times[i] = responses[i].getDuration(); + reducedTimes[i] = times[i] - baseTime; testable.reset(); } - mean = Arrays.stream(times).sum() / count; + mean = Arrays.stream(reducedTimes).sum() / count; - long[] sorted = times.clone(); + long[] sorted = reducedTimes.clone(); Arrays.sort(sorted); if (count % 2 == 0) { median = (sorted[(count / 2) - 1] + sorted[count / 2]) / 2; @@ -99,6 +123,10 @@ public class PerformanceTest extends SimpleTest<CommandTestable> { return times; } + public long[] getReducedTimes() { + return reducedTimes; + } + public long getMean() { return mean; } |
