From 46b290eb6d24cd0d337d54421c8e10c9acbd6a6f Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Aug 2024 15:43:22 +0200 Subject: Add support for deterministic PRNG to OpenSSL. --- .../ectester/standalone/ECTesterStandalone.java | 42 +++++++++++++++++++++- .../crcs/ectester/standalone/libs/OpensslLib.java | 6 ++++ .../standalone/libs/ProviderECLibrary.java | 15 +++++--- 3 files changed, 58 insertions(+), 5 deletions(-) (limited to 'standalone/src/main/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 4f76639..7967bcb 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -191,7 +191,8 @@ public class ECTesterStandalone { Option output = Option.builder("o").longOpt("output").desc("Output into file . The file can be prefixed by the format (one of text,yml,xml), such as: xml:.").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build(); 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, perfcount}").hasArgs().argName("source").optionalArg(false).numberOfArgs(1).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(); Options testOpts = new Options(); testOpts.addOption(bits); @@ -199,6 +200,7 @@ public class ECTesterStandalone { testOpts.addOption(curveName); testOpts.addOption(output); testOpts.addOption(quiet); + testOpts.addOption(prngSeed); testOpts.addOption(Option.builder("gt").longOpt("kpg-type").desc("Set the KeyPairGenerator object [type].").hasArg().argName("type").optionalArg(false).build()); testOpts.addOption(Option.builder("kt").longOpt("ka-type").desc("Set the KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build()); testOpts.addOption(Option.builder("st").longOpt("sig-type").desc("Set the Signature object [type].").hasArg().argName("type").optionalArg(false).build()); @@ -215,6 +217,7 @@ public class ECTesterStandalone { ecdhOpts.addOption(curveName); ecdhOpts.addOption(outputRaw); ecdhOpts.addOption(timeSource); + ecdhOpts.addOption(prngSeed); ecdhOpts.addOption(Option.builder("t").longOpt("type").desc("Set KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build()); ecdhOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build()); ecdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDH [amount] times.").build()); @@ -231,6 +234,7 @@ public class ECTesterStandalone { ecdsaOpts.addOption(curveName); ecdsaOpts.addOption(outputRaw); ecdsaOpts.addOption(timeSource); + ecdsaOpts.addOption(prngSeed); ecdsaOpts.addOptionGroup(privateKey); ecdsaOpts.addOptionGroup(publicKey); ecdsaOpts.addOption(Option.builder().longOpt("fixed").desc("Perform all ECDSA with fixed keypair.").build()); @@ -246,6 +250,7 @@ public class ECTesterStandalone { generateOpts.addOption(curveName); generateOpts.addOption(outputRaw); generateOpts.addOption(timeSource); + generateOpts.addOption(prngSeed); generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build()); generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build()); ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs."); @@ -307,6 +312,7 @@ public class ECTesterStandalone { System.out.println(Colors.bold("\t\t- Fullname: ") + lib.getProvider().getName()); System.out.println(Colors.bold("\t\t- Version: ") + lib.getProvider().getVersionStr()); System.out.println(Colors.bold("\t\t- Supports native timing: ") + lib.getNativeTimingSupport().toString()); + System.out.println(Colors.bold("\t\t- Supports deterministic PRNG: ") + lib.supportsDeterministicPRNG()); Set kpgs = lib.getKPGs(); if (!kpgs.isEmpty()) { System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + kpgs.stream().map(KeyPairGeneratorIdent::getName).sorted().collect(Collectors.joining(", "))); @@ -430,6 +436,12 @@ public class ECTesterStandalone { kpg.initialize(spec); } + if (cli.hasOption("ecdh.prng-seed")) { + String seedString = cli.getOptionValue("ecdh.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + lib.setupDeterministicPRNG(seed); + } + if (cli.hasOption("ecdh.time-source")) { if (!lib.setNativeTimingType(cli.getOptionValue("ecdh.time-source"))) { System.err.println("Couldn't set native time source."); @@ -586,6 +598,12 @@ public class ECTesterStandalone { kpg.initialize(new ECGenParameterSpec(curveName)); } + if (cli.hasOption("ecdsa.prng-seed")) { + String seedString = cli.getOptionValue("ecdsa.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + lib.setupDeterministicPRNG(seed); + } + if (cli.hasOption("ecdsa.time-source")) { if (!lib.setNativeTimingType(cli.getOptionValue("ecdsa.time-source"))) { System.err.println("Couldn't set native time source."); @@ -722,6 +740,12 @@ public class ECTesterStandalone { kpg.initialize(new ECGenParameterSpec(curveName)); } + if (cli.hasOption("generate.prng-seed")) { + String seedString = cli.getOptionValue("generate.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + lib.setupDeterministicPRNG(seed); + } + if (cli.hasOption("generate.time-source")) { if (!lib.setNativeTimingType(cli.getOptionValue("generate.time-source"))) { System.err.println("Couldn't set native time source."); @@ -818,6 +842,13 @@ public class ECTesterStandalone { testTo = -1; } + ProviderECLibrary lib = cfg.selected; + if (cli.hasOption("test.prng-seed")) { + String seedString = cli.getOptionValue("test.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + lib.setupDeterministicPRNG(seed); + } + switch (testSuite) { case "test-vectors": suite = new StandaloneTestVectorSuite(writer, cfg, cli); @@ -997,6 +1028,15 @@ public class ECTesterStandalone { } } + if (cli.isNext("generate") || cli.isNext("ecdh") || cli.isNext("ecdsa") || cli.isNext("test")) { + if (cli.hasOption(next + ".prng-seed")) { + if (!selected.supportsDeterministicPRNG()) { + System.err.printf("Deterministic PRNG is not supported by library %s.%n", selected.name()); + return false; + } + } + } + return true; } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java index 61f00a4..13490f9 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java @@ -16,4 +16,10 @@ public class OpensslLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public native boolean supportsDeterministicPRNG(); + + @Override + public native void setupDeterministicPRNG(byte[] seed); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java index d9d6749..936120f 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java @@ -69,21 +69,28 @@ public abstract class ProviderECLibrary implements ECLibrary { } public boolean setNativeTimingType(String type) { - return false; + return false; } public long getNativeTimingResolution() { return 0; } - public String getNativeTimingUnit() { - return null; - } + public String getNativeTimingUnit() { + return null; + } public long getLastNativeTiming() { return 0; } + public boolean supportsDeterministicPRNG() { + return false; + } + + public void setupDeterministicPRNG(byte[] seed) { + } + @Override public Set getKAs() { return getIdents("KeyAgreement", KeyAgreementIdent::get); -- cgit v1.2.3-70-g09d2 From a3af2abefa537d570c4018729465abf32444fe15 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Aug 2024 16:13:11 +0200 Subject: Add deterministic PRNG support to tomcrypt. --- .../crcs/ectester/standalone/libs/TomcryptLib.java | 6 + .../cz/crcs/ectester/standalone/libs/jni/native.h | 158 ++------------------- .../cz/crcs/ectester/standalone/libs/jni/openssl.c | 1 - .../crcs/ectester/standalone/libs/jni/tomcrypt.c | 15 ++ 4 files changed, 31 insertions(+), 149 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java index 8c000a2..1897617 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java @@ -17,4 +17,10 @@ public class TomcryptLib extends NativeECLibrary { @Override public native Set getCurves(); + + @Override + public native boolean supportsDeterministicPRNG(); + + @Override + public native void setupDeterministicPRNG(byte[] seed); } 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 89f4b63..68e96c8 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 @@ -74,159 +74,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves (JNIEnv *, jobject); -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392LL -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840LL -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739LL -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt_DEFAULT_KEYSIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt_DEFAULT_KEYSIZE 256L -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2 - (JNIEnv *, jobject, jint, jobject); - /* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2 - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;Ljava/lang/String;)Ljavax/crypto/SecretKey; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2 - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jstring); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: supportsDeterministicPRNG + * Signature: ()Z */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG + (JNIEnv *, jobject); /* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: setupDeterministicPRNG + * Signature: ([B)V */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus } diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c index d791646..0b07821 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c @@ -114,7 +114,6 @@ RAND_METHOD stdlib_rand_meth = { stdlib_rand_seed, }; JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { - printf("Enabling rand method.\n"); RAND_set_rand_method(&stdlib_rand_meth); jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); jsize seed_length = (*env)->GetArrayLength(env, seed); diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c index ec107b8..6e9dfbf 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c @@ -76,6 +76,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getC return result; } + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + yarrow_start(<c_prng); + jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); + jsize seed_length = (*env)->GetArrayLength(env, seed); + yarrow_add_entropy(seed_data, seed_length, <c_prng); + yarrow_ready(<c_prng); + (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); +} + + JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize){ int key_bytes = (keysize + 7) / 8; const ltc_ecc_set_type * curve = ltc_ecc_sets; -- cgit v1.2.3-70-g09d2 From abb89ea702d046e27ea457df31a7d69bab3b0802 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 5 Aug 2024 17:50:11 +0200 Subject: Add deterministic PRNG to Botan. --- .../ectester/standalone/ECTesterStandalone.java | 20 +++++++-- .../cz/crcs/ectester/standalone/libs/BotanLib.java | 6 +++ .../crcs/ectester/standalone/libs/OpensslLib.java | 2 +- .../standalone/libs/ProviderECLibrary.java | 3 +- .../crcs/ectester/standalone/libs/TomcryptLib.java | 2 +- .../cz/crcs/ectester/standalone/libs/jni/Makefile | 4 +- .../cz/crcs/ectester/standalone/libs/jni/botan.cpp | 47 ++++++++++++++++------ .../cz/crcs/ectester/standalone/libs/jni/native.h | 24 +++++++++-- .../cz/crcs/ectester/standalone/libs/jni/openssl.c | 3 +- .../crcs/ectester/standalone/libs/jni/tomcrypt.c | 3 +- 10 files changed, 86 insertions(+), 28 deletions(-) (limited to 'standalone/src/main/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 7967bcb..3194796 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -439,7 +439,10 @@ public class ECTesterStandalone { if (cli.hasOption("ecdh.prng-seed")) { String seedString = cli.getOptionValue("ecdh.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - lib.setupDeterministicPRNG(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } } if (cli.hasOption("ecdh.time-source")) { @@ -601,7 +604,10 @@ public class ECTesterStandalone { if (cli.hasOption("ecdsa.prng-seed")) { String seedString = cli.getOptionValue("ecdsa.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - lib.setupDeterministicPRNG(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } } if (cli.hasOption("ecdsa.time-source")) { @@ -743,7 +749,10 @@ public class ECTesterStandalone { if (cli.hasOption("generate.prng-seed")) { String seedString = cli.getOptionValue("generate.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - lib.setupDeterministicPRNG(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } } if (cli.hasOption("generate.time-source")) { @@ -846,7 +855,10 @@ public class ECTesterStandalone { if (cli.hasOption("test.prng-seed")) { String seedString = cli.getOptionValue("test.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - lib.setupDeterministicPRNG(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } } switch (testSuite) { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java index e8f6e13..c072e84 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BotanLib.java @@ -17,4 +17,10 @@ public class BotanLib 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/java/cz/crcs/ectester/standalone/libs/OpensslLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java index 13490f9..69c84bc 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/OpensslLib.java @@ -21,5 +21,5 @@ public class OpensslLib extends NativeECLibrary { public native boolean supportsDeterministicPRNG(); @Override - public native void setupDeterministicPRNG(byte[] seed); + public native boolean setupDeterministicPRNG(byte[] seed); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java index 936120f..a9178f6 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java @@ -88,7 +88,8 @@ public abstract class ProviderECLibrary implements ECLibrary { return false; } - public void setupDeterministicPRNG(byte[] seed) { + public boolean setupDeterministicPRNG(byte[] seed) { + return false; } @Override diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java index 1897617..e499451 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/TomcryptLib.java @@ -22,5 +22,5 @@ public class TomcryptLib extends NativeECLibrary { public native boolean supportsDeterministicPRNG(); @Override - public native void setupDeterministicPRNG(byte[] seed); + public native boolean setupDeterministicPRNG(byte[] seed); } 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 6282574..aec0c03 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 @@ -12,9 +12,9 @@ DEBUG ?= 0 PROJECT_ROOT_PATH ?= ../../../../../../../../../.. ifeq ($(DEBUG), 1) - CFLAGS+=-g -Wall + CFLAGS+=-g -O0 -Wall LFLAGS+=-g - CXXFLAGS+=-g -Wall + CXXFLAGS+=-g -O0 -Wall else CFLAGS+=-O2 LFLAGS+=-O2 diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp index 52c8dbb..b3977e1 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include #include @@ -23,7 +25,7 @@ */ static jclass provider_class; -static Botan::AutoSeeded_RNG rng; +std::unique_ptr rng = std::make_unique(); JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) { /* Create the custom provider. */ @@ -82,7 +84,7 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ init_classes(env, "Botan"); } -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self) { jclass set_class = env->FindClass("java/util/TreeSet"); jmethodID set_ctr = env->GetMethodID(set_class, "", "()V"); @@ -99,6 +101,25 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv return result; } +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + jsize seed_length = env->GetArrayLength(seed); + if (seed_length < 32) { + fprintf(stderr, "Error setting seed, needs to be at least 32 bytes.\n"); + return JNI_FALSE; + } + jbyte *seed_data = env->GetByteArrayElements(seed, nullptr); + Botan::secure_vector vec((uint8_t *)seed_data, (uint8_t *)seed_data + seed_length); + Botan::ChaCha_RNG *cha = new Botan::ChaCha_RNG(vec); + rng.reset(cha); + env->ReleaseByteArrayElements(seed, seed_data, JNI_ABORT); + return JNI_TRUE; +} + + JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){ return JNI_TRUE; } @@ -252,13 +273,13 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr try { native_timing_start(); if (type_str == "ECDH") { - skey = std::make_unique(rng, group); + skey = std::make_unique(*rng, group); } else if (type_str == "ECDSA") { - skey = std::make_unique(rng, group); + skey = std::make_unique(*rng, group); } else if (type_str == "ECKCDSA") { - skey = std::make_unique(rng, group); + skey = std::make_unique(*rng, group); } else if (type_str == "ECGDSA") { - skey = std::make_unique(rng, group); + skey = std::make_unique(*rng, group); } native_timing_stop(); } catch (Botan::Exception & ex) { @@ -375,7 +396,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr Botan::BigInt privkey_scalar((unsigned char *) privkey_data, privkey_length); env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT); - Botan::ECDH_PrivateKey skey(rng, curve_group, privkey_scalar); + Botan::ECDH_PrivateKey skey(*rng, curve_group, privkey_scalar); jsize pubkey_length = env->GetArrayLength(pubkey); jbyte *pubkey_data = env->GetByteArrayElements(pubkey, nullptr); @@ -402,7 +423,7 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr size_t key_len = (get_kdf_bits(env, algorithm) + 7) / 8; std::string kdf = get_kdf(type_str, &key_len); - Botan::PK_Key_Agreement ka(skey, rng, kdf); + Botan::PK_Key_Agreement ka(skey, *rng, kdf); std::vector derived; try { @@ -469,11 +490,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig std::unique_ptr skey; try { if (type_str.find("ECDSA") != std::string::npos) { - skey = std::make_unique(rng, curve_group, privkey_scalar); + skey = std::make_unique(*rng, curve_group, privkey_scalar); } else if (type_str.find("ECKCDSA") != std::string::npos) { - skey = std::make_unique(rng, curve_group, privkey_scalar); + skey = std::make_unique(*rng, curve_group, privkey_scalar); } else if (type_str.find("ECGDSA") != std::string::npos) { - skey = std::make_unique(rng, curve_group, privkey_scalar); + skey = std::make_unique(*rng, curve_group, privkey_scalar); } } catch (Botan::Exception & ex) { throw_new(env, "java/security/GeneralSecurityException", ex.what()); @@ -504,10 +525,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jbyte *data_bytes = env->GetByteArrayElements(data, nullptr); std::vector sig; try { - Botan::PK_Signer signer(*skey, rng, emsa, sigformat); + Botan::PK_Signer signer(*skey, *rng, emsa, sigformat); native_timing_start(); - sig = signer.sign_message((uint8_t*) data_bytes, data_length, rng); + sig = signer.sign_message((uint8_t*) data_bytes, data_length, *rng); native_timing_stop(); } catch (Botan::Exception & ex) { throw_new(env, "java/security/GeneralSecurityException", ex.what()); 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 b1296cc..49be801 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 @@ -85,9 +85,9 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_sup /* * Class: cz_crcs_ectester_standalone_libs_TomcryptLib * Method: setupDeterministicPRNG - * Signature: ([B)V + * Signature: ([B)Z */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG (JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus @@ -271,6 +271,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_BotanLib + * Method: supportsDeterministicPRNG + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsDeterministicPRNG + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_BotanLib + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif @@ -644,9 +660,9 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supp /* * Class: cz_crcs_ectester_standalone_libs_OpensslLib * Method: setupDeterministicPRNG - * Signature: ([B)V + * Signature: ([B)Z */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG (JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c index 0b07821..5110c8b 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/openssl.c @@ -113,12 +113,13 @@ RAND_METHOD stdlib_rand_meth = { stdlib_rand_seed, stdlib_rand_status }; -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { RAND_set_rand_method(&stdlib_rand_meth); jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); jsize seed_length = (*env)->GetArrayLength(env, seed); RAND_seed(seed_data, seed_length); (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + return JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c index 6e9dfbf..12c1936 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c @@ -81,13 +81,14 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_sup return JNI_TRUE; } -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { yarrow_start(<c_prng); jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); jsize seed_length = (*env)->GetArrayLength(env, seed); yarrow_add_entropy(seed_data, seed_length, <c_prng); yarrow_ready(<c_prng); (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + return JNI_TRUE; } -- cgit v1.2.3-70-g09d2 From 231e33a8bfd352574ef999c4e91f28c5e8551bdf Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 6 Aug 2024 19:58:50 +0200 Subject: Simplify KeyAgreementTestable. --- .../standalone/test/base/KeyAgreementTestable.java | 176 +++++++++++---------- .../test/suites/StandaloneCofactorSuite.java | 2 +- .../test/suites/StandaloneCompositeSuite.java | 4 +- .../test/suites/StandaloneDefaultSuite.java | 4 +- .../test/suites/StandaloneEdgeCasesSuite.java | 6 +- .../test/suites/StandaloneForeignSuite.java | 2 +- .../test/suites/StandaloneMiscSuite.java | 2 +- .../test/suites/StandalonePerformanceSuite.java | 4 +- .../test/suites/StandaloneTestVectorSuite.java | 2 +- .../test/suites/StandaloneWrongSuite.java | 4 +- 10 files changed, 107 insertions(+), 99 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java index 579904c..308ade7 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyAgreementTestable.java @@ -5,6 +5,7 @@ import javax.crypto.SecretKey; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.AlgorithmParameterSpec; @@ -21,90 +22,20 @@ public class KeyAgreementTestable extends StandaloneTestable() { @Override public Result apply(KeyAgreementTestable testable) { @@ -247,7 +247,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { private Test ecdhTest(KeyGeneratorTestable kgt, BigInteger SParam, ECParameterSpec spec, String desc, Result.ExpectedValue expect) throws NoSuchAlgorithmException { ECPrivateKey priv = new RawECPrivateKey(SParam, spec); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, priv); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(priv).publicKgt(kgt).build(); return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, KeyAgreementTest.expectError(testable, expect)); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java index 21431ae..2139233 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java @@ -156,7 +156,7 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite { for (EC_Key.Public pub : keys) { ECPublicKey ecpub = ECUtil.toPublicKey(pub); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, ecpub, theKgt); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(theKgt).build(); Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", keyAgreement)); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java index 657c2ff..801b2ca 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java @@ -88,7 +88,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite { for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).build(); kaTests.add(KeyAgreementTest.expectError(testable, expected)); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java index 30a0c0f..8127e6d 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java @@ -94,9 +94,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); KeyAgreementTestable testable; if (kaIdent.requiresKeyAlgo()) { - testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec, keyAlgo); + testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).keyAlgo(keyAlgo).build(); } else { - testable = new KeyAgreementTestable(ka, kgtOne, kgtOther, spec); + testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).build(); } kaTests.add(PerformanceTest.repeat(testable, cfg.selected, kaIdent.getName(), count)); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java index 111d354..7faae99 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java @@ -56,7 +56,7 @@ public class StandaloneTestVectorSuite extends StandaloneTestSuite { KeyAgreementIdent kaIdent = KeyAgreementIdent.get("ECDH"); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, privkey, pubkey); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(privkey).publicKey(pubkey).build(); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test vector " + result.getId(), KeyAgreementTest.match(testable, result.getData(0)))); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java index 4634ab0..1990f22 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java @@ -77,7 +77,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).build(); Test ecdh = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); doTest(CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, "Wrong curve test of " + curve.getBits() + "b " + type + ". " + curve.getDesc(), generate, ecdh)); @@ -238,7 +238,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { //perform ECDH KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = new KeyAgreementTestable(ka, kgt, kgt); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).build(); Test ecdh = KeyAgreementTest.expect(testable, Result.ExpectedValue.FAILURE); return CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, desc, generate, ecdh); } -- cgit v1.2.3-70-g09d2 From 9b1b1a6f6da1e4c8429ba1632103d276f3cbdaad Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 6 Aug 2024 20:25:35 +0200 Subject: Cleanup KeyGeneratorTestable. --- .../standalone/test/base/KeyGeneratorTestable.java | 68 +++++++++++++++++++++- .../test/suites/StandaloneDefaultSuite.java | 12 ++-- .../test/suites/StandaloneEdgeCasesSuite.java | 4 +- .../test/suites/StandaloneForeignSuite.java | 6 +- .../test/suites/StandaloneMiscSuite.java | 2 +- .../test/suites/StandalonePerformanceSuite.java | 12 ++-- .../test/suites/StandaloneWrongSuite.java | 4 +- 7 files changed, 86 insertions(+), 22 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java index bc44eb8..8865576 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/base/KeyGeneratorTestable.java @@ -3,6 +3,7 @@ package cz.crcs.ectester.standalone.test.base; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; @@ -15,11 +16,23 @@ public class KeyGeneratorTestable extends StandaloneTestable() { @Override public Result apply(KeyAgreementTestable testable) { @@ -134,7 +134,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { ECParameterSpec spec = curve.toSpec(); //generate KeyPair - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); //perform ECDH tests @@ -213,7 +213,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { Arrays.sort(zeros); //generate KeyPair - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); //perform ECDH tests @@ -247,7 +247,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { private Test ecdhTest(KeyGeneratorTestable kgt, BigInteger SParam, ECParameterSpec spec, String desc, Result.ExpectedValue expect) throws NoSuchAlgorithmException { ECPrivateKey priv = new RawECPrivateKey(SParam, spec); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(priv).publicKgt(kgt).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(priv).publicKgt(kgt).random(getRandom()).build(); return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, KeyAgreementTest.expectError(testable, expect)); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java index 5385fa2..da5d19a 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneForeignSuite.java @@ -57,9 +57,9 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite { ECParameterSpec spec = curve.toSpec(); ECGenParameterSpec namedSpec = new ECGenParameterSpec(curve.getId()); - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); - KeyGeneratorTestable kgtOnNamedCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(namedSpec).build(); - KeyGeneratorTestable kgtOnDefaultCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(curve.getBits()).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(spec).build(); + KeyGeneratorTestable kgtOnNamedCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).spec(namedSpec).build(); + KeyGeneratorTestable kgtOnDefaultCurve = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).keysize(curve.getBits()).build(); // This is some nasty hacking... KeyGeneratorTestable theKgt = new KeyGeneratorTestable(kpg) { @@ -156,7 +156,7 @@ public abstract class StandaloneForeignSuite extends StandaloneTestSuite { for (EC_Key.Public pub : keys) { ECPublicKey ecpub = ECUtil.toPublicKey(pub); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(theKgt).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKey(ecpub).privateKgt(theKgt).random(getRandom()).build(); Test keyAgreement = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); specificKaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", keyAgreement)); } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java index d0d83e6..87ad0b3 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneMiscSuite.java @@ -81,7 +81,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite { private void testCurve(EC_Curve curve, String catName, KeyPairGenerator kpg, Result.ExpectedValue expected) throws NoSuchAlgorithmException { //generate KeyPair - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(curve.toSpec()).random(getRandom()).build(); Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); //perform KeyAgreement tests @@ -89,7 +89,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite { for (KeyAgreementIdent kaIdent : cfg.selected.getKAs()) { if (kaAlgo == null || kaIdent.containsAny(kaTypes)) { KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).publicKgt(kgt).privateKgt(kgt).random(getRandom()).build(); kaTests.add(KeyAgreementTest.expectError(testable, expected)); } } @@ -103,7 +103,7 @@ public class StandaloneMiscSuite extends StandaloneTestSuite { if (sigAlgo == null || sigIdent.containsAny(sigTypes)) { Signature sig = sigIdent.getInstance(cfg.selected.getProvider()); byte[] data = sigIdent.toString().getBytes(); - SignatureTestable testable = new SignatureTestable(sig, kgt, data, null); + SignatureTestable testable = new SignatureTestable(sig, kgt, data, getRandom()); sigTests.add(SignatureTest.expectError(testable, expected)); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java index e3a5969..909b252 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java @@ -67,8 +67,8 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { KeyPairGenerator kpg = kpgIdent.getInstance(cfg.selected.getProvider()); if (cli.hasOption("test.bits")) { int bits = Integer.parseInt(cli.getOptionValue("test.bits")); - kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).build(); - kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).build(); + kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build(); + kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).keysize(bits).random(getRandom()).build(); } else if (cli.hasOption("test.named-curve")) { String curveName = cli.getOptionValue("test.named-curve"); EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); @@ -77,11 +77,11 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { return; } spec = curve.toSpec(); - kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); - kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); + kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); + kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); } else { - kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).build(); - kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).build(); + kgtOne = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build(); + kgtOther = KeyGeneratorTestable.builder().keyPairGenerator(kpg).random(getRandom()).build(); } kpgTests.add(PerformanceTest.repeat(kgtOne, cfg.selected, kpgIdent.getName(), count)); kpgTests.add(PerformanceTest.repeat(kgtOther, cfg.selected, kpgIdent.getName(), count)); @@ -94,9 +94,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); KeyAgreementTestable testable; if (kaIdent.requiresKeyAlgo()) { - testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).keyAlgo(keyAlgo).build(); + testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).keyAlgo(keyAlgo).build(); } else { - testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).build(); + testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgtOne).publicKgt(kgtOther).spec(spec).random(getRandom()).build(); } kaTests.add(PerformanceTest.repeat(testable, cfg.selected, kaIdent.getName(), count)); } @@ -112,11 +112,11 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { if (sigAlgo == null || sigIdent.containsAny(sigTypes)) { Signature sig = sigIdent.getInstance(cfg.selected.getProvider()); byte[] data = sigIdent.toString().getBytes(); - sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, data, null), cfg.selected, sigIdent.getName(), count)); + sigTests.add(PerformanceTest.repeat(new SignatureTestable(sig, kgtOne, data, getRandom()), cfg.selected, sigIdent.getName(), count)); // TODO: The following will always fail as a runTest is not done at this point. if (kgtOne.getKeyPair() != null) { ECPrivateKey signKey = (ECPrivateKey) kgtOne.getKeyPair().getPrivate(); - sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, data, null), cfg.selected, sigIdent.getName(), count)); + sigTestsNoVerification.add(PerformanceTest.repeat(new SignatureTestable(sig, signKey, null, data, getRandom()), cfg.selected, sigIdent.getName(), count)); } } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java index 81ed535..740dca7 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneSignatureSuite.java @@ -65,7 +65,7 @@ public class StandaloneSignatureSuite extends StandaloneTestSuite { } Signature signature = sigIdent.getInstance(cfg.selected.getProvider()); - SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0), null); + SignatureTestable testable = new SignatureTestable(signature, ecpub, data, sig.getData(0), getRandom()); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + ".", SignatureTest.expectError(testable, expected))); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java index ac164e1..284194c 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java @@ -3,6 +3,7 @@ package cz.crcs.ectester.standalone.test.suites; import cz.crcs.ectester.common.cli.TreeCommandLine; import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.test.TestSuite; +import cz.crcs.ectester.common.util.ByteUtil; import cz.crcs.ectester.standalone.ECTesterStandalone; import cz.crcs.ectester.standalone.consts.Ident; import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; @@ -10,6 +11,7 @@ import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; import cz.crcs.ectester.standalone.consts.SignatureIdent; import cz.crcs.ectester.standalone.libs.ProviderECLibrary; +import java.security.SecureRandom; import java.util.Optional; import java.util.Set; @@ -19,17 +21,34 @@ import java.util.Set; public abstract class StandaloneTestSuite extends TestSuite { TreeCommandLine cli; ECTesterStandalone.Config cfg; + SecureRandom random; + byte[] seed; public StandaloneTestSuite(TestWriter writer, ECTesterStandalone.Config cfg, TreeCommandLine cli, String name, String... description) { super(writer, name, description); this.cfg = cfg; this.cli = cli; + if (cli.hasOption("test.prng-seed")) { + String seedString = cli.getOptionValue("generate.prng-seed"); + this.seed = ByteUtil.hexToBytes(seedString, true); + } else { + seed = new SecureRandom().generateSeed(16); + } + this.random = new SecureRandom(seed); } public ProviderECLibrary getLibrary() { return cfg.selected; } + public byte[] getSeed() { + return seed; + } + + SecureRandom getRandom() { + return this.random; + } + private T getIdent(Set options, String choice, String identName, String defaultChoice) { T ident; if (choice == null) { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java index 7faae99..1766953 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestVectorSuite.java @@ -56,7 +56,7 @@ public class StandaloneTestVectorSuite extends StandaloneTestSuite { KeyAgreementIdent kaIdent = KeyAgreementIdent.get("ECDH"); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(privkey).publicKey(pubkey).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKey(privkey).publicKey(pubkey).random(getRandom()).build(); doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test vector " + result.getId(), KeyAgreementTest.match(testable, result.getData(0)))); } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java index dacaa15..fe954a8 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java @@ -73,11 +73,11 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { String type = curve.getField() == javacard.security.KeyPair.ALG_EC_FP ? "FP" : "F2M"; //try generating a keypair - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.ANY); KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build(); Test ecdh = KeyAgreementTest.expectError(testable, Result.ExpectedValue.FAILURE); doTest(CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, "Wrong curve test of " + curve.getBits() + "b " + type + ". " + curve.getDesc(), generate, ecdh)); @@ -233,12 +233,12 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { private Test ecdhTest(ECParameterSpec spec, String desc) throws NoSuchAlgorithmException { //generate KeyPair - KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).build(); + KeyGeneratorTestable kgt = KeyGeneratorTestable.builder().keyPairGenerator(kpg).spec(spec).random(getRandom()).build(); Test generate = KeyGeneratorTest.expectError(kgt, Result.ExpectedValue.FAILURE); //perform ECDH KeyAgreement ka = kaIdent.getInstance(cfg.selected.getProvider()); - KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).build(); + KeyAgreementTestable testable = KeyAgreementTestable.builder().ka(ka).privateKgt(kgt).publicKgt(kgt).random(getRandom()).build(); Test ecdh = KeyAgreementTest.expect(testable, Result.ExpectedValue.FAILURE); return CompoundTest.function(CompoundTest.EXPECT_ALL_SUCCESS, CompoundTest.RUN_ALL_IF_FIRST, desc, generate, ecdh); } -- cgit v1.2.3-70-g09d2 From b8054933b3d07ef8bfc3bec56b2bb795c1d01e5e Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 13:02:34 +0200 Subject: Add support for deterministic PRNG to SunEC and BouncyCastle. --- .../java/cz/crcs/ectester/common/util/Util.java | 23 ++++- .../crcs/ectester/reader/test/CardTestSuite.java | 5 +- .../ectester/standalone/ECTesterStandalone.java | 113 +++++++++++++-------- .../ectester/standalone/libs/BouncyCastleLib.java | 12 +++ .../cz/crcs/ectester/standalone/libs/SunECLib.java | 12 +++ .../test/suites/StandaloneEdgeCasesSuite.java | 2 +- .../test/suites/StandaloneTestSuite.java | 3 +- .../test/suites/StandaloneWrongSuite.java | 2 +- 8 files changed, 122 insertions(+), 50 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/common/src/main/java/cz/crcs/ectester/common/util/Util.java b/common/src/main/java/cz/crcs/ectester/common/util/Util.java index 5b0cd79..9e6daa2 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/Util.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/Util.java @@ -1,5 +1,8 @@ package cz.crcs.ectester.common.util; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + /** * @author Jan Jancar johny@neuromancer.sk */ @@ -18,11 +21,25 @@ public class Util { public static int getVersion() { String version = System.getProperty("java.version"); - if(version.startsWith("1.")) { + if (version.startsWith("1.")) { version = version.substring(2, 3); } else { int dot = version.indexOf("."); - if(dot != -1) { version = version.substring(0, dot); } - } return Integer.parseInt(version); + if (dot != -1) { + version = version.substring(0, dot); + } + } + return Integer.parseInt(version); + } + + public static SecureRandom getRandom(byte[] seed) { + SecureRandom random; + try { + random = SecureRandom.getInstance("DRBG"); + } catch (NoSuchAlgorithmException ignored) { + return null; + } + random.setSeed(seed); + return random; } } diff --git a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java index af66a75..e2d9dd1 100644 --- a/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java +++ b/reader/src/main/java/cz/crcs/ectester/reader/test/CardTestSuite.java @@ -10,6 +10,7 @@ import cz.crcs.ectester.common.test.Test; import cz.crcs.ectester.common.test.TestSuite; import cz.crcs.ectester.common.util.CardConsts; import cz.crcs.ectester.common.util.ECUtil; +import cz.crcs.ectester.common.util.Util; import cz.crcs.ectester.reader.CardMngr; import cz.crcs.ectester.reader.ECTesterReader; import cz.crcs.ectester.reader.command.Command; @@ -93,7 +94,7 @@ public abstract class CardTestSuite extends TestSuite { if (cfg.testDataSetup.equals("random")) { return new SecureRandom(); } else { - return new SecureRandom(ECUtil.hashCurve(curve)); + return Util.getRandom(ECUtil.hashCurve(curve)); } } @@ -103,7 +104,7 @@ public abstract class CardTestSuite extends TestSuite { } else { ByteBuffer b = ByteBuffer.allocate(4); b.putInt(seed); - return new SecureRandom(b.array()); + return Util.getRandom(b.array()); } } } 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 3194796..f358662 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -415,12 +415,26 @@ public class ECTesterStandalone { throw new NoSuchAlgorithmException(algo); } + SecureRandom random; + if (cli.hasOption("ecdh.prng-seed")) { + String seedString = cli.getOptionValue("ecdh.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + random = SecureRandom.getInstance("DRBG"); + random.setSeed(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } + } else { + random = new SecureRandom(); + } + KeyAgreement ka = kaIdent.getInstance(lib.getProvider()); KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider()); AlgorithmParameterSpec spec = null; if (cli.hasOption("ecdh.bits")) { int bits = Integer.parseInt(cli.getOptionValue("ecdh.bits")); - kpg.initialize(bits); + kpg.initialize(bits, random); } else if (cli.hasOption("ecdh.named-curve")) { String curveName = cli.getOptionValue("ecdh.named-curve"); EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); @@ -429,20 +443,15 @@ public class ECTesterStandalone { return; } spec = curve.toSpec(); - kpg.initialize(spec); + kpg.initialize(spec, random); } else if (cli.hasOption("ecdh.curve-name")) { String curveName = cli.getOptionValue("ecdh.curve-name"); spec = new ECGenParameterSpec(curveName); - kpg.initialize(spec); - } - - if (cli.hasOption("ecdh.prng-seed")) { - String seedString = cli.getOptionValue("ecdh.prng-seed"); - byte[] seed = ByteUtil.hexToBytes(seedString, true); - if (!lib.setupDeterministicPRNG(seed)) { - System.err.println("Couldn't set PRNG seed."); - return; - } + kpg.initialize(spec, random); + } else if (cli.hasOption("ecdh.prng-seed") && !(lib instanceof NativeECLibrary)) { + // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated. + System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options."); + return; } if (cli.hasOption("ecdh.time-source")) { @@ -498,9 +507,9 @@ public class ECTesterStandalone { long elapsed = -System.nanoTime(); if (spec instanceof ECParameterSpec && lib instanceof NativeECLibrary) { - ka.init(privkey, spec); + ka.init(privkey, spec, random); } else { - ka.init(privkey); + ka.init(privkey, random); } ka.doPhase(pubkey, true); elapsed += System.nanoTime(); @@ -534,6 +543,22 @@ public class ECTesterStandalone { * */ private void ecdsa() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, SignatureException { + ProviderECLibrary lib = cfg.selected; + + SecureRandom random; + if (cli.hasOption("ecdsa.prng-seed")) { + String seedString = cli.getOptionValue("ecdsa.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + random = SecureRandom.getInstance("DRBG"); + random.setSeed(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } + } else { + random = new SecureRandom(); + } + byte[] data; String dataString; if (cli.hasOption("ecdsa.file")) { @@ -546,12 +571,12 @@ public class ECTesterStandalone { data = Files.readAllBytes(in.toPath()); dataString = ""; } else { - Random random = new Random(); + Random dataRandom = new Random(); data = new byte[32]; - random.nextBytes(data); + dataRandom.nextBytes(data); dataString = ByteUtil.bytesToHex(data, false); } - ProviderECLibrary lib = cfg.selected; + String algo = cli.getOptionValue("ecdsa.type", "ECDSA"); SignatureIdent sigIdent = lib.getSigs().stream() .filter((ident) -> ident.contains(algo)) @@ -586,7 +611,7 @@ public class ECTesterStandalone { ECParameterSpec spec = null; if (cli.hasOption("ecdsa.bits")) { int bits = Integer.parseInt(cli.getOptionValue("ecdsa.bits")); - kpg.initialize(bits); + kpg.initialize(bits, random); } else if (cli.hasOption("ecdsa.named-curve")) { String curveName = cli.getOptionValue("ecdsa.named-curve"); EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); @@ -595,19 +620,14 @@ public class ECTesterStandalone { return; } spec = curve.toSpec(); - kpg.initialize(spec); + kpg.initialize(spec, random); } else if (cli.hasOption("ecdsa.curve-name")) { String curveName = cli.getOptionValue("ecdsa.curve-name"); - kpg.initialize(new ECGenParameterSpec(curveName)); - } - - if (cli.hasOption("ecdsa.prng-seed")) { - String seedString = cli.getOptionValue("ecdsa.prng-seed"); - byte[] seed = ByteUtil.hexToBytes(seedString, true); - if (!lib.setupDeterministicPRNG(seed)) { - System.err.println("Couldn't set PRNG seed."); - return; - } + kpg.initialize(new ECGenParameterSpec(curveName), random); + } else if (cli.hasOption("ecdsa.prng-seed") && !(lib instanceof NativeECLibrary)) { + // TODO: This only happens if at least one of the (pubkey and privkey) needs to be generated. + System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options."); + return; } if (cli.hasOption("ecdsa.time-source")) { @@ -660,7 +680,7 @@ public class ECTesterStandalone { } } - sig.initSign(privkey); + sig.initSign(privkey, random); sig.update(data); long signTime = -System.nanoTime(); @@ -729,10 +749,25 @@ public class ECTesterStandalone { if (ident == null) { throw new NoSuchAlgorithmException(algo); } + + SecureRandom random; + if (cli.hasOption("generate.prng-seed")) { + String seedString = cli.getOptionValue("generate.prng-seed"); + byte[] seed = ByteUtil.hexToBytes(seedString, true); + random = SecureRandom.getInstance("DRBG"); + random.setSeed(seed); + if (!lib.setupDeterministicPRNG(seed)) { + System.err.println("Couldn't set PRNG seed."); + return; + } + } else { + random = new SecureRandom(); + } + KeyPairGenerator kpg = ident.getInstance(lib.getProvider()); if (cli.hasOption("generate.bits")) { int bits = Integer.parseInt(cli.getOptionValue("generate.bits")); - kpg.initialize(bits); + kpg.initialize(bits, random); } else if (cli.hasOption("generate.named-curve")) { String curveName = cli.getOptionValue("generate.named-curve"); EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName); @@ -740,19 +775,13 @@ public class ECTesterStandalone { System.err.println("Curve not found: " + curveName); return; } - kpg.initialize(curve.toSpec()); + kpg.initialize(curve.toSpec(), random); } else if (cli.hasOption("generate.curve-name")) { String curveName = cli.getOptionValue("generate.curve-name"); - kpg.initialize(new ECGenParameterSpec(curveName)); - } - - if (cli.hasOption("generate.prng-seed")) { - String seedString = cli.getOptionValue("generate.prng-seed"); - byte[] seed = ByteUtil.hexToBytes(seedString, true); - if (!lib.setupDeterministicPRNG(seed)) { - System.err.println("Couldn't set PRNG seed."); - return; - } + kpg.initialize(new ECGenParameterSpec(curveName), random); + } else if (cli.hasOption("generate.prng-seed") && !(lib instanceof NativeECLibrary)) { + System.err.println("Unable to pass PRNG seed to a non-native library without specifying either key-size, named curve or curve name options."); + return; } if (cli.hasOption("generate.time-source")) { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java index e8a4d30..0a7ea8c 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/BouncyCastleLib.java @@ -25,4 +25,16 @@ public class BouncyCastleLib extends ProviderECLibrary { } return result; } + + @Override + public boolean supportsDeterministicPRNG() { + return true; + } + + @Override + public boolean setupDeterministicPRNG(byte[] seed) { + // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature + // instances. Thus, this does nothing. + return true; + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java index 7209dc3..c38300d 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/SunECLib.java @@ -25,4 +25,16 @@ public class SunECLib extends ProviderECLibrary { } return result; } + + @Override + public boolean supportsDeterministicPRNG() { + return true; + } + + @Override + public boolean setupDeterministicPRNG(byte[] seed) { + // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature + // instances. Thus, this does nothing. + return true; + } } diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java index 01c3a53..12a9f16 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneEdgeCasesSuite.java @@ -129,7 +129,7 @@ public class StandaloneEdgeCasesSuite extends StandaloneTestSuite { e.getKey().endsWith("r1") && e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList()); curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor128p2")); curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor160p4")); - Random rand = new Random(); + Random rand = getRandom(); for (EC_Curve curve : curves) { ECParameterSpec spec = curve.toSpec(); diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java index 284194c..3ce58e1 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java @@ -4,6 +4,7 @@ import cz.crcs.ectester.common.cli.TreeCommandLine; import cz.crcs.ectester.common.output.TestWriter; import cz.crcs.ectester.common.test.TestSuite; import cz.crcs.ectester.common.util.ByteUtil; +import cz.crcs.ectester.common.util.Util; import cz.crcs.ectester.standalone.ECTesterStandalone; import cz.crcs.ectester.standalone.consts.Ident; import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; @@ -34,7 +35,7 @@ public abstract class StandaloneTestSuite extends TestSuite { } else { seed = new SecureRandom().generateSeed(16); } - this.random = new SecureRandom(seed); + this.random = Util.getRandom(seed); } public ProviderECLibrary getLibrary() { diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java index fe954a8..1a18188 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneWrongSuite.java @@ -96,7 +96,7 @@ public class StandaloneWrongSuite extends StandaloneTestSuite { Map curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg"); List curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") && e.getValue().getField() == javacard.security.KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList()); - Random r = new Random(); + Random r = getRandom(); for (EC_Curve curve : curves) { short bits = curve.getBits(); final byte[] originalp = curve.getParam(EC_Consts.PARAMETER_FP)[0]; -- cgit v1.2.3-70-g09d2 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/common/util/Util.java | 2 +- .../ectester/standalone/ECTesterStandalone.java | 10 +++--- .../java/cz/crcs/ectester/standalone/AppTests.java | 39 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/common/src/main/java/cz/crcs/ectester/common/util/Util.java b/common/src/main/java/cz/crcs/ectester/common/util/Util.java index 9e6daa2..1d9bcf4 100644 --- a/common/src/main/java/cz/crcs/ectester/common/util/Util.java +++ b/common/src/main/java/cz/crcs/ectester/common/util/Util.java @@ -35,7 +35,7 @@ public class Util { public static SecureRandom getRandom(byte[] seed) { SecureRandom random; try { - random = SecureRandom.getInstance("DRBG"); + random = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException ignored) { return null; } 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 f358662..44fc1b4 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -31,6 +31,7 @@ import cz.crcs.ectester.common.test.TestException; import cz.crcs.ectester.common.util.ByteUtil; import cz.crcs.ectester.common.util.ECUtil; import cz.crcs.ectester.common.util.FileUtil; +import cz.crcs.ectester.common.util.Util; import cz.crcs.ectester.data.EC_Store; import cz.crcs.ectester.standalone.consts.KeyAgreementIdent; import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent; @@ -419,8 +420,7 @@ public class ECTesterStandalone { if (cli.hasOption("ecdh.prng-seed")) { String seedString = cli.getOptionValue("ecdh.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - random = SecureRandom.getInstance("DRBG"); - random.setSeed(seed); + random = Util.getRandom(seed); if (!lib.setupDeterministicPRNG(seed)) { System.err.println("Couldn't set PRNG seed."); return; @@ -549,8 +549,7 @@ public class ECTesterStandalone { if (cli.hasOption("ecdsa.prng-seed")) { String seedString = cli.getOptionValue("ecdsa.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - random = SecureRandom.getInstance("DRBG"); - random.setSeed(seed); + random = Util.getRandom(seed); if (!lib.setupDeterministicPRNG(seed)) { System.err.println("Couldn't set PRNG seed."); return; @@ -754,8 +753,7 @@ public class ECTesterStandalone { if (cli.hasOption("generate.prng-seed")) { String seedString = cli.getOptionValue("generate.prng-seed"); byte[] seed = ByteUtil.hexToBytes(seedString, true); - random = SecureRandom.getInstance("DRBG"); - random.setSeed(seed); + random = Util.getRandom(seed); if (!lib.setupDeterministicPRNG(seed)) { System.err.println("Couldn't set PRNG seed."); return; 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 c55d804aed8b63eb62c74018a720c4804c43c681 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 13:34:46 +0200 Subject: Allow for passing Random to wolfCrypt. --- .../java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java index c8d5ad5..390e45f 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java @@ -25,4 +25,16 @@ public class WolfCryptLib extends ProviderECLibrary { public Set getCurves() { return new HashSet<>(); } + + @Override + public boolean supportsDeterministicPRNG() { + return true; + } + + @Override + public boolean setupDeterministicPRNG(byte[] seed) { + // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature + // instances. Thus, this does nothing. + return true; + } } -- cgit v1.2.3-70-g09d2 From aa37d2b0853670cb6e13e41ae65cd74f6b64d021 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 13:48:00 +0200 Subject: Add deterministic PRNG support to Nettle. --- .../crcs/ectester/standalone/libs/NettleLib.java | 6 ++++ .../cz/crcs/ectester/standalone/libs/jni/native.h | 15 ++++++++++ .../cz/crcs/ectester/standalone/libs/jni/nettle.c | 32 +++++++++++++++++++--- 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java index d4df414..aa90c38 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/NettleLib.java @@ -49,4 +49,10 @@ public class NettleLib extends NativeECLibrary { } throw new InvalidAlgorithmParameterException("Unknown curve."); } + + @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/native.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/native.h index 49be801..b8b2af1 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 @@ -1932,6 +1932,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_create JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves (JNIEnv *, jobject); +/* +* Class: cz_crcs_ectester_standalone_libs_NettleLib +* Method: supportsDeterministicPRNG +* Signature: ()Z +*/ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG +(JNIEnv *, jobject); + +/* +* Class: cz_crcs_ectester_standalone_libs_NettleLib +* Method: setupDeterministicPRNG +* Signature: ([B)Z +*/ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG +(JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus } #endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c index e7ec00e..08b09d5 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/nettle.c @@ -44,10 +44,16 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ init_classes(env, "Nettle"); yarrow256_init(&yarrow, 0, NULL); - uint8_t file = open("/dev/random", O_RDONLY); - yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, &file); - close(file); - + FILE *urandom = fopen("/dev/urandom", "rb"); + uint8_t seed[YARROW256_SEED_FILE_SIZE]; + if (urandom) { + size_t read = 0; + while (read < sizeof(seed)) { + read += fread(((uint8_t *)&seed) + read, 1, sizeof(seed) - read, urandom); + } + fclose(urandom); + } + yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCurves(JNIEnv *env, jobject self) { @@ -66,6 +72,24 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_getCur return result; } +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_NettleLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + jsize seed_length = (*env)->GetArrayLength(env, seed); + if (seed_length < YARROW256_SEED_FILE_SIZE) { + fprintf(stderr, "Error setting seed, needs to be at least %i bytes.\n", YARROW256_SEED_FILE_SIZE); + return JNI_FALSE; + } + + jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); + yarrow256_init(&yarrow, 0, NULL); + yarrow256_seed(&yarrow, YARROW256_SEED_FILE_SIZE, seed_data); + (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + return JNI_TRUE; +} + static const struct ecc_curve* create_curve_from_name(JNIEnv *env, const char* curve_name) { if (!curve_name) { return NULL; -- cgit v1.2.3-70-g09d2 From ae4e8f69b68e51973a20ba59d2fc6fd1e7849972 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 14:00:59 +0200 Subject: Add deterministic PRNG support to ippcp. --- .../cz/crcs/ectester/standalone/libs/IppcpLib.java | 6 ++++++ .../cz/crcs/ectester/standalone/libs/jni/ippcp.c | 23 ++++++++++++++++++++++ .../cz/crcs/ectester/standalone/libs/jni/native.h | 16 +++++++++++++++ 3 files changed, 45 insertions(+) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java index 115fe00..fa51585 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/IppcpLib.java @@ -17,4 +17,10 @@ public class IppcpLib 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/ippcp.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c index fbf917e..86f0f7e 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/ippcp.c @@ -136,6 +136,29 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurv return result; } + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG(JNIEnv *env, jobject self, jbyteArray seed) { + jsize seed_length = (*env)->GetArrayLength(env, seed); + if (seed_length % 4 != 0) { + fprintf(stderr, "Error setting seed, needs to be a multiple of 4 bytes.\n"); + return JNI_FALSE; + } + int bn_size; + ippsBigNumGetSize(seed_length / 4, &bn_size); + uint8_t bn_buf[bn_size]; + IppsBigNumState *bn = (IppsBigNumState *)bn_buf; + ippsBigNumInit(seed_length / 4, bn); + jbyte *seed_data = (*env)->GetByteArrayElements(env, seed, NULL); + ippsSet_BN(IppsBigNumPOS, seed_length / 4, (Ipp32u *) seed_data, bn); + ippsPRNGSetSeed(bn, prng_state); + (*env)->ReleaseByteArrayElements(env, seed, seed_data, JNI_ABORT); + return JNI_TRUE; +} + JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Ippcp_keysizeSupported(JNIEnv *env, jobject this, jint keysize) { 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 b8b2af1..627f38f 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 @@ -1570,6 +1570,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_createP JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_getCurves (JNIEnv *, jobject); +/* +* Class: cz_crcs_ectester_standalone_libs_IppcpLib +* Method: supportsDeterministicPRNG +* Signature: ()Z +*/ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_supportsDeterministicPRNG +(JNIEnv *, jobject); + +/* +* Class: cz_crcs_ectester_standalone_libs_IppcpLib +* Method: setupDeterministicPRNG +* Signature: ([B)Z +*/ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_IppcpLib_setupDeterministicPRNG +(JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif -- 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/main/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/main/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/main/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 6416595eeb031869de50a87f123855c5ad7bbc76 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 20:59:46 +0200 Subject: WolfCrypt is not deterministic? --- .../java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java index 390e45f..c8d5ad5 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/libs/WolfCryptLib.java @@ -25,16 +25,4 @@ public class WolfCryptLib extends ProviderECLibrary { public Set getCurves() { return new HashSet<>(); } - - @Override - public boolean supportsDeterministicPRNG() { - return true; - } - - @Override - public boolean setupDeterministicPRNG(byte[] seed) { - // This is done by passing the SecureRandom into the individual KeyPairGenerator, KeyAgreement and Signature - // instances. Thus, this does nothing. - return true; - } } -- cgit v1.2.3-70-g09d2 From c58adb1f975af0938e2716ae328b37e31da3bbe0 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 21:07:53 +0200 Subject: Fix listSuites. --- standalone/build.gradle.kts | 1 - .../cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/standalone/build.gradle.kts b/standalone/build.gradle.kts index e1fc265..d485bcb 100644 --- a/standalone/build.gradle.kts +++ b/standalone/build.gradle.kts @@ -40,7 +40,6 @@ tasks.named("test") { doFirst { resultsDir.mkdirs(); } - ignoreFailures = true useJUnitPlatform() // Report is always generated after tests run finalizedBy(tasks.named("testCodeCoverageReport")) diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java index 3ce58e1..bfea628 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandaloneTestSuite.java @@ -29,8 +29,8 @@ public abstract class StandaloneTestSuite extends TestSuite { super(writer, name, description); this.cfg = cfg; this.cli = cli; - if (cli.hasOption("test.prng-seed")) { - String seedString = cli.getOptionValue("generate.prng-seed"); + if (cli != null && cli.hasOption("test.prng-seed")) { + String seedString = cli.getOptionValue("test.prng-seed"); this.seed = ByteUtil.hexToBytes(seedString, true); } else { seed = new SecureRandom().generateSeed(16); -- cgit v1.2.3-70-g09d2 From b6c35d175e5d71ec7e3840d984ff77840af9344e Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 7 Aug 2024 22:52:45 +0200 Subject: Continue on test errors. --- .github/workflows/build.yml | 2 +- .../ectester/standalone/test/suites/StandalonePerformanceSuite.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'standalone/src/main/java/cz') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b626eb0..de3f6cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -189,7 +189,7 @@ jobs: run: ./gradlew standalone:run --args="list-libs" - name: Test - run: ./gradlew standalone:test + run: ./gradlew standalone:test --continue - name: Upload build artifacts uses: actions/upload-artifact@v4 diff --git a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java index 909b252..46e4141 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/test/suites/StandalonePerformanceSuite.java @@ -38,9 +38,9 @@ public class StandalonePerformanceSuite extends StandaloneTestSuite { @Override protected void runTests() throws Exception { - String kpgAlgo = cli.getOptionValue("test.kpg-type"); - String kaAlgo = cli.getOptionValue("test.ka-type"); - String sigAlgo = cli.getOptionValue("test.sig-type"); + String kpgAlgo = cli.getOptionValue("test.kpg-type", "EC"); + String kaAlgo = cli.getOptionValue("test.ka-type", "ECDH"); + String sigAlgo = cli.getOptionValue("test.sig-type", "ECDSA"); String keyAlgo = cli.getOptionValue("test.key-type", "AES"); List kpgTypes = kpgAlgo != null ? Arrays.asList(kpgAlgo.split(",")) : new ArrayList<>(); -- 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/main/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 be605a27d095d95cfb477d339b1b6e698d83fa76 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 9 Aug 2024 16:53:35 +0200 Subject: Fix orphan import. --- .../src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java | 1 - 1 file changed, 1 deletion(-) (limited to 'standalone/src/main/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 6822a30..04537f0 100644 --- a/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/standalone/src/main/java/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -23,7 +23,6 @@ */ 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; -- cgit v1.2.3-70-g09d2