diff options
| author | Ján Jančár | 2024-08-09 20:33:18 +0200 |
|---|---|---|
| committer | GitHub | 2024-08-09 20:33:18 +0200 |
| commit | a5a6ef2b5776573d5bd55d6c75f806d752b957c5 (patch) | |
| tree | de46d4ccd6baea24133b5d39c218158079a40d70 /standalone/src/main/resources | |
| parent | 91b425798be6cbc918a9b892d7e76eababc08d6b (diff) | |
| parent | 65ddb496e2090581e40bce003f6c14490e6cf5fb (diff) | |
| download | ECTester-a5a6ef2b5776573d5bd55d6c75f806d752b957c5.tar.gz ECTester-a5a6ef2b5776573d5bd55d6c75f806d752b957c5.tar.zst ECTester-a5a6ef2b5776573d5bd55d6c75f806d752b957c5.zip | |
Merge branch 'master' into build-with-nix
Diffstat (limited to 'standalone/src/main/resources')
26 files changed, 1509 insertions, 44 deletions
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 3ceb718..baa8635 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 @@ -73,6 +73,18 @@ c_utils.o: c_utils.c lib_timing.so: c_timing.c $(CC) -o $@ -shared $(CFLAGS) -Wl,-soname,lib_timing.so $< +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 $< @@ -83,10 +95,15 @@ 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 +openssl_provider.so: openssl.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -Wl,-Bstatic $(shell pkg-config --libs libcrypto) -lcrypto -L. -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so openssl.o: openssl.c @@ -96,7 +113,7 @@ openssl.o: openssl.c # BoringSSL shim boringssl: boringssl_provider.so -boringssl_provider.so: boringssl.o c_utils.o | lib_timing.so lib_csignals.so +boringssl_provider.so: boringssl.o c_utils.o | clibs $(CC) $(CFLAGS) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic -l:lib_boringssl.a -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so boringssl.o: boringssl.c @@ -106,7 +123,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 +gcrypt_provider.so: gcrypt.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -pthread -lpthread -Wl,-Bstatic $(shell libgcrypt-config --libs) -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so gcrypt.o: gcrypt.c @@ -116,7 +133,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 +tomcrypt_provider.so: tomcrypt.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic $(shell pkg-config --libs libtomcrypt libtommath) -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so tomcrypt.o: tomcrypt.c @@ -126,7 +143,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 +botan_provider.so: botan.o cpp_utils.o | cpplibs $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic $(shell pkg-config --libs botan-2) -Wl,-Bdynamic -l:lib_timing.so -l:lib_cppsignals.so botan.o: botan.cpp @@ -140,7 +157,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 +cryptopp_provider.so: cryptopp.o cpp_utils.o | cpplibs $(CXX) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic $(shell pkg-config --libs $(CRYPTOPP_NAME)) -Wl,-Bdynamic -l:lib_timing.so -l:lib_cppsignals.so cryptopp.o: cryptopp.cpp @@ -150,18 +167,17 @@ cryptopp.o: cryptopp.cpp # mbedTLS shim mbedtls: mbedtls_provider.so -mbedtls_provider.so: mbedtls.o c_utils.o | lib_timing.so lib_csignals.so +mbedtls_provider.so: mbedtls.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic -lmbedcrypto -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so mbedtls.o: mbedtls.c $(CC) $(CFLAGS) -c $< - # Intel Performance Primitives crypto shim ippcp: ippcp_provider.so -ippcp_provider.so: ippcp.o c_utils.o | lib_timing.so lib_csignals.so +ippcp_provider.so: ippcp.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L$(IPP_CRYPTO_LIB) -Wl,-Bstatic -l:libippcp.a -L. -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so ippcp.o: ippcp.c @@ -171,7 +187,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 +nettle_provider.so: nettle.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic $(shell pkg-config --libs nettle hogweed gmp) \ -Wl,-Bdynamic -l:lib_timing.so -l:lib_csignals.so @@ -182,7 +198,7 @@ nettle.o: nettle.c # LibreSSL shim libressl: libressl_provider.so -libressl_provider.so: libressl.o c_utils.o | lib_timing.so lib_csignals.so +libressl_provider.so: libressl.o c_utils.o | clibs $(CC) $(LFLAGS) -o $@ -Wl,-rpath,'$$ORIGIN/lib' $^ -L. -Wl,-Bstatic $(shell pkg-config --libs libresslcrypto) -Wl,-Bdynamic -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/botan.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/botan.cpp index c5bc5f1..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 <botan/version.h> #include <botan/rng.h> #include <botan/secmem.h> +#include <botan/system_rng.h> #include <botan/auto_rng.h> +#include <botan/chacha_rng.h> #include <botan/ec_group.h> #include <botan/ecc_key.h> @@ -23,7 +25,7 @@ */ static jclass provider_class; -static Botan::AutoSeeded_RNG rng; +std::unique_ptr<Botan::RandomNumberGenerator> rng = std::make_unique<Botan::AutoSeeded_RNG>(); JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider(JNIEnv *env, jobject self) { /* Create the custom provider. */ @@ -33,12 +35,11 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP jmethodID init = env->GetMethodID(local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V"); const char* info_str = Botan::version_cstr(); - const char* v_str = Botan::short_version_cstr(); std::string name_str = Botan::short_version_string(); name_str.insert(0, "Botan "); jstring name = env->NewStringUTF(name_str.c_str()); - double version = strtod(v_str, nullptr); + double version = BOTAN_VERSION_MAJOR + ((double)BOTAN_VERSION_MINOR/100) + ((double)BOTAN_VERSION_PATCH/1000); jstring info = env->NewStringUTF(info_str); return env->NewObject(provider_class, init, name, version, info); @@ -83,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, "<init>", "()V"); @@ -100,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<uint8_t> 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; } @@ -253,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<Botan::ECDH_PrivateKey>(rng, group); + skey = std::make_unique<Botan::ECDH_PrivateKey>(*rng, group); } else if (type_str == "ECDSA") { - skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, group); + skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, group); } else if (type_str == "ECKCDSA") { - skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, group); + skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, group); } else if (type_str == "ECGDSA") { - skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, group); + skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, group); } native_timing_stop(); } catch (Botan::Exception & ex) { @@ -376,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); @@ -403,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<uint8_t> derived; try { @@ -470,11 +490,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig std::unique_ptr<Botan::EC_PrivateKey> skey; try { if (type_str.find("ECDSA") != std::string::npos) { - skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, curve_group, privkey_scalar); + skey = std::make_unique<Botan::ECDSA_PrivateKey>(*rng, curve_group, privkey_scalar); } else if (type_str.find("ECKCDSA") != std::string::npos) { - skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, curve_group, privkey_scalar); + skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(*rng, curve_group, privkey_scalar); } else if (type_str.find("ECGDSA") != std::string::npos) { - skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, curve_group, privkey_scalar); + skey = std::make_unique<Botan::ECGDSA_PrivateKey>(*rng, curve_group, privkey_scalar); } } catch (Botan::Exception & ex) { throw_new(env, "java/security/GeneralSecurityException", ex.what()); @@ -496,14 +516,19 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig emsa = "EMSA1(SHA-512)"; } + Botan::Signature_Format sigformat = Botan::Signature_Format::DER_SEQUENCE; + if (type_str.find("ECKCDSA") != std::string::npos) { + sigformat = Botan::Signature_Format::IEEE_1363; + } + jsize data_length = env->GetArrayLength(data); jbyte *data_bytes = env->GetByteArrayElements(data, nullptr); std::vector<uint8_t> sig; try { - Botan::PK_Signer signer(*skey, rng, emsa, Botan::DER_SEQUENCE); + 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()); @@ -581,6 +606,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna emsa = "EMSA1(SHA-512)"; } + Botan::Signature_Format sigformat = Botan::Signature_Format::DER_SEQUENCE; + if (type_str.find("ECKCDSA") != std::string::npos) { + sigformat = Botan::Signature_Format::IEEE_1363; + } + jsize data_length = env->GetArrayLength(data); jsize sig_length = env->GetArrayLength(signature); jbyte *data_bytes = env->GetByteArrayElements(data, nullptr); @@ -589,7 +619,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna bool result; try { - Botan::PK_Verifier verifier(*pkey, emsa, Botan::DER_SEQUENCE); + Botan::PK_Verifier verifier(*pkey, emsa, sigformat); native_timing_start(); result = verifier.verify_message((uint8_t*)data_bytes, data_length, (uint8_t*)sig_bytes, sig_length); 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 <dlfcn.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/random.h> +#include <sys/syscall.h> + +#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 <jni.h> +#include <stdbool.h> +#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/cryptopp.cpp b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp index 028c321..2cff58c 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<RandomNumberGenerator> rng = std::make_unique<AutoSeededRandomPool>(); 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<OID> ecp_oids = get_curve_oids<ECP>(); for (auto & ecp_oid : ecp_oids) { @@ -517,7 +538,7 @@ template <class EC> 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<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/gcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c index 795c30a..40376f9 100644 --- a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/gcrypt.c @@ -25,6 +25,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V"); + gcry_control(GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS); const char *running_with = gcry_check_version(GCRYPT_VERSION); if (!running_with) { return NULL; @@ -40,9 +41,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup(JNIEnv *env, jobject this) { gcry_control(GCRYCTL_DISABLE_SECMEM, 0); - //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1); - gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1); INIT_PROVIDER(env, provider_class); @@ -651,4 +651,4 @@ release_init: gcry_sexp_release(pub_sexp); gcry_sexp_release(data_sexp); return result; -}
\ No newline at end of file +} 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/mbedtls.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/mbedtls.c index 7a552da..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; @@ -28,7 +29,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_creat jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V"); jstring name = (*env)->NewStringUTF(env, MBEDTLS_VERSION_STRING_FULL); - double version = MBEDTLS_VERSION_MAJOR + (MBEDTLS_VERSION_MINOR/10) + (MBEDTLS_VERSION_PATCH/100); + double version = MBEDTLS_VERSION_MAJOR + ((double)MBEDTLS_VERSION_MINOR/10) + ((double)MBEDTLS_VERSION_PATCH/100); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -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 60c59b1..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 @@ -74,6 +82,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: supportsDeterministicPRNG + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsDeterministicPRNG + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif @@ -255,6 +279,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 @@ -436,6 +476,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 @@ -617,6 +673,22 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_creat JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves (JNIEnv *, jobject); +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: supportsDeterministicPRNG + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: setupDeterministicPRNG + * Signature: ([B)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_setupDeterministicPRNG + (JNIEnv *, jobject, jbyteArray); + #ifdef __cplusplus } #endif @@ -1341,6 +1413,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 @@ -1522,6 +1610,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 @@ -1884,6 +1988,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; 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 59eb0db..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 @@ -14,6 +14,7 @@ #include <openssl/err.h> #include <openssl/ec.h> #include <openssl/ecdsa.h> +#include <openssl/rand.h> @@ -69,6 +70,58 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCu return result; } +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsDeterministicPRNG(JNIEnv *env, jobject self) { + return JNI_TRUE; +} + +static int stdlib_rand_seed(const void *buf, int num) +{ + unsigned int s = 0; + for (int i = 0; i < num && i < sizeof(unsigned int); ++i) { + s |= ((unsigned char*)buf)[i] << 8*i; + } + srand(s); + return 1; +} + +// Fill the buffer with random bytes. For each byte in the buffer, we generate +// a random number and clamp it to the range of a byte, 0-255. +static int stdlib_rand_bytes(unsigned char *buf, int num) +{ + for (int index = 0; index < num; ++index) + { + buf[index] = rand() % 256; + } + return 1; +} + +static void stdlib_rand_cleanup() {} +static int stdlib_rand_add(const void *buf, int num, double add_entropy) +{ + return 1; +} +static int stdlib_rand_status() +{ + return 1; +} + +RAND_METHOD stdlib_rand_meth = { stdlib_rand_seed, + stdlib_rand_bytes, + stdlib_rand_cleanup, + stdlib_rand_add, + stdlib_rand_bytes, + stdlib_rand_status +}; + +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) { size_t ncurves = EC_get_builtin_curves(NULL, 0); EC_builtin_curve curves[ncurves]; 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 <string.h> +#include <stdlib.h> +#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; i<length; i++) + state[i] ^= data[i]; +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length) +{ + memcpy((unsigned char*)state+offset, data, length); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_OverwriteWithZeroes(void *state, unsigned int byteCount) +{ + memset(state, 0, byteCount); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_Permute_Nrounds(void *argState, unsigned int nr) +{ + tSmallUInt x, y; + tKeccakLane temp; + tKeccakLane BC[5]; + tKeccakLane *state; + const tKeccakLane *rc; + + state = (tKeccakLane*)argState; + rc = KeccakF200_RoundConstants + 18 - nr; + do + { + /* Theta */ + for ( x = 0; x < 5; ++x ) + { + BC[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^ state[15 + x] ^ state[20 + x]; + } + for ( x = 0; x < 5; ++x ) + { + temp = BC[MOD5(x+4)] ^ ROL8(BC[MOD5(x+1)], 1); + for ( y = 0; y < 25; y += 5 ) + { + state[y + x] ^= temp; + } + } + + /* Rho Pi */ + temp = state[1]; + for ( x = 0; x < 24; ++x ) + { + BC[0] = state[KeccakP200_PiLane[x]]; + state[KeccakP200_PiLane[x]] = ROL8( temp, KeccakP200_RotationConstants[x] ); + temp = BC[0]; + } + + /* Chi */ + for ( y = 0; y < 25; y += 5 ) + { +#if defined(UNROLL_CHILOOP) + BC[0] = state[y + 0]; + BC[1] = state[y + 1]; + BC[2] = state[y + 2]; + BC[3] = state[y + 3]; + BC[4] = state[y + 4]; +#else + for ( x = 0; x < 5; ++x ) + { + BC[x] = state[y + x]; + } +#endif + for ( x = 0; x < 5; ++x ) + { + state[y + x] = BC[x] ^((~BC[MOD5(x+1)]) & BC[MOD5(x+2)]); + } + } + + /* Iota */ + temp = *(rc++); + state[0] ^= temp; + } + while( temp != 0x80 ); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_Permute_18rounds(void *argState) +{ + KeccakP200_Permute_Nrounds(argState, 18); +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length) +{ + if (length) { + memcpy(data, (UINT8*)state+offset, length); + } +} + +/* ---------------------------------------------------------------- */ + +void KeccakP200_ExtractAndAddBytes(const void *argState, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) +{ + unsigned int i; + tKeccakLane * state = (tKeccakLane*)argState + offset; + for(i=0; i<length; i++) + output[i] = input[i] ^ state[i]; +} + +/* ---------------------------------------------------------------- */ diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h new file mode 100644 index 0000000..eca5d2e --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG-common.h @@ -0,0 +1,28 @@ +/* +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 _KeccakPRGCommon_h_ +#define _KeccakPRGCommon_h_ + +#include "align.h" + +#define KCP_DeclareSpongePRG_Structure(prefix, size, alignment) \ + ALIGN(alignment) typedef struct prefix##_SpongePRG_InstanceStruct { \ + prefix##_DuplexInstance duplex; \ + } prefix##_SpongePRG_Instance; + +#define KCP_DeclareSpongePRG_Functions(prefix) \ + int prefix##_SpongePRG_Initialize(prefix##_SpongePRG_Instance *instance, unsigned int capacity); \ + int prefix##_SpongePRG_Feed(prefix##_SpongePRG_Instance *instance, const unsigned char *input, unsigned int inputByteLen); \ + int prefix##_SpongePRG_Fetch(prefix##_SpongePRG_Instance *Instance, unsigned char *out, unsigned int outByteLen); \ + int prefix##_SpongePRG_Forget(prefix##_SpongePRG_Instance *instance); + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h new file mode 100644 index 0000000..83a2144 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.h @@ -0,0 +1,20 @@ +/* +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 _KeccakPRG_h_ +#define _KeccakPRG_h_ + +/* For the documentation, please follow the link: */ +/* #include "KeccakPRG-documentation.h" */ + +#include "KeccakPRGWidth200.h" + +#endif diff --git a/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc new file mode 100644 index 0000000..aa65db0 --- /dev/null +++ b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/prng/KeccakPRG.inc @@ -0,0 +1,123 @@ +/* +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/ +*/ + +#define JOIN0(a, b) a ## b +#define JOIN(a, b) JOIN0(a, b) + +#define SpongePRG_Instance JOIN(prefix, _SpongePRG_Instance) +#define SpongePRG_Initialize JOIN(prefix, _SpongePRG_Initialize) +#define SpongePRG_Feed JOIN(prefix, _SpongePRG_Feed) +#define SpongePRG_Fetch JOIN(prefix, _SpongePRG_Fetch) +#define SpongePRG_Forget JOIN(prefix, _SpongePRG_Forget) + +#define DuplexInstance JOIN(prefix, _DuplexInstance) +#define DuplexInitialize JOIN(prefix, _DuplexInitialize) +#define Duplexing JOIN(prefix, _Duplexing) +#define DuplexingFeedPartialInput JOIN(prefix, _DuplexingFeedPartialInput) +#define DuplexingOverwriteWithZeroes JOIN(prefix, _DuplexingOverwriteWithZeroes) +#define DuplexingGetFurtherOutput JOIN(prefix, _DuplexingGetFurtherOutput) +#define DuplexGetInputIndex(duplex) (duplex)->byteInputIndex +#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 <stdlib.h> + + +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 <stdint.h> + +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/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/standalone/src/main/resources/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c index 23f28ca..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 @@ -5,8 +5,10 @@ #include "native.h" #include <stdio.h> #include <string.h> +#include <locale.h> #include <tomcrypt.h> + static prng_state ltc_prng; static jclass provider_class; @@ -18,7 +20,9 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V"); jstring name = (*env)->NewStringUTF(env, "libtomcrypt " SCRYPT); + char *locale = setlocale(LC_NUMERIC, "C"); double version = strtod(SCRYPT, NULL); + setlocale(LC_NUMERIC, locale); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -72,6 +76,22 @@ 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 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; +} + + 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; |
