diff options
4 files changed, 141 insertions, 58 deletions
diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index 5edeb04..c79af1b 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -59,11 +59,16 @@ testlogger { } tasks.withType<JavaCompile> { - if (JavaVersion.current() > JavaVersion.VERSION_1_8) { + if (JavaVersion.current() > JavaVersion.VERSION_1_8 && JavaVersion.current() < JavaVersion.VERSION_22) { options.compilerArgs.addAll(arrayOf( "--add-modules", "jdk.crypto.ec", "--add-exports", "jdk.crypto.ec/sun.security.ec=ALL-UNNAMED" )) + } else if (JavaVersion.current() >= JavaVersion.VERSION_22) { + options.compilerArgs.addAll(arrayOf( + "--add-modules", "java.base", + "--add-exports", "java.base/sun.security.ec=ALL-UNNAMED" + )) } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java index 72ac87e..77eaf85 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -201,6 +201,7 @@ public class ECTesterStandalone { testOpts.addOption(bits); testOpts.addOption(namedCurve); testOpts.addOption(curveName); + testOpts.addOption(output); testOpts.addOption(Option.builder("gt").longOpt("kpg-type").desc("Set the KeyPairGenerator object [type].").hasArg().argName("type").optionalArg(false).build()); testOpts.addOption(Option.builder("kt").longOpt("ka-type").desc("Set the KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build()); testOpts.addOption(Option.builder("st").longOpt("sig-type").desc("Set the Signature object [type].").hasArg().argName("type").optionalArg(false).build()); @@ -755,19 +756,26 @@ public class ECTesterStandalone { /** * */ - private void test() throws TestException, ParserConfigurationException { + private void test() throws TestException, ParserConfigurationException, FileNotFoundException { + PrintStream out; + if (cli.hasOption("test.output")) { + out = new PrintStream(FileUtil.openStream(cli.getOptionValues("test.output"))); + } else { + out = System.out; + } + TestWriter writer; switch (cli.getOptionValue("test.format", "text").toLowerCase()) { case "yaml": case "yml": - writer = new YAMLTestWriter(System.out); + writer = new YAMLTestWriter(out); break; case "xml": - writer = new XMLTestWriter(System.out); + writer = new XMLTestWriter(out); break; case "text": default: - writer = new TextTestWriter(System.out); + writer = new TextTestWriter(out); break; } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp index 9bb99a3..bffa6a3 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp @@ -672,28 +672,39 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig std::unique_ptr<DL_GroupParameters_EC<ECP>> ecp_group = fp_group_from_params(env, params); if (ecp_group == nullptr) { std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params); - if (type_str.find("SHA1") != std::string::npos) { - result = sign_message<EC2N, SHA1>(env, *ec2n_group, data, private_key_x); - } else if (type_str.find("SHA224") != std::string::npos) { - result = sign_message<EC2N, SHA224>(env, *ec2n_group, data, private_key_x); - } else if (type_str.find("SHA256") != std::string::npos) { - result = sign_message<EC2N, SHA256>(env, *ec2n_group, data, private_key_x); - } else if (type_str.find("SHA384") != std::string::npos) { - result = sign_message<EC2N, SHA384>(env, *ec2n_group, data, private_key_x); - } else if (type_str.find("SHA512") != std::string::npos) { - result = sign_message<EC2N, SHA512>(env, *ec2n_group, data, private_key_x); + + try { + if (type_str.find("SHA1") != std::string::npos) { + result = sign_message<EC2N, SHA1>(env, *ec2n_group, data, private_key_x); + } else if (type_str.find("SHA224") != std::string::npos) { + result = sign_message<EC2N, SHA224>(env, *ec2n_group, data, private_key_x); + } else if (type_str.find("SHA256") != std::string::npos) { + result = sign_message<EC2N, SHA256>(env, *ec2n_group, data, private_key_x); + } else if (type_str.find("SHA384") != std::string::npos) { + result = sign_message<EC2N, SHA384>(env, *ec2n_group, data, private_key_x); + } else if (type_str.find("SHA512") != std::string::npos) { + result = sign_message<EC2N, SHA512>(env, *ec2n_group, data, private_key_x); + } + } catch (Exception & ex) { + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return nullptr; } } else { - if (type_str.find("SHA1") != std::string::npos) { - result = sign_message<ECP, SHA1>(env, *ecp_group, data, private_key_x); - } else if (type_str.find("SHA224") != std::string::npos) { - result = sign_message<ECP, SHA224>(env, *ecp_group, data, private_key_x); - } else if (type_str.find("SHA256") != std::string::npos) { - result = sign_message<ECP, SHA256>(env, *ecp_group, data, private_key_x); - } else if (type_str.find("SHA384") != std::string::npos) { - result = sign_message<ECP, SHA384>(env, *ecp_group, data, private_key_x); - } else if (type_str.find("SHA512") != std::string::npos) { - result = sign_message<ECP, SHA512>(env, *ecp_group, data, private_key_x); + try { + if (type_str.find("SHA1") != std::string::npos) { + result = sign_message<ECP, SHA1>(env, *ecp_group, data, private_key_x); + } else if (type_str.find("SHA224") != std::string::npos) { + result = sign_message<ECP, SHA224>(env, *ecp_group, data, private_key_x); + } else if (type_str.find("SHA256") != std::string::npos) { + result = sign_message<ECP, SHA256>(env, *ecp_group, data, private_key_x); + } else if (type_str.find("SHA384") != std::string::npos) { + result = sign_message<ECP, SHA384>(env, *ecp_group, data, private_key_x); + } else if (type_str.find("SHA512") != std::string::npos) { + result = sign_message<ECP, SHA512>(env, *ecp_group, data, private_key_x); + } + } catch (Exception & ex) { + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return nullptr; } } @@ -744,28 +755,38 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna if (ecp_group == nullptr) { std::unique_ptr<DL_GroupParameters_EC<EC2N>> ec2n_group = f2m_group_from_params(env, params); - if (type_str.find("SHA1") != std::string::npos) { - return verify_message<EC2N, SHA1>(env, *ec2n_group, data, signature, pubkey); - } else if (type_str.find("SHA224") != std::string::npos) { - return verify_message<EC2N, SHA224>(env, *ec2n_group, data, signature, pubkey); - } else if (type_str.find("SHA256") != std::string::npos) { - return verify_message<EC2N, SHA256>(env, *ec2n_group, data, signature, pubkey); - } else if (type_str.find("SHA384") != std::string::npos) { - return verify_message<EC2N, SHA384>(env, *ec2n_group, data, signature, pubkey); - } else if (type_str.find("SHA512") != std::string::npos) { - return verify_message<EC2N, SHA512>(env, *ec2n_group, data, signature, pubkey); + try { + if (type_str.find("SHA1") != std::string::npos) { + return verify_message<EC2N, SHA1>(env, *ec2n_group, data, signature, pubkey); + } else if (type_str.find("SHA224") != std::string::npos) { + return verify_message<EC2N, SHA224>(env, *ec2n_group, data, signature, pubkey); + } else if (type_str.find("SHA256") != std::string::npos) { + return verify_message<EC2N, SHA256>(env, *ec2n_group, data, signature, pubkey); + } else if (type_str.find("SHA384") != std::string::npos) { + return verify_message<EC2N, SHA384>(env, *ec2n_group, data, signature, pubkey); + } else if (type_str.find("SHA512") != std::string::npos) { + return verify_message<EC2N, SHA512>(env, *ec2n_group, data, signature, pubkey); + } + } catch (Exception & ex) { + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return JNI_FALSE; } } else { - if (type_str.find("SHA1") != std::string::npos) { - return verify_message<ECP, SHA1>(env, *ecp_group, data, signature, pubkey); - } else if (type_str.find("SHA224") != std::string::npos) { - return verify_message<ECP, SHA224>(env, *ecp_group, data, signature, pubkey); - } else if (type_str.find("SHA256") != std::string::npos) { - return verify_message<ECP, SHA256>(env, *ecp_group, data, signature, pubkey); - } else if (type_str.find("SHA384") != std::string::npos) { - return verify_message<ECP, SHA384>(env, *ecp_group, data, signature, pubkey); - } else if (type_str.find("SHA512") != std::string::npos) { - return verify_message<ECP, SHA512>(env, *ecp_group, data, signature, pubkey); + try { + if (type_str.find("SHA1") != std::string::npos) { + return verify_message<ECP, SHA1>(env, *ecp_group, data, signature, pubkey); + } else if (type_str.find("SHA224") != std::string::npos) { + return verify_message<ECP, SHA224>(env, *ecp_group, data, signature, pubkey); + } else if (type_str.find("SHA256") != std::string::npos) { + return verify_message<ECP, SHA256>(env, *ecp_group, data, signature, pubkey); + } else if (type_str.find("SHA384") != std::string::npos) { + return verify_message<ECP, SHA384>(env, *ecp_group, data, signature, pubkey); + } else if (type_str.find("SHA512") != std::string::npos) { + return verify_message<ECP, SHA512>(env, *ecp_group, data, signature, pubkey); + } + } catch (Exception & ex) { + throw_new(env, "java/security/GeneralSecurityException", ex.what()); + return JNI_FALSE; } } // unreachable diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java index c869233..e3ae573 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -1,12 +1,14 @@ package cz.crcs.ectester.standalone; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.params.provider.MethodSource; import org.junitpioneer.jupiter.StdIo; import org.junitpioneer.jupiter.StdOut; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assumptions.assumeFalse; @@ -53,9 +55,13 @@ public class AppTests { assertTrue(s.contains("NONEwithECDSA")); } + static Stream<String> libs() { + return Stream.of("BoringSSL", "Botan", "BouncyCastle", "Crypto++", "IPPCP", "LibreSSL", "libgcrypt", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt", "wolfCrypt"); + } + @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void defaultSuite(String libName, StdOut out) { // TODO: "Nettle" is very broken here for a weird reason. @@ -74,7 +80,7 @@ public class AppTests { @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void testVectorSuite(String libName, StdOut out) { String[] args = new String[]{"test", "test-vectors", libName}; @@ -89,14 +95,14 @@ public class AppTests { } @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") public void performanceSuite(String libName) { // TODO: "Nettle" is very broken here for a weird reason. assumeFalse(libName.equals("Nettle")); - String[] args = new String[]{"test", "performance", "-o", "/dev/null", libName}; + String[] args = new String[]{"test", "performance", libName}; if (libName.equals("Botan") || libName.equals("Crypto++")) { - args = new String[]{"test", "--kpg-type", "ECDH", "performance", "-o", "/dev/null", libName}; + args = new String[]{"test", "--kpg-type", "ECDH", "performance", libName}; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); @@ -108,9 +114,51 @@ public class AppTests { } } + @ParameterizedTest + @MethodSource("libs") + public void signatureSuite(String libName) { + String[] args = new String[]{"test", "signature", libName}; + switch (libName) { + case "Nettle": + case "libgcrypt": + case "BoringSSL": + case "OpenSSL": + case "tomcrypt": + case "LibreSSL": + case "IPPCP": + case "mbedTLS": + args = new String[]{"test", "-st", "NONEwithECDSA", "signature", libName}; + break; + } + ECTesterStandalone.main(args); + } + + @ParameterizedTest + @MethodSource("libs") + public void miscSuite(String libName) { + String[] args = new String[]{"test", "miscellaneous", libName}; + if (libName.equals("Botan") || libName.equals("Crypto++")) { + args = new String[]{"test", "--kpg-type", "ECDH", "miscellaneous", libName}; + } + ECTesterStandalone.main(args); + } + + @ParameterizedTest + @MethodSource("libs") + public void invalidSuite(String libName) { + // TODO: "Nettle" is very broken here for a weird reason. + assumeFalse(libName.equals("Nettle")); + + String[] args = new String[]{"test", "invalid", libName}; + if (libName.equals("Botan") || libName.equals("Crypto++")) { + args = new String[]{"test", "--kpg-type", "ECDH", "invalid", libName}; + } + ECTesterStandalone.main(args); + } + @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void generate(String libName, StdOut out) { String[] args = new String[]{"generate", "-n", "10", "-nc", "secg/secp256r1", libName}; @@ -133,7 +181,7 @@ public class AppTests { @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void ecdh(String libName, StdOut out) { String[] args = new String[]{"ecdh", "-n", "10", "-nc", "secg/secp256r1", libName}; @@ -152,7 +200,7 @@ public class AppTests { @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void ecdsa(String libName, StdOut out) { String[] args = new String[]{"ecdsa", "-n", "10", "-nc", "secg/secp256r1", libName}; @@ -164,10 +212,11 @@ public class AppTests { case "BoringSSL": args = new String[]{"ecdsa", "-n", "10", "-cn", "prime256v1", "-t", "NONEwithECDSA", libName}; break; - case "OpenSSL 3": - case "libtomcrypt": + case "OpenSSL": + case "tomcrypt": case "LibreSSL": - case "2021": + case "IPPCP": + case "mbedTLS": args = new String[]{"ecdsa", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName}; break; case "wolfCrypt": @@ -179,7 +228,7 @@ public class AppTests { @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest - @ValueSource(strings = {"Bouncy", "Sun", "libtomcrypt", "Botan", "Crypto++", "OpenSSL 3", "BoringSSL", "libgcrypt", "mbed TLS", "2021" /* IPPCP */, "Nettle", "LibreSSL", "wolfCrypt"}) + @MethodSource("libs") @StdIo() public void export(String libName, StdOut out) { // TODO: wolfCrypt is weirdly broken here. |
