From 6e399ce3dec913be7728c2892301dd3eceb2cd83 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 13:31:39 +0200 Subject: Test deterministic keygen in standalone. --- .../java/cz/crcs/ectester/standalone/AppTests.java | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'standalone/src/test/java/cz') 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 d401e58..6072e68 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -10,9 +10,11 @@ import org.junitpioneer.jupiter.StdOut; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; +import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -85,6 +87,43 @@ public class AppTests { return args.toArray(new String[]{}); } + @SuppressWarnings("JUnitMalformedDeclaration") + @ParameterizedTest + @MethodSource("libs") + @StdIo() + public void deterministicGenerate(String libName, StdOut out) { + String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName}; + switch (libName) { + case "Botan": + case "Crypto++": + args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; + break; + case "Nettle": + case "libgcrypt": + case "wolfCrypt": + args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName}; + break; + case "BoringSSL": + args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "prime256v1", libName}; + break; + } + ECTesterStandalone.main(args); + String out1 = out.capturedString(); + ECTesterStandalone.main(args); + String out2 = out.capturedString().substring(out1.length()); + if (!out1.contains(";")) + return; + List lines1 = out1.lines().collect(Collectors.toList()); + List lines2 = out2.lines().collect(Collectors.toList()); + assertEquals(lines1.size(), lines2.size()); + for (int i = 0; i < lines1.size(); ++i) { + String[] parts1 = lines1.get(i).split(";"); + String[] parts2 = lines2.get(i).split(";"); + assertEquals(parts1[2], parts2[2]); + assertEquals(parts1[3], parts2[3]); + } + } + @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest @MethodSource("libs") -- cgit v1.2.3-70-g09d2 From 84858177fe6c2b9bdc6ea9785a92781ba1237e04 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 20:18:23 +0200 Subject: Add deterministic RNG to mbedTLS. --- .../crcs/ectester/standalone/libs/MbedTLSLib.java | 6 +++ .../cz/crcs/ectester/standalone/libs/jni/mbedtls.c | 46 ++++++++++++++++++++-- .../cz/crcs/ectester/standalone/libs/jni/native.h | 16 ++++++++ .../java/cz/crcs/ectester/standalone/AppTests.java | 3 ++ 4 files changed, 67 insertions(+), 4 deletions(-) (limited to 'standalone/src/test/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java index e44598c..efc8cad 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/MbedTLSLib.java @@ -17,4 +17,10 @@ public class MbedTLSLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public native boolean supportsDeterministicPRNG(); + + @Override + public native boolean setupDeterministicPRNG(byte[] seed); } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c index 5fc879b..8f5e0fb 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c @@ -16,7 +16,8 @@ static mbedtls_ctr_drbg_context ctr_drbg; -static mbedtls_entropy_context entropy; +static mbedtls_entropy_context urandom_entropy; +static mbedtls_entropy_context fixed_entropy; static jclass provider_class; @@ -62,6 +63,17 @@ static int dev_urandom(void *data, unsigned char *output, size_t len, size_t *ol return 0; } +static unsigned char seed_store[32] = {0}; + +static int fixed_random(void *data, unsigned char *output, size_t len, size_t *olen) { + for (size_t i = 0; i < len; ++i) { + output[i] = seed_store[i % 32]; + } + *olen = len; + return 0; +} + + static int ctr_drbg_wrapper(void *ctx, unsigned char *buf, size_t len) { native_timing_pause(); int result = mbedtls_ctr_drbg_random(ctx, buf, len); @@ -77,9 +89,9 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ADD_SIG(env, this, "NONEwithECDSA", "MbedTLSECDSAwithNONE"); mbedtls_ctr_drbg_init(&ctr_drbg); - mbedtls_entropy_init(&entropy); - mbedtls_entropy_add_source(&entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG); - mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); + mbedtls_entropy_init(&urandom_entropy); + mbedtls_entropy_add_source(&urandom_entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG); + mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &urandom_entropy, NULL, 0); init_classes(env, "MbedTLS"); } @@ -101,6 +113,32 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCu return result; } +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG(JNIEnv *env, jobject this) { + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG(JNIEnv *env, jobject this, jbyteArray seed) { + jsize seed_length = (*env)->GetArrayLength(env, seed); + if (seed_length > 32) { + fprintf(stderr, "Error setting seed, needs to be at most 32 bytes, is %i.\n", seed_length); + return JNI_FALSE; + } + jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); + memcpy(seed_store, seed_data, seed_length); + (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + + memset(&ctr_drbg, 0, sizeof(ctr_drbg)); + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_entropy_init(&fixed_entropy); + // This is NASTY! We are accessing something the library does not want us to. + fixed_entropy.private_source_count = 0; + mbedtls_entropy_add_source(&fixed_entropy, fixed_random, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG); + mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &fixed_entropy, NULL, 0); + + return JNI_TRUE; +} + JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_keysizeSupported(JNIEnv *env, jobject this, jint keysize) { for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h index 627f38f..287b450 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h @@ -1389,6 +1389,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_creat JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCurves (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib + * Method: supportsDeterministicPRNG + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsDeterministicPRNG + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif 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 6072e68..8693b7b 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -106,6 +106,9 @@ public class AppTests { case "BoringSSL": args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "prime256v1", libName}; break; + case "mbedTLS": + args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName}; + break; } ECTesterStandalone.main(args); String out1 = out.capturedString(); -- cgit v1.2.3-70-g09d2 From 50c576e0f28eac393985073d7d91dac1262bf5da Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 20:34:48 +0200 Subject: Add deterministic RNG to Crypto++. --- .../crcs/ectester/standalone/libs/CryptoppLib.java | 6 +++++ .../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 27 +++++++++++++++++++--- .../cz/crcs/ectester/standalone/libs/jni/native.h | 16 +++++++++++++ .../java/cz/crcs/ectester/standalone/AppTests.java | 4 +++- 4 files changed, 49 insertions(+), 4 deletions(-) (limited to 'standalone/src/test/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java index 66aa9ea..25f2de4 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/CryptoppLib.java @@ -17,4 +17,10 @@ public class CryptoppLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public native boolean supportsDeterministicPRNG(); + + @Override + public native boolean setupDeterministicPRNG(byte[] seed); } 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 c4c74a6..1f82f8a 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 @@ -22,8 +22,12 @@ using CryptoPP::Exception; using CryptoPP::byte; #include "cryptopp/osrng.h" +using CryptoPP::RandomNumberGenerator; using CryptoPP::AutoSeededRandomPool; +#include "cryptopp/mersenne.h" +using CryptoPP::MT19937; + #include "cryptopp/sha.h" using CryptoPP::SHA1; using CryptoPP::SHA224; @@ -89,7 +93,7 @@ using CryptoPP::Integer; */ static jclass provider_class; -static AutoSeededRandomPool rng; +static std::unique_ptr rng = std::make_unique(); JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider(JNIEnv *env, jobject self) { @@ -187,6 +191,23 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getC return result; } +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + jsize seed_length = env->GetArrayLength(seed); + if (seed_length > 4) { + fprintf(stderr, "Error setting seed, needs to be at most 4 bytes.\n"); + return JNI_FALSE; + } + jbyte *seed_data = env->GetByteArrayElements(seed, nullptr); + uint32_t seed_int = seed_data[0] | seed_data[1] << 8 | seed_data[2] << 16 | seed_data[3] << 24; + rng.reset(new MT19937(seed_int)); + env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT); + return JNI_TRUE; +} + JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported(JNIEnv *env, jobject self, jint keysize){ std::vector ecp_oids = get_curve_oids(); for (auto & ecp_oid : ecp_oids) { @@ -517,7 +538,7 @@ template jobject generate_from_group(JNIEnv *env, DL_GroupParameters_ SIG_TRY(TIMEOUT) { try { native_timing_start(); - ec_domain.GenerateKeyPair(rng, priv, pub); + ec_domain.GenerateKeyPair(*rng, priv, pub); native_timing_stop(); } catch (Exception & ex) { SIG_DEINIT(); @@ -661,7 +682,7 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC group, jbyteArray size_t len; SIG_TRY(TIMEOUT) { native_timing_start(); - len = signer.SignMessage(rng, (byte *)data_bytes, data_length, (byte *)signature.c_str()); + len = signer.SignMessage(*rng, (byte *)data_bytes, data_length, (byte *)signature.c_str()); native_timing_stop(); } SIG_CATCH_HANDLE(env); env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT); diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h index 287b450..91cada9 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h @@ -468,6 +468,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_crea JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: supportsDeterministicPRNG + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsDeterministicPRNG + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif 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 8693b7b..6e8ec76 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -95,9 +95,11 @@ public class AppTests { String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName}; switch (libName) { case "Botan": - case "Crypto++": args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; break; + case "Crypto++": + args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; + break; case "Nettle": case "libgcrypt": case "wolfCrypt": -- cgit v1.2.3-70-g09d2 From c447744282771b4922faf3fbd4080ed7b31adc02 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 20:59:22 +0200 Subject: Split off deterministic tests. --- .../ectester/standalone/ECTesterStandalone.java | 33 +++-- .../java/cz/crcs/ectester/standalone/AppTests.java | 45 ------- .../ectester/standalone/DeterministicTests.java | 137 +++++++++++++++++++++ 3 files changed, 162 insertions(+), 53 deletions(-) create mode 100644 standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java (limited to 'standalone/src/test/java/cz') 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 44fc1b4..dc61192 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -193,7 +193,14 @@ public class ECTesterStandalone { Option outputRaw = Option.builder("o").longOpt("output").desc("Output CSV into file .").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build(); Option quiet = Option.builder("q").longOpt("quiet").desc("Do not output to stdout.").build(); Option timeSource = Option.builder("ts").longOpt("time-source").desc("Use a given native timing source: {rdtsc, monotonic, monotonic-raw, cputime-process, cputime-thread}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).build(); - Option prngSeed = Option.builder("ps").longOpt("prng-seed").desc("Use a deterministic PRNG with the given seed (hexadecimal).").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build(); + Option prngSeed = Option.builder("ps").longOpt("prng-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) in the library.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build(); + Option file = Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build(); + Option message = Option.builder("d").longOpt("data").desc("Sign the given [message].").hasArgs().argName("message").optionalArg(false).numberOfArgs(1).build(); + Option messageSeed = Option.builder("ds").longOpt("data-seed").desc("Use a deterministic PRNG with the given [seed] (hexadecimal) to generate the messages.").hasArgs().argName("seed").optionalArg(false).numberOfArgs(1).build(); + OptionGroup ecdsaMessage = new OptionGroup(); + ecdsaMessage.addOption(file); + ecdsaMessage.addOption(message); + ecdsaMessage.addOption(messageSeed); Options testOpts = new Options(); testOpts.addOption(bits); @@ -241,7 +248,7 @@ public class ECTesterStandalone { ecdsaOpts.addOption(Option.builder().longOpt("fixed").desc("Perform all ECDSA with fixed keypair.").build()); ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build()); ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build()); - ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build()); + ecdsaOpts.addOptionGroup(ecdsaMessage); ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts, "Perform EC based Signature."); actions.put("ecdsa", ecdsa); @@ -558,8 +565,9 @@ public class ECTesterStandalone { random = new SecureRandom(); } - byte[] data; - String dataString; + byte[] data = null; + String dataString = null; + SecureRandom dataRandom = null; if (cli.hasOption("ecdsa.file")) { String fileName = cli.getOptionValue("ecdsa.file"); File in = new File(fileName); @@ -569,11 +577,15 @@ public class ECTesterStandalone { } data = Files.readAllBytes(in.toPath()); dataString = ""; + } else if (cli.hasOption("ecdsa.data")) { + dataString = cli.getOptionValue("ecdsa.data"); + data = ByteUtil.hexToBytes(dataString); + } else if (cli.hasOption("ecdsa.data-seed")) { + String seedString = cli.getOptionValue("ecdsa.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + dataRandom = Util.getRandom(seed); } else { - Random dataRandom = new Random(); - data = new byte[32]; - dataRandom.nextBytes(data); - dataString = ByteUtil.bytesToHex(data, false); + dataRandom = new SecureRandom(); } String algo = cli.getOptionValue("ecdsa.type", "ECDSA"); @@ -679,6 +691,11 @@ public class ECTesterStandalone { } } + if (dataRandom != null) { + data = dataRandom.generateSeed(16); + dataString = ByteUtil.bytesToHex(data, false); + } + sig.initSign(privkey, random); sig.update(data); 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 6e8ec76..1ff9556 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/AppTests.java @@ -1,6 +1,5 @@ package cz.crcs.ectester.standalone; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -10,11 +9,9 @@ import org.junitpioneer.jupiter.StdOut; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; -import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -87,48 +84,6 @@ public class AppTests { return args.toArray(new String[]{}); } - @SuppressWarnings("JUnitMalformedDeclaration") - @ParameterizedTest - @MethodSource("libs") - @StdIo() - public void deterministicGenerate(String libName, StdOut out) { - String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName}; - switch (libName) { - case "Botan": - args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; - break; - case "Crypto++": - args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; - break; - case "Nettle": - case "libgcrypt": - case "wolfCrypt": - args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName}; - break; - case "BoringSSL": - args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "prime256v1", libName}; - break; - case "mbedTLS": - args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName}; - break; - } - ECTesterStandalone.main(args); - String out1 = out.capturedString(); - ECTesterStandalone.main(args); - String out2 = out.capturedString().substring(out1.length()); - if (!out1.contains(";")) - return; - List lines1 = out1.lines().collect(Collectors.toList()); - List lines2 = out2.lines().collect(Collectors.toList()); - assertEquals(lines1.size(), lines2.size()); - for (int i = 0; i < lines1.size(); ++i) { - String[] parts1 = lines1.get(i).split(";"); - String[] parts2 = lines2.get(i).split(";"); - assertEquals(parts1[2], parts2[2]); - assertEquals(parts1[3], parts2[3]); - } - } - @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest @MethodSource("libs") diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java new file mode 100644 index 0000000..de9e65f --- /dev/null +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java @@ -0,0 +1,137 @@ +package cz.crcs.ectester.standalone; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junitpioneer.jupiter.StdIo; +import org.junitpioneer.jupiter.StdOut; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DeterministicTests { + + static Stream libs() { + return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt"); + } + + @SuppressWarnings("JUnitMalformedDeclaration") + @ParameterizedTest + @MethodSource("libs") + @StdIo() + public void generate(String libName, StdOut out) { + String[] args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName}; + switch (libName) { + case "Botan": + args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; + break; + case "Crypto++": + args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; + break; + case "Nettle": + args = new String[]{"generate", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName}; + break; + case "mbedTLS": + args = new String[]{"generate", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName}; + break; + } + ECTesterStandalone.main(args); + String out1 = out.capturedString(); + ECTesterStandalone.main(args); + String out2 = out.capturedString().substring(out1.length()); + if (!out1.contains(";")) + return; + List lines1 = out1.lines().collect(Collectors.toList()); + List lines2 = out2.lines().collect(Collectors.toList()); + assertEquals(lines1.size(), lines2.size()); + for (int i = 0; i < lines1.size(); ++i) { + String[] parts1 = lines1.get(i).split(";"); + String[] parts2 = lines2.get(i).split(";"); + assertEquals(parts1[2], parts2[2]); + assertEquals(parts1[3], parts2[3]); + } + } + + @SuppressWarnings("JUnitMalformedDeclaration") + @ParameterizedTest + @MethodSource("libs") + @StdIo() + public void ecdh(String libName, StdOut out) { + String[] args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-nc", "secg/secp256r1", libName}; + switch (libName) { + case "Nettle": + args = new String[]{"ecdh", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-n", "10", "-cn", "secp256r1", libName}; + break; + case "Crypto++": + args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDH", libName}; + break; + case "mbedTLS": + args = new String[]{"ecdh", "-ps", "12345678", "-n", "10", "-nc", "secg/secp256r1", libName}; + break; + } + ECTesterStandalone.main(args); + String out1 = out.capturedString(); + ECTesterStandalone.main(args); + String out2 = out.capturedString().substring(out1.length()); + if (!out1.contains(";")) + return; + List lines1 = out1.lines().collect(Collectors.toList()); + List lines2 = out2.lines().collect(Collectors.toList()); + assertEquals(lines1.size(), lines2.size()); + for (int i = 0; i < lines1.size(); ++i) { + String[] parts1 = lines1.get(i).split(";"); + String[] parts2 = lines2.get(i).split(";"); + assertEquals(parts1[2], parts2[2]); // pubkey + assertEquals(parts1[3], parts2[3]); // privkey + assertEquals(parts1[4], parts2[4]); // secret + } + } + + @SuppressWarnings("JUnitMalformedDeclaration") + @ParameterizedTest + @MethodSource("libs") + @StdIo() + public void ecdsa(String libName, StdOut out) { + String[] args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", libName}; + switch (libName) { + case "Nettle": + args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-cn", "secp256r1", "-t", "NONEwithECDSA", libName}; + break; + case "OpenSSL": + case "tomcrypt": + args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName}; + break; + case "IPPCP": + // TODO: Weird, IPPCP cannot sign less than 4 bytes. + args = new String[]{"ecdsa", "-ps", "123412341234123412341234123412341234123412341234123412341234123412341234123412341234123412341234", "-d", "12345678", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName}; + break; + case "Crypto++": + args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDSA", libName}; + break; + case "mbedTLS": + args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName}; + break; + } + ECTesterStandalone.main(args); + String out1 = out.capturedString(); + ECTesterStandalone.main(args); + String out2 = out.capturedString().substring(out1.length()); + if (!out1.contains(";")) + return; + List lines1 = out1.lines().collect(Collectors.toList()); + List lines2 = out2.lines().collect(Collectors.toList()); + assertEquals(lines1.size(), lines2.size()); + for (int i = 0; i < lines1.size(); ++i) { + String[] parts1 = lines1.get(i).split(";"); + String[] parts2 = lines2.get(i).split(";"); + assertEquals(parts1[3], parts2[3]); // data + assertEquals(parts1[4], parts2[4]); // pubkey + assertEquals(parts1[5], parts2[5]); // privkey + assertEquals(parts1[6], parts2[6]); // signature + assertEquals(parts1[7], parts2[7]); // nonce + } + } +} -- cgit v1.2.3-70-g09d2 From 06fd1cee79c7587e08a3240992c58f7fb361d7fd Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 21:18:01 +0200 Subject: Add deterministic PRNG example to docs. --- README.md | 122 +++++++++++++-------- .../ectester/standalone/DeterministicTests.java | 1 - 2 files changed, 79 insertions(+), 44 deletions(-) (limited to 'standalone/src/test/java/cz') diff --git a/README.md b/README.md index 726be68..379f05f 100644 --- a/README.md +++ b/README.md @@ -440,103 +440,121 @@ To install, place them in `${java.home}/jre/lib/security/`. Snippet below shows how the `list-libs` command for well, listing currently supported libraries, behaves if all supported libraries are present (on Linux). ``` > java -jar ECTesterStandalone.jar list-libs - - Sun Elliptic Curve provider - - Version: 21.000000 + - SunEC + - Fullname: SunEC + - Version: 21 - Supports native timing: [] - - KeyPairGenerators: EC - - KeyAgreements: ECDH - - Signatures: SHA3-256withECDSA, NONEwithECDSA, ECDSA, SHA3-384withECDSA, SHA384withECDSA, SHA3-512withECDSA, SHA224withECDSA, SHA512withECDSA, SHA3-224withECDSA, SHA256withECDSA + - Supports deterministic PRNG: true + - KeyPairGenerators: EC, Ed25519, Ed448, EdDSA, X25519, X448, XDH + - KeyAgreements: ECDH, X25519, X448, XDH + - Signatures: ECDSA, Ed25519, Ed448, EdDSA, NONEwithECDSA, SHA224withECDSA, SHA256withECDSA, SHA3-224withECDSA, SHA3-256withECDSA, SHA3-384withECDSA, SHA3-512withECDSA, SHA384withECDSA, SHA512withECDSA - Curves: secp256r1, secp384r1, secp521r1 - - BouncyCastle Security Provider v1.77 - - Version: 1.770000 + - BouncyCastle + - Fullname: BC + - Version: 1.77 - Supports native timing: [] - - KeyPairGenerators: ECDSA, ECMQV, EC, ECDH, ECDHC - - KeyAgreements: ECCDHwithSHA384KDF, ECDHwithSHA384KDF, ECDHwithSHA256KDF, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDH, ECDHC, ECDHwithSHA512KDF, ECCDHwithSHA1KDF, ECCDHwithSHA512KDF, ECCDHwithSHA224KDF, ECCDHwithSHA256KDF - - Signatures: SHA1withCVC-ECDSA, NONEwithECDSA, ECGOST3410, SHA256withECNR, ECGOST3410-2012-512, SHA512withECDDSA, GOST3411-2012-512withECGOST3410-2012-512, SHA3-512withECDSA, SHA384withPLAIN-ECDSA, SHA256withECDSA, SHA256withECDDSA, SHA224withECDDSA, SHA3-256withECDSA, ECDSA, SHA256withPLAIN-ECDSA, SHA224withECNR, SHA384withECDDSA, SHA512withECNR, SHA256withCVC-ECDSA, SHA1withECNR, ECDDSA, SHA1withPLAIN-ECDSA, GOST3411-2012-256withECGOST3410-2012-256, SHA512withPLAIN-ECDSA, SHA384withCVC-ECDSA, SHA224withCVC-ECDSA, SHA3-224withECDSA, SHA3-224withECDDSA, SHA224withPLAIN-ECDSA, SHA3-384withECDDSA, SHA384withECDSA, SHA3-384withECDSA, SHA3-512withECDDSA, SM3withSM2, GOST3411withECGOST3410, ECGOST3410-2012-256, SHA224withECDSA, SHA512withECDSA, RIPEMD160withECDSA, SHA512withCVC-ECDSA, RIPEMD160withPLAIN-ECDSA, SHA3-256withECDDSA + - Supports deterministic PRNG: true + - KeyPairGenerators: EC, ECDH, ECDHC, ECDSA, ECMQV, Ed25519, Ed448, EdDSA, X25519, X448, XDH + - KeyAgreements: ECCDHwithSHA1KDF, ECCDHwithSHA224KDF, ECCDHwithSHA256KDF, ECCDHwithSHA384KDF, ECCDHwithSHA512KDF, ECDH, ECDHC, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDHwithSHA256KDF, ECDHwithSHA384KDF, ECDHwithSHA512KDF, X25519, X448, XDH + - Signatures: ECDDSA, ECDSA, ECGOST3410, ECGOST3410-2012-256, ECGOST3410-2012-512, Ed25519, Ed448, EdDSA, GOST3411-2012-256withECGOST3410-2012-256, GOST3411-2012-512withECGOST3410-2012-512, GOST3411withECGOST3410, NONEwithECDSA, RIPEMD160withECDSA, RIPEMD160withPLAIN-ECDSA, SHA1withCVC-ECDSA, SHA1withECNR, SHA1withPLAIN-ECDSA, SHA224withCVC-ECDSA, SHA224withECDDSA, SHA224withECDSA, SHA224withECNR, SHA224withPLAIN-ECDSA, SHA256withCVC-ECDSA, SHA256withECDDSA, SHA256withECDSA, SHA256withECNR, SHA256withPLAIN-ECDSA, SHA3-224withECDDSA, SHA3-224withECDSA, SHA3-256withECDDSA, SHA3-256withECDSA, SHA3-384withECDDSA, SHA3-384withECDSA, SHA3-512withECDDSA, SHA3-512withECDSA, SHA384withCVC-ECDSA, SHA384withECDDSA, SHA384withECDSA, SHA384withPLAIN-ECDSA, SHA512withCVC-ECDSA, SHA512withECDDSA, SHA512withECDSA, SHA512withECNR, SHA512withPLAIN-ECDSA, SM3withSM2 - Curves: B-163, B-233, B-283, B-409, B-571, FRP256v1, GostR3410-2001-CryptoPro-A, GostR3410-2001-CryptoPro-B, GostR3410-2001-CryptoPro-C, GostR3410-2001-CryptoPro-XchA, GostR3410-2001-CryptoPro-XchB, K-163, K-233, K-283, K-409, K-571, P-192, P-224, P-256, P-384, P-521, Tc26-Gost-3410-12-256-paramSetA, Tc26-Gost-3410-12-512-paramSetA, Tc26-Gost-3410-12-512-paramSetB, Tc26-Gost-3410-12-512-paramSetC, brainpoolP160r1, brainpoolP160t1, brainpoolP192r1, brainpoolP192t1, brainpoolP224r1, brainpoolP224t1, brainpoolP256r1, brainpoolP256t1, brainpoolP320r1, brainpoolP320t1, brainpoolP384r1, brainpoolP384t1, brainpoolP512r1, brainpoolP512t1, c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176w1, c2pnb208w1, c2pnb272w1, c2pnb304w1, c2pnb368w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2tnb359v1, c2tnb431r1, prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1, secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, sect113r1, sect113r2, sect131r1, sect131r2, sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, sm2p256v1, wapi192v1, wapip192v1 - - libtomcrypt 1.18.2 - - Version: 1.000000 + - tomcrypt + - Fullname: libtomcrypt 1.18.2 + - Version: 1.18 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: true - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: ECC-192, ECC-224, ECC-256, ECC-384, ECC-521, SECP112R1, SECP128R1, SECP160R1 - - Botan 2.19.3 (release, dated 20221116, revision git:15dc32f12d05e99a267f0fc47d88b678b71b8b05, distribution unspecified) - - Version: 2.000000 + - Botan + - Fullname: Botan 2.19.5 + - Version: 2.193 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] - - KeyPairGenerators: ECGDSA, ECKCDSA, ECDSA, ECDH - - KeyAgreements: ECDHwithSHA384KDF, ECDHwithSHA256KDF, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDH, ECDHwithSHA512KDF - - Signatures: NONEwithECDSA, NONEwithECKCDSA, SHA256withECKCDSA, SHA512withECGDSA, SHA256withECDSA, NONEwithECGDSA, ECKCDSA, ECDSA, SHA224withECKCDSA, SHA384withECKCDSA, SHA224withECGDSA, SHA384withECDSA, ECGDSA, SHA384withECGDSA, SHA224withECDSA, SHA512withECDSA, SHA512withECKCDSA + - Supports deterministic PRNG: true + - KeyPairGenerators: ECDH, ECDSA, ECGDSA, ECKCDSA + - KeyAgreements: ECDH, ECDHwithSHA1KDF, ECDHwithSHA224KDF, ECDHwithSHA256KDF, ECDHwithSHA384KDF, ECDHwithSHA512KDF + - Signatures: ECDSA, ECGDSA, ECKCDSA, NONEwithECDSA, NONEwithECGDSA, NONEwithECKCDSA, SHA224withECDSA, SHA224withECGDSA, SHA224withECKCDSA, SHA256withECDSA, SHA256withECKCDSA, SHA384withECDSA, SHA384withECGDSA, SHA384withECKCDSA, SHA512withECDSA, SHA512withECGDSA, SHA512withECKCDSA - Curves: brainpool160r1, brainpool192r1, brainpool224r1, brainpool256r1, brainpool320r1, brainpool384r1, brainpool512r1, frp256v1, gost_256A, gost_512A, secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, sm2p256v1, x962_p192v2, x962_p192v3, x962_p239v1, x962_p239v2, x962_p239v3 - - Crypto++ 8.9.0 - - Version: 8.000000 + - Crypto++ + - Fullname: Crypto++ + - Version: 8.0 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] - - KeyPairGenerators: ECDSA, ECDH + - Supports deterministic PRNG: true + - KeyPairGenerators: ECDH, ECDSA - KeyAgreements: ECDH - - Signatures: ECDSA, SHA384withECDSA, SHA224withECDSA, SHA512withECDSA, SHA256withECDSA + - Signatures: ECDSA, SHA224withECDSA, SHA256withECDSA, SHA384withECDSA, SHA512withECDSA - Curves: 1.2.156.10197.1.301, 1.2.156.10197.1.301.3.1, 1.2.840.10045.3.1.1, 1.2.840.10045.3.1.7, 1.3.132.0.1, 1.3.132.0.10, 1.3.132.0.15, 1.3.132.0.16, 1.3.132.0.17, 1.3.132.0.2, 1.3.132.0.22, 1.3.132.0.23, 1.3.132.0.24, 1.3.132.0.25, 1.3.132.0.26, 1.3.132.0.27, 1.3.132.0.28, 1.3.132.0.29, 1.3.132.0.3, 1.3.132.0.30, 1.3.132.0.31, 1.3.132.0.32, 1.3.132.0.33, 1.3.132.0.34, 1.3.132.0.35, 1.3.132.0.36, 1.3.132.0.37, 1.3.132.0.38, 1.3.132.0.39, 1.3.132.0.4, 1.3.132.0.5, 1.3.132.0.6, 1.3.132.0.7, 1.3.132.0.8, 1.3.132.0.9, 1.3.36.3.3.2.8.1.1.1, 1.3.36.3.3.2.8.1.1.11, 1.3.36.3.3.2.8.1.1.13, 1.3.36.3.3.2.8.1.1.3, 1.3.36.3.3.2.8.1.1.5, 1.3.36.3.3.2.8.1.1.7, 1.3.36.3.3.2.8.1.1.9 - - OpenSSL 3.2.1 30 Jan 2024 - - Version: 3.200000 + - OpenSSL + - Fullname: OpenSSL 3.2.1 30 Jan 2024 + - Version: 3.2 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: true - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: Oakley-EC2N-3, Oakley-EC2N-4, SM2, brainpoolP160r1, brainpoolP160t1, brainpoolP192r1, brainpoolP192t1, brainpoolP224r1, brainpoolP224t1, brainpoolP256r1, brainpoolP256t1, brainpoolP320r1, brainpoolP320t1, brainpoolP384r1, brainpoolP384t1, brainpoolP512r1, brainpoolP512t1, c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176v1, c2pnb208w1, c2pnb272w1, c2pnb304w1, c2pnb368w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2tnb359v1, c2tnb431r1, prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1, secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1, secp224k1, secp224r1, secp256k1, secp384r1, secp521r1, sect113r1, sect113r2, sect131r1, sect131r2, sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, wap-wsg-idm-ecid-wtls1, wap-wsg-idm-ecid-wtls10, wap-wsg-idm-ecid-wtls11, wap-wsg-idm-ecid-wtls12, wap-wsg-idm-ecid-wtls3, wap-wsg-idm-ecid-wtls4, wap-wsg-idm-ecid-wtls5, wap-wsg-idm-ecid-wtls6, wap-wsg-idm-ecid-wtls7, wap-wsg-idm-ecid-wtls8, wap-wsg-idm-ecid-wtls9 - - OpenSSL 1.1.1 (compatible; BoringSSL) - - Version: 1.110000 + - BoringSSL + - Fullname: OpenSSL 1.1.1 (compatible; BoringSSL) + - Version: 1.11 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: false - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: prime256v1, secp224r1, secp384r1, secp521r1 - - libgcrypt 1.10.3-unknown - - Version: 1.000000 + - libgcrypt + - Fullname: libgcrypt 1.11.0-unknown + - Version: 1.11 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: false - KeyPairGenerators: EC - KeyAgreements: ECDH - - Signatures: SHA224withECDDSA, SHA256withECDDSA, NONEwithECDSA, ECDSA, ECDDSA, SHA384withECDSA, SHA512withECDDSA, SHA224withECDSA, SHA512withECDSA, SHA384withECDDSA, SHA256withECDSA + - Signatures: ECDDSA, ECDSA, NONEwithECDSA, SHA224withECDDSA, SHA224withECDSA, SHA256withECDDSA, SHA256withECDSA, SHA384withECDDSA, SHA384withECDSA, SHA512withECDDSA, SHA512withECDSA - Curves: Curve25519, Ed25519, Ed448, GOST2001-CryptoPro-A, GOST2001-CryptoPro-B, GOST2001-CryptoPro-C, GOST2001-test, GOST2012-256-A, GOST2012-512-tc26-A, GOST2012-512-tc26-B, GOST2012-512-tc26-C, GOST2012-512-test, NIST P-192, NIST P-224, NIST P-256, NIST P-384, NIST P-521, X448, brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1, secp256k1, sm2p256v1 - - wolfCrypt JCE Provider - - Version: 1.500000 - - Supports native timing: [] - - KeyAgreements: ECDH - - Signatures: ECDSA, SHA384withECDSA, SHA512withECDSA, SHA256withECDSA - - - Mbed TLS 3.5.2 - - Version: 3.000000 + - mbedTLS + - Fullname: Mbed TLS 3.5.2 + - Version: 3.52 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: true - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: brainpoolP256r1, brainpoolP384r1, brainpoolP512r1, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1, x25519, x448 - - 2021.7.0 (11.5 ) (-) - - Version: 2021.700000 + - IPPCP + - Fullname: ippCP AVX2 (l9) + - Version: 2021.7 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: true - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: secp112r1, secp112r2, secp128r1, secp128r2, secp160r1, secp160r2, secp192r1, secp224r1, secp256r1, secp384r1, secp521r1 - Nettle - - Version: 3.900000 + - Fullname: Nettle + - Version: 3.9 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: true - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA - Curves: secp192r1, secp224r1, secp256r1, secp384r1, secp521r1 - - LibreSSL 3.9.0 - - Version: 3.900000 + - LibreSSL + - Fullname: LibreSSL 3.9.0 + - Version: 3.9 - Supports native timing: [cputime-processor, cputime-thread, monotonic, monotonic-raw, rdtsc] + - Supports deterministic PRNG: false - KeyPairGenerators: EC - KeyAgreements: ECDH - Signatures: NONEwithECDSA @@ -559,7 +577,7 @@ index;time[nano];pubW;privS Snippet below demonstrates performing 10 ECDSA signatures, without hashing the message (`-t NONEwithECDSA`) on the `secp256r1` curve, with a fixed keypair throught the process (`--fixed`), utilizing the rdtsc instruction to measure duration (`--time-source`) and using the MatrixSSL library. ``` -> java -jar ECTesterStandalone.jar ecdsa -n 10 -t NONEwithECDSA -nc secg/secp256r1 --fixed --time-source rdtsc Matrix +> java -jar ECTesterStandalone.jar ecdsa -n 10 -t NONEwithECDSA -nc secg/secp256r1 --fixed --time-source rdtsc OpenSSL index;signTime[instr];verifyTime[instr];data;pubW;privS;signature[NONE];nonce;verified 0;6785333;18200703;24b064ff5a4d08df6f982d0e139677fb4e66602bea01e381e16d4d3614fd09d5;0429ef9b52fc5c9b8711c938820f4d15d6aab1dcd8aa5a80e754233f23c622a5a174cca795068aff9c979bff7e6f1345b529612a4d16df6adf56b8ac250a1fafc3;54d06d1a79b2b43dc072b96ca7b9f045fda84ac13f74ef81fab0d561a47d11d1;3045022070ca3dfe2017892d23a2301b2465ab387af7999c79de7dae53ec04d1600a25800221009fc9a6fe20c7930b9d8be40424ab4b08fa641f339efa81e6ccf5497cd71180f0;57ebf83913734ff0a78fa952da12996c48da17fbcf5967e74eb3e2c6b5e726b1;1 1;8582180;16170010;24b064ff5a4d08df6f982d0e139677fb4e66602bea01e381e16d4d3614fd09d5;0429ef9b52fc5c9b8711c938820f4d15d6aab1dcd8aa5a80e754233f23c622a5a174cca795068aff9c979bff7e6f1345b529612a4d16df6adf56b8ac250a1fafc3;54d06d1a79b2b43dc072b96ca7b9f045fda84ac13f74ef81fab0d561a47d11d1;3045022100efd3efc1bb2ed243eec9bea4bc331966e869c02df1fc8686a7649708c106595a022050e9a2548bac56bb3287f27c1761136947eefaa8a92f31978ed9485a03cb8f3d;0f5d3cc25d3eb69177b7917631f5639a088773873e91c1adb0a2b753987cace8;1 @@ -571,7 +589,7 @@ index;signTime[instr];verifyTime[instr];data;pubW;privS;signature[NONE];nonce;ve Snippet below demonstrates performing 10000 ECDH key agreements, using the curve name `secp256r1` (`-cn`, the difference between the `-cn` option and the `-nc` option is that the latter looks up the curve in ECTester's database and passes the parameters to the library explicitly, while the former passes the name to the library) using the MbedTLS library. ``` -> java -jar ECTesterStandalone.jar ecdh -n 10000 -cn secp256r1 mbed +> java -jar ECTesterStandalone.jar ecdh -n 10000 -cn secp256r1 mbedTLS index;time[nano];pubW;privS;secret[NONE] 0;5952101;04367ef86b5fbf1b4716bf7822342ebb19a9b6bcfbdb4f4950bf090ba2d1263579dac3e8447c21202432c76f89a0b48a1c16970e4fde67853c8d389da3f02fcdfc;00ecc7b46513149ab19fbeb1c49c1706712dc7da3899add30eb935e18fe5851d79;a94524fa98e0e5b3e139afdb89b73b843e48d5491b19585a5dcae02f20f13088 1;6099022;0439803db68efddbfc3fba1feae41118b02e35d009670fbb4c5dfe6a56fe20829b42e101d0c55bf905276ac71af7e215714cf41742c1f8a2d102761b9eb307d209;6f43118f50ddfef724288ad4f116354bec4735370cb221547b76b18832daaea9;d1b90ed000ca9542ac2101383397a7180cdcd6896b1ccfb5b719da734ad96bf1 @@ -585,6 +603,24 @@ index;time[nano];pubW;privS;secret[NONE] ... ``` +Snippet below demonstrates the support for using a deterministic PRNG (`-ps`) in some of the libraries (see the output of `list-libs`): +``` +> java -jar ECTesterStandalone.jar generate -n 5 -ps 1234 -b 256 Bouncy +index;time[nano];pubW;privS +0;33664582;04db8bdd6cb30d08a0355d48b65ddfc123944d29395f9f5e1bc2bfe70b4ee44ad39e4005df1e61251b4e9a9d8d47b78fd4ce98181883d2bfd634743758397f54ae;00e08df38827302c3315b833022189f61af3af9fbcb6e53697724374861f1982ee +1;3584575;0458bc7baf831c1a316a8deb9fb3109841f10d3cb8828b583b9883a518fa04633488e2fa991e70c98612c989fdfd6aa25118947e8a17bfc36ad1f51a8bdc473e3d;0f5a481f518751bbd2112e4fcc3d1ac60cd66a474af9a57cedbd1e62a52b6bd9 +2;2746750;04827d7247b6d478cc85df313a9ea4f102301b0bd125b18e0111cd02e53b319830b2d0218551504cfc6b1226ac7fa430388f677cab2ea36997e344078328d12207;222898920190d28dac732b8e1fa69dd9907c667604c54db70c41b4815eafc94b +3;2828535;0473104cec678c5ea20857435f19280975c2a3b2d22e7f8005c33d019de6b707012960b96a80f0f358a69dcd5dd34c748cae3fa9f45b720f5a7d241017010c1af1;3fb2f7c3a15f86f000017e42f79557befe7472ff462d3321bc13a043c251345c +4;14181365;04854011114eb3e0fcf21f2416e0adbb0fc81d84530860ca40b6a86c85aa4e66b455382b71f8b6144f6294376912334ff1b23bb49da8fe1bda0e0e89ccbe9145f6;65675a954fff3287be1fc61dbb176f6784ece16c6b5675d556c57fd58974b358 +> java -jar ECTesterStandalone.jar generate -n 5 -ps 1234 -b 256 Bouncy +index;time[nano];pubW;privS +0;35138528;04db8bdd6cb30d08a0355d48b65ddfc123944d29395f9f5e1bc2bfe70b4ee44ad39e4005df1e61251b4e9a9d8d47b78fd4ce98181883d2bfd634743758397f54ae;00e08df38827302c3315b833022189f61af3af9fbcb6e53697724374861f1982ee +1;2351304;0458bc7baf831c1a316a8deb9fb3109841f10d3cb8828b583b9883a518fa04633488e2fa991e70c98612c989fdfd6aa25118947e8a17bfc36ad1f51a8bdc473e3d;0f5a481f518751bbd2112e4fcc3d1ac60cd66a474af9a57cedbd1e62a52b6bd9 +2;3315124;04827d7247b6d478cc85df313a9ea4f102301b0bd125b18e0111cd02e53b319830b2d0218551504cfc6b1226ac7fa430388f677cab2ea36997e344078328d12207;222898920190d28dac732b8e1fa69dd9907c667604c54db70c41b4815eafc94b +3;2883430;0473104cec678c5ea20857435f19280975c2a3b2d22e7f8005c33d019de6b707012960b96a80f0f358a69dcd5dd34c748cae3fa9f45b720f5a7d241017010c1af1;3fb2f7c3a15f86f000017e42f79557befe7472ff462d3321bc13a043c251345c +4;2060970;04854011114eb3e0fcf21f2416e0adbb0fc81d84530860ca40b6a86c85aa4e66b455382b71f8b6144f6294376912334ff1b23bb49da8fe1bda0e0e89ccbe9145f6;65675a954fff3287be1fc61dbb176f6784ece16c6b5675d556c57fd58974b358 +``` + It is recommended to disable [CPU frequency scaling](https://wiki.archlinux.org/index.php/CPU_frequency_scaling) of your processor before performing collection of timing data, as it adds significant noise to the data as it kicks in. Also, running the collection on very high priority and locked to a single core (`taskset -c 0`) helps as well. ## Analysis diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java index de9e65f..bebb3c5 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java @@ -5,7 +5,6 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junitpioneer.jupiter.StdIo; import org.junitpioneer.jupiter.StdOut; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -- cgit v1.2.3-70-g09d2 From 77469ff0f8daaa1c47719d88885d5a66431cdce5 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 9 Aug 2024 16:42:32 +0200 Subject: Add deterministic PRNG via preload of RNG functions. --- standalone/build.gradle.kts | 4 + .../ectester/standalone/ECTesterStandalone.java | 50 +++- .../ectester/standalone/libs/BoringsslLib.java | 6 + .../crcs/ectester/standalone/libs/GcryptLib.java | 6 + .../crcs/ectester/standalone/libs/LibresslLib.java | 6 + .../ectester/standalone/libs/NativeECLibrary.java | 3 + .../cz/crcs/ectester/standalone/libs/jni/Makefile | 37 ++- .../crcs/ectester/standalone/libs/jni/c_preload.c | 316 +++++++++++++++++++++ .../cz/crcs/ectester/standalone/libs/jni/c_prng.c | 18 ++ .../cz/crcs/ectester/standalone/libs/jni/native.h | 8 + .../cz/crcs/ectester/standalone/libs/jni/preload.c | 255 ----------------- .../standalone/libs/jni/prng/KeccakDuplex-common.h | 37 +++ .../standalone/libs/jni/prng/KeccakDuplex.inc | 192 +++++++++++++ .../libs/jni/prng/KeccakDuplexWidth200.c | 29 ++ .../libs/jni/prng/KeccakDuplexWidth200.h | 25 ++ .../standalone/libs/jni/prng/KeccakP-200-SnP.h | 34 +++ .../standalone/libs/jni/prng/KeccakP-200-compact.c | 187 ++++++++++++ .../standalone/libs/jni/prng/KeccakPRG-common.h | 28 ++ .../ectester/standalone/libs/jni/prng/KeccakPRG.h | 20 ++ .../standalone/libs/jni/prng/KeccakPRG.inc | 123 ++++++++ .../standalone/libs/jni/prng/KeccakPRGWidth200.c | 22 ++ .../standalone/libs/jni/prng/KeccakPRGWidth200.h | 24 ++ .../crcs/ectester/standalone/libs/jni/prng/align.h | 32 +++ .../crcs/ectester/standalone/libs/jni/prng/prng.c | 21 ++ .../crcs/ectester/standalone/libs/jni/prng/prng.h | 13 + .../ectester/standalone/DeterministicTests.java | 4 +- 26 files changed, 1228 insertions(+), 272 deletions(-) create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c create mode 100644 standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h (limited to 'standalone/src/test/java/cz') diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index c5bd604..07bf2ab 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -58,6 +58,10 @@ tasks.named("test") { environment( "LD_LIBRARY_PATH", "$rootDir/ext/wolfcrypt-jni/lib/:" + System.getenv("LD_LIBRARY_PATH") ) + // Add our preload to tests, so they do not need to start another process. + environment( + "LD_PRELOAD", "$rootDir/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/lib_preload.so" + ) // Add a path where we will store our test results. environment( "RESULT_PATH", resultsDir.absolutePath 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 dc61192..6822a30 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -23,6 +23,7 @@ */ package cz.crcs.ectester.standalone; +import com.sun.source.tree.StringTemplateTree; import cz.crcs.ectester.common.cli.*; import cz.crcs.ectester.common.ec.EC_Consts; import cz.crcs.ectester.common.ec.EC_Curve; @@ -105,12 +106,52 @@ public class ECTesterStandalone { if (!System.getProperty("os.name").startsWith("Windows")) { FileUtil.write(LIB_RESOURCE_DIR + "lib_timing.so", reqs.resolve("lib_timing.so")); - System.load(reqs.resolve("lib_timing.so").toString()); - + FileUtil.write(LIB_RESOURCE_DIR + "lib_preload.so", reqs.resolve("lib_preload.so")); + FileUtil.write(LIB_RESOURCE_DIR + "lib_prng.so", reqs.resolve("lib_prng.so")); FileUtil.write(LIB_RESOURCE_DIR + "lib_csignals.so", reqs.resolve("lib_csignals.so")); - System.load(reqs.resolve("lib_csignals.so").toString()); FileUtil.write(LIB_RESOURCE_DIR + "lib_cppsignals.so", reqs.resolve("lib_cppsignals.so")); - System.load(reqs.resolve("lib_cppsignals.so").toString()); + + String preloadLibPath = reqs.resolve("lib_preload.so").toAbsolutePath().toString(); + String preload = System.getenv("LD_PRELOAD"); + if (preload == null && !cli.hasOption("no-preload")) { + ProcessBuilder builder = new ProcessBuilder(); + Map env = builder.environment(); + env.put("LD_PRELOAD", preloadLibPath); + + ProcessHandle.Info info = ProcessHandle.current().info(); + List argList = new LinkedList<>(); + if (info.command().isPresent()) { + argList.add(info.command().get()); + } else { + System.err.println("Cannot locate command to spawn preloaded-subprocess."); + return; + } + if (info.arguments().isPresent()) { + argList.addAll(List.of(info.arguments().get())); + } else { + System.err.println("Cannot locate arguments to spawn preloaded-subprocess."); + return; + } + builder.command(argList); + builder.inheritIO(); + + Process process = builder.start(); + int result; + while (true) { + try { + result = process.waitFor(); + break; + } catch (InterruptedException ignored) { + } + } + System.exit(result); + } else { + // Load the utility libs. + System.load(reqs.resolve("lib_prng.so").toString()); + System.load(reqs.resolve("lib_timing.so").toString()); + System.load(reqs.resolve("lib_csignals.so").toString()); + System.load(reqs.resolve("lib_cppsignals.so").toString()); + } } List libObjects = new LinkedList<>(); @@ -296,6 +337,7 @@ public class ECTesterStandalone { opts.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build()); opts.addOption(Option.builder("h").longOpt("help").desc("Print help(about ).").hasArg().argName("command").optionalArg(true).build()); opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build()); + opts.addOption(Option.builder().longOpt("no-preload").desc("Do not use LD_PRELOAD.").build()); return optParser.parse(opts, args); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java index af4d969..06e6b4a 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BoringsslLib.java @@ -16,4 +16,10 @@ public class BoringsslLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public boolean supportsDeterministicPRNG() { + // This is provided by the native preload that hooks all randomness sources. + return true; + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java index 83d78ef..d1452a9 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/GcryptLib.java @@ -17,4 +17,10 @@ public class GcryptLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public boolean supportsDeterministicPRNG() { + // This is provided by the native preload that hooks all randomness sources. + return true; + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java index 2dba049..e53399c 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/LibresslLib.java @@ -16,4 +16,10 @@ public class LibresslLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public boolean supportsDeterministicPRNG() { + // This is provided by the native preload that hooks all randomness sources. + return true; + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java index c11dbdb..fb4e430 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NativeECLibrary.java @@ -86,5 +86,8 @@ public abstract class NativeECLibrary extends ProviderECLibrary { @Override public native long getLastNativeTiming(); + @Override + public native boolean setupDeterministicPRNG(byte[] seed); + abstract Provider createProvider(); } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile index d243f68..f947c78 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -73,8 +73,17 @@ c_utils.o: c_utils.c lib_timing.so: c_timing.c $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $< -lib_preload.so: preload.c - $(CC) -shared -fPIC -ldl $< -o $@ +prng.o: prng/prng.c + $(CC) $(CFLAGS) -c $< + +lib_prng.so: c_prng.c + $(CC) -o $@ -shared -Wl,-soname,lib_prng.so $(CFLAGS) $< + +c_preload.o: c_preload.c + $(CC) $(CFLAGS) -c $< + +lib_preload.so: c_preload.o prng.o + $(CC) -o $@ -shared $(CFLAGS) -ldl -Wl,-soname,lib_preload.so $^ lib_csignals.so: c_signals.c $(CC) -o $@ -shared $(CFLAGS) -pthread -lpthread -Wl,-soname,lib_csignals.so $< @@ -86,10 +95,14 @@ cpp_utils.o: cpp_utils.cpp $(CXX) $(CXXFLAGS) -c $< +clibs: lib_timing.so lib_csignals.so lib_preload.so lib_prng.so + +cpplibs: lib_timing.so lib_cppsignals.so lib_preload.so lib_prng.so + # OpenSSL shim openssl: openssl_provider.so -openssl_provider.so: openssl.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so +openssl_provider.so: openssl.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs openssl) -l:lib_timing.so -l:lib_csignals.so openssl.o: openssl.c @@ -102,7 +115,7 @@ boringssl: boringssl_provider.so lib_boringssl.so: cp $(PROJECT_ROOT_PATH)/ext/boringssl/build/crypto/libcrypto.so lib_boringssl.so -boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so lib_boringssl.so +boringssl_provider.so: boringssl.o c_utils.o | clibs lib_boringssl.so $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_boringssl.so -l:lib_timing.so -l:lib_csignals.so boringssl.o: boringssl.c @@ -112,7 +125,7 @@ boringssl.o: boringssl.c # libgcrypt shim gcrypt: gcrypt_provider.so -gcrypt_provider.so: gcrypt.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so +gcrypt_provider.so: gcrypt.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread $(shell libgcrypt-config --libs) -l:lib_timing.so -l:lib_csignals.so gcrypt.o: gcrypt.c @@ -122,7 +135,7 @@ gcrypt.o: gcrypt.c # Libtomcrypt shim tomcrypt: tomcrypt_provider.so -tomcrypt_provider.so: tomcrypt.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so +tomcrypt_provider.so: tomcrypt.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt) -l:lib_timing.so -l:lib_csignals.so tomcrypt.o: tomcrypt.c @@ -132,7 +145,7 @@ tomcrypt.o: tomcrypt.c # Botan-2 shim botan: botan_provider.so -botan_provider.so: botan.o cpp_utils.o | lib_timing.so lib_cppsignals.so lib_preload.so +botan_provider.so: botan.o cpp_utils.o | cpplibs $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs botan-2) -l:lib_timing.so -l:lib_cppsignals.so botan.o: botan.cpp @@ -146,7 +159,7 @@ ifeq ($(shell pkg-config --exists $(CRYPTOPP_NAME); echo $$?),1) endif cryptopp: cryptopp_provider.so -cryptopp_provider.so: cryptopp.o cpp_utils.o | lib_timing.so lib_cppsignals.so lib_preload.so +cryptopp_provider.so: cryptopp.o cpp_utils.o | cpplibs $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs $(CRYPTOPP_NAME)) -l:lib_timing.so -l:lib_cppsignals.so cryptopp.o: cryptopp.cpp @@ -159,7 +172,7 @@ mbedtls: mbedtls_provider.so lib_mbedtls.so: cp $(PROJECT_ROOT_PATH)/ext/mbedtls/build/library/libmbedcrypto.so lib_mbedtls.so -mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so lib_mbedtls.so +mbedtls_provider.so: mbedtls.o c_utils.o | clibs lib_mbedtls.so $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_mbedtls.so -l:lib_timing.so -l:lib_csignals.so mbedtls.o: mbedtls.c @@ -172,7 +185,7 @@ ippcp: ippcp_provider.so lib_ippcp.so: cp $(PROJECT_ROOT_PATH)/ext/ipp-crypto/build/.build/RELEASE/lib/libippcp.so lib_ippcp.so -ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so lib_ippcp.so +ippcp_provider.so: ippcp.o c_utils.o | clibs lib_ippcp.so $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_ippcp.so -l:lib_timing.so -l:lib_csignals.so ippcp.o: ippcp.c @@ -182,7 +195,7 @@ ippcp.o: ippcp.c # Nettle shim nettle: nettle_provider.so -nettle_provider.so: nettle.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so +nettle_provider.so: nettle.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. $(shell pkg-config --libs nettle) -l:lib_timing.so -l:lib_csignals.so $(shell pkg-config --libs hogweed) -lgmp nettle.o: nettle.c @@ -195,7 +208,7 @@ libressl: libressl_provider.so lib_libressl.so: cp $(PROJECT_ROOT_PATH)/ext/libressl/build/crypto/libcrypto.so lib_libressl.so -libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_csignals.so lib_preload.so lib_libressl.so +libressl_provider.so: libressl.o c_utils.o | clibs lib_libressl.so $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. lib_libressl.so -l:lib_timing.so -l:lib_csignals.so libressl.o: libressl.c diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c new file mode 100644 index 0000000..1f597a3 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_preload.c @@ -0,0 +1,316 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "native.h" +#include "prng/prng.h" + + +#ifdef DEBUG_PRELOAD + +void print_buf(uint8_t *buf, size_t len) { + for (int i = 0; i < len; ++i) { + fprintf(stderr, "%02x ", buf[i]); + } + fprintf(stderr, "\n"); +} + +#else + +#define print_buf(buf, len) + +#endif + +typedef int (*open_t)(const char *pathname, int flags, ...); +static open_t real_open; +typedef int (*openat_t)(int fd, const char *pathname, int flags, ...); +static openat_t real_openat; +typedef ssize_t (*read_t)(int fd, void *buf, size_t count); +static read_t real_read; +typedef FILE *(*fopen_t)(const char *pathname, const char *mode); +static fopen_t real_fopen; +typedef size_t (*fread_t)(void *ptr, size_t size, size_t nmemb, FILE *stream); +static fread_t real_fread; +typedef ssize_t (*getrandom_t)(void *buf, size_t buflen, unsigned int flags); +static getrandom_t real_getrandom; +typedef int (*getentropy_t)(void *buffer, size_t length); +static getentropy_t real_getentropy; +typedef long (*syscall_t)(long number, ...); +static syscall_t real_syscall; +typedef uint32_t (*arc4random_t)(void); +static arc4random_t real_arc4random; +typedef uint32_t (*arc4random_uniform_t)(uint32_t upper_bound); +static arc4random_uniform_t real_arc4random_uniform; +typedef void (*arc4random_buf_t)(void *buf, size_t n); +static arc4random_buf_t real_arc4random_buf; + +prng_state preload_prng_state; +bool preload_prng_enabled = false; + +static int *random_fds = NULL; +static size_t random_fds_used = 0; +static size_t random_fds_allocd = 0; + +void check_random_fds() { + if (random_fds_allocd == 0) { + random_fds_allocd = 10; + random_fds = calloc(random_fds_allocd, sizeof(int)); + } else if (random_fds_allocd == random_fds_used) { + random_fds_allocd *= 2; + random_fds = realloc(random_fds, random_fds_allocd * sizeof(int)); + } +} + +void store_random_fd(int fd) { + check_random_fds(); + random_fds[random_fds_used++] = fd; +} + +int open(const char *pathname, int flags, ...) { + if (!real_open) { + real_open = dlsym(RTLD_NEXT, "open"); + } + + va_list args; + va_start(args, flags); + int mode = va_arg(args, int); + va_end(args); + + int result = real_open(pathname, flags, mode); + if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called open(%s, %i, %i)\n", pathname, flags, mode); +#endif + store_random_fd(result); + } + return result; +} + +int openat(int fd, const char *pathname, int flags, ...) { + if (!real_openat) { + real_openat = dlsym(RTLD_NEXT, "openat"); + } + + va_list args; + va_start(args, flags); + int mode = va_arg(args, int); + va_end(args); + + int result = real_openat(fd, pathname, flags, mode); + if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called openat(%s, %i, %i)\n", pathname, flags, mode); +#endif + store_random_fd(result); + } + return result; +} + +ssize_t read(int fd, void *buf, size_t count) { + if (!real_read) { + real_read = dlsym(RTLD_NEXT, "read"); + } + + if (preload_prng_enabled) { + for (int i = 0; i < random_fds_used; ++i) { + int random_fd = random_fds[i]; + if (random_fd == fd) { + prng_get(&preload_prng_state, buf, count); +#ifdef DEBUG_PRELOAD + fprintf(stderr, "read from random\n"); + print_buf(buf, count); +#endif + return count; + } + } + } + + return real_read(fd, buf, count); +} + +static FILE **random_files = NULL; +static size_t random_files_used = 0; +static size_t random_files_allocd = 0; + +void check_random_files() { + if (random_files_allocd == 0) { + random_files_allocd = 10; + random_files = calloc(random_files_allocd, sizeof(FILE *)); + } else if (random_files_allocd == random_files_used) { + random_files_allocd *= 2; + random_files = realloc(random_files, random_files_allocd * sizeof(FILE*)); + } +} + +void store_random_file(FILE *file) { + check_random_files(); + random_files[random_files_used++] = file; +} + +FILE *fopen(const char *pathname, const char *mode) { + if (!real_fopen) { + real_fopen = dlsym(RTLD_NEXT, "fopen"); + } + + FILE *result = real_fopen(pathname, mode); + + if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called fopen(%s, %s)\n", pathname, mode); +#endif + store_random_file(result); + } + return result; +} + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { + if (!real_fread) { + real_fread = dlsym(RTLD_NEXT, "fread"); + } + + if (preload_prng_enabled) { + for (int i = 0; i < random_files_used; ++i) { + FILE *random_file = random_files[i]; + if (random_file == stream) { + prng_get(&preload_prng_state, ptr, size * nmemb); +#ifdef DEBUG_PRELOAD + fprintf(stderr, "fread from random\n"); + print_buf(ptr, size * nmemb); +#endif + return size * nmemb; + } + } + } + + return real_fread(ptr, size, nmemb, stream); +} + +ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { + if (!real_getrandom) { + real_getrandom = dlsym(RTLD_NEXT, "getrandom"); + } + +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called getrandom(*, %lu, %u)\n", buflen, flags); +#endif + if (preload_prng_enabled) { + prng_get(&preload_prng_state, buf, buflen); + print_buf(buf, buflen); + return buflen; + } else { + return real_getrandom(buf, buflen, flags); + } +} + +int getentropy(void *buffer, size_t length) { + if (!real_getentropy) { + real_getentropy = dlsym(RTLD_NEXT, "getentropy"); + } + +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called getentropy(*, %lu)\n", length); +#endif + if (preload_prng_enabled) { + prng_get(&preload_prng_state, buffer, length); + print_buf(buffer, length); + return 0; + } else { + return real_getentropy(buffer, length); + } +} + +long syscall(long number, ...) { + if (!real_syscall) { + real_syscall = dlsym(RTLD_NEXT, "syscall"); + } + va_list args; + + va_start(args, number); + long int a0 = va_arg(args, long int); + long int a1 = va_arg(args, long int); + long int a2 = va_arg(args, long int); + long int a3 = va_arg(args, long int); + long int a4 = va_arg(args, long int); + long int a5 = va_arg(args, long int); + va_end(args); + + if (number == SYS_getrandom) { +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called syscall(getrandom, %li, %li, %li, %li, %li, %li)\n", a0, a1, a2, a3, a4, a5); +#endif + if (preload_prng_enabled) { + uint8_t *buf = (uint8_t*)a0; + long n = a1; + prng_get(&preload_prng_state, buf, n); + print_buf(buf, n); + return n; + } + } + return real_syscall(number, a0, a1, a2, a3, a4, a5); +} + +uint32_t arc4random(void) { + if (!real_arc4random) { + real_arc4random = dlsym(RTLD_NEXT, "arc4random"); + } + +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called arc4random\n"); +#endif + if (preload_prng_enabled) { + uint32_t val = 0; + prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val)); +#ifdef DEBUG_PRELOAD + fprintf(stderr, "%u\n", val); +#endif + return val; + } else { + return real_arc4random(); + } +} + +uint32_t arc4random_uniform(uint32_t upper_bound) { + if (!real_arc4random_uniform) { + real_arc4random_uniform = dlsym(RTLD_NEXT, "arc4random_uniform"); + } + +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called arc4random_uniform(%u)\n", upper_bound); +#endif + if (preload_prng_enabled) { + uint64_t val = 0; + prng_get(&preload_prng_state, (uint8_t*)&val, sizeof(val)); + uint32_t result = (uint32_t)(val % (uint64_t)upper_bound); +#ifdef DEBUG_PRELOAD + fprintf(stderr, "%u\n", result); +#endif + return result; + } else { + return real_arc4random_uniform(upper_bound); + } +} + +void arc4random_buf(void *buf, size_t n) { + if (!real_arc4random_buf) { + real_arc4random_buf = dlsym(RTLD_NEXT, "arc4random_buf"); + } + +#ifdef DEBUG_PRELOAD + fprintf(stderr, "called arc4random_buf(%p, %lu) = ", buf, n); +#endif + if (preload_prng_enabled) { + prng_get(&preload_prng_state, buf, n); + print_buf(buf, n); + } else { + real_arc4random_buf(buf, n); + } +} \ No newline at end of file diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c new file mode 100644 index 0000000..13bd172 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/c_prng.c @@ -0,0 +1,18 @@ +#include +#include +#include "prng/prng.h" + +extern prng_state preload_prng_state; +extern bool preload_prng_enabled; + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + jsize seed_length = (*env)->GetArrayLength(env, seed); + jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); + + preload_prng_enabled = true; + prng_init(&preload_prng_state); + prng_seed(&preload_prng_state, seed_data, seed_length); + + (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + return JNI_TRUE; +} \ No newline at end of file diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h index 91cada9..881243f 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h @@ -47,6 +47,14 @@ JNIEXPORT jstring JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_ JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_getLastNativeTiming (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_NativeECLibrary + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NativeECLibrary_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/preload.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/preload.c index ff7b67b..e69de29 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/preload.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/preload.c @@ -1,255 +0,0 @@ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef int (*open_t)(const char *pathname, int flags, ...); -static open_t real_open; -typedef int (*openat_t)(int fd, const char *pathname, int flags, ...); -static openat_t real_openat; -typedef ssize_t (*read_t)(int fd, void *buf, size_t count); -static read_t real_read; -typedef FILE *(*fopen_t)(const char *pathname, const char *mode); -static fopen_t real_fopen; -typedef size_t (*fread_t)(void *ptr, size_t size, size_t nmemb, FILE *stream); -static fread_t real_fread; -typedef ssize_t (*getrandom_t)(void *buf, size_t buflen, unsigned int flags); -static getrandom_t real_getrandom; -typedef int (*getentropy_t)(void *buffer, size_t length); -static getentropy_t real_getentropy; -typedef long (*syscall_t)(long number, ...); -static syscall_t real_syscall; -typedef uint32_t (*arc4random_t)(void); -static arc4random_t real_arc4random; -typedef uint32_t (*arc4random_uniform_t)(uint32_t upper_bound); -static arc4random_uniform_t real_arc4random_uniform; -typedef void (*arc4random_buf_t)(void *buf, size_t n); -static arc4random_buf_t real_arc4random_buf; - -static int *random_fds = NULL; -static size_t random_fds_used = 0; -static size_t random_fds_allocd = 0; - -void check_random_fds() { - if (random_fds_allocd == 0) { - random_fds_allocd = 10; - random_fds = calloc(random_fds_allocd, sizeof(int)); - } else if (random_fds_allocd == random_fds_used) { - random_fds_allocd *= 2; - random_fds = realloc(random_fds, random_fds_allocd * sizeof(int)); - } -} - -void store_random_fd(int fd) { - check_random_fds(); - random_fds[random_fds_used++] = fd; -} - -int open(const char *pathname, int flags, ...) { - if (!real_open) { - real_open = dlsym(RTLD_NEXT, "open"); - } - - va_list args; - va_start(args, flags); - int mode = va_arg(args, int); - va_end(args); - - int result = real_open(pathname, flags, mode); - if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { - fprintf(stderr, "called open(%s, %i, %i)\n", pathname, flags, mode); - store_random_fd(result); - } - return result; -} - -int openat(int fd, const char *pathname, int flags, ...) { - if (!real_openat) { - real_openat = dlsym(RTLD_NEXT, "openat"); - } - - va_list args; - va_start(args, flags); - int mode = va_arg(args, int); - va_end(args); - - int result = real_openat(fd, pathname, flags, mode); - if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { - fprintf(stderr, "called openat(%s, %i, %i)\n", pathname, flags, mode); - store_random_fd(result); - } - return result; -} - -ssize_t read(int fd, void *buf, size_t count) { - if (!real_read) { - real_read = dlsym(RTLD_NEXT, "read"); - } - - for (int i = 0; i < random_fds_used; ++i) { - int random_fd = random_fds[i]; - if (random_fd == fd) { - fprintf(stderr, "read from random\n"); - uint8_t *buffer = (uint8_t*)buf; - for (size_t c = 0; c < count; ++c) { - buffer[c] = (uint8_t)0x00; - } - return count; - } - } - - return real_read(fd, buf, count); -} - -static FILE **random_files = NULL; -static size_t random_files_used = 0; -static size_t random_files_allocd = 0; - -void check_random_files() { - if (random_files_allocd == 0) { - random_files_allocd = 10; - random_files = calloc(random_files_allocd, sizeof(FILE *)); - } else if (random_files_allocd == random_files_used) { - random_files_allocd *= 2; - random_files = realloc(random_files, random_files_allocd * sizeof(FILE*)); - } -} - -void store_random_file(FILE *file) { - check_random_files(); - random_files[random_files_used++] = file; -} - -FILE *fopen(const char *pathname, const char *mode) { - if (!real_fopen) { - real_fopen = dlsym(RTLD_NEXT, "fopen"); - } - - FILE *result = real_fopen(pathname, mode); - - if (strcmp(pathname, "/dev/random") == 0 || strcmp(pathname, "/dev/urandom") == 0) { - fprintf(stderr, "called fopen(%s, %s)\n", pathname, mode); - store_random_file(result); - } - return result; -} - -size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { - if (!real_fread) { - real_fread = dlsym(RTLD_NEXT, "fread"); - } - - for (int i = 0; i < random_files_used; ++i) { - FILE *random_file = random_files[i]; - if (random_file == stream) { - fprintf(stderr, "fread from random\n"); - uint8_t *buffer = (uint8_t*)ptr; - for (size_t c = 0; c < size * nmemb; ++c) { - buffer[c] = (uint8_t)0x00; - } - return size * nmemb; - } - } - - return real_fread(ptr, size, nmemb, stream); -} - -ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) { - if (!real_getrandom) { - real_getrandom = dlsym(RTLD_NEXT, "getrandom"); - } - - fprintf(stderr, "called getrandom(*, %lu, %u)\n", buflen, flags); - uint8_t *buffer = (uint8_t*)buf; - for (size_t i = 0; i < buflen; ++i) { - buffer[i] = (uint8_t)0x00; - } - return buflen; -} - -int getentropy(void *buffer, size_t length) { - if (!real_getentropy) { - real_getentropy = dlsym(RTLD_NEXT, "getentropy"); - } - - fprintf(stderr, "called getentropy(*, %lu)\n", length); - uint8_t *buf = (uint8_t*)buffer; - for (size_t i = 0; i < length; ++i) { - buf[i] = (uint8_t)0x00; - } - return 0; -} - -long syscall(long number, ...) { - if (!real_syscall) { - real_syscall = dlsym(RTLD_NEXT, "syscall"); - } - va_list args; - - va_start(args, number); - long int a0 = va_arg(args, long int); - long int a1 = va_arg(args, long int); - long int a2 = va_arg(args, long int); - long int a3 = va_arg(args, long int); - long int a4 = va_arg(args, long int); - long int a5 = va_arg(args, long int); - va_end(args); - - if (number == SYS_getrandom) { - fprintf(stderr, "called syscall(getrandom, %li, %li, %li, %li, %li, %li)\n", a0, a1, a2, a3, a4, a5); - uint8_t *buf = (uint8_t*)a0; - long n = a1; - for (size_t i = 0; i < n; ++i) { - buf[i] = (uint8_t)0x00; - } - return n; - } - return real_syscall(number, a0, a1, a2, a3, a4, a5); -} - -uint32_t arc4random(void) { - if (!real_arc4random) { - real_arc4random = dlsym(RTLD_NEXT, "arc4random"); - } - - fprintf(stderr, "called arc4random\n"); - return 0; -} - -uint32_t arc4random_uniform(uint32_t upper_bound) { - if (!real_arc4random_uniform) { - real_arc4random_uniform = dlsym(RTLD_NEXT, "arc4random_uniform"); - } - - fprintf(stderr, "called arc4random_uniform(%u)\n", upper_bound); - return 0; -} - -void arc4random_buf(void *buf, size_t n) { - if (!real_arc4random_buf) { - real_arc4random_buf = dlsym(RTLD_NEXT, "arc4random_buf"); - } - - fprintf(stderr, "called arc4random_buf(%p, %lu)\n", buf, n); - uint8_t *buffer = (uint8_t*)buf; - for (size_t i = 0; i < n; ++i) { - buffer[i] = (uint8_t)0x00; - } -} - - -void __attribute__((destructor)) dealloc() { - if (random_fds != NULL) { - free(random_fds); - } - if (random_files != NULL) { - free(random_files); - } -} diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h new file mode 100644 index 0000000..6371611 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex-common.h @@ -0,0 +1,37 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakDuplexCommon_h_ +#define _KeccakDuplexCommon_h_ + +#include "align.h" + +#define KCP_DeclareDuplexStructure(prefix, size, alignment) \ + ALIGN(alignment) typedef struct prefix##_DuplexInstanceStruct { \ + unsigned char state[size]; \ + unsigned int rate; \ + unsigned int byteInputIndex; \ + unsigned int byteOutputIndex; \ + } prefix##_DuplexInstance; + +#define KCP_DeclareDuplexFunctions(prefix) \ + int prefix##_DuplexInitialize(prefix##_DuplexInstance *duplexInstance, unsigned int rate, unsigned int capacity); \ + int prefix##_Duplexing(prefix##_DuplexInstance *duplexInstance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd); \ + int prefix##_DuplexingFeedPartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \ + int prefix##_DuplexingFeedZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \ + int prefix##_DuplexingOverwritePartialInput(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned int inputByteLen); \ + int prefix##_DuplexingOverwriteWithZeroes(prefix##_DuplexInstance *duplexInstance, unsigned int inputByteLen); \ + int prefix##_DuplexingGetFurtherOutput(prefix##_DuplexInstance *duplexInstance, unsigned char *out, unsigned int outByteLen); \ + int prefix##_DuplexingGetFurtherOutputAndAdd(prefix##_DuplexInstance *duplexInstance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen); + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc new file mode 100644 index 0000000..bd58043 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplex.inc @@ -0,0 +1,192 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#define JOIN0(a, b) a ## b +#define JOIN(a, b) JOIN0(a, b) + +#define DuplexInstance JOIN(prefix, _DuplexInstance) +#define DuplexInitialize JOIN(prefix, _DuplexInitialize) +#define Duplexing JOIN(prefix, _Duplexing) +#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput) +#define DuplexingFeedZeroes JOIN(prefix, _DuplexingFeedZeroes) +#define DuplexingOverwritePartialInput JOIN(prefix, _DuplexingOverwritePartialInput) +#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes) +#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput) +#define DuplexingGetFurtherOutputAndAdd JOIN(prefix, _DuplexingGetFurtherOutputAndAdd) + +#define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes) +#define SnP_stateAlignment JOIN(SnP, _stateAlignment) +#define SnP_StaticInitialize JOIN(SnP, _StaticInitialize) +#define SnP_Initialize JOIN(SnP, _Initialize) +#define SnP_AddByte JOIN(SnP, _AddByte) +#define SnP_AddBytes JOIN(SnP, _AddBytes) +#define SnP_OverwriteBytes JOIN(SnP, _OverwriteBytes) +#define SnP_OverwriteWithZeroes JOIN(SnP, _OverwriteWithZeroes) +#define SnP_ExtractBytes JOIN(SnP, _ExtractBytes) +#define SnP_ExtractAndAddBytes JOIN(SnP, _ExtractAndAddBytes) + +int DuplexInitialize(DuplexInstance *instance, unsigned int rate, unsigned int capacity) +{ + if (rate+capacity != SnP_width) + return 1; + if ((rate <= 2) || (rate > SnP_width)) + return 1; + SnP_StaticInitialize(); + instance->rate = rate; + SnP_Initialize(instance->state); + instance->byteInputIndex = 0; + instance->byteOutputIndex = (instance->rate+7)/8; + return 0; +} + +int Duplexing(DuplexInstance *instance, const unsigned char *sigmaBegin, unsigned int sigmaBeginByteLen, unsigned char *Z, unsigned int ZByteLen, unsigned char delimitedSigmaEnd) +{ + const unsigned int rho_max = instance->rate - 2; + + if (delimitedSigmaEnd == 0) + return 1; + if ((instance->byteInputIndex+sigmaBeginByteLen)*8 > rho_max) + return 1; + if (rho_max - sigmaBeginByteLen*8 < 7) { + unsigned int maxBitsInDelimitedSigmaEnd = rho_max - sigmaBeginByteLen*8; + if (delimitedSigmaEnd >= (1 << (maxBitsInDelimitedSigmaEnd+1))) + return 1; + } + if (ZByteLen > (instance->rate+7)/8) + return 1; /* The output length must not be greater than the rate (rounded up to a byte) */ + + SnP_AddBytes(instance->state, sigmaBegin, instance->byteInputIndex, sigmaBeginByteLen); + #ifdef KeccakReference + { + unsigned char block[SnP_width/8]; + memcpy(block, sigmaBegin, sigmaBeginByteLen); + block[sigmaBeginByteLen] = delimitedSigmaEnd; + memset(block+sigmaBeginByteLen+1, 0, sizeof(block)-sigmaBeginByteLen-1); + block[(instance->rate-1)/8] |= 1 << ((instance->rate-1) % 8); + displayBytes(1, "Block to be absorbed (after padding)", block, (instance->rate+7)/8); + } + #endif + + /* Last few bits, whose delimiter coincides with first bit of padding */ + SnP_AddByte(instance->state, delimitedSigmaEnd, instance->byteInputIndex+sigmaBeginByteLen); + /* Second bit of padding */ + SnP_AddByte(instance->state, (unsigned char)1 << ((instance->rate - 1)%8), (instance->rate - 1)/8); + SnP_Permute(instance->state); + SnP_ExtractBytes(instance->state, Z, 0, ZByteLen); + + if (ZByteLen*8 > instance->rate) { + unsigned char mask = (unsigned char)(1 << (instance->rate % 8)) - 1; + Z[ZByteLen-1] &= mask; + } + + instance->byteInputIndex = 0; + instance->byteOutputIndex = ZByteLen; + + return 0; +} + +int DuplexingFeedPartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen) +{ + const unsigned int rho_max = instance->rate - 2; + + if ((instance->byteInputIndex+inputByteLen)*8 > rho_max) + return 1; + + SnP_AddBytes(instance->state, input, instance->byteInputIndex, inputByteLen); + instance->byteInputIndex += inputByteLen; + return 0; +} + +int DuplexingFeedZeroes(DuplexInstance *instance, unsigned int inputByteLen) +{ + const unsigned int rho_max = instance->rate - 2; + + if ((instance->byteInputIndex+inputByteLen)*8 > rho_max) + return 1; + + instance->byteInputIndex += inputByteLen; + return 0; +} + +int DuplexingOverwritePartialInput(DuplexInstance *instance, const unsigned char *input, unsigned int inputByteLen) +{ + const unsigned int rho_max = instance->rate - 2; + + if ((instance->byteInputIndex+inputByteLen)*8 > rho_max) + return 1; + + SnP_OverwriteBytes(instance->state, input, instance->byteInputIndex, inputByteLen); + instance->byteInputIndex += inputByteLen; + return 0; +} + +int DuplexingOverwriteWithZeroes(DuplexInstance *instance, unsigned int inputByteLen) +{ + const unsigned int rho_max = instance->rate - 2; + + if ((instance->byteInputIndex != 0) || (inputByteLen*8 > rho_max)) + return 1; + + SnP_OverwriteWithZeroes(instance->state, inputByteLen); + instance->byteInputIndex = inputByteLen; + + return 0; +} + +int DuplexingGetFurtherOutput(DuplexInstance *instance, unsigned char *output, unsigned int outputByteLen) +{ + if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8) + return 1; /* The output length must not be greater than the rate (rounded up to a byte) */ + + SnP_ExtractBytes(instance->state, output, instance->byteOutputIndex, outputByteLen); + instance->byteOutputIndex += outputByteLen; + if (instance->byteOutputIndex*8 > instance->rate) { + unsigned char mask = (1 << (instance->rate % 8)) - 1; + output[outputByteLen-1] &= mask; + } + return 0; +} + +int DuplexingGetFurtherOutputAndAdd(DuplexInstance *instance, const unsigned char *input, unsigned char *output, unsigned int outputByteLen) +{ + if ((outputByteLen+instance->byteOutputIndex) > (instance->rate+7)/8) + return 1; /* The output length must not be greater than the rate (rounded up to a byte) */ + + SnP_ExtractAndAddBytes(instance->state, input, output, instance->byteOutputIndex, outputByteLen); + instance->byteOutputIndex += outputByteLen; + if (instance->byteOutputIndex*8 > instance->rate) { + unsigned char mask = (1 << (instance->rate % 8)) - 1; + output[outputByteLen-1] &= mask; + } + return 0; +} + +#undef DuplexInstance +#undef DuplexInitialize +#undef Duplexing +#undef DuplexingFeedPartialInput +#undef DuplexingFeedZeroes +#undef DuplexingOverwritePartialInput +#undef DuplexingOverwriteWithZeroes +#undef DuplexingGetFurtherOutput +#undef DuplexingGetFurtherOutputAndAdd +#undef SnP_stateSizeInBytes +#undef SnP_stateAlignment +#undef SnP_StaticInitialize +#undef SnP_Initialize +#undef SnP_AddByte +#undef SnP_AddBytes +#undef SnP_OverwriteBytes +#undef SnP_OverwriteWithZeroes +#undef SnP_ExtractBytes +#undef SnP_ExtractAndAddBytes diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c new file mode 100644 index 0000000..d6f56d2 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.c @@ -0,0 +1,29 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "KeccakDuplexWidth200.h" + +#ifndef KeccakP200_excluded + #include "KeccakP-200-SnP.h" + + #define prefix KeccakWidth200 + #define SnP KeccakP200 + #define SnP_width 200 + #define SnP_Permute KeccakP200_Permute_18rounds + #include "KeccakDuplex.inc" + #undef prefix + #undef SnP + #undef SnP_width + #undef SnP_Permute + #undef SnP_FastLoop_Absorb +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h new file mode 100644 index 0000000..8bb76f4 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakDuplexWidth200.h @@ -0,0 +1,25 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakDuplexWidth200_h_ +#define _KeccakDuplexWidth200_h_ + +#include "KeccakDuplex-common.h" + +#ifndef KeccakP200_excluded + #include "KeccakP-200-SnP.h" + KCP_DeclareDuplexStructure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment) + KCP_DeclareDuplexFunctions(KeccakWidth200) +#endif + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h new file mode 100644 index 0000000..4acf932 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-SnP.h @@ -0,0 +1,34 @@ +/* +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ + +--- + +Please refer to SnP-documentation.h for more details. +*/ + +#ifndef _KeccakP_200_SnP_h_ +#define _KeccakP_200_SnP_h_ + +#define KeccakP200_implementation "8-bit compact implementation" +#define KeccakP200_stateSizeInBytes 25 +#define KeccakP200_stateAlignment 1 + +#define KeccakP200_StaticInitialize() +void KeccakP200_Initialize(void *state); +void KeccakP200_AddByte(void *state, unsigned char data, unsigned int offset); +void KeccakP200_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount); +void KeccakP200_Permute_Nrounds(void *state, unsigned int nrounds); +void KeccakP200_Permute_18rounds(void *state); +void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length); +void KeccakP200_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c new file mode 100644 index 0000000..f07bae9 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakP-200-compact.c @@ -0,0 +1,187 @@ +/* +Implementation by Ronny Van Keer, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ + +--- + +This file implements Keccak-p[200] in a SnP-compatible way. +Please refer to SnP-documentation.h for more details. + +This implementation comes with KeccakP-200-SnP.h in the same folder. +Please refer to LowLevel.build for the exact list of other files it must be combined with. +*/ + +#include +#include +#include "KeccakP-200-SnP.h" + +// #define DIVISION_INSTRUCTION /* comment if no division instruction or more compact when not using division */ +#define UNROLL_CHILOOP /* comment if more compact using for loop */ + +typedef unsigned char UINT8; +typedef unsigned int tSmallUInt; /*INFO It could be more optimized to use "unsigned char" on an 8-bit CPU */ +typedef UINT8 tKeccakLane; + +#define ROL8(a, offset) (UINT8)((((UINT8)a) << (offset&7)) ^ (((UINT8)a) >> (8-(offset&7)))) + +const UINT8 KeccakP200_RotationConstants[25] = +{ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +}; + +const UINT8 KeccakP200_PiLane[25] = +{ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +}; + +#if defined(DIVISION_INSTRUCTION) +#define MOD5(argValue) ((argValue) % 5) +#else +const UINT8 KeccakP200_Mod5[10] = +{ + 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 +}; +#define MOD5(argValue) KeccakP200_Mod5[argValue] +#endif + +const UINT8 KeccakF200_RoundConstants[] = +{ + 0x01, 0x82, 0x8a, 0x00, 0x8b, 0x01, 0x81, 0x09, 0x8a, 0x88, 0x09, 0x0a, 0x8b, 0x8b, 0x89, 0x03, 0x02, 0x80 +}; + +/* ---------------------------------------------------------------- */ + +void KeccakP200_Initialize(void *argState) +{ + memset( argState, 0, 25 * sizeof(tKeccakLane) ); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_AddByte(void *argState, unsigned char byte, unsigned int offset) +{ + ((tKeccakLane*)argState)[offset] ^= byte; +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_AddBytes(void *argState, const unsigned char *data, unsigned int offset, unsigned int length) +{ + tSmallUInt i; + tKeccakLane * state = (tKeccakLane*)argState + offset; + for(i=0; ibyteInputIndex +#define DuplexGetOutputIndex(duplex) (duplex)->byteOutputIndex +#define DuplexSetOutputIndex(duplex, i) (duplex)->byteOutputIndex = (i) + +int SpongePRG_Initialize(SpongePRG_Instance *instance, unsigned int capacity) +{ + unsigned int rate; + unsigned int rhoInBytes; + + if (capacity > (SnP_width-10)) + return 1; + + rate = SnP_width - capacity; + rhoInBytes = (rate-2)/8; + + if ( (rhoInBytes == 0) || (rhoInBytes >= SnP_width/8) ) + return 1; + return DuplexInitialize(&instance->duplex, rate, capacity); +} + +int SpongePRG_Feed(SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen) +{ + unsigned int rhoInBytes = (instance->duplex.rate-2)/8; + int error = 0; + + while( !error && ((DuplexGetInputIndex(&instance->duplex) + inputByteLen) >= rhoInBytes)) { + unsigned int localSize = rhoInBytes - DuplexGetInputIndex(&instance->duplex); + error |= DuplexingFeedPartialInput(&instance->duplex, input, localSize); + error |= Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01); + input += localSize; + inputByteLen -= localSize; + } + if (!error) + error = DuplexingFeedPartialInput(&instance->duplex, input, inputByteLen); + DuplexSetOutputIndex(&instance->duplex, rhoInBytes); + return error; +} + +int SpongePRG_Fetch(SpongePRG_Instance *instance, unsigned char *output, unsigned int outputByteLen) +{ + unsigned int rhoInBytes = (instance->duplex.rate-2)/8; + int error = 0; + + if (DuplexGetOutputIndex(&instance->duplex) < rhoInBytes) { + unsigned int localSize = rhoInBytes - DuplexGetOutputIndex(&instance->duplex); + localSize = (localSize <= outputByteLen) ? localSize : outputByteLen; + error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize); + output += localSize; + outputByteLen -= localSize; + } + + while( !error && (outputByteLen > 0) ) { + error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01); + if (!error) { + unsigned int localSize = (rhoInBytes <= outputByteLen) ? rhoInBytes : outputByteLen; + error = DuplexingGetFurtherOutput(&instance->duplex, output, localSize); + output += localSize; + outputByteLen -= localSize; + } + } + return error; +} + +int SpongePRG_Forget(SpongePRG_Instance *instance) +{ + unsigned int rhoInBytes = (instance->duplex.rate-2)/8; + unsigned int capacity = SnP_width - instance->duplex.rate; + int error; + + if ((rhoInBytes*8) < capacity) + return 1; + + error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01); + if ( !error ) { + error = DuplexingOverwriteWithZeroes(&instance->duplex, rhoInBytes); + if ( !error ) + error = Duplexing(&instance->duplex, 0, 0, 0, 0, 0x01); + } + DuplexSetOutputIndex(&instance->duplex, rhoInBytes); + return error; +} + +#undef SpongePRG_Instance +#undef SpongePRG_Initialize +#undef SpongePRG_Feed +#undef SpongePRG_Fetch +#undef SpongePRG_Forget + +#undef DuplexInstance +#undef DuplexInitialize +#undef Duplexing +#undef DuplexingFeedPartialInput +#undef DuplexingOverwriteWithZeroes +#undef DuplexingGetFurtherOutput +#undef DuplexGetInputIndex +#undef DuplexGetOutputIndex +#undef DuplexSetOutputIndex diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c new file mode 100644 index 0000000..067375e --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.c @@ -0,0 +1,22 @@ +/* +Implementation by Gilles Van Assche, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include "KeccakPRGWidth200.h" + +#ifndef KeccakP200_excluded + #include "KeccakP-200-SnP.h" + + #define prefix KeccakWidth200 + #define SnP_width 200 + #include "KeccakPRG.inc" + #undef prefix + #undef SnP_width +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h new file mode 100644 index 0000000..d7cfcc9 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRGWidth200.h @@ -0,0 +1,24 @@ +/* +Implementation by Gilles Van Assche, hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakPRGWidth200_h_ +#define _KeccakPRGWidth200_h_ + +#include "KeccakDuplexWidth200.h" +#include "KeccakPRG-common.h" + +#ifndef KeccakP200_excluded + #include "KeccakP-200-SnP.h" + KCP_DeclareSpongePRG_Structure(KeccakWidth200, KeccakP200_stateSizeInBytes, KeccakP200_stateAlignment) + KCP_DeclareSpongePRG_Functions(KeccakWidth200) +#endif + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h new file mode 100644 index 0000000..90c1b37 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/align.h @@ -0,0 +1,32 @@ +/* +Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, +Michaël Peeters, Gilles Van Assche and Ronny Van Keer, +hereby denoted as "the implementer". + +For more information, feedback or questions, please refer to our website: +https://keccak.team/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _align_h_ +#define _align_h_ + +/* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */ +#ifdef ALIGN +#undef ALIGN +#endif + +#if defined(__GNUC__) +#define ALIGN(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) +#define ALIGN(x) __declspec(align(x)) +#elif defined(__ARMCC_VERSION) +#define ALIGN(x) __align(x) +#else +#define ALIGN(x) +#endif + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c new file mode 100644 index 0000000..c44db6f --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.c @@ -0,0 +1,21 @@ +#include "KeccakPRG.h" +#include "KeccakP-200-compact.c" +#include "KeccakDuplexWidth200.c" +#include "KeccakPRGWidth200.c" +#include "prng.h" +#include + + +void prng_init(prng_state *state) { + memset(state, 0, sizeof(state)); + KeccakWidth200_SpongePRG_Initialize(state, 70); +} + +void prng_seed(prng_state *state, const uint8_t *seed, size_t size) { + KeccakWidth200_SpongePRG_Feed(state, seed, size); + KeccakWidth200_SpongePRG_Forget(state); +} + +void prng_get(prng_state *state, uint8_t *out, size_t size) { + KeccakWidth200_SpongePRG_Fetch(state, out, size); +} \ No newline at end of file diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h new file mode 100644 index 0000000..2cc4f21 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/prng.h @@ -0,0 +1,13 @@ +#include "KeccakPRG.h" +#include + +typedef KeccakWidth200_SpongePRG_Instance prng_state; + +void prng_init(prng_state *state); + +void prng_seed(prng_state *state, const uint8_t *seed, size_t size); + +void prng_get(prng_state *state, uint8_t *out, size_t size); + + + diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java index bebb3c5..e5caae8 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java @@ -14,7 +14,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class DeterministicTests { static Stream libs() { - return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt"); + return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt", "LibreSSL"); + // BoringSSL and libgcrypt cannot be easily tested here, because they initialize their RNG only once per process. } @SuppressWarnings("JUnitMalformedDeclaration") @@ -110,6 +111,7 @@ public class DeterministicTests { case "Crypto++": args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "ECDSA", libName}; break; + case "LibreSSL": case "mbedTLS": args = new String[]{"ecdsa", "-ps", "12345678", "-d", "1234", "-n", "10", "-nc", "secg/secp256r1", "-t", "NONEwithECDSA", libName}; break; -- cgit v1.2.3-70-g09d2 From c6b752a7a8980372ff6a5f49660f94d9495e5f33 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 9 Aug 2024 17:19:57 +0200 Subject: Do not test deterministic LibreSSL in CI. --- .../src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'standalone/src/test/java/cz') diff --git a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java index e5caae8..5c7a21f 100644 --- a/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java +++ b/standalone/src/test/java/cz/crcs/ectester/standalone/DeterministicTests.java @@ -14,8 +14,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class DeterministicTests { static Stream libs() { - return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt", "LibreSSL"); + return Stream.of("Botan", "BouncyCastle", "Crypto++", "IPPCP", "mbedTLS", "Nettle", "OpenSSL", "SunEC", "tomcrypt"); // BoringSSL and libgcrypt cannot be easily tested here, because they initialize their RNG only once per process. + // LibreSSL hangs in CI. } @SuppressWarnings("JUnitMalformedDeclaration") -- cgit v1.2.3-70-g09d2