diff options
Diffstat (limited to 'src')
8 files changed, 482 insertions, 8 deletions
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index f5686b2..072926c 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -39,9 +39,7 @@ import cz.crcs.ectester.standalone.libs.*; import cz.crcs.ectester.standalone.output.TextTestWriter; import cz.crcs.ectester.standalone.output.XMLTestWriter; import cz.crcs.ectester.standalone.output.YAMLTestWriter; -import cz.crcs.ectester.standalone.test.suites.StandaloneDefaultSuite; -import cz.crcs.ectester.standalone.test.suites.StandaloneTestSuite; -import cz.crcs.ectester.standalone.test.suites.StandaloneTestVectorSuite; +import cz.crcs.ectester.standalone.test.suites.*; import org.apache.commons.cli.*; import javax.crypto.KeyAgreement; @@ -314,7 +312,11 @@ public class ECTesterStandalone { private void listSuites() { StandaloneTestSuite[] suites = new StandaloneTestSuite[]{ new StandaloneDefaultSuite(null, null, null), - new StandaloneTestVectorSuite(null, null, null)}; + new StandaloneTestVectorSuite(null, null, null), + new StandaloneInvalidSuite(null, null, null), + new StandaloneDegenerateSuite(null, null, null), + new StandaloneCofactorSuite(null, null, null), + new StandaloneTwistSuite(null, null, null)}; for (StandaloneTestSuite suite : suites) { System.out.println(" - " + suite.getName()); for (String line : suite.getDescription()) { @@ -748,6 +750,18 @@ public class ECTesterStandalone { case "test-vectors": suite = new StandaloneTestVectorSuite(writer, cfg, cli); break; + case "degenerate": + suite = new StandaloneDegenerateSuite(writer, cfg, cli); + break; + case "cofactor": + suite = new StandaloneCofactorSuite(writer, cfg, cli); + break; + case "invalid": + suite = new StandaloneInvalidSuite(writer, cfg, cli); + break; + case "twist": + suite = new StandaloneTwistSuite(writer, cfg, cli); + break; case "default": default: suite = new StandaloneDefaultSuite(writer, cfg, cli); diff --git a/src/cz/crcs/ectester/standalone/consts/Ident.java b/src/cz/crcs/ectester/standalone/consts/Ident.java index 1c7a962..fcc811d 100644 --- a/src/cz/crcs/ectester/standalone/consts/Ident.java +++ b/src/cz/crcs/ectester/standalone/consts/Ident.java @@ -2,10 +2,7 @@ package cz.crcs.ectester.standalone.consts; import java.security.NoSuchAlgorithmException; import java.security.Provider; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.function.BiFunction; public abstract class Ident { @@ -31,6 +28,15 @@ public abstract class Ident { return name.equals(other) || idents.contains(other); } + public boolean containsAny(List<String> others) { + for(String other : others) { + if(name.equals(other) || idents.contains(other)) { + return true; + } + } + return false; + } + <T> T getInstance(BiFunction<String, Provider, T> getter, Provider provider) throws NoSuchAlgorithmException { T instance = null; try { diff --git a/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java index bfd39fc..fd48212 100644 --- a/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java +++ b/src/cz/crcs/ectester/standalone/test/base/KeyAgreementTest.java @@ -37,6 +37,16 @@ public class KeyAgreementTest extends SimpleTest<KeyAgreementTestable> { }); } + public static KeyAgreementTest expectError(KeyAgreementTestable ka, Result.ExpectedValue expected) { + return new KeyAgreementTest(ka, new TestCallback<KeyAgreementTestable>() { + @Override + public Result apply(KeyAgreementTestable keyAgreementTestable) { + Result.Value value = Result.Value.fromExpected(expected, keyAgreementTestable.ok(), false); + return new Result(value, value.description()); + } + }); + } + public static KeyAgreementTest function(KeyAgreementTestable ka, TestCallback<KeyAgreementTestable> callback) { return new KeyAgreementTest(ka, callback); } diff --git a/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java index b232456..32f82cb 100644 --- a/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java +++ b/src/cz/crcs/ectester/standalone/test/base/KeyGeneratorTest.java @@ -22,6 +22,16 @@ public class KeyGeneratorTest extends SimpleTest<KeyGeneratorTestable> { }); } + public static KeyGeneratorTest expectError(KeyGeneratorTestable kg, Result.ExpectedValue expected) { + return new KeyGeneratorTest(kg, new TestCallback<KeyGeneratorTestable>() { + @Override + public Result apply(KeyGeneratorTestable keyGenerationTestable) { + Result.Value value = Result.Value.fromExpected(expected, keyGenerationTestable.ok(), false); + return new Result(value, value.description()); + } + }); + } + public static KeyGeneratorTest function(KeyGeneratorTestable ka, TestCallback<KeyGeneratorTestable> callback) { return new KeyGeneratorTest(ka, callback); } diff --git a/src/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java new file mode 100644 index 0000000..92a89fe --- /dev/null +++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneCofactorSuite.java @@ -0,0 +1,109 @@ +package cz.crcs.ectester.standalone.test.suites; + +import cz.crcs.ectester.common.cli.TreeCommandLine; +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; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.ECTesterStandalone; +import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; +import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTest; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTest; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable; + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.util.*; + +public class StandaloneCofactorSuite extends StandaloneTestSuite { + public StandaloneCofactorSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) { + super(writer, cfg, cli, "cofactor", "The cofactor test suite tests whether the library correctly rejects points on the curve", + "but not in the subgroup generated by the generator (so of small order, dividing the cofactor) during ECDH.", + "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type (select multiple types by separating them with commas)"); + } + + @Override + protected void runTests() throws Exception { + String kpgAlgo = cli.getOptionValue("test.kpg-type"); + String kaAlgo = cli.getOptionValue("test.ka-type"); + List<String> kaTypes = kaAlgo != null ? Arrays.asList(kaAlgo.split(",")) : new ArrayList<>(); + + KeyPairGeneratorIdent kpgIdent; + if (kpgAlgo == null) { + // try EC, if not, fail with: need to specify kpg algo. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong kpg algo/not found. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains(kpgAlgo)) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found."); + return; + } + } + + Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "cofactor"); + 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(); + + KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); + ECParameterSpec spec = curve.toSpec(); + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if(kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + + List<Test> allKaTests = new LinkedList<>(); + for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { + if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { + KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); + + List<Test> specificKaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + ECPublicKey ecpub = ECUtil.toPublicKey(pub); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); + Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); + specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", keyAgreement)); + } + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with public points on non-generator subgroup.", specificKaTests.toArray(new Test[0]))); + } + } + if(allKaTests.isEmpty()) { + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); + } + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", generateSuccess, tests)); + } + } +} diff --git a/src/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java new file mode 100644 index 0000000..5024bb7 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneDegenerateSuite.java @@ -0,0 +1,109 @@ +package cz.crcs.ectester.standalone.test.suites; + +import cz.crcs.ectester.common.cli.TreeCommandLine; +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; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.ECTesterStandalone; +import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; +import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTest; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTest; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable; + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.util.*; + +public class StandaloneDegenerateSuite extends StandaloneTestSuite { + public StandaloneDegenerateSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) { + super(writer, cfg, cli, "degenerate", "The degenerate suite tests whether the library 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 degenerate into exponentiation in the base finite field.", + "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type (select multiple types by separating them with commas)"); + } + + @Override + protected void runTests() throws Exception { + String kpgAlgo = cli.getOptionValue("test.kpg-type"); + String kaAlgo = cli.getOptionValue("test.ka-type"); + List<String> kaTypes = kaAlgo != null ? Arrays.asList(kaAlgo.split(",")) : new ArrayList<>(); + + KeyPairGeneratorIdent kpgIdent; + if (kpgAlgo == null) { + // try EC, if not, fail with: need to specify kpg algo. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong kpg algo/not found. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains(kpgAlgo)) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found."); + return; + } + } + + Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate"); + 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(); + + KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); + ECParameterSpec spec = curve.toSpec(); + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if(kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + + List<Test> allKaTests = new LinkedList<>(); + for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { + if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { + KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); + + List<Test> specificKaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + ECPublicKey ecpub = ECUtil.toPublicKey(pub); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); + Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); + specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " degenerate key test.", keyAgreement)); + } + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with degenerate public points..", specificKaTests.toArray(new Test[0]))); + } + } + if(allKaTests.isEmpty()) { + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); + } + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", generateSuccess, tests)); + } + } +} diff --git a/src/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java new file mode 100644 index 0000000..47e939e --- /dev/null +++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneInvalidSuite.java @@ -0,0 +1,108 @@ +package cz.crcs.ectester.standalone.test.suites; + +import cz.crcs.ectester.common.cli.TreeCommandLine; +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; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.ECTesterStandalone; +import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; +import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTest; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTest; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable; + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.util.*; + +public class StandaloneInvalidSuite extends StandaloneTestSuite { + public StandaloneInvalidSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) { + super(writer, cfg, cli, "invalid", "The invalid curve suite tests whether the library rejects points outside of the curve during ECDH.", + "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type (select multiple types by separating them with commas)"); + } + + @Override + protected void runTests() throws Exception { + String kpgAlgo = cli.getOptionValue("test.kpg-type"); + String kaAlgo = cli.getOptionValue("test.ka-type"); + List<String> kaTypes = kaAlgo != null ? Arrays.asList(kaAlgo.split(",")) : new ArrayList<>(); + + KeyPairGeneratorIdent kpgIdent; + if (kpgAlgo == null) { + // try EC, if not, fail with: need to specify kpg algo. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong kpg algo/not found. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains(kpgAlgo)) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found."); + return; + } + } + + Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid"); + 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(); + + KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); + ECParameterSpec spec = curve.toSpec(); + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if(kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + + List<Test> allKaTests = new LinkedList<>(); + for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { + if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { + KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); + + List<Test> specificKaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + ECPublicKey ecpub = ECUtil.toPublicKey(pub); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); + Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); + specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", keyAgreement)); + } + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with invalid public points.", specificKaTests.toArray(new Test[0]))); + } + } + if(allKaTests.isEmpty()) { + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); + } + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", generateSuccess, tests)); + } + } +} diff --git a/src/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java new file mode 100644 index 0000000..0e410a0 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/test/suites/StandaloneTwistSuite.java @@ -0,0 +1,108 @@ +package cz.crcs.ectester.standalone.test.suites; + +import cz.crcs.ectester.common.cli.TreeCommandLine; +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; +import cz.crcs.ectester.common.test.Test; +import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.data.EC_Store; +import cz.crcs.ectester.standalone.ECTesterStandalone; +import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; +import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTest; +import cz.crcs.ectester.standalone.test.base.KeyAgreementTestable; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTest; +import cz.crcs.ectester.standalone.test.base.KeyGeneratorTestable; + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.util.*; + +public class StandaloneTwistSuite extends StandaloneTestSuite { + public StandaloneTwistSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli) { + super(writer, cfg, cli, "twist", "The twist test suite tests whether the library correctly rejects points on the quadratic twist of the curve during ECDH.", + "Supports options:", "\t - gt/kpg-type", "\t - kt/ka-type (select multiple types by separating them with commas)"); + } + + @Override + protected void runTests() throws Exception { + String kpgAlgo = cli.getOptionValue("test.kpg-type"); + String kaAlgo = cli.getOptionValue("test.ka-type"); + List<String> kaTypes = kaAlgo != null ? Arrays.asList(kaAlgo.split(",")) : new ArrayList<>(); + + KeyPairGeneratorIdent kpgIdent; + if (kpgAlgo == null) { + // try EC, if not, fail with: need to specify kpg algo. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The default KeyPairGenerator algorithm type of \"EC\" was not found. Need to specify a type."); + return; + } + } else { + // try the specified, if not, fail with: wrong kpg algo/not found. + Optional<KeyPairGeneratorIdent> kpgIdentOpt = cfg.selected.getKPGs().stream() + .filter((ident) -> ident.contains(kpgAlgo)) + .findFirst(); + if (kpgIdentOpt.isPresent()) { + kpgIdent = kpgIdentOpt.get(); + } else { + System.err.println("The KeyPairGenerator algorithm type of \"" + kpgAlgo + "\" was not found."); + return; + } + } + + Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist"); + 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(); + + KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); + ECParameterSpec spec = curve.toSpec(); + KeyGeneratorTestable kgt = new KeyGeneratorTestable(kpg, spec); + + Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); + runTest(generate); + KeyPair kp = kgt.getKeyPair(); + if(kp == null) { + Test generateFail = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generating KeyPair has failed on " + curve.getId() + ". " + "KeyAgreement tests will be skipped.", generate); + doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", generateFail)); + continue; + } + Test generateSuccess = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Generate keypair.", generate); + ECPrivateKey ecpriv = (ECPrivateKey) kp.getPrivate(); + + List<Test> allKaTests = new LinkedList<>(); + for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { + if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { + KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); + + List<Test> specificKaTests = new LinkedList<>(); + for (EC_Key.Public pub : keys) { + ECPublicKey ecpub = ECUtil.toPublicKey(pub); + KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpriv, ecpub); + Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); + specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " twist key test.", keyAgreement)); + } + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform " + kaIdent.getName() + " with public points on twist.", specificKaTests.toArray(new Test[0]))); + } + } + if(allKaTests.isEmpty()) { + allKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "None of the specified key agreement types is supported by the library.")); + } + Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", allKaTests.toArray(new Test[0])); + doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", generateSuccess, tests)); + } + } +} |
