diff options
| author | J08nY | 2018-05-02 20:08:49 +0200 |
|---|---|---|
| committer | J08nY | 2018-05-02 20:08:49 +0200 |
| commit | 87c4accbecc2f37a42c96e2bbc3c90618bfa2fdc (patch) | |
| tree | f24d78af5e7a14e1a322a2b3978b0204bb0e5ec3 /src/cz/crcs/ectester/reader | |
| parent | 92c28a15e018e55b8f195993414f769ecf96a663 (diff) | |
| download | ECTester-87c4accbecc2f37a42c96e2bbc3c90618bfa2fdc.tar.gz ECTester-87c4accbecc2f37a42c96e2bbc3c90618bfa2fdc.tar.zst ECTester-87c4accbecc2f37a42c96e2bbc3c90618bfa2fdc.zip | |
Add compression test suite.
Diffstat (limited to 'src/cz/crcs/ectester/reader')
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTesterReader.java | 7 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/test/CardCofactorSuite.java (renamed from src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java) | 4 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/test/CardCompressionSuite.java | 119 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/test/CardDefaultSuite.java | 18 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/test/PerformanceTest.java | 23 |
5 files changed, 159 insertions, 12 deletions
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java index 0a3031b..6098cd4 100644 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ b/src/cz/crcs/ectester/reader/ECTesterReader.java @@ -406,6 +406,9 @@ public class ECTesterReader { case "test-vectors": suite = new CardTestVectorSuite(writer, cfg, cardManager); break; + case "compression": + suite = new CardCompressionSuite(writer, cfg, cardManager); + break; default: // These run are dangerous, prompt before them. System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous."); @@ -436,7 +439,7 @@ public class ECTesterReader { suite = new CardTwistTestSuite(writer, cfg, cardManager); break; case "cofactor": - suite = new CardCofactorTestSuite(writer, cfg, cardManager); + suite = new CardCofactorSuite(writer, cfg, cardManager); break; default: System.err.println("Unknown test suite."); @@ -767,7 +770,7 @@ public class ECTesterReader { } testSuite = cli.getOptionValue("test", "default").toLowerCase(); - String[] tests = new String[]{"default", "composite", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor"}; + String[] tests = new String[]{"default", "composite", "compression", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor"}; if (!Arrays.asList(tests).contains(testSuite)) { System.err.println("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests)); return false; diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java index 8cf59e2..aca3371 100644 --- a/src/cz/crcs/ectester/reader/test/CardCofactorTestSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java @@ -22,8 +22,8 @@ import static cz.crcs.ectester.common.test.Result.ExpectedValue; /** * @author Jan Jancar johny@neuromancer.sk */ -public class CardCofactorTestSuite extends CardTestSuite { - public CardCofactorTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { +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."); } diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java new file mode 100644 index 0000000..7300653 --- /dev/null +++ b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java @@ -0,0 +1,119 @@ +package cz.crcs.ectester.reader.test; + +import cz.crcs.ectester.applet.ECTesterApplet; +import cz.crcs.ectester.applet.EC_Consts; +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.ByteUtil; +import cz.crcs.ectester.common.util.CardUtil; +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; +import cz.crcs.ectester.reader.response.Response; +import javacard.security.KeyPair; + +import java.security.spec.ECPoint; +import java.util.LinkedList; +import java.util.List; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class CardCompressionSuite extends CardTestSuite { + public CardCompressionSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { + super(writer, cfg, cardManager, "compression", ""); + } + + @Override + protected void runTests() throws Exception { + //iterate over default curve sizes + // for Fp + // - allocate, set custom curve, generate keypairs, -> export generated. + // - test ecdh with local and remote simply(no compression) + // - test local privkey, remote pubkey (compressed) + // - test local privkey, remote pubkey (hybrid) + // - test local privkey, remote pubkey (hybrid with wrong y) + // - test local privkey, remote pubkey (point at infinity) + if (cfg.primeField) { + runCompression(KeyPair.ALG_EC_FP); + } + // for F2m + // - allocate, set custom curve, generate keypairs, -> export generated. + // - test ecdh with local and remote simply(no compression) + // - test local privkey, remote pubkey (compressed) + // - test local privkey, remote pubkey (hybrid) + // - test local privkey, remote pubkey (hybrid with wrong y) + // - test local privkey, remote pubkey (point at infinity) + if (cfg.binaryField) { + runCompression(KeyPair.ALG_EC_F2M); + } + } + + private void runCompression(byte field) throws Exception { + short[] keySizes = field == KeyPair.ALG_EC_FP ? EC_Consts.FP_SIZES : EC_Consts.F2M_SIZES; + short domain = field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; + + for (short keyLength : keySizes) { + String spec = keyLength + "b " + CardUtil.getKeyTypeString(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)); + 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 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); + ECPoint pub; + try { + pub = ECUtil.fromX962(pubkey, null); + } 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; + } + + List<Test> kaTests = new LinkedList<>(); + for (byte kaType : EC_Consts.KA_TYPES) { + List<Test> thisTests = new LinkedList<>(); + Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), Result.ExpectedValue.SUCCESS)); + if (allocate.ok()) { + Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), Result.ExpectedValue.SUCCESS)); + + thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement setup and basic test.", allocate, ka)); + if (ka.ok()) { + // tests of the good stuff + Test kaCompressed = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS, kaType), Result.ExpectedValue.SUCCESS); + Test kaHybrid = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS_HYBRID, kaType), Result.ExpectedValue.SUCCESS); + thisTests.add(CompoundTest.any(Result.ExpectedValue.SUCCESS, "Tests of compressed and hybrid form.", kaCompressed, kaHybrid)); + + // tests the bad stuff here + byte[] pubHybrid = ECUtil.toX962Hybrid(pub, keyLength); + pubHybrid[pubHybrid.length - 1] ^= 1; + byte[] pubHybridEncoded = ByteUtil.prependLength(pubHybrid); + Test kaBadHybrid = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubHybridEncoded), Result.ExpectedValue.FAILURE); + + byte[] pubInfinityEncoded = {0x01, 0x00}; + Test kaBadInfinity = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubInfinityEncoded), Result.ExpectedValue.FAILURE); + thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of corrupted hybrid form and infinity.", kaBadHybrid, kaBadInfinity)); + } + kaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement tests of " + CardUtil.getKATypeString(kaType) + ".", thisTests.toArray(new Test[0]))); + } + } + compressionTests.addAll(kaTests); + + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Compression test of " + spec + ".", compressionTests.toArray(new Test[0]))); + new Command.Cleanup(this.card).send(); + } + } +} diff --git a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java index 611f5ec..4480962 100644 --- a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java +++ b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java @@ -14,9 +14,11 @@ import javacard.security.KeyPair; import java.util.LinkedList; import java.util.List; +import java.util.Random; import java.util.function.Function; import static cz.crcs.ectester.common.test.Result.ExpectedValue; +import static cz.crcs.ectester.common.test.Result.Value; /** * @author Jan Jancar johny@neuromancer.sk @@ -70,9 +72,9 @@ public class CardDefaultSuite extends CardTestSuite { String kaDesc = "Test of the " + CardUtil.getKATypeString(kaType) + " KeyAgreement."; Function<Test[], Result> kaCallback = (tests) -> { if (tests[1].ok() || tests[2].ok()) { - return new Result(Result.Value.SUCCESS, "Some ECDH is supported."); + return new Result(Value.SUCCESS, "Some ECDH is supported."); } else { - return new Result(Result.Value.FAILURE, "ECDH failed."); + return new Result(Value.FAILURE, "ECDH failed."); } }; @@ -102,10 +104,18 @@ public class CardDefaultSuite extends CardTestSuite { String signDesc = "Test of the " + CardUtil.getSigTypeString(sigType) + " signature."; + Random rand = new Random(); + byte[] sigData = new byte[64]; + rand.nextBytes(sigData); + Test compound; if (expect.ok()) { - Test perfTest = runTest(PerformanceTest.repeat(ecdsa, 10)); - compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect, perfTest)); + Command ecdsaSign = new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_TRUE, sigData); + PerformanceTest signTest = runTest(PerformanceTest.repeat("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)); + 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/PerformanceTest.java b/src/cz/crcs/ectester/reader/test/PerformanceTest.java index 2e5f376..9abaadc 100644 --- a/src/cz/crcs/ectester/reader/test/PerformanceTest.java +++ b/src/cz/crcs/ectester/reader/test/PerformanceTest.java @@ -5,6 +5,7 @@ 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.command.Command; +import cz.crcs.ectester.reader.response.Response; import java.util.Arrays; @@ -13,12 +14,14 @@ import java.util.Arrays; */ public class PerformanceTest extends SimpleTest<CommandTestable> { private long[] times; + private Response[] responses; private long mean; private long median; private long mode; private int count; + private String desc; - private PerformanceTest(CommandTestable testable, int count) { + private PerformanceTest(CommandTestable testable, int count, String desc) { super(testable, new TestCallback<CommandTestable>() { @Override public Result apply(CommandTestable testable) { @@ -26,23 +29,31 @@ public class PerformanceTest extends SimpleTest<CommandTestable> { } }); this.count = count; + this.desc = desc; } public static PerformanceTest repeat(Command cmd, int count) { - return new PerformanceTest(new CommandTestable(cmd), count); + return new PerformanceTest(new CommandTestable(cmd), count, null); + } + + public static PerformanceTest repeat(String desc, Command cmd, int count) { + return new PerformanceTest(new CommandTestable(cmd), count, desc); } @Override public String getDescription() { - return String.format("Mean = %d ns, Median = %d ns, Mode = %d ns", mean, median, mode); + String rest = String.format("Mean = %d ns, Median = %d ns, Mode = %d ns", mean, median, mode); + return (desc == null ? rest : desc + " (" + rest + ")"); } @Override protected void runSelf() { times = new long[count]; + responses = new Response[count]; for (int i = 0; i < count; ++i) { testable.run(); - times[i] = testable.getResponse().getDuration(); + responses[i] = testable.getResponse(); + times[i] = responses[i].getDuration(); testable.reset(); } @@ -81,6 +92,10 @@ public class PerformanceTest extends SimpleTest<CommandTestable> { return testable.getCommand(); } + public Response[] getResponses() { + return responses; + } + public long[] getTimes() { return times; } |
