aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java4
-rw-r--r--src/cz/crcs/ectester/standalone/libs/BoringsslLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/BotanLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/CryptoppLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/GcryptLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/MscngLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/OpensslLib.java9
-rw-r--r--src/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java12
-rw-r--r--src/cz/crcs/ectester/standalone/libs/TomcryptLib.java10
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/Makefile15
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/boringssl.c35
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/botan.cpp21
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_timing.c57
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_timing.h38
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp23
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c27
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/mscng.c12
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h168
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/openssl.c36
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c45
-rwxr-xr-xutil/plot_dh.py76
-rwxr-xr-xutil/plot_gen.py43
23 files changed, 593 insertions, 92 deletions
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 46c60e0..037e8b2 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -241,6 +241,7 @@ public class ECTesterStandalone {
for (ProviderECLibrary lib : libs) {
if (lib.isInitialized() && (cfg.selected == null || lib == cfg.selected)) {
System.out.println("\t- " + Colors.bold(lib.name()));
+ System.out.println(Colors.bold("\t\t- Supports native timing: ") + lib.supportsNativeTiming());
Set<KeyPairGeneratorIdent> kpgs = lib.getKPGs();
if (!kpgs.isEmpty()) {
System.out.println(Colors.bold("\t\t- KeyPairGenerators: ") + String.join(", ", kpgs.stream().map(KeyPairGeneratorIdent::getName).collect(Collectors.toList())));
@@ -555,6 +556,9 @@ public class ECTesterStandalone {
long elapsed = -System.nanoTime();
KeyPair kp = kpg.genKeyPair();
elapsed += System.nanoTime();
+ if (lib.supportsNativeTiming()) {
+ elapsed = lib.getLastNativeTiming();
+ }
ECPublicKey publicKey = (ECPublicKey) kp.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
diff --git a/src/cz/crcs/ectester/standalone/libs/BoringsslLib.java b/src/cz/crcs/ectester/standalone/libs/BoringsslLib.java
index 60ca5d9..35a48a8 100644
--- a/src/cz/crcs/ectester/standalone/libs/BoringsslLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/BoringsslLib.java
@@ -12,6 +12,15 @@ public class BoringsslLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/BotanLib.java b/src/cz/crcs/ectester/standalone/libs/BotanLib.java
index cd28791..34fb178 100644
--- a/src/cz/crcs/ectester/standalone/libs/BotanLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/BotanLib.java
@@ -13,6 +13,15 @@ public class BotanLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java
index 5112d7d..5153df5 100644
--- a/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/CryptoppLib.java
@@ -13,6 +13,15 @@ public class CryptoppLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/GcryptLib.java b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
index a0a7fc8..ef20f97 100644
--- a/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
@@ -13,6 +13,15 @@ public class GcryptLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/MscngLib.java b/src/cz/crcs/ectester/standalone/libs/MscngLib.java
index 527a65b..354199a 100644
--- a/src/cz/crcs/ectester/standalone/libs/MscngLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/MscngLib.java
@@ -13,6 +13,15 @@ public class MscngLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
index ff23fd9..7870377 100644
--- a/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
+++ b/src/cz/crcs/ectester/standalone/libs/NativeECLibrary.java
@@ -130,5 +130,14 @@ public abstract class NativeECLibrary extends ProviderECLibrary {
return true;
}
+ @Override
+ public abstract boolean supportsNativeTiming();
+
+ @Override
+ public abstract long getNativeTimingResolution();
+
+ @Override
+ public abstract long getLastNativeTiming();
+
abstract Provider createProvider();
}
diff --git a/src/cz/crcs/ectester/standalone/libs/OpensslLib.java b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java
index e558336..4f44a2a 100644
--- a/src/cz/crcs/ectester/standalone/libs/OpensslLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/OpensslLib.java
@@ -12,6 +12,15 @@ public class OpensslLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java b/src/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
index 9108eaf..83a9dc9 100644
--- a/src/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
+++ b/src/cz/crcs/ectester/standalone/libs/ProviderECLibrary.java
@@ -62,6 +62,18 @@ public abstract class ProviderECLibrary implements ECLibrary {
return results;
}
+ public boolean supportsNativeTiming() {
+ return false;
+ }
+
+ public long getNativeTimingResolution() {
+ return 0;
+ }
+
+ public long getLastNativeTiming() {
+ return 0;
+ }
+
@Override
public Set<KeyAgreementIdent> getKAs() {
return getIdents("KeyAgreement", KeyAgreementIdent::get);
diff --git a/src/cz/crcs/ectester/standalone/libs/TomcryptLib.java b/src/cz/crcs/ectester/standalone/libs/TomcryptLib.java
index 78db00e..6ac74c9 100644
--- a/src/cz/crcs/ectester/standalone/libs/TomcryptLib.java
+++ b/src/cz/crcs/ectester/standalone/libs/TomcryptLib.java
@@ -13,6 +13,16 @@ public class TomcryptLib extends NativeECLibrary {
}
@Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+
+ @Override
native Provider createProvider();
@Override
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index 2232e3d..c8ab47b 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -64,12 +64,15 @@ all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provide
c_utils.o: c_utils.c
$(CC) $(CFLAGS) -c $<
+c_timing.o: c_timing.c
+ $(CC) $(CFLAGS) -c $<
+
cpp_utils.o: cpp_utils.cpp
$(CXX) $(CXXFLAGS) -c $<
# OpenSSL shim
-openssl_provider.so: openssl.o c_utils.o
+openssl_provider.so: openssl.o c_utils.o c_timing.o
$(CC) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs openssl)
openssl.o: openssl.c
@@ -77,7 +80,7 @@ openssl.o: openssl.c
# BoringSSL shim
-boringssl_provider.so: boringssl.o c_utils.o
+boringssl_provider.so: boringssl.o c_utils.o c_timing.o
$(CC) $(LFLAGS) -o $@ $^ -L. ../../../../../../../ext/boringssl/build/crypto/libcrypto.so
cp ../../../../../../../ext/boringssl/build/crypto/libcrypto.so lib_boringssl.so
@@ -86,7 +89,7 @@ boringssl.o: boringssl.c
# libgcrypt shim
-gcrypt_provider.so: gcrypt.o c_utils.o
+gcrypt_provider.so: gcrypt.o c_utils.o c_timing.o
$(CC) $(LFLAGS) -o $@ $^ -L. $(shell libgcrypt-config --libs)
gcrypt.o: gcrypt.c
@@ -94,7 +97,7 @@ gcrypt.o: gcrypt.c
# Libtomcrypt shim
-tomcrypt_provider.so: tomcrypt.o c_utils.o
+tomcrypt_provider.so: tomcrypt.o c_utils.o c_timing.o
$(CC) $(LFLAGS) -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt)
tomcrypt.o: tomcrypt.c
@@ -102,7 +105,7 @@ tomcrypt.o: tomcrypt.c
# Botan-2 shim
-botan_provider.so: botan.o cpp_utils.o
+botan_provider.so: botan.o cpp_utils.o c_timing.o
$(CXX) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs botan-2)
botan.o: botan.cpp
@@ -110,7 +113,7 @@ botan.o: botan.cpp
# Crypto++ shim
-cryptopp_provider.so: cryptopp.o cpp_utils.o
+cryptopp_provider.so: cryptopp.o cpp_utils.o c_timing.o
$(CXX) $(LFLAGS) -o $@ $^ -L. $(shell pkg-config --libs libcrypto++)
cryptopp.o: cryptopp.cpp
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
index cb1ea77..0484d28 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
@@ -13,6 +13,7 @@
#include <openssl/ecdsa.h>
#include "c_utils.h"
+#include "c_timing.h"
static jclass provider_class;
@@ -279,7 +280,12 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) {
EC_KEY *key = EC_KEY_new();
EC_KEY_set_group(key, curve);
- if (!EC_KEY_generate_key(key)) {
+
+ native_timing_start();
+ int err = EC_KEY_generate_key(key);
+ native_timing_stop();
+
+ if (!err) {
throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key.");
EC_KEY_free(key);
return NULL;
@@ -412,7 +418,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
// probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string.
jbyteArray result = (*env)->NewByteArray(env, secret_len);
jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
- if (ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL) <= 0) {
+
+ native_timing_start();
+ int err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL);
+ native_timing_stop();
+
+ if (err <= 0) {
throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key.");
EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve);
(*env)->ReleaseByteArrayElements(env, result, result_data, JNI_ABORT);
@@ -443,7 +454,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jsize data_size = (*env)->GetArrayLength(env, data);
jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
// TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually?
+
+ native_timing_start();
ECDSA_SIG *signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv);
+ native_timing_stop();
+
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
if (!signature) {
throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign.");
@@ -481,7 +496,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
jsize data_size = (*env)->GetArrayLength(env, data);
jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ native_timing_start();
int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub);
+ native_timing_stop();
+
if (result < 0) {
throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify.");
EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj);
@@ -495,3 +514,15 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
EC_GROUP_free(curve);
return (result == 1) ? JNI_TRUE : JNI_FALSE;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_supportsNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_getNativeTimingResolution(JNIEnv *env, jobject this) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_getLastNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_last();
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
index b7940df..813b9f8 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp
@@ -17,6 +17,7 @@
#include <botan/ecdh.h>
#include <botan/pubkey.h>
#include "cpp_utils.hpp"
+#include "c_timing.h"
static jclass provider_class;
static Botan::AutoSeeded_RNG rng;
@@ -244,6 +245,7 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
std::unique_ptr<Botan::EC_PrivateKey> skey;
try {
+ native_timing_start();
if (type_str == "ECDH") {
skey = std::make_unique<Botan::ECDH_PrivateKey>(rng, group);
} else if (type_str == "ECDSA") {
@@ -253,6 +255,7 @@ static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group gr
} else if (type_str == "ECGDSA") {
skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, group);
}
+ native_timing_stop();
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
return NULL;
@@ -371,7 +374,9 @@ jbyteArray generate_secret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteAr
std::vector<uint8_t> derived;
try {
+ native_timing_start();
derived = Botan::unlock(ka.derive_key(key_len, pkey.public_value()).bits_of());
+ native_timing_stop();
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
return NULL;
@@ -442,7 +447,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
std::vector<uint8_t> sig;
try {
+ native_timing_start();
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());
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
@@ -506,7 +513,9 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
bool result;
try {
+ native_timing_start();
result = verifier.verify_message((uint8_t*)data_bytes, data_length, (uint8_t*)sig_bytes, sig_length);
+ native_timing_stop();
} catch (Botan::Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
@@ -519,4 +528,16 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
return JNI_TRUE;
}
return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsNativeTiming(JNIEnv *env, jobject self) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getNativeTimingResolution(JNIEnv *env, jobject self) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getLastNativeTiming(JNIEnv *env, jobject self) {
+ return native_timing_last();
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c
new file mode 100644
index 0000000..be46398
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c
@@ -0,0 +1,57 @@
+#include "c_timing.h"
+#include <time.h>
+
+#if _POSIX_TIMERS > 0
+
+struct timespec start = {0};
+struct timespec end = {0};
+
+jboolean native_timing_supported() {
+ return JNI_TRUE;
+}
+
+jlong native_timing_resolution() {
+ struct timespec timeval;
+ clock_getres(CLOCK_MONOTONIC, &timeval);
+ return timeval.tv_nsec;
+}
+
+
+void native_timing_start() {
+ clock_gettime(CLOCK_MONOTONIC, &start);
+}
+
+
+void native_timing_stop() {
+ clock_gettime(CLOCK_MONOTONIC, &end);
+}
+
+
+jlong native_timing_last() {
+ jlong res = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec);
+ if (res < 0) {
+ return 0;
+ } else {
+ return res;
+ }
+}
+
+#else
+
+jboolean native_timing_supported() {
+ return JNI_FALSE;
+}
+
+jlong native_timing_resolution() {
+ return 0;
+}
+
+void native_timing_start() {}
+
+void native_timing_stop() {}
+
+jlong native_timing_last() {
+ return 0;
+}
+
+#endif \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h
new file mode 100644
index 0000000..bce2a19
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <jni.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ *
+ */
+jboolean native_timing_supported();
+
+/**
+ *
+ */
+jlong native_timing_resolution();
+
+/**
+ *
+ */
+void native_timing_start();
+
+/**
+ *
+ */
+void native_timing_stop();
+
+/**
+ *
+ */
+jlong native_timing_last();
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
index f14aa97..089724e 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
+++ b/src/cz/crcs/ectester/standalone/libs/jni/cryptopp.cpp
@@ -70,6 +70,7 @@ using CryptoPP::Integer;
#include "cpp_utils.hpp"
+#include "c_timing.h"
static jclass provider_class;
static AutoSeededRandomPool rng;
@@ -498,7 +499,9 @@ template <class EC> jobject generate_from_group(JNIEnv *env, DL_GroupParameters_
SecByteBlock priv(ec_domain.PrivateKeyLength()), pub(ec_domain.PublicKeyLength());
try {
+ native_timing_start();
ec_domain.GenerateKeyPair(rng, priv, pub);
+ native_timing_stop();
} catch (Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
return NULL;
@@ -579,7 +582,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
try {
secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ native_timing_start();
success = dh_agreement.Agree(*secret, private_key, public_key);
+ native_timing_stop();
} catch (Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
return NULL;
@@ -589,7 +594,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
try {
secret = std::make_unique<SecByteBlock>(dh_agreement.AgreedValueLength());
+ native_timing_start();
success = dh_agreement.Agree(*secret, private_key, public_key);
+ native_timing_stop();
} catch (Exception & ex) {
throw_new(env, "java/security/GeneralSecurityException", ex.what());
return NULL;
@@ -624,7 +631,9 @@ jbyteArray sign_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray
jsize data_length = env->GetArrayLength(data);
jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ native_timing_start();
size_t len = signer.SignMessage(rng, (byte *)data_bytes, data_length, (byte *)signature.c_str());
+ native_timing_stop();
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
signature.resize(len);
@@ -709,7 +718,9 @@ jboolean verify_message(JNIEnv *env, DL_GroupParameters_EC<EC> group, jbyteArray
jsize data_length = env->GetArrayLength(data);
jbyte *data_bytes = env->GetByteArrayElements(data, NULL);
+ native_timing_start();
bool result = verifier.VerifyMessage((byte *)data_bytes, data_length, sig, sig_len);
+ native_timing_stop();
env->ReleaseByteArrayElements(data, data_bytes, JNI_ABORT);
return result;
@@ -754,3 +765,15 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
// unreachable
return JNI_FALSE;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsNativeTiming(JNIEnv *env, jobject self) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getNativeTimingResolution(JNIEnv *env, jobject self) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getLastNativeTiming(JNIEnv *env, jobject self) {
+ return native_timing_last();
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
index 9590d0a..359d0f4 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <gcrypt.h>
#include "c_utils.h"
+#include "c_timing.h"
static jclass provider_class;
@@ -262,7 +263,11 @@ end:
static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) {
jobject result = NULL;
gcry_sexp_t key_sexp;
+
+ native_timing_start();
gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp);
+ native_timing_stop();
+
if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error generating key. Error: %ui", gcry_err_code(err));
goto release_sexp;
@@ -438,7 +443,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
gcry_sexp_build(&enc_sexp, NULL, "(data (flags raw) (value %M))", priv, NULL);
gcry_sexp_t res_sexp;
// TODO: figure out why ecc_encrypt_raw takes signed representation.. Nobody uses that., everybody uses unsigned reduced mod p.
+
+ native_timing_start();
gcry_error_t err = gcry_pk_encrypt(&res_sexp, enc_sexp, pub);
+ native_timing_stop();
+
if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDH. Error: %ui", gcry_err_code(err));
goto end;
@@ -543,7 +552,9 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
get_sign_data_sexp(env, &data_sexp, this, data);
gcry_sexp_t res_sexp;
+ native_timing_start();
gcry_error_t err = gcry_pk_sign(&res_sexp, data_sexp, priv_sexp);
+ native_timing_stop();
if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDSA. Error: %ui", gcry_err_code(err));
goto release_init;
@@ -591,7 +602,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
gcry_sexp_t sig_sexp;
gcry_sexp_build(&sig_sexp, NULL, "(sig-val (ecdsa (r %M) (s %M)))", r_mpi, s_mpi);
+
+ native_timing_start();
gcry_error_t err = gcry_pk_verify(sig_sexp, data_sexp, pub_sexp);
+ native_timing_stop();
+
if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) {
throw_new(env, "java/security/GeneralSecurityException", "Error verif sig.");
@@ -605,4 +620,16 @@ release_init:
gcry_sexp_release(pub_sexp);
gcry_sexp_release(data_sexp);
return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_supportsNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getNativeTimingResolution(JNIEnv *env, jobject this) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getLastNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_last();
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
index 5820afd..568e924 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c
@@ -1211,4 +1211,16 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptVerifySignature\n", status);
return JNI_FALSE;
}
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_supportsNativeTiming(JNIEnv *env, jobject self) {
+ return JNI_FALSE;
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getNativeTimingResolution(JNIEnv *env, jobject self) {
+ return 0;
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getLastNativeTiming(JNIEnv *env, jobject self) {
+ return 0;
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h
index 47031e4..e410204 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -9,6 +9,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_TomcryptLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -190,6 +214,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BotanLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -371,6 +419,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_CryptoppLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -552,6 +624,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_OpensslLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -733,6 +829,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MscngLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -914,6 +1034,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_BoringsslLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BoringsslLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BoringsslLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_BoringsslLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_BoringsslLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
@@ -1095,6 +1239,30 @@ extern "C" {
#endif
/*
* Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
* Method: createProvider
* Signature: ()Ljava/security/Provider;
*/
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
index 639503a..a63c2fb 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -12,6 +12,8 @@
#include <openssl/ecdsa.h>
#include "c_utils.h"
+#include "c_timing.h"
+
static jclass provider_class;
@@ -348,7 +350,12 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) {
EC_KEY *key = EC_KEY_new();
EC_KEY_set_group(key, curve);
- if (!EC_KEY_generate_key(key)) {
+
+ native_timing_start();
+ int result = EC_KEY_generate_key(key);
+ native_timing_stop();
+
+ if (!result) {
throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key.");
EC_KEY_free(key);
return NULL;
@@ -481,7 +488,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
// probably using the ECDH_KDF_X9_62 by wrapping it and dynamically choosing the EVP_MD. from the type string.
jbyteArray result = (*env)->NewByteArray(env, secret_len);
jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL);
- if (ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL) <= 0) {
+
+ native_timing_start();
+ int err = ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL);
+ native_timing_stop();
+
+ if (err <= 0) {
throw_new(env, "java/security/GeneralSecurityException", "Error computing ECDH, ECDH_compute_key.");
EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve);
(*env)->ReleaseByteArrayElements(env, result, result_data, JNI_ABORT);
@@ -512,7 +524,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
jsize data_size = (*env)->GetArrayLength(env, data);
jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
// TODO: Do more Signatures here, maybe use the EVP interface to get to the hashes easier and not hash manually?
+
+ native_timing_start();
ECDSA_SIG *signature = ECDSA_do_sign((unsigned char *) data_data, data_size, priv);
+ native_timing_stop();
+
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
if (!signature) {
throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign.");
@@ -550,7 +566,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
jsize data_size = (*env)->GetArrayLength(env, data);
jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ native_timing_start();
int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub);
+ native_timing_stop();
+
if (result < 0) {
throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify.");
EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj);
@@ -564,3 +584,15 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
EC_GROUP_free(curve);
return (result == 1) ? JNI_TRUE : JNI_FALSE;
}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_supportsNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getNativeTimingResolution(JNIEnv *env, jobject this) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getLastNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_last();
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index 49e997a..471190e 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -3,6 +3,7 @@
#include <string.h>
#include <tomcrypt.h>
#include "c_utils.h"
+#include "c_timing.h"
static prng_state ltc_prng;
static jclass provider_class;
@@ -20,7 +21,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_crea
return (*env)->NewObject(env, provider_class, init, name, version, name);
}
-
JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup(JNIEnv *env, jobject this) {
/* Initialize libtommath as the math lib. */
ltc_mp = ltm_desc;
@@ -243,8 +243,12 @@ static void free_curve(ltc_ecc_set_type *curve) {
static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
ecc_key key;
- int err;
- if ((err = ecc_make_key_ex(&ltc_prng, find_prng("yarrow"), &key, curve)) != CRYPT_OK) {
+
+ native_timing_start();
+ int err = ecc_make_key_ex(&ltc_prng, find_prng("yarrow"), &key, curve);
+ native_timing_stop();
+
+ if (err != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
return NULL;
}
@@ -380,8 +384,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
unsigned char result[curve->size];
unsigned long output_len = curve->size;
- int err;
- if ((err = ecc_shared_secret(&priv, &pub, result, &output_len)) != CRYPT_OK) {
+
+ native_timing_start();
+ int err = ecc_shared_secret(&priv, &pub, result, &output_len);
+ native_timing_stop();
+
+ if (err != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
free_curve(curve);
return NULL;
@@ -416,8 +424,12 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig
unsigned char result[curve->size*4];
unsigned long output_len = curve->size*4;
- int err;
- if ((err = ecc_sign_hash((unsigned char *) data_data, data_size, result, &output_len, &ltc_prng, find_prng("yarrow"), &priv)) != CRYPT_OK) {
+
+ native_timing_start();
+ int err = ecc_sign_hash((unsigned char *) data_data, data_size, result, &output_len, &ltc_prng, find_prng("yarrow"), &priv);
+ native_timing_stop();
+
+ if (err != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
@@ -450,9 +462,12 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
jsize sig_size = (*env)->GetArrayLength(env, signature);
jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL);
- int err;
int result;
- if ((err = ecc_verify_hash((unsigned char *) sig_data, sig_size, (unsigned char *) data_data, data_size, &result, &pub)) != CRYPT_OK) {
+ native_timing_start();
+ int err = ecc_verify_hash((unsigned char *) sig_data, sig_size, (unsigned char *) data_data, data_size, &result, &pub);
+ native_timing_stop();
+
+ if (err != CRYPT_OK) {
throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
free_curve(curve);
(*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
@@ -464,4 +479,16 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
(*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
free_curve(curve);
return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_supportsNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getNativeTimingResolution(JNIEnv *env, jobject this) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getLastNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_last();
} \ No newline at end of file
diff --git a/util/plot_dh.py b/util/plot_dh.py
index 468e73a..60e20ae 100755
--- a/util/plot_dh.py
+++ b/util/plot_dh.py
@@ -18,10 +18,17 @@ import argparse
from copy import deepcopy
from operator import itemgetter
+from utils import hw, moving_average, plot_hist
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plot ECTester ECDH timing.")
parser.add_argument("-o", "--output", dest="output", type=argparse.FileType("wb"), help="Write image to [file], do not display.", metavar="file")
- parser.add_argument("--skip-first", dest="skip_first", action="store_true", help="Skip first entry, as it's usually a large outlier.")
+ parser.add_argument("--priv", dest="priv", action="store_true", help="Show private key MSB heatmap plot.")
+ parser.add_argument("--hist", dest="hist", action="store_true", help="Show time histogram.")
+ parser.add_argument("--hw-hist", dest="hw_hist", action="store_true", help="Show Hamming weight heatmap (private key Hamming weight and time).")
+ parser.add_argument("--avg", dest="avg", action="store_true", help="Show moving average of time.")
+ parser.add_argument("--log", dest="log", action="store_true", help="Use logarithmic scale.")
+ parser.add_argument("--skip-first", dest="skip_first", nargs="?", const=1, type=int, help="Skip first entry, as it's usually a large outlier.")
parser.add_argument("-t", "--title", dest="title", nargs="?", default="", type=str, help="What title to give the figure.")
parser.add_argument("file", type=str, help="The file to plot(csv).")
@@ -34,18 +41,17 @@ if __name__ == "__main__":
hx = lambda x: int(x, 16)
data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={2: hx, 3: hx, 4: hx}, dtype=np.dtype([("index","u4"), ("time","u4"), ("pub", "O"), ("priv", "O"), ("secret","O")]))
if opts.skip_first:
- data = data[1:]
+ data = data[opts.skip_first:]
+ time_data = data["time"]
if "nano" in header_names[1]:
unit = r"$\mu s$"
- time_data = map(lambda x: x[1]//1000, data)
+ time_data = np.array(list(map(lambda x: x//1000, time_data)))
else:
unit = r"ms"
- time_data = map(itemgetter(1), data)
- time_data = list(time_data)
- priv_data = list(map(itemgetter(2), data))
- pub_data = list(map(itemgetter(3), data))
- secret_data = list(map(itemgetter(4), data))
+ priv_data = data["priv"]
+ pub_data = data["pub"]
+ secret_data = data["secret"]
plt.style.use("ggplot")
fig = plt.figure()
@@ -58,43 +64,37 @@ if __name__ == "__main__":
layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
fig.tight_layout(**layout_kwargs)
- axe_hist = fig.add_subplot(2,1,1)
time_max = max(time_data)
- time_avg = np.average(time_data)
- time_median = np.median(time_data)
- axe_hist.hist(time_data, bins=time_max//3, log=True)
- axe_hist.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="red", label="avg = {}".format(time_avg))
- axe_hist.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median))
- axe_hist.set_ylabel("count\n(log)")
- axe_hist.set_xlabel("time ({})".format(unit))
- axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
- axe_hist.legend(loc="best")
+ time_min = min(time_data)
+ bit_size = len(bin(max(priv_data))) - 2
- priv_bit_bins = {}
- for i in range(len(data)):
- skey = priv_data[i]
- time = time_data[i]
- skey_hw = 0
- while skey:
- skey_hw += 1
- skey &= skey - 1
- if skey_hw in priv_bit_bins:
- priv_bit_bins[skey_hw].append(time)
- else:
- priv_bit_bins[skey_hw] = [time]
- priv_bit_x = []
- priv_bit_y = []
- for k,v in priv_bit_bins.items():
- priv_bit_x.extend([k] * len(v))
- priv_bit_y.extend(v)
-
- axe_priv_hist = fig.add_subplot(2,1,2)
- h, xe, ye = np.histogram2d(priv_bit_x, priv_bit_y, bins=[max(priv_bit_bins) - min(priv_bit_bins), (time_max - min(time_data))//5])
cmap = deepcopy(plt.cm.plasma)
cmap.set_bad("black")
+
+ norm = colors.Normalize()
+ if opts.log:
+ norm = colors.LogNorm()
+
+ axe_private = fig.add_subplot(3,1,1)
+ priv_msb = np.array(list(map(lambda x: x >> (bit_size - 8), priv_data)), dtype=np.dtype("u1"))
+ heatmap, xedges, yedges = np.histogram2d(priv_msb, time_data, bins=[128, time_max - time_min])
+ extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
+ axe_private.imshow(heatmap.T, extent=extent, aspect="auto", cmap=cmap, origin="low", interpolation="nearest", norm=norm)
+ axe_private.set_xlabel("private key MSB value")
+ axe_private.set_ylabel("ECDH time ({})".format(unit))
+
+ axe_hist = fig.add_subplot(3,1,2)
+ plot_hist(axe_hist, time_data, "ECDH time ({})".format(unit), opts.log)
+ axe_hist.legend(loc="best")
+
+ axe_priv_hist = fig.add_subplot(3,1,3)
+ priv_hw = np.array(list(map(hw, priv_data)), dtype=np.dtype("u2"))
+ h, xe, ye = np.histogram2d(priv_hw, time_data, bins=[max(priv_hw) - min(priv_hw), time_max - time_min])
im = axe_priv_hist.imshow(h.T, origin="low", cmap=cmap, aspect="auto", extent=[xe[0], xe[-1], ye[0], ye[-1]], norm=colors.LogNorm())
+ axe_priv_hist.axvline(x=bit_size//2, alpha=0.7, linestyle="dotted", color="white", label=str(bit_size//2) + " bits")
axe_priv_hist.set_xlabel("private key Hamming weight")
axe_priv_hist.set_ylabel("time ({})".format(unit))
+ axe_priv_hist.legend(loc="best")
fig.colorbar(im, ax=axe_priv_hist)
fig.text(0.01, 0.02, "Data size: {}".format(len(time_data)), size="small")
diff --git a/util/plot_gen.py b/util/plot_gen.py
index c07fc91..9d4863f 100755
--- a/util/plot_gen.py
+++ b/util/plot_gen.py
@@ -17,17 +17,7 @@ from matplotlib import ticker, colors
from copy import deepcopy
import argparse
-def hw(i):
- res = 0
- while i:
- res += 1
- i &= i - 1
- return res
-
-def moving_average(a, n) :
- ret = np.cumsum(a, dtype=float)
- ret[n:] = ret[n:] - ret[:-n]
- return ret[n - 1:] / n
+from utils import hw, moving_average, plot_hist
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plot results of ECTester key generation timing.")
@@ -85,7 +75,6 @@ if __name__ == "__main__":
pub_data = data["pub"]
priv_data = data["priv"]
-
gen_unit = "ms"
if header_names[1].endswith("[nano]"):
gen_unit = r"$\mu s$"
@@ -121,39 +110,23 @@ if __name__ == "__main__":
if plots[0]:
axe_private = fig.add_subplot(n_plots, 1, plot_i)
priv_msb = np.array(list(map(lambda x: x >> (bit_size - 8), priv_data)), dtype=np.dtype("u1"))
- heatmap, xedges, yedges = np.histogram2d(priv_msb, gen_time_data, bins=[256, max_gen_time - min_gen_time])
- extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
+ max_msb = max(priv_msb)
+ min_msb = min(priv_msb)
+ heatmap, xedges, yedges = np.histogram2d(priv_msb, gen_time_data, bins=[max_msb - min_msb, max_gen_time - min_gen_time])
+ extent = [min_msb, max_msb, yedges[0], yedges[-1]]
axe_private.imshow(heatmap.T, extent=extent, aspect="auto", cmap=cmap, origin="low", interpolation="nearest", norm=norm)
- axe_private.set_xlabel("private key MSB value\n(big endian)")
+ axe_private.set_xlabel("private key MSB value")
axe_private.set_ylabel("keygen time ({})".format(gen_unit))
plot_i += 1
if plots[1]:
axe_hist = fig.add_subplot(n_plots, 1, plot_i)
- time_avg = np.average(gen_time_data)
- time_median = np.median(gen_time_data)
- axe_hist.hist(gen_time_data, bins=max_gen_time - min_gen_time, log=opts.log)
- axe_hist.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="blue", label="avg = {}".format(time_avg))
- axe_hist.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median))
- axe_hist.set_ylabel("count" + ("\n(log)" if opts.log else ""))
- axe_hist.set_xlabel("keygen time ({})".format(gen_unit))
- axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
- axe_hist.legend(loc="best")
+ plot_hist(axe_hist, gen_time_data, "keygen time ({})".format(gen_unit), opts.log)
plot_i += 1
if plots[2]:
axe_hist = fig.add_subplot(n_plots, 1, plot_i)
- time_max = max(export_time_data)
- time_min = min(export_time_data)
- time_avg = np.average(export_time_data)
- time_median = np.median(export_time_data)
- axe_hist.hist(export_time_data, bins=time_max - time_min, log=opts.log)
- axe_hist.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="blue", label="avg = {}".format(time_avg))
- axe_hist.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median))
- axe_hist.set_ylabel("count" + ("\n(log)" if opts.log else ""))
- axe_hist.set_xlabel("export time ({})".format(export_unit))
- axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
- axe_hist.legend(loc="best")
+ plot_hist(axe_hist, export_time_data, "export time ({})".format(export_unit), opts.log)
plot_i += 1
if plots[3]: