From 40ec0fea381a6538f5498b9fb75706ef9fa79f59 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Tue, 16 Oct 2018 00:57:24 +0200
Subject: Add support for BoringSSL.
---
src/cz/crcs/ectester/standalone/ECTesterStandalone.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 1d7b821..cb6728b 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -66,7 +66,7 @@ import java.util.stream.Collectors;
* @version v0.3.0
*/
public class ECTesterStandalone {
- private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new MscngLib()};
+ private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new MscngLib()};
private Config cfg;
private Options opts = new Options();
--
cgit v1.2.3-70-g09d2
From 030629076791f517622f7fc8fcfcf51e10f6e063 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Wed, 17 Oct 2018 00:23:07 +0200
Subject: Add libgcrypt support, only keygen first.
---
build-standalone.xml | 5 +
.../ectester/standalone/ECTesterStandalone.java | 2 +-
.../crcs/ectester/standalone/libs/GcryptLib.java | 20 ++
src/cz/crcs/ectester/standalone/libs/jni/Makefile | 71 ++++--
.../standalone/libs/jni/NativeECPrivateKey.java | 6 +
.../standalone/libs/jni/NativeECPublicKey.java | 6 +
.../libs/jni/NativeKeyPairGeneratorSpi.java | 18 ++
.../standalone/libs/jni/NativeProvider.java | 10 +
.../crcs/ectester/standalone/libs/jni/boringssl.c | 2 -
src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 284 +++++++++++++++++++++
src/cz/crcs/ectester/standalone/libs/jni/native.h | 105 ++++++++
src/cz/crcs/ectester/standalone/libs/jni/openssl.c | 2 -
12 files changed, 501 insertions(+), 30 deletions(-)
create mode 100644 src/cz/crcs/ectester/standalone/libs/GcryptLib.java
create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/build-standalone.xml b/build-standalone.xml
index c141509..84f4595 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -164,6 +164,11 @@
+
+
+
+
+
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index cb6728b..cc0e465 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -66,7 +66,7 @@ import java.util.stream.Collectors;
* @version v0.3.0
*/
public class ECTesterStandalone {
- private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new MscngLib()};
+ private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new GcryptLib(), new MscngLib()};
private Config cfg;
private Options opts = new Options();
diff --git a/src/cz/crcs/ectester/standalone/libs/GcryptLib.java b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
new file mode 100644
index 0000000..a0a7fc8
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
@@ -0,0 +1,20 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class GcryptLib extends NativeECLibrary {
+
+ public GcryptLib() {
+ super("gcrypt_provider", "gcrypt", "gpg-error");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index 189a6dd..2232e3d 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -1,3 +1,28 @@
+###############################################################################
+## General CC setup.
+
+CC?=gcc
+CXX?=g++
+
+LFLAGS+=-fPIC -shared
+CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+
+DEBUG ?= 0
+
+ifeq ($(DEBUG), 1)
+ CFLAGS+=-g -Wall
+ LFLAGS+=-g
+ CXXFLAGS+=-g -Wall
+else
+ CFLAGS+=-O2
+ LFLAGS+=-O2
+ CXXFLAGS+=-O2
+endif
+
+###############################################################################
+## Java JNI setup.
+
ifeq ($(JAVA_HOME),)
ifeq ($(OS),Windows_NT)
which = $(shell where $1)
@@ -24,37 +49,16 @@ ifeq ($(JNI_PLATFORM),)
else
ifeq ($(findstring linux,$(TARGETTRIPLET)),linux)
JNI_PLATFORM:= linux
- # add more checks here
endif
endif
endif
JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM)
-LOCAL_INCLUDES = /usr/local/include
-LOCAL_LIBS = /usr/local/lib
+###############################################################################
+## Targets.
-CC?=gcc
-CXX?=g++
-STRIP?=strip
-
-LFLAGS+=-fPIC -shared
-CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-
-DEBUG ?= 0
-
-ifeq ($(DEBUG), 1)
- CFLAGS+=-g
- LFLAGS+=-g
- CXXFLAGS+=-g
-else
- CFLAGS+=-O2
- LFLAGS+=-O2
- CXXFLAGS+=-O2
-endif
-
-all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so
+all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so gcrypt_provider.so
# Common utils
c_utils.o: c_utils.c
@@ -81,6 +85,14 @@ boringssl.o: boringssl.c
$(CC) -I../../../../../../../ext/boringssl/include/ $(CFLAGS) -c $<
+# libgcrypt shim
+gcrypt_provider.so: gcrypt.o c_utils.o
+ $(CC) $(LFLAGS) -o $@ $^ -L. $(shell libgcrypt-config --libs)
+
+gcrypt.o: gcrypt.c
+ $(CC) $(shell libgcrypt-config --cflags) $(CFLAGS) -c $<
+
+
# Libtomcrypt shim
tomcrypt_provider.so: tomcrypt.o c_utils.o
$(CC) $(LFLAGS) -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt)
@@ -104,9 +116,18 @@ cryptopp_provider.so: cryptopp.o cpp_utils.o
cryptopp.o: cryptopp.cpp
$(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $<
+help:
+ @echo "# This makefile builds the JNI shims necessary to test native libraries."
+ @echo "# Targets:"
+ @echo " - openssl_provider.so"
+ @echo " - boringssl_provider.so"
+ @echo " - gcrypt_provider.so"
+ @echo " - tomcrypt_provider.so"
+ @echo " - botan_provider.so"
+ @echo " - cryptopp_provider.so"
clean:
rm -rf *.o
rm -rf *.so
-.PHONY: all clean
\ No newline at end of file
+.PHONY: all help clean
\ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
index a74c155..6d8101f 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
@@ -91,6 +91,12 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
}
}
+ public static class Gcrypt extends Raw {
+ public Gcrypt(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
public static class Mscng extends Raw {
// 0 -> implicit (meta = curveName UTF16, header = full);
// 1 -> explicit (meta = null, header = full);
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
index 7c17646..dcb8b3f 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
@@ -92,6 +92,12 @@ public abstract class NativeECPublicKey implements ECPublicKey {
}
}
+ public static class Gcrypt extends ANSIX962 {
+ public Gcrypt(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
public static class Mscng extends ANSIX962 {
// 0 -> implicit (meta = curveName UTF16, header = full);
// 1 -> explicit (meta = null, header = full);
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
index 77f0d18..78656fc 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
@@ -198,6 +198,24 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
}
+ public static class Gcrypt extends NativeKeyPairGeneratorSpi {
+
+ public Gcrypt() {
+ }
+
+ @Override
+ native boolean keysizeSupported(int keysize);
+
+ @Override
+ native boolean paramsSupported(AlgorithmParameterSpec params);
+
+ @Override
+ native KeyPair generate(int keysize, SecureRandom random);
+
+ @Override
+ native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
+ }
+
public static abstract class Mscng extends NativeKeyPairGeneratorSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
index 1399500..99baa97 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
@@ -74,6 +74,16 @@ public abstract class NativeProvider extends Provider {
native void setup();
}
+ public static class Gcrypt extends NativeProvider {
+
+ public Gcrypt(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
+
public static class Mscng extends NativeProvider {
public Mscng(String name, double version, String info) {
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
index 0353741..965e396 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
@@ -1,6 +1,5 @@
#include "native.h"
#include
-#include
#include
#include
@@ -256,7 +255,6 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) {
jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a_int, b_int);
- fflush(stderr);
BN_free(a);
BN_free(b);
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
new file mode 100644
index 0000000..0705df6
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -0,0 +1,284 @@
+#include "native.h"
+#include
+#include
+#include "c_utils.h"
+
+static jclass provider_class;
+
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_createProvider(JNIEnv *env, jobject this){
+ /* Create the custom provider. */
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Gcrypt");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ const char *built_with = GCRYPT_VERSION;
+ const char *running_with = gcry_check_version(GCRYPT_VERSION);
+ if (!running_with) {
+ return NULL;
+ }
+ char full_name[strlen("libgcrypt ") + strlen(running_with) + 1];
+ strcpy(full_name, "libgcrypt ");
+ strcat(full_name, running_with);
+ jstring name = (*env)->NewStringUTF(env, full_name);
+ double version = strtod(running_with, NULL);
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+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);
+
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, this, "EC", "Gcrypt");
+ //ADD_KA(env, self, "ECDH", "OpensslECDH");
+ //ADD_SIG(env, self, "NONEwithECDSA", "OpensslECDSAwithNONE");
+
+ init_classes(env, "Gcrypt");
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getCurves(JNIEnv *env, jobject this) {
+ jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet");
+
+ jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "", "()V");
+ jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr);
+
+ const char *name;
+ unsigned int nbits;
+
+ for (size_t i = 0; (name = gcry_pk_get_curve(NULL, i, &nbits)); i++){
+ jstring curve_name = (*env)->NewStringUTF(env, name);
+ (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name);
+ }
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize) {
+ const char *name;
+ unsigned int nbits;
+
+ for (size_t i = 0; (name = gcry_pk_get_curve(NULL, i, &nbits)); i++){
+ if (nbits == keysize) {
+ return JNI_TRUE;
+ }
+ }
+
+ return JNI_FALSE;
+}
+
+static void print_sexp(gcry_sexp_t sexp) {
+ size_t len = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+ char string[len];
+ gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, string, len);
+ printf("%s\n", string);
+ fflush(stdout);
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_paramsSupported(JNIEnv *env, jobject this, jobject params) {
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ return JNI_FALSE;
+ } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL);
+ gcry_sexp_t curve_sexp;
+ gcry_sexp_build(&curve_sexp, NULL, "(public-key (ecc (curve %s)))", utf_name);
+ unsigned int nbits;
+ const char *ret_name = gcry_pk_get_curve(curve_sexp, 0, &nbits);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ gcry_sexp_release(curve_sexp);
+ return ret_name ? JNI_TRUE : JNI_FALSE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static jobject mpi_to_biginteger(JNIEnv *env, gcry_mpi_t mpi) {
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
+ size_t len = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
+ jbyteArray bytes = (*env)->NewByteArray(env, len);
+ jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL);
+ gcry_mpi_print(GCRYMPI_FMT_USG, data, len, &len, mpi);
+ (*env)->ReleaseByteArrayElements(env, bytes, data, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes);
+ return result;
+}
+
+static gcry_mpi_t biginteger_to_mpi(JNIEnv *env, jobject bigint) {
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, bigint, to_byte_array);
+ jsize byte_length = (*env)->GetArrayLength(env, byte_array);
+ jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ gcry_mpi_t result;
+ gcry_mpi_scan(&result, GCRYMPI_FMT_USG, byte_data, byte_length, NULL);
+ (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
+ return result;
+}
+
+static jint mpi_to_jint(gcry_mpi_t mpi) {
+ jint result = 0;
+ unsigned long nbits = gcry_mpi_get_nbits(mpi);
+ int max_bits = sizeof(jint) * 8;
+ for (size_t i = 0; i < nbits && i < max_bits; ++i) {
+ if (gcry_mpi_test_bit(mpi, nbits - i - 1)) {
+ result = ((result << 1) | 1);
+ } else {
+ result = (result << 1);
+ }
+ }
+ return result;
+}
+
+static jobject buff_to_ecpoint(JNIEnv *env, gcry_buffer_t buff) {
+ jint coord_size = (buff.size - 1) / 2;
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, coord_size);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, ((char *) buff.data) + 1, coord_size);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+ jobject xi = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, x_bytes);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, coord_size);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, ((char *) buff.data) + 1 + coord_size, coord_size);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+ jobject yi = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, y_bytes);
+
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ return (*env)->NewObject(env, point_class, point_init, xi, yi);
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, gcry_sexp_t key) {
+ jobject result = NULL;
+ gcry_mpi_t p, a, b, n, h;
+ gcry_buffer_t g = {0};
+ gcry_error_t err = gcry_sexp_extract_param(key, "ecc", "pab&g+nh", &p, &a, &b, &g, &n, &h, NULL);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error exporting domain parameters. Error: %ui", gcry_err_code(err));
+ goto end;
+ }
+
+ jobject pi = mpi_to_biginteger(env, p);
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V");
+ jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, pi);
+
+ jobject ai = mpi_to_biginteger(env, a);
+ jobject bi = mpi_to_biginteger(env, b);
+
+ jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, ai, bi);
+
+ jobject gen = buff_to_ecpoint(env, g);
+
+ jobject order = mpi_to_biginteger(env, n);
+ jint cofactor = mpi_to_jint(h);
+
+ jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ result = (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, gen, order, cofactor);
+
+end:
+ gcry_mpi_release(p);
+ gcry_mpi_release(a);
+ gcry_mpi_release(b);
+ gcry_free(g.data);
+ gcry_mpi_release(n);
+ gcry_mpi_release(h);
+ return result;
+}
+
+static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) {
+ jobject result = NULL;
+ gcry_sexp_t key_sexp;
+ gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp);
+ 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;
+ }
+ gcry_sexp_t pkey = gcry_sexp_find_token(key_sexp, "public-key", 0);
+ gcry_sexp_t skey = gcry_sexp_find_token(key_sexp, "private-key", 0);
+
+ jobject ec_param_spec = create_ec_param_spec(env, skey);
+ if (!ec_param_spec) {
+ goto release_keypair;
+ }
+
+ gcry_buffer_t q = {0};
+ gcry_mpi_t d;
+ err = gcry_sexp_extract_param(skey, "ecc", "&q+d", &q, &d, NULL);
+
+ jbyteArray pub_bytes = (*env)->NewByteArray(env, q.size);
+ jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
+ memcpy(key_pub, q.data, q.size);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
+
+ size_t priv_len = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &priv_len, d);
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, priv_len);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ gcry_mpi_print(GCRYMPI_FMT_USG, key_priv, priv_len, NULL, d);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_param_spec);
+
+ jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject privkey = (*env)->NewObject(env, privkey_class, ec_priv_init, priv_bytes, ec_priv_param_spec);
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+ result = (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+
+ gcry_mpi_release(d);
+ gcry_free(q.data);
+
+release_keypair:
+ gcry_sexp_release(pkey);
+ gcry_sexp_release(skey);
+release_sexp:
+ gcry_sexp_release(key_sexp);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject this, jint keysize, jobject random) {
+ gcry_sexp_t gen_sexp;
+ gcry_sexp_build(&gen_sexp, NULL, "(genkey (ecc (flags no-keytest param) (nbits %d)))", keysize);
+
+ jobject result = generate_from_sexp(env, gen_sexp);
+ gcry_sexp_release(gen_sexp);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject this, jobject params, jobject random) {
+
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ return NULL;
+ } else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
+ jmethodID get_name = (*env)->GetMethodID(env, ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;");
+ jstring name = (*env)->CallObjectMethod(env, params, get_name);
+ const char *utf_name = (*env)->GetStringUTFChars(env, name, NULL);
+ gcry_sexp_t gen_sexp;
+ gcry_sexp_build(&gen_sexp, NULL, "(genkey (ecc (flags no-keytest param) (curve %s)))", utf_name);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ jobject result = generate_from_sexp(env, gen_sexp);
+ gcry_sexp_release(gen_sexp);
+ return result;
+ } else {
+ return NULL;
+ }
+}
\ 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 eb64b53..e86a847 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1086,3 +1086,108 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
}
#endif
#endif
+/* Header for class cz_crcs_ectester_standalone_libs_GcryptLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_GcryptLib
+#define _Included_cz_crcs_ectester_standalone_libs_GcryptLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID 1421746759512286392LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID 4112578634029874840LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID -4298000515446427739LL
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt_DEFAULT_KEYSIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt_DEFAULT_KEYSIZE 256L
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2
+ (JNIEnv *, jobject, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
index 255834a..4ea5f6c 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -1,6 +1,5 @@
#include "native.h"
#include
-#include
#include
#include
@@ -327,7 +326,6 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) {
jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a_int, b_int);
- fflush(stderr);
BN_free(a);
BN_free(b);
--
cgit v1.2.3-70-g09d2
From ba5cfcc98d7bf5107e6aac3a4e5c7416ab7b76a7 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Wed, 17 Oct 2018 22:41:19 +0200
Subject: Add support for libgcrypt ecdh and ecdsa.
---
build-standalone.xml | 2 +
.../ectester/standalone/ECTesterStandalone.java | 2 +-
.../ectester/standalone/consts/SignatureIdent.java | 2 +-
.../standalone/libs/jni/NativeKeyAgreementSpi.java | 23 +-
.../standalone/libs/jni/NativeSignatureSpi.java | 91 ++++++
src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 101 +++++-
src/cz/crcs/ectester/standalone/libs/jni/c_utils.h | 11 +
src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 360 +++++++++++++++++++--
src/cz/crcs/ectester/standalone/libs/jni/native.h | 76 +++++
9 files changed, 645 insertions(+), 23 deletions(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/build-standalone.xml b/build-standalone.xml
index 84f4595..9a47642 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -169,6 +169,8 @@
+
+
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index cc0e465..7480215 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -325,7 +325,7 @@ public class ECTesterStandalone {
ECPublicKey pubkey = (ECPublicKey) other.getPublic();
long elapsed = -System.nanoTime();
- if (spec != null) {
+ if (spec instanceof ECParameterSpec) {
ka.init(privkey, spec);
} else {
ka.init(privkey);
diff --git a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
index dea8abe..93b7f99 100644
--- a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
@@ -52,7 +52,7 @@ public class SignatureIdent extends Ident {
ALL.add(new SignatureIdent("ECGOST3410-2012-512", "GOST-3410-2012-512"));
ALL.add(new SignatureIdent("GOST3411-2012-512withECGOST3410-2012-512", "GOST3411-2012-512/ECGOST3410-2012-5120", "1.2.643.7.1.1.3.3"));
ALL.add(new SignatureIdent("SM3withSM2"));
- // ECDDSA
+ // ECDDSA (rfc6979?)
ALL.add(new SignatureIdent("ECDDSA", "DETECDSA", "ECDETDSA"));
ALL.add(new SignatureIdent("SHA1withECDDSA", "SHA1withDETECDSA"));
ALL.add(new SignatureIdent("SHA224withECDDSA", "SHA224withDETECDSA"));
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index 5fca448..7b531f5 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -65,7 +65,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
@Override
protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
if (!(params instanceof ECParameterSpec)) {
- throw new InvalidAlgorithmParameterException();
+ throw new InvalidAlgorithmParameterException(params.toString());
}
engineInit(key, random);
this.params = params;
@@ -254,6 +254,27 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
}
+ public abstract static class Gcrypt extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public Gcrypt(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native SecretKey generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params, String algorithm);
+ }
+
+ public static class GcryptECDH extends Gcrypt {
+ public GcryptECDH() {
+ super("ECDH");
+ }
+ }
+
+
public abstract static class Mscng extends ExtendedKeyAgreementSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index 3f99771..f2b1ab9 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -349,6 +349,97 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
}
}
+ public abstract static class Gcrypt extends SimpleSignatureSpi {
+ private String type;
+
+ public Gcrypt(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class GcryptECDSAwithNONE extends Gcrypt {
+
+ public GcryptECDSAwithNONE() {
+ super("NONEwithECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA1 extends Gcrypt {
+
+ public GcryptECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA224 extends Gcrypt {
+
+ public GcryptECDSAwithSHA224() {
+ super("SHA224withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA256 extends Gcrypt {
+
+ public GcryptECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA384 extends Gcrypt {
+
+ public GcryptECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA512 extends Gcrypt {
+
+ public GcryptECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA1 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA1() {
+ super("SHA1withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA224 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA224() {
+ super("SHA224withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA256 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA256() {
+ super("SHA256withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA384 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA384() {
+ super("SHA384withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA512 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA512() {
+ super("SHA512withECDDSA");
+ }
+ }
+
public abstract static class Mscng extends ExtendedSignatureSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
index 49cab44..c36d3c9 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
@@ -75,7 +75,7 @@ void throw_new_var(JNIEnv *env, const char *class, const char *format, ...) {
char buffer[2048];
va_list args;
va_start(args, format);
- int res = vsnprintf(buffer, 2048, format, args);
+ vsnprintf(buffer, 2048, format, args);
va_end(args);
throw_new(env, class, buffer);
}
@@ -105,4 +105,103 @@ jint get_kdf_bits(JNIEnv *env, jstring algorithm) {
}
(*env)->ReleaseStringUTFChars(env, algorithm, algo_data);
return result;
+}
+
+jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyte *s, size_t s_len) {
+ jbyte r_length = (jbyte) r_len + (r[0] & 0x80 ? 1 : 0);
+ jbyte s_length = (jbyte) s_len + (s[0] & 0x80 ? 1 : 0);
+
+ // R and S are < 128 bytes, so 1 byte tag + 1 byte len + len bytes value
+ size_t seq_value_len = 2 + r_length + 2 + s_length;
+ size_t whole_len = seq_value_len;
+
+ // The SEQUENCE length might be >= 128, so more bytes of length
+ size_t seq_len_len = 0;
+ if (seq_value_len >= 128) {
+ size_t s = seq_value_len;
+ while ((s = s >> 8)) {
+ seq_len_len++;
+ }
+ }
+ // seq_len_len bytes for length and one for length of length
+ whole_len += seq_len_len + 1;
+
+ // 1 byte tag for SEQUENCE
+ whole_len += 1;
+
+ jbyteArray result = (jbyteArray) (*env)->NewByteArray(env, whole_len);
+ jbyte *data = (*env)->GetByteArrayElements(env, result, NULL);
+ size_t i = 0;
+ data[i++] = 0x30; // SEQUENCE
+ if (seq_value_len < 128) {
+ data[i++] = (jbyte) seq_value_len;
+ } else {
+ data[i++] = (jbyte) (seq_len_len | (1 << 7));
+ for (size_t j = 0; j < seq_len_len; ++j) {
+ data[i++] = (jbyte) (seq_value_len & (0xff << (seq_len_len - j)));
+ }
+ }
+ data[i++] = 0x02; //INTEGER
+ data[i++] = r_length;
+ if (r[0] & 0x80) {
+ data[i++] = 0;
+ }
+ memcpy(data + i, r, r_len);
+ i += r_len;
+ data[i++] = 0x02; //INTEGER
+ data[i++] = s_length;
+ if (s[0] & 0x80) {
+ data[i++] = 0;
+ }
+ memcpy(data + i, s, s_len);
+ i += s_len;
+ (*env)->ReleaseByteArrayElements(env, result, data, 0);
+
+ return result;
+}
+
+bool asn1_der_decode(JNIEnv *env, jbyteArray sig, jbyte **r_data, size_t *r_len, jbyte **s_data, size_t *s_len) {
+ size_t sig_len = (*env)->GetArrayLength(env, sig);
+ jbyte *data = (*env)->GetByteArrayElements(env, sig, NULL);
+ size_t i = 0;
+ if (data[i++] != 0x30) {//SEQUENCE
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t seq_value_len = 0;
+ if (!(data[i] & 0x80)) {
+ seq_value_len = data[i++];
+ } else {
+ size_t seq_len_len = data[i++] & 0x7f;
+ while (seq_len_len > 0) {
+ seq_value_len |= (data[i++] << (seq_len_len - 1));
+ seq_len_len--;
+ }
+ }
+
+ if (data[i++] != 0x02) {//INTEGER
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t r_length = data[i++];
+ jbyte *r_out = malloc(r_length);
+ memcpy(r_out, data + i, r_length);
+ i += r_length;
+
+ if (data[i++] != 0x02) {//INTEGER
+ free(r_out);
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t s_length = data[i++];
+ jbyte *s_out = malloc(s_length);
+ memcpy(s_out, data + i, s_length);
+ i += s_length;
+
+ *r_len = r_length;
+ *r_data = r_out;
+ *s_len = s_length;
+ *s_data = s_out;
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return true;
}
\ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
index b767b61..82c3538 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
@@ -1,6 +1,7 @@
#pragma once
#include "native.h"
+#include
/**
* Classes that are accessed alot are cached here, manually.
@@ -38,6 +39,16 @@ void throw_new_var(JNIEnv *env, const char *class, const char *format, ...);
*/
jint get_kdf_bits(JNIEnv *env, jstring algorithm);
+/**
+ * DER encode the r and s values.
+ */
+jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyte *s, size_t s_len);
+
+/**
+ * DER decode a signature into r and s values.
+ */
+bool asn1_der_decode(JNIEnv *env, jbyteArray sig, jbyte **r_data, size_t *r_len, jbyte **s_data, size_t *s_len);
+
/**
* Some useful defines to init the provider.
*/
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
index 0705df6..0ba94c6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -1,5 +1,7 @@
#include "native.h"
#include
+#include
+#include
#include
#include "c_utils.h"
@@ -13,7 +15,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_create
jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V");
- const char *built_with = GCRYPT_VERSION;
const char *running_with = gcry_check_version(GCRYPT_VERSION);
if (!running_with) {
return NULL;
@@ -36,8 +37,18 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
INIT_PROVIDER(env, provider_class);
ADD_KPG(env, this, "EC", "Gcrypt");
- //ADD_KA(env, self, "ECDH", "OpensslECDH");
- //ADD_SIG(env, self, "NONEwithECDSA", "OpensslECDSAwithNONE");
+ ADD_KA(env, this, "ECDH", "GcryptECDH");
+ ADD_SIG(env, this, "NONEwithECDSA", "GcryptECDSAwithNONE");
+ ADD_SIG(env, this, "SHA1withECDSA", "GcryptECDSAwithSHA1");
+ ADD_SIG(env, this, "SHA224withECDSA", "GcryptECDSAwithSHA224");
+ ADD_SIG(env, this, "SHA256withECDSA", "GcryptECDSAwithSHA256");
+ ADD_SIG(env, this, "SHA384withECDSA", "GcryptECDSAwithSHA384");
+ ADD_SIG(env, this, "SHA512withECDSA", "GcryptECDSAwithSHA512");
+ ADD_SIG(env, this, "SHA1withECDDSA", "GcryptECDDSAwithSHA1");
+ ADD_SIG(env, this, "SHA224withECDDSA", "GcryptECDDSAwithSHA224");
+ ADD_SIG(env, this, "SHA256withECDDSA", "GcryptECDDSAwithSHA256");
+ ADD_SIG(env, this, "SHA384withECDDSA", "GcryptECDDSAwithSHA384");
+ ADD_SIG(env, this, "SHA512withECDDSA", "GcryptECDDSAwithSHA512");
init_classes(env, "Gcrypt");
}
@@ -82,6 +93,13 @@ static void print_sexp(gcry_sexp_t sexp) {
fflush(stdout);
}
+static void print_chrray(unsigned char *arr, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ printf("%02x,", ((unsigned char) arr[i] & 0xff));
+ }
+ printf("\n");
+}
+
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_paramsSupported(JNIEnv *env, jobject this, jobject params) {
if (params == NULL) {
return JNI_FALSE;
@@ -105,28 +123,66 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa
}
}
-static jobject mpi_to_biginteger(JNIEnv *env, gcry_mpi_t mpi) {
- jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
- size_t len = 0;
- gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
- jbyteArray bytes = (*env)->NewByteArray(env, len);
+static gcry_mpi_t bytearray_to_mpi(JNIEnv *env, jbyteArray array) {
+ if (!array) {
+ return NULL;
+ }
+
+ gcry_mpi_t result;
+
+ size_t length = (*env)->GetArrayLength(env, array);
+ char data[length + 1];
+ data[0] = 0;
+ (*env)->GetByteArrayRegion(env, array, 0, length, data + 1);
+ gcry_mpi_scan(&result, GCRYMPI_FMT_USG, data, length + 1, NULL);
+ return result;
+}
+
+static jbyteArray mpi_to_bytearray0(JNIEnv *env, gcry_mpi_t mpi, size_t start, size_t len) {
+ if (!mpi) {
+ return NULL;
+ }
+
+ size_t mpi_len = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &mpi_len, mpi);
+ if (start >= mpi_len) {
+ return NULL;
+ }
+ if (start + len > mpi_len || len == 0) {
+ len = mpi_len - start;
+ }
+ unsigned char buff[mpi_len];
+ gcry_mpi_print(GCRYMPI_FMT_USG, buff, mpi_len, NULL, mpi);
+ jbyteArray bytes = (*env)->NewByteArray(env, len);
jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL);
- gcry_mpi_print(GCRYMPI_FMT_USG, data, len, &len, mpi);
+ memcpy(data, buff + start, len);
(*env)->ReleaseByteArrayElements(env, bytes, data, 0);
+ return bytes;
+}
+
+static jbyteArray mpi_to_bytearray(JNIEnv *env, gcry_mpi_t mpi) {
+ return mpi_to_bytearray0(env, mpi, 0, 0);
+}
+
+static jobject mpi_to_biginteger(JNIEnv *env, gcry_mpi_t mpi) {
+ if (!mpi) {
+ return NULL;
+ }
+
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
+ jbyteArray bytes = mpi_to_bytearray(env, mpi);
jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes);
return result;
}
static gcry_mpi_t biginteger_to_mpi(JNIEnv *env, jobject bigint) {
- jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+ if (!bigint) {
+ return NULL;
+ }
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, bigint, to_byte_array);
- jsize byte_length = (*env)->GetArrayLength(env, byte_array);
- jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL);
- gcry_mpi_t result;
- gcry_mpi_scan(&result, GCRYMPI_FMT_USG, byte_data, byte_length, NULL);
- (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
- return result;
+ return bytearray_to_mpi(env, byte_array);
}
static jint mpi_to_jint(gcry_mpi_t mpi) {
@@ -144,7 +200,7 @@ static jint mpi_to_jint(gcry_mpi_t mpi) {
}
static jobject buff_to_ecpoint(JNIEnv *env, gcry_buffer_t buff) {
- jint coord_size = (buff.size - 1) / 2;
+ jint coord_size = (buff.len - 1) / 2;
jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
jbyteArray x_bytes = (*env)->NewByteArray(env, coord_size);
@@ -235,7 +291,7 @@ static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) {
jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
- jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_param_spec);
+ jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_pub_param_spec);
jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -265,7 +321,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
}
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject this, jobject params, jobject random) {
-
if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
return NULL;
} else if ((*env)->IsInstanceOf(env, params, ecgen_parameter_spec_class)) {
@@ -281,4 +336,271 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
} else {
return NULL;
}
+}
+
+static gcry_sexp_t create_key(JNIEnv *env, jobject ec_param_spec, const char *key_fmt, gcry_mpi_t q, gcry_mpi_t d) {
+ gcry_sexp_t inner;
+ gcry_mpi_t p, a, b, g, n, h;
+
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, ec_param_spec, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ jint bytes = (bits + 7) / 8;
+
+ jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject big_a = (*env)->CallObjectMethod(env, elliptic_curve, get_a);
+ a = biginteger_to_mpi(env, big_a);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject big_b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
+ b = biginteger_to_mpi(env, big_b);
+
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject big_p = (*env)->CallObjectMethod(env, field, get_p);
+ p = biginteger_to_mpi(env, big_p);
+
+ jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g_point = (*env)->CallObjectMethod(env, ec_param_spec, get_g);
+
+ jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = (*env)->CallObjectMethod(env, g_point, get_x);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g_point, get_y);
+
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray gx_bytes = (jbyteArray) (*env)->CallObjectMethod(env, gx, to_byte_array);
+ size_t gx_len = (*env)->GetArrayLength(env, gx_bytes);
+ jbyteArray gy_bytes = (jbyteArray) (*env)->CallObjectMethod(env, gy, to_byte_array);
+ size_t gy_len = (*env)->GetArrayLength(env, gy_bytes);
+ unsigned char g_data[1 + 2 * bytes];
+ g_data[0] = 0x04;
+ jbyte *gx_data = (*env)->GetByteArrayElements(env, gx_bytes, NULL);
+ memcpy(g_data + 1, gx_data + (gx_len - bytes), bytes);
+ (*env)->ReleaseByteArrayElements(env, gx_bytes, gx_data, JNI_ABORT);
+ jbyte *gy_data = (*env)->GetByteArrayElements(env, gy_bytes, NULL);
+ memcpy(g_data + 1 + bytes, gy_data + (gy_len - bytes), bytes);
+ (*env)->ReleaseByteArrayElements(env, gy_bytes, gy_data, JNI_ABORT);
+
+ gcry_mpi_scan(&g, GCRYMPI_FMT_USG, g_data, 1 + 2 * bytes, NULL);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject big_n = (*env)->CallObjectMethod(env, ec_param_spec, get_n);
+ n = biginteger_to_mpi(env, big_n);
+
+ jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I");
+ jint jh = (*env)->CallIntMethod(env, ec_param_spec, get_h);
+ h = gcry_mpi_set_ui(NULL, jh);
+
+ if (q && d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (q %M) (d %M))", p, a, b, g, n, h, q, d, NULL);
+ } else if (q && !d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (q %M))", p, a, b, g, n, h, q, NULL);
+ } else if (!q && d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (d %M))", p, a, b, g, n, h, d, NULL);
+ }
+ gcry_sexp_t result;
+ gcry_sexp_build(&result, NULL, key_fmt, inner, NULL);
+ gcry_sexp_release(inner);
+ return result;
+}
+
+static gcry_sexp_t create_pubkey(JNIEnv *env, jobject ec_param_spec, jbyteArray pubkey) {
+ gcry_mpi_t q = bytearray_to_mpi(env, pubkey);
+ gcry_sexp_t result = create_key(env, ec_param_spec, "(public-key %S)", q, NULL);
+ gcry_mpi_release(q);
+ return result;
+}
+
+static gcry_sexp_t create_privkey(JNIEnv *env, jobject ec_param_spec, jbyteArray pubkey, jbyteArray privkey) {
+ gcry_mpi_t q = bytearray_to_mpi(env, pubkey);
+ gcry_mpi_t d = bytearray_to_mpi(env, privkey);
+ gcry_sexp_t result = create_key(env, ec_param_spec, "(private-key %S)", q, d);
+ gcry_mpi_release(q);
+ gcry_mpi_release(d);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ jbyteArray result = NULL;
+ gcry_sexp_t pub = create_pubkey(env, params, pubkey);
+ gcry_mpi_t priv = bytearray_to_mpi(env, privkey);
+
+ gcry_sexp_t enc_sexp;
+ 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.
+ gcry_error_t err = gcry_pk_encrypt(&res_sexp, enc_sexp, pub);
+ 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;
+ }
+
+ gcry_mpi_t derived;
+ err = gcry_sexp_extract_param(res_sexp, NULL, "s", &derived, NULL);
+
+ size_t derived_bytes;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &derived_bytes, derived);
+ size_t coord_bytes = (derived_bytes - 1) / 2;
+ result = mpi_to_bytearray0(env, derived, 1, coord_bytes);
+
+ gcry_mpi_release(derived);
+end:
+ gcry_sexp_release(enc_sexp);
+ gcry_sexp_release(res_sexp);
+ gcry_sexp_release(pub);
+ gcry_mpi_release(priv);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params, jstring algorithm) {
+ throw_new(env, "java/lang/UnsupportedOperationException", "Not supported.");
+ return NULL;
+}
+
+static int starts_with(const char *whole, const char *prefix) {
+ return !strncmp(whole, prefix, strlen(prefix));
+}
+
+static int get_hash_algo(const char *sig_type) {
+ if (starts_with(sig_type, "SHA1")) {
+ return GCRY_MD_SHA1;
+ } else if (starts_with(sig_type, "SHA224")) {
+ return GCRY_MD_SHA224;
+ } else if (starts_with(sig_type, "SHA256")) {
+ return GCRY_MD_SHA256;
+ } else if (starts_with(sig_type, "SHA384")) {
+ return GCRY_MD_SHA384;
+ } else if (starts_with(sig_type, "SHA512")) {
+ return GCRY_MD_SHA512;
+ } else {
+ return GCRY_MD_NONE;
+ }
+}
+
+static const char *get_sig_algo(const char *sig_type) {
+ const char *start = strstr(sig_type, "with") + strlen("with");
+ if (starts_with(start, "ECDSA")) {
+ return NULL;
+ } else if (starts_with(start, "ECDDSA")) {
+ return "rfc6979";
+ } else {
+ return NULL;
+ }
+}
+
+static void get_sign_data_sexp(JNIEnv *env, gcry_sexp_t *result, jobject this, jbyteArray data) {
+ jclass sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Gcrypt");
+ jfieldID type_id = (*env)->GetFieldID(env, sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, this, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ int hash_algo = get_hash_algo(type_data);
+ const char *sig_algo = get_sig_algo(type_data);
+ const char *with = strstr(type_data, "with");
+ char hash_name[with - type_data + 1];
+ memcpy(hash_name, type_data, with - type_data);
+ for (size_t i = 0; i < with - type_data; ++i) {
+ hash_name[i] = tolower(hash_name[i]);
+ }
+ hash_name[with - type_data] = 0;
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ if (hash_algo == GCRY_MD_NONE) {
+ gcry_mpi_t data_mpi = bytearray_to_mpi(env, data);
+ gcry_sexp_build(result, NULL, "(data (flags raw param) (value %M))", data_mpi);
+ gcry_mpi_release(data_mpi);
+ } else {
+ unsigned int hash_len = gcry_md_get_algo_dlen(hash_algo);
+ size_t data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ unsigned char out_hash[hash_len];
+ gcry_md_hash_buffer(hash_algo, out_hash, data_bytes, data_len);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ gcry_mpi_t hash_mpi;
+ gcry_mpi_scan(&hash_mpi, GCRYMPI_FMT_USG, out_hash, hash_len, NULL);
+ if (!sig_algo) {
+ gcry_sexp_build(result, NULL, "(data (flags raw param) (value %M))", hash_mpi);
+ } else {
+ gcry_sexp_build(result, NULL, "(data (flags %s param) (hash %s %M))", sig_algo, hash_name, hash_mpi);
+ }
+ gcry_mpi_release(hash_mpi);
+ }
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_sign(JNIEnv *env, jobject this, jbyteArray data, jbyteArray privkey, jobject params) {
+ jbyteArray result = NULL;
+ gcry_sexp_t priv_sexp = create_privkey(env, params, NULL, privkey);
+
+ gcry_sexp_t data_sexp;
+ get_sign_data_sexp(env, &data_sexp, this, data);
+
+ gcry_sexp_t res_sexp;
+ gcry_error_t err = gcry_pk_sign(&res_sexp, data_sexp, priv_sexp);
+ 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;
+ }
+
+ gcry_buffer_t r_buf = {0};
+ gcry_buffer_t s_buf = {0};
+ err = gcry_sexp_extract_param(res_sexp, "ecdsa", "&rs", &r_buf, &s_buf, NULL);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error extracting ECDSA output. Error: %ui", gcry_err_code(err));
+ goto release_res;
+ }
+ result = asn1_der_encode(env, r_buf.data, r_buf.len, s_buf.data, s_buf.len);
+
+ gcry_free(r_buf.data);
+ gcry_free(s_buf.data);
+release_res:
+ gcry_sexp_release(res_sexp);
+release_init:
+ gcry_sexp_release(priv_sexp);
+ gcry_sexp_release(data_sexp);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_verify(JNIEnv *env, jobject this, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) {
+ jboolean result = JNI_FALSE;
+ gcry_sexp_t pub_sexp = create_pubkey(env, params, pubkey);
+
+ gcry_sexp_t data_sexp;
+ get_sign_data_sexp(env, &data_sexp, this, data);
+
+ size_t r_len, s_len;
+ jbyte *r_data, *s_data;
+ bool decode = asn1_der_decode(env, sig, &r_data, &r_len, &s_data, &s_len);
+ if (!decode) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error decoding sig.");
+ goto release_init;
+ }
+
+ gcry_mpi_t r_mpi, s_mpi;
+ gcry_mpi_scan(&r_mpi, GCRYMPI_FMT_USG, r_data, r_len, NULL);
+ gcry_mpi_scan(&s_mpi, GCRYMPI_FMT_USG, s_data, s_len, NULL);
+ free(r_data);
+ free(s_data);
+
+ gcry_sexp_t sig_sexp;
+ gcry_sexp_build(&sig_sexp, NULL, "(sig-val (ecdsa (r %M) (s %M)))", r_mpi, s_mpi);
+ gcry_error_t err = gcry_pk_verify(sig_sexp, data_sexp, pub_sexp);
+ 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.");
+ goto release_init;
+ }
+ } else {
+ result = JNI_TRUE;
+ }
+
+release_init:
+ gcry_sexp_release(pub_sexp);
+ gcry_sexp_release(data_sexp);
+ return result;
}
\ 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 e86a847..47031e4 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1191,3 +1191,79 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
}
#endif
#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;Ljava/lang/String;)Ljavax/crypto/SecretKey;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--
cgit v1.2.3-70-g09d2
From f59aaf972a83330206e8b0d2e1819f45da38f74e Mon Sep 17 00:00:00 2001
From: J08nY
Date: Sun, 11 Nov 2018 17:51:53 +0100
Subject: Add WolfCrypt provider to testing.
---
README.md | 1 +
docs/LIBS.md | 2 ++
lib/wolfcrypt-jni.jar | Bin 0 -> 83453 bytes
nbproject/standalone/manifest.mf | 2 +-
nbproject/standalone/project.properties | 1 +
.../crcs/ectester/standalone/ECTesterStandalone.java | 13 ++++++++++++-
.../crcs/ectester/standalone/libs/WolfCryptLib.java | 18 ++++++++++++++++++
7 files changed, 35 insertions(+), 2 deletions(-)
create mode 100644 lib/wolfcrypt-jni.jar
create mode 100644 src/cz/crcs/ectester/standalone/libs/WolfCryptLib.java
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/README.md b/README.md
index d70ae9b..d23922d 100644
--- a/README.md
+++ b/README.md
@@ -270,6 +270,7 @@ Currently supported libraries include:
- [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC)
- [OpenSSL](https://www.openssl.org/)
- [BoringSSL](https://boringssl.googlesource.com/boringssl)
+ - [wolfSSL](https://www.wolfssl.com/)
- [Crypto++](https://cryptopp.com/)
- [libtomcrypt](http://www.libtom.net/LibTomCrypt/)
- [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/)
diff --git a/docs/LIBS.md b/docs/LIBS.md
index faab84d..d41f98a 100644
--- a/docs/LIBS.md
+++ b/docs/LIBS.md
@@ -55,6 +55,8 @@ Libraries that ECTester can test.
- Uses Lopez-Dahab (Montgomery) ladder, XZ coordinates (ec2_mont.c): Fast multiplication on elliptic curves over GF(2^m) without precomputation (Algorithm 2P)
- Contains an implementation of IEEE P1363 algorithm A.10.3 using affine coordinates (ec2_aff.c)
- Has some custom arithmetic for some of the NIST primes.
+ - [WolfCrypt](https://www.wolfssl.com)
+ - C + Java
- [OpenSSL](https://www.openssl.org/)
- C
- For prime field curves:
diff --git a/lib/wolfcrypt-jni.jar b/lib/wolfcrypt-jni.jar
new file mode 100644
index 0000000..890ae14
Binary files /dev/null and b/lib/wolfcrypt-jni.jar differ
diff --git a/nbproject/standalone/manifest.mf b/nbproject/standalone/manifest.mf
index 5e8f5d9..ad7aacb 100644
--- a/nbproject/standalone/manifest.mf
+++ b/nbproject/standalone/manifest.mf
@@ -1,4 +1,4 @@
Manifest-Version: 1.0
-Class-Path: lib/bcprov-jdk15on-1.58.jar lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.4.jar lib/snakeyaml-1.19.jar
+Class-Path: lib/bcprov-jdk15on-1.58.jar lib/wolfcrypt-jni.jar lib/jcardsim-3.0.4-SNAPSHOT.jar lib/commons-cli-1.4.jar lib/snakeyaml-1.19.jar
Main-Class: cz.crcs.ectester.standalone.ECTesterStandalone
diff --git a/nbproject/standalone/project.properties b/nbproject/standalone/project.properties
index 6b6d440..29ad3cc 100644
--- a/nbproject/standalone/project.properties
+++ b/nbproject/standalone/project.properties
@@ -34,6 +34,7 @@ includes=**/common/**,**/standalone/**,**/data/**,**/applet/*
jar.compress=true
javac.classpath=\
lib/bcprov-jdk15on-1.58.jar:\
+ lib/wolfcrypt-jni.jar:\
lib/jcardsim-3.0.4-SNAPSHOT.jar:\
lib/commons-cli-1.4.jar:\
lib/snakeyaml-1.19.jar
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 7480215..b6f5478 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -49,6 +49,7 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.nio.file.Files;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
@@ -66,7 +67,17 @@ import java.util.stream.Collectors;
* @version v0.3.0
*/
public class ECTesterStandalone {
- private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new GcryptLib(), new MscngLib()};
+ private ProviderECLibrary[] libs = new ProviderECLibrary[]{
+ new SunECLib(),
+ new BouncyCastleLib(),
+ new TomcryptLib(),
+ new BotanLib(),
+ new CryptoppLib(),
+ new OpensslLib(),
+ new BoringsslLib(),
+ new GcryptLib(),
+ new MscngLib(),
+ new WolfCryptLib()};
private Config cfg;
private Options opts = new Options();
diff --git a/src/cz/crcs/ectester/standalone/libs/WolfCryptLib.java b/src/cz/crcs/ectester/standalone/libs/WolfCryptLib.java
new file mode 100644
index 0000000..b58eb91
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/WolfCryptLib.java
@@ -0,0 +1,18 @@
+package cz.crcs.ectester.standalone.libs;
+
+import com.wolfssl.provider.jce.WolfCryptProvider;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class WolfCryptLib extends ProviderECLibrary {
+
+ public WolfCryptLib() {
+ super(new WolfCryptProvider());
+ }
+
+ @Override
+ public Set getCurves() {
+ return new HashSet<>();
+ }
+}
--
cgit v1.2.3-70-g09d2
From 105228a6e842df46ba8523fc5214b3a8833cbef0 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Sun, 18 Nov 2018 19:37:59 +0100
Subject: Output duration of keygen and export as well.
---
src/cz/crcs/ectester/reader/ECTesterReader.java | 5 +-
.../ectester/standalone/ECTesterStandalone.java | 6 +-
util/plot_gen.py | 151 +++++++++++++--------
3 files changed, 97 insertions(+), 65 deletions(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java
index 377e2ff..abc7264 100644
--- a/src/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/src/cz/crcs/ectester/reader/ECTesterReader.java
@@ -439,7 +439,7 @@ public class ECTesterReader {
respWriter.outputResponse(allocate);
OutputStreamWriter keysFile = FileUtil.openFiles(cfg.outputs);
- keysFile.write("index;time;pubW;privS\n");
+ keysFile.write("index;genTime;exportTime;pubW;privS\n");
int generated = 0;
int retry = 0;
@@ -451,7 +451,6 @@ public class ECTesterReader {
Command.Generate generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL);
Response.Generate response = generate.send();
- long elapsed = response.getDuration();
respWriter.outputResponse(response);
Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR).send();
@@ -469,7 +468,7 @@ public class ECTesterReader {
String pub = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W), false);
String priv = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S), false);
- String line = String.format("%d;%d;%s;%s\n", generated, elapsed / 1000000, pub, priv);
+ String line = String.format("%d;%d;%d;%s;%s\n", generated, response.getDuration() / 1000000, export.getDuration() / 1000000, pub, priv);
keysFile.write(line);
keysFile.flush();
generated++;
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index b6f5478..e75274d 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -325,7 +325,7 @@ public class ECTesterStandalone {
kpg.initialize(spec);
}
- System.out.println("index;nanotime;pubW;privS;secret");
+ System.out.println("index;time[nano];pubW;privS;secret");
int amount = Integer.parseInt(cli.getOptionValue("ecdh.amount", "1"));
for (int i = 0; i < amount; ++i) {
@@ -435,7 +435,7 @@ public class ECTesterStandalone {
kpg.initialize(new ECGenParameterSpec(curveName));
}
- System.out.println("index;data;signtime;verifytime;pubW;privS;signature;verified");
+ System.out.println("index;data;signTime[nano];verifyTime[nano];pubW;privS;signature;verified");
int amount = Integer.parseInt(cli.getOptionValue("ecdsa.amount", "1"));
for (int i = 0; i < amount; ++i) {
@@ -499,7 +499,7 @@ public class ECTesterStandalone {
String curveName = cli.getOptionValue("generate.curve-name");
kpg.initialize(new ECGenParameterSpec(curveName));
}
- System.out.println("index;nanotime;pubW;privS");
+ System.out.println("index;time[nano];pubW;privS");
int amount = Integer.parseInt(cli.getOptionValue("generate.amount", "1"));
for (int i = 0; i < amount; ++i) {
diff --git a/util/plot_gen.py b/util/plot_gen.py
index 98d8261..f6cd8e4 100755
--- a/util/plot_gen.py
+++ b/util/plot_gen.py
@@ -13,19 +13,24 @@
import numpy as np
import matplotlib.pyplot as plt
-import matplotlib.ticker as ticker
-import matplotlib.colors as colors
-from operator import itemgetter
+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
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plot results of ECTester key generation 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("--pub", dest="pub", action="store_true", help="Show public key scatter plot.")
- parser.add_argument("--priv", dest="priv", action="store_true", help="Show private key scatter plot.")
- parser.add_argument("--hist", dest="hist", action="store_true", help="Show histogram.")
- parser.add_argument("--hw-hist", dest="hw_hist", action="store_true", help="Show Hamming weight 2D histogram (private key Hamming weight and generation time).")
+ 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 keygen time histogram.")
+ parser.add_argument("--export-hist", dest="export_hist", action="store_true", help="Show export time histogram.")
+ parser.add_argument("--hw-hist", dest="hw_hist", action="store_true", help="Show Hamming weight heatmap (private key Hamming weight and keygen time).")
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("-t", "--title", dest="title", type=str, nargs="?", default="", help="What title to give the figure.")
parser.add_argument("file", type=str, help="The file to plot(csv).")
@@ -35,99 +40,127 @@ if __name__ == "__main__":
with open(opts.file, "r") as f:
header = f.readline()
header_names = header.split(";")
+ if len(header_names) not in (4, 5):
+ print("Bad data?")
+ exit(1)
- plots = [opts.priv, opts.pub, opts.hist, opts.hw_hist]
+ plots = [opts.priv, opts.hist, opts.export_hist, opts.hw_hist]
n_plots = sum(plots)
if n_plots == 0:
- n_plots = 4
- plots = [True, True, True, True]
+ if len(header_names) == 4:
+ n_plots = 3
+ else:
+ n_plots = 4
+ plots = [True for _ in range(n_plots)]
+
+ if plots[2] and len(header_names) != 5:
+ n_plots = n_plots - 1
+ if n_plots == 0:
+ print("Nothing to plot.")
+ exit(1)
+ plots[2] = False
hx = lambda x: int(x, 16)
- data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={2: hx, 3: hx}, dtype=np.dtype([("index","u4"), ("time","u4"), ("pub", "O"), ("priv", "O")]))
+ if len(header_names) == 4:
+ data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={2: hx, 3: hx}, dtype=np.dtype([("index", "u4"), ("gen_time", "u4"), ("pub", "O"), ("priv", "O")]))
+ else:
+ data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={3: hx, 4: hx}, dtype=np.dtype([("index", "u4"), ("gen_time", "u4"), ("export_time", "u4"), ("pub", "O"), ("priv", "O")]))
+
if opts.skip_first:
data = data[1:]
- if "nano" in header_names[1]:
- unit = r"$\mu s$"
- time_data = map(lambda x: x[1]//1000, 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))
+ gen_time_data = data["gen_time"]
+ export_time_data = None
+ if "export_time" in data.dtype.names:
+ export_time_data = data["export_time"]
+ pub_data = data["pub"]
+ priv_data = data["priv"]
+
+
+ gen_unit = "ms"
+ if header_names[1].endswith("[nano]"):
+ gen_unit = r"$\mu s$"
+ gen_time_data = list(map(lambda x: x[1]//1000, gen_time_data))
+ export_unit = "ms"
+ if len(header_names) == 5 and header_names[2].endswith("[nano]"):
+ export_unit = r"$\mu s$"
+ export_time_data = list(map(lambda x: x[1]//1000, export_time_data))
plt.style.use("ggplot")
fig = plt.figure()
layout_kwargs = {}
if opts.title is None:
fig.suptitle(opts.file)
- layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ #layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
elif opts.title:
fig.suptitle(opts.title)
- layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
- fig.tight_layout(**layout_kwargs)
+ #layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ fig.tight_layout(**layout_kwargs)
+
+ max_gen_time = max(gen_time_data)
+ min_gen_time = min(gen_time_data)
+ bit_size = len(bin(max(priv_data))) - 2
+
+ cmap = deepcopy(plt.cm.plasma)
+ cmap.set_bad("black")
plot_i = 1
if plots[0]:
axe_private = fig.add_subplot(n_plots, 1, plot_i)
- axe_private.scatter(time_data, priv_data, marker="x", s=10)
- axe_private.set_ylabel("private key value\n(big endian)")
- axe_private.set_xlabel("time ({})".format(unit))
+ 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=[128, max_gen_time - min_gen_time])
+ 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=colors.LogNorm())
+ axe_private.set_xlabel("private key MSB value\n(big endian)")
+ axe_private.set_ylabel("time ({})".format(gen_unit))
plot_i += 1
if plots[1]:
- axe_public = fig.add_subplot(n_plots, 1, plot_i)
- axe_public.scatter(time_data, pub_data, marker="x", s=10)
- axe_public.set_ylabel("public key value\n(big endian)")
- axe_public.set_xlabel("time ({})".format(unit))
+ axe_hist = fig.add_subplot(n_plots, 1, plot_i)
+ time_max = max(gen_time_data)
+ time_min = min(gen_time_data)
+ time_avg = np.average(gen_time_data)
+ time_median = np.median(gen_time_data)
+ axe_hist.hist(gen_time_data, bins=int((time_max - time_min)/1.2), log=True)
+ 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)")
+ axe_hist.set_xlabel("keygen time ({})".format(gen_unit))
+ axe_hist.xaxis.set_major_locator(ticker.MultipleLocator())
+ axe_hist.legend(loc="best")
plot_i += 1
if plots[2]:
axe_hist = fig.add_subplot(n_plots, 1, plot_i)
- 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))
+ 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=int((time_max - time_min)/1.2), log=True)
+ 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)")
- axe_hist.set_xlabel("time ({})".format(unit))
- axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
+ axe_hist.set_xlabel("export time ({})".format(export_unit))
+ axe_hist.xaxis.set_major_locator(ticker.MultipleLocator())
axe_hist.legend(loc="best")
plot_i += 1
if plots[3]:
- 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(n_plots, 1, plot_i)
- h, xe, ye = np.histogram2d(priv_bit_x, priv_bit_y, bins=[max(priv_bit_bins) - min(priv_bit_bins), (max(time_data) - min(time_data))//5])
- cmap = deepcopy(plt.cm.plasma)
- cmap.set_bad("black")
+ priv_hw = np.array(list(map(hw, priv_data)), dtype=np.dtype("u2"))
+ h, xe, ye = np.histogram2d(priv_hw, gen_time_data, bins=[max(priv_hw) - min(priv_hw), max_gen_time - min_gen_time])
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.set_ylabel("time ({})".format(gen_unit))
+ axe_priv_hist.legend(loc="best")
fig.colorbar(im, ax=axe_priv_hist)
if plot_i > 2:
- fig.text(0.01, 0.02, "Data size: {}".format(len(time_data)), size="small")
+ fig.text(0.01, 0.02, "Data size: {}".format(len(gen_time_data)), size="small")
if opts.output is None:
+ plt.tight_layout()
plt.show()
else:
fig.set_size_inches(12, 10)
--
cgit v1.2.3-70-g09d2
From 7e524b3ac2898c4373be9a3c81733ba725f9772d Mon Sep 17 00:00:00 2001
From: J08nY
Date: Sun, 18 Nov 2018 20:01:23 +0100
Subject: Fix keygen plotting.
---
.../ectester/standalone/ECTesterStandalone.java | 2 +-
util/plot_gen.py | 75 ++++++++++++++--------
2 files changed, 50 insertions(+), 27 deletions(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index e75274d..d740579 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -502,7 +502,7 @@ public class ECTesterStandalone {
System.out.println("index;time[nano];pubW;privS");
int amount = Integer.parseInt(cli.getOptionValue("generate.amount", "1"));
- for (int i = 0; i < amount; ++i) {
+ for (int i = 0; i < amount || amount == 0; ++i) {
long elapsed = -System.nanoTime();
KeyPair kp = kpg.genKeyPair();
elapsed += System.nanoTime();
diff --git a/util/plot_gen.py b/util/plot_gen.py
index f6cd8e4..c07fc91 100755
--- a/util/plot_gen.py
+++ b/util/plot_gen.py
@@ -24,14 +24,21 @@ def hw(i):
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
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Plot results of ECTester key generation 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("--priv", dest="priv", action="store_true", help="Show private key MSB heatmap plot.")
parser.add_argument("--hist", dest="hist", action="store_true", help="Show keygen time histogram.")
parser.add_argument("--export-hist", dest="export_hist", action="store_true", help="Show export time histogram.")
+ parser.add_argument("--avg", dest="avg", action="store_true", help="Show moving average of keygen time.")
parser.add_argument("--hw-hist", dest="hw_hist", action="store_true", help="Show Hamming weight heatmap (private key Hamming weight and keygen time).")
- 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("--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", type=str, nargs="?", default="", help="What title to give the figure.")
parser.add_argument("file", type=str, help="The file to plot(csv).")
@@ -44,14 +51,16 @@ if __name__ == "__main__":
print("Bad data?")
exit(1)
- plots = [opts.priv, opts.hist, opts.export_hist, opts.hw_hist]
+ plots = [opts.priv, opts.hist, opts.export_hist, opts.avg, opts.hw_hist]
n_plots = sum(plots)
if n_plots == 0:
+ plots = [True for _ in range(5)]
if len(header_names) == 4:
- n_plots = 3
- else:
n_plots = 4
- plots = [True for _ in range(n_plots)]
+ plots[2] = False
+ else:
+ n_plots = 5
+
if plots[2] and len(header_names) != 5:
n_plots = n_plots - 1
@@ -67,7 +76,7 @@ if __name__ == "__main__":
data = np.genfromtxt(opts.file, delimiter=";", skip_header=1, converters={3: hx, 4: hx}, dtype=np.dtype([("index", "u4"), ("gen_time", "u4"), ("export_time", "u4"), ("pub", "O"), ("priv", "O")]))
if opts.skip_first:
- data = data[1:]
+ data = data[opts.skip_first:]
gen_time_data = data["gen_time"]
export_time_data = None
@@ -80,21 +89,21 @@ if __name__ == "__main__":
gen_unit = "ms"
if header_names[1].endswith("[nano]"):
gen_unit = r"$\mu s$"
- gen_time_data = list(map(lambda x: x[1]//1000, gen_time_data))
+ gen_time_data = list(map(lambda x: x//1000, gen_time_data))
export_unit = "ms"
if len(header_names) == 5 and header_names[2].endswith("[nano]"):
export_unit = r"$\mu s$"
- export_time_data = list(map(lambda x: x[1]//1000, export_time_data))
+ export_time_data = list(map(lambda x: x//1000, export_time_data))
plt.style.use("ggplot")
fig = plt.figure()
layout_kwargs = {}
if opts.title is None:
fig.suptitle(opts.file)
- #layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
elif opts.title:
fig.suptitle(opts.title)
- #layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
+ layout_kwargs["rect"] = [0, 0.02, 1, 0.98]
fig.tight_layout(**layout_kwargs)
max_gen_time = max(gen_time_data)
@@ -104,29 +113,31 @@ if __name__ == "__main__":
cmap = deepcopy(plt.cm.plasma)
cmap.set_bad("black")
+ norm = colors.Normalize()
+ if opts.log:
+ norm = colors.LogNorm()
+
plot_i = 1
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=[128, max_gen_time - min_gen_time])
+ 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]]
- axe_private.imshow(heatmap.T, extent=extent, aspect="auto", cmap=cmap, origin="low", interpolation="nearest", norm=colors.LogNorm())
+ 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_ylabel("time ({})".format(gen_unit))
+ 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_max = max(gen_time_data)
- time_min = min(gen_time_data)
time_avg = np.average(gen_time_data)
time_median = np.median(gen_time_data)
- axe_hist.hist(gen_time_data, bins=int((time_max - time_min)/1.2), log=True)
+ 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)")
+ 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.MultipleLocator())
+ axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
axe_hist.legend(loc="best")
plot_i += 1
@@ -136,31 +147,43 @@ if __name__ == "__main__":
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=int((time_max - time_min)/1.2), log=True)
+ 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)")
+ 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.MultipleLocator())
+ axe_hist.xaxis.set_major_locator(ticker.MaxNLocator())
axe_hist.legend(loc="best")
plot_i += 1
if plots[3]:
+ axe_avg = fig.add_subplot(n_plots, 1, plot_i)
+ #if len(header_names) == 5:
+ # axe_other = axe_avg.twinx()
+ # axe_other.plot(moving_average(export_time_data, 100), color="green", alpha=0.6, label="export, window = 100")
+ # axe_other.plot(moving_average(export_time_data, 1000), color="yellow", alpha=0.6, label="export, window = 1000")
+ # axe_other.legend(loc="lower right")
+ axe_avg.plot(moving_average(gen_time_data, 100), label="window = 100")
+ axe_avg.plot(moving_average(gen_time_data, 1000), label="window = 1000")
+ axe_avg.set_ylabel("keygen time ({})".format(gen_unit))
+ axe_avg.set_xlabel("index")
+ axe_avg.legend(loc="best")
+ plot_i += 1
+
+ if plots[4]:
axe_priv_hist = fig.add_subplot(n_plots, 1, plot_i)
priv_hw = np.array(list(map(hw, priv_data)), dtype=np.dtype("u2"))
h, xe, ye = np.histogram2d(priv_hw, gen_time_data, bins=[max(priv_hw) - min(priv_hw), max_gen_time - min_gen_time])
- 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())
+ im = axe_priv_hist.imshow(h.T, origin="low", cmap=cmap, aspect="auto", extent=[xe[0], xe[-1], ye[0], ye[-1]], norm=norm)
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(gen_unit))
+ axe_priv_hist.set_ylabel("keygen time ({})".format(gen_unit))
axe_priv_hist.legend(loc="best")
fig.colorbar(im, ax=axe_priv_hist)
- if plot_i > 2:
- fig.text(0.01, 0.02, "Data size: {}".format(len(gen_time_data)), size="small")
+ fig.text(0.01, 0.02, "Data size: {}".format(len(gen_time_data)), size="small")
if opts.output is None:
- plt.tight_layout()
plt.show()
else:
fig.set_size_inches(12, 10)
--
cgit v1.2.3-70-g09d2
From 644ebed6714df70df0a78bbeb04c9941eb7f69f8 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Sun, 18 Nov 2018 22:30:50 +0100
Subject: Add more keygen/ecdh/ecdsa options to standalone.
---
.../ectester/standalone/ECTesterStandalone.java | 294 ++++++++++++---------
1 file changed, 173 insertions(+), 121 deletions(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index d740579..46c60e0 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -28,6 +28,7 @@ import cz.crcs.ectester.common.output.TestWriter;
import cz.crcs.ectester.common.test.TestException;
import cz.crcs.ectester.common.util.ByteUtil;
import cz.crcs.ectester.common.util.ECUtil;
+import cz.crcs.ectester.common.util.FileUtil;
import cz.crcs.ectester.data.EC_Store;
import cz.crcs.ectester.standalone.consts.KeyAgreementIdent;
import cz.crcs.ectester.standalone.consts.KeyPairGeneratorIdent;
@@ -49,7 +50,7 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.lang.reflect.Field;
+import java.io.PrintStream;
import java.nio.file.Files;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
@@ -151,6 +152,7 @@ public class ECTesterStandalone {
Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).build();
Option curveName = Option.builder("cn").longOpt("curve-name").desc("Use a named curve, search from curves supported by the library: ").hasArg().argName("name").optionalArg(false).build();
Option bits = Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").build();
+ Option output = Option.builder("o").longOpt("output").desc("Output into file .").hasArgs().argName("output_file").optionalArg(false).build();
Options testOpts = new Options();
testOpts.addOption(bits);
@@ -170,9 +172,12 @@ public class ECTesterStandalone {
ecdhOpts.addOption(bits);
ecdhOpts.addOption(namedCurve);
ecdhOpts.addOption(curveName);
+ ecdhOpts.addOption(output);
ecdhOpts.addOption(Option.builder("t").longOpt("type").desc("Set KeyAgreement object [type].").hasArg().argName("type").optionalArg(false).build());
ecdhOpts.addOption(Option.builder().longOpt("key-type").desc("Set the key [algorithm] for which the key should be derived in KeyAgreements with KDF. Default is \"AES\".").hasArg().argName("algorithm").optionalArg(false).build());
ecdhOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDH [amount] times.").build());
+ ecdhOpts.addOption(Option.builder().longOpt("fixed-private").desc("Perform ECDH with fixed private key.").build());
+ ecdhOpts.addOption(Option.builder().longOpt("fixed-public").desc("Perform ECDH with fixed public key.").build());
ParserOptions ecdh = new ParserOptions(new DefaultParser(), ecdhOpts, "Perform EC based KeyAgreement.");
actions.put("ecdh", ecdh);
@@ -180,6 +185,7 @@ public class ECTesterStandalone {
ecdsaOpts.addOption(bits);
ecdsaOpts.addOption(namedCurve);
ecdsaOpts.addOption(curveName);
+ ecdhOpts.addOption(output);
ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build());
ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build());
ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build());
@@ -190,6 +196,7 @@ public class ECTesterStandalone {
generateOpts.addOption(bits);
generateOpts.addOption(namedCurve);
generateOpts.addOption(curveName);
+ ecdhOpts.addOption(output);
generateOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Generate [amount] of EC keys.").build());
generateOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPairGenerator object [type].").build());
ParserOptions generate = new ParserOptions(new DefaultParser(), generateOpts, "Generate EC keypairs.");
@@ -197,6 +204,7 @@ public class ECTesterStandalone {
Options exportOpts = new Options();
exportOpts.addOption(bits);
+ ecdhOpts.addOption(output);
exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build());
ParserOptions export = new ParserOptions(new DefaultParser(), exportOpts, "Export default curve parameters.");
actions.put("export", export);
@@ -270,7 +278,7 @@ public class ECTesterStandalone {
/**
*
*/
- private void ecdh() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
+ private void ecdh() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, FileNotFoundException {
ProviderECLibrary lib = cfg.selected;
String algo = cli.getOptionValue("ecdh.type", "ECDH");
@@ -303,63 +311,87 @@ public class ECTesterStandalone {
if (kaIdent == null || kpIdent == null) {
throw new NoSuchAlgorithmException(algo);
- } else {
- KeyAgreement ka = kaIdent.getInstance(lib.getProvider());
- KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
- AlgorithmParameterSpec spec = null;
- if (cli.hasOption("ecdh.bits")) {
- int bits = Integer.parseInt(cli.getOptionValue("ecdh.bits"));
- kpg.initialize(bits);
- } else if (cli.hasOption("ecdh.named-curve")) {
- String curveName = cli.getOptionValue("ecdh.named-curve");
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
- if (curve == null) {
- System.err.println("Curve not found: " + curveName);
- return;
- }
- spec = curve.toSpec();
- kpg.initialize(spec);
- } else if (cli.hasOption("ecdh.curve-name")) {
- String curveName = cli.getOptionValue("ecdh.curve-name");
- spec = new ECGenParameterSpec(curveName);
- kpg.initialize(spec);
+ }
+
+ KeyAgreement ka = kaIdent.getInstance(lib.getProvider());
+ KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
+ AlgorithmParameterSpec spec = null;
+ if (cli.hasOption("ecdh.bits")) {
+ int bits = Integer.parseInt(cli.getOptionValue("ecdh.bits"));
+ kpg.initialize(bits);
+ } else if (cli.hasOption("ecdh.named-curve")) {
+ String curveName = cli.getOptionValue("ecdh.named-curve");
+ EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
+ if (curve == null) {
+ System.err.println("Curve not found: " + curveName);
+ return;
}
+ spec = curve.toSpec();
+ kpg.initialize(spec);
+ } else if (cli.hasOption("ecdh.curve-name")) {
+ String curveName = cli.getOptionValue("ecdh.curve-name");
+ spec = new ECGenParameterSpec(curveName);
+ kpg.initialize(spec);
+ }
- System.out.println("index;time[nano];pubW;privS;secret");
+ PrintStream out;
+ if (cli.hasOption("ecdh.output")) {
+ out = new PrintStream(FileUtil.openStream(cli.getOptionValues("ecdh.output")));
+ } else {
+ out = System.out;
+ }
- int amount = Integer.parseInt(cli.getOptionValue("ecdh.amount", "1"));
- for (int i = 0; i < amount; ++i) {
- KeyPair one = kpg.genKeyPair();
- KeyPair other = kpg.genKeyPair();
+ out.println("index;time[nano];pubW;privS;secret");
- ECPrivateKey privkey = (ECPrivateKey) one.getPrivate();
- ECPublicKey pubkey = (ECPublicKey) other.getPublic();
+ KeyPair one = null;
+ if (cli.hasOption("ecdh.fixed-private")) {
+ one = kpg.genKeyPair();
+ }
+ KeyPair other = null;
+ if (cli.hasOption("ecdh.fixed-public")) {
+ other = kpg.genKeyPair();
+ }
- long elapsed = -System.nanoTime();
- if (spec instanceof ECParameterSpec) {
- ka.init(privkey, spec);
- } else {
- ka.init(privkey);
- }
- ka.doPhase(pubkey, true);
- elapsed += System.nanoTime();
- SecretKey derived;
- byte[] result;
- elapsed -= System.nanoTime();
- if (kaIdent.requiresKeyAlgo()) {
- derived = ka.generateSecret(keyAlgo);
- result = derived.getEncoded();
- } else {
- result = ka.generateSecret();
- }
- elapsed += System.nanoTime();
- ka = kaIdent.getInstance(lib.getProvider());
+ int amount = Integer.parseInt(cli.getOptionValue("ecdh.amount", "1"));
+ for (int i = 0; i < amount; ++i) {
+ if (!cli.hasOption("ecdh.fixed-private")) {
+ one = kpg.genKeyPair();
+ }
+ if (!cli.hasOption("ecdh.fixed-public")) {
+ other = kpg.genKeyPair();
+ }
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
- String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
- String dh = ByteUtil.bytesToHex(result, false);
- System.out.println(String.format("%d;%d;%s;%s;%s", i, elapsed, pub, priv, dh));
+ ECPrivateKey privkey = (ECPrivateKey) one.getPrivate();
+ ECPublicKey pubkey = (ECPublicKey) other.getPublic();
+
+ long elapsed = -System.nanoTime();
+ if (spec instanceof ECParameterSpec) {
+ ka.init(privkey, spec);
+ } else {
+ ka.init(privkey);
+ }
+ ka.doPhase(pubkey, true);
+ elapsed += System.nanoTime();
+ SecretKey derived;
+ byte[] result;
+ elapsed -= System.nanoTime();
+ if (kaIdent.requiresKeyAlgo()) {
+ derived = ka.generateSecret(keyAlgo);
+ result = derived.getEncoded();
+ } else {
+ result = ka.generateSecret();
}
+ elapsed += System.nanoTime();
+ ka = kaIdent.getInstance(lib.getProvider());
+
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
+ String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
+ String dh = ByteUtil.bytesToHex(result, false);
+ out.println(String.format("%d;%d;%s;%s;%s", i, elapsed, pub, priv, dh));
+ }
+
+ if (cli.hasOption("ecdh.output")) {
+ out.close();
}
}
@@ -416,61 +448,70 @@ public class ECTesterStandalone {
if (sigIdent == null || kpIdent == null) {
throw new NoSuchAlgorithmException(algo);
- } else {
- Signature sig = sigIdent.getInstance(lib.getProvider());
- KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
- if (cli.hasOption("ecdsa.bits")) {
- int bits = Integer.parseInt(cli.getOptionValue("ecdsa.bits"));
- kpg.initialize(bits);
- } else if (cli.hasOption("ecdsa.named-curve")) {
- String curveName = cli.getOptionValue("ecdsa.named-curve");
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
- if (curve == null) {
- System.err.println("Curve not found: " + curveName);
- return;
- }
- kpg.initialize(curve.toSpec());
- } else if (cli.hasOption("ecdsa.curve-name")) {
- String curveName = cli.getOptionValue("ecdsa.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
+ }
+ Signature sig = sigIdent.getInstance(lib.getProvider());
+ KeyPairGenerator kpg = kpIdent.getInstance(lib.getProvider());
+ if (cli.hasOption("ecdsa.bits")) {
+ int bits = Integer.parseInt(cli.getOptionValue("ecdsa.bits"));
+ kpg.initialize(bits);
+ } else if (cli.hasOption("ecdsa.named-curve")) {
+ String curveName = cli.getOptionValue("ecdsa.named-curve");
+ EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
+ if (curve == null) {
+ System.err.println("Curve not found: " + curveName);
+ return;
}
+ kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("ecdsa.curve-name")) {
+ String curveName = cli.getOptionValue("ecdsa.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
+ }
- System.out.println("index;data;signTime[nano];verifyTime[nano];pubW;privS;signature;verified");
+ PrintStream out;
+ if (cli.hasOption("ecdsa.output")) {
+ out = new PrintStream(FileUtil.openStream(cli.getOptionValues("ecdh.output")));
+ } else {
+ out = System.out;
+ }
- int amount = Integer.parseInt(cli.getOptionValue("ecdsa.amount", "1"));
- for (int i = 0; i < amount; ++i) {
- KeyPair one = kpg.genKeyPair();
+ out.println("index;data;signTime[nano];verifyTime[nano];pubW;privS;signature;verified");
- ECPrivateKey privkey = (ECPrivateKey) one.getPrivate();
- ECPublicKey pubkey = (ECPublicKey) one.getPublic();
+ int amount = Integer.parseInt(cli.getOptionValue("ecdsa.amount", "1"));
+ for (int i = 0; i < amount; ++i) {
+ KeyPair one = kpg.genKeyPair();
- sig.initSign(privkey);
- sig.update(data);
+ ECPrivateKey privkey = (ECPrivateKey) one.getPrivate();
+ ECPublicKey pubkey = (ECPublicKey) one.getPublic();
- long signTime = -System.nanoTime();
- byte[] signature = sig.sign();
- signTime += System.nanoTime();
+ sig.initSign(privkey);
+ sig.update(data);
- sig.initVerify(pubkey);
- sig.update(data);
+ long signTime = -System.nanoTime();
+ byte[] signature = sig.sign();
+ signTime += System.nanoTime();
- long verifyTime = -System.nanoTime();
- boolean verified = sig.verify(signature);
- verifyTime += System.nanoTime();
+ sig.initVerify(pubkey);
+ sig.update(data);
+ long verifyTime = -System.nanoTime();
+ boolean verified = sig.verify(signature);
+ verifyTime += System.nanoTime();
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
- String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
- String sign = ByteUtil.bytesToHex(signature, false);
- System.out.println(String.format("%d;%s;%d;%d;%s;%s;%s;%d", i, dataString, signTime, verifyTime, pub, priv, sign, verified ? 1 : 0));
- }
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
+ String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
+ String sign = ByteUtil.bytesToHex(signature, false);
+ out.println(String.format("%d;%s;%d;%d;%s;%s;%s;%d", i, dataString, signTime, verifyTime, pub, priv, sign, verified ? 1 : 0));
+ }
+
+ if (cli.hasOption("ecdsa.output")) {
+ out.close();
}
}
/**
*
*/
- private void generate() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ private void generate() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, FileNotFoundException {
ProviderECLibrary lib = cfg.selected;
KeyPairGeneratorIdent ident = null;
String algo = cli.getOptionValue("generate.type", "EC");
@@ -482,37 +523,48 @@ public class ECTesterStandalone {
}
if (ident == null) {
throw new NoSuchAlgorithmException(algo);
- } else {
- KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
- if (cli.hasOption("generate.bits")) {
- int bits = Integer.parseInt(cli.getOptionValue("generate.bits"));
- kpg.initialize(bits);
- } else if (cli.hasOption("generate.named-curve")) {
- String curveName = cli.getOptionValue("generate.named-curve");
- EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
- if (curve == null) {
- System.err.println("Curve not found: " + curveName);
- return;
- }
- kpg.initialize(curve.toSpec());
- } else if (cli.hasOption("generate.curve-name")) {
- String curveName = cli.getOptionValue("generate.curve-name");
- kpg.initialize(new ECGenParameterSpec(curveName));
- }
- System.out.println("index;time[nano];pubW;privS");
-
- int amount = Integer.parseInt(cli.getOptionValue("generate.amount", "1"));
- for (int i = 0; i < amount || amount == 0; ++i) {
- long elapsed = -System.nanoTime();
- KeyPair kp = kpg.genKeyPair();
- elapsed += System.nanoTime();
- ECPublicKey publicKey = (ECPublicKey) kp.getPublic();
- ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
-
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false);
- String priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false);
- System.out.println(String.format("%d;%d;%s;%s", i, elapsed, pub, priv));
+ }
+ KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
+ if (cli.hasOption("generate.bits")) {
+ int bits = Integer.parseInt(cli.getOptionValue("generate.bits"));
+ kpg.initialize(bits);
+ } else if (cli.hasOption("generate.named-curve")) {
+ String curveName = cli.getOptionValue("generate.named-curve");
+ EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, curveName);
+ if (curve == null) {
+ System.err.println("Curve not found: " + curveName);
+ return;
}
+ kpg.initialize(curve.toSpec());
+ } else if (cli.hasOption("generate.curve-name")) {
+ String curveName = cli.getOptionValue("generate.curve-name");
+ kpg.initialize(new ECGenParameterSpec(curveName));
+ }
+
+ PrintStream out;
+ if (cli.hasOption("generate.output")) {
+ out = new PrintStream(FileUtil.openStream(cli.getOptionValues("ecdh.output")));
+ } else {
+ out = System.out;
+ }
+
+ out.println("index;time[nano];pubW;privS");
+
+ int amount = Integer.parseInt(cli.getOptionValue("generate.amount", "1"));
+ for (int i = 0; i < amount || amount == 0; ++i) {
+ long elapsed = -System.nanoTime();
+ KeyPair kp = kpg.genKeyPair();
+ elapsed += System.nanoTime();
+ ECPublicKey publicKey = (ECPublicKey) kp.getPublic();
+ ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
+
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false);
+ String priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false);
+ out.println(String.format("%d;%d;%s;%s", i, elapsed, pub, priv));
+ }
+
+ if (cli.hasOption("generate.output")) {
+ out.close();
}
}
--
cgit v1.2.3-70-g09d2
From 977bc58d83195e804769f837bd206c3467354ffe Mon Sep 17 00:00:00 2001
From: J08nY
Date: Fri, 23 Nov 2018 15:25:22 +0100
Subject: Improve native lib timing.
---
.../ectester/standalone/ECTesterStandalone.java | 4 +
.../ectester/standalone/libs/BoringsslLib.java | 9 ++
src/cz/crcs/ectester/standalone/libs/BotanLib.java | 9 ++
.../crcs/ectester/standalone/libs/CryptoppLib.java | 9 ++
.../crcs/ectester/standalone/libs/GcryptLib.java | 9 ++
src/cz/crcs/ectester/standalone/libs/MscngLib.java | 9 ++
.../ectester/standalone/libs/NativeECLibrary.java | 9 ++
.../crcs/ectester/standalone/libs/OpensslLib.java | 9 ++
.../standalone/libs/ProviderECLibrary.java | 12 ++
.../crcs/ectester/standalone/libs/TomcryptLib.java | 10 ++
src/cz/crcs/ectester/standalone/libs/jni/Makefile | 15 +-
.../crcs/ectester/standalone/libs/jni/boringssl.c | 35 ++++-
src/cz/crcs/ectester/standalone/libs/jni/botan.cpp | 21 +++
.../crcs/ectester/standalone/libs/jni/c_timing.c | 57 +++++++
.../crcs/ectester/standalone/libs/jni/c_timing.h | 38 +++++
.../crcs/ectester/standalone/libs/jni/cryptopp.cpp | 23 +++
src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c | 27 ++++
src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 12 ++
src/cz/crcs/ectester/standalone/libs/jni/native.h | 168 +++++++++++++++++++++
src/cz/crcs/ectester/standalone/libs/jni/openssl.c | 36 ++++-
.../crcs/ectester/standalone/libs/jni/tomcrypt.c | 45 ++++--
util/plot_dh.py | 76 +++++-----
util/plot_gen.py | 43 +-----
23 files changed, 593 insertions(+), 92 deletions(-)
create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/c_timing.c
create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/c_timing.h
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
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 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
@@ -11,6 +11,15 @@ public class BoringsslLib extends NativeECLibrary {
super("boringssl_provider", "lib_boringssl.so");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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
@@ -12,6 +12,15 @@ public class BotanLib extends NativeECLibrary {
super("botan_provider", "botan-2");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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
@@ -12,6 +12,15 @@ public class CryptoppLib extends NativeECLibrary {
super("cryptopp_provider", "cryptopp");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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
@@ -12,6 +12,15 @@ public class GcryptLib extends NativeECLibrary {
super("gcrypt_provider", "gcrypt", "gpg-error");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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
@@ -12,6 +12,15 @@ public class MscngLib extends NativeECLibrary {
super("mscng_provider", "bcrypt");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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
@@ -11,6 +11,15 @@ public class OpensslLib extends NativeECLibrary {
super("openssl_provider", "crypto");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
@Override
native Provider createProvider();
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 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
@@ -12,6 +12,16 @@ public class TomcryptLib extends NativeECLibrary {
super("tomcrypt_provider", "tommath", "tomcrypt");
}
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+
@Override
native Provider createProvider();
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
#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
#include
#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 skey;
try {
+ native_timing_start();
if (type_str == "ECDH") {
skey = std::make_unique(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(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 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 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
+
+#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
+#include
+
+#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 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(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(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 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 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
#include
#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
@@ -7,6 +7,30 @@
#ifdef __cplusplus
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
@@ -188,6 +212,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
@@ -369,6 +417,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
@@ -550,6 +622,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
@@ -731,6 +827,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
@@ -912,6 +1032,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
@@ -1093,6 +1237,30 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
#ifdef __cplusplus
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
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
#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
#include
#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(<c_prng, find_prng("yarrow"), &key, curve)) != CRYPT_OK) {
+
+ native_timing_start();
+ int err = ecc_make_key_ex(<c_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, <c_prng, find_prng("yarrow"), &priv)) != CRYPT_OK) {
+
+ native_timing_start();
+ int err = ecc_sign_hash((unsigned char *) data_data, data_size, result, &output_len, <c_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]:
--
cgit v1.2.3-70-g09d2
From f4c37b69a15a01bb3b0ead8b00b01536234dd7dd Mon Sep 17 00:00:00 2001
From: J08nY
Date: Fri, 23 Nov 2018 18:13:14 +0100
Subject: Use native timing when available.
---
.../ectester/standalone/ECTesterStandalone.java | 32 ++++++++++++++--------
1 file changed, 20 insertions(+), 12 deletions(-)
(limited to 'src/cz/crcs/ectester/standalone/ECTesterStandalone.java')
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 037e8b2..e19377d 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -383,6 +383,9 @@ public class ECTesterStandalone {
result = ka.generateSecret();
}
elapsed += System.nanoTime();
+ if (lib.supportsNativeTiming()) {
+ elapsed = lib.getLastNativeTiming();
+ }
ka = kaIdent.getInstance(lib.getProvider());
String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
@@ -490,6 +493,9 @@ public class ECTesterStandalone {
long signTime = -System.nanoTime();
byte[] signature = sig.sign();
signTime += System.nanoTime();
+ if (lib.supportsNativeTiming()) {
+ signTime = lib.getLastNativeTiming();
+ }
sig.initVerify(pubkey);
sig.update(data);
@@ -497,6 +503,9 @@ public class ECTesterStandalone {
long verifyTime = -System.nanoTime();
boolean verified = sig.verify(signature);
verifyTime += System.nanoTime();
+ if (lib.supportsNativeTiming()) {
+ verifyTime = lib.getLastNativeTiming();
+ }
String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
@@ -612,19 +621,18 @@ public class ECTesterStandalone {
}
if (ident == null) {
throw new NoSuchAlgorithmException(algo);
- } else {
- KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
- if (cli.hasOption("export.bits")) {
- int bits = Integer.parseInt(cli.getOptionValue("export.bits"));
- kpg.initialize(bits);
- }
- KeyPair kp = kpg.genKeyPair();
- ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
- ECParameterSpec params = privateKey.getParams();
- System.out.println(params);
- EC_Curve curve = EC_Curve.fromSpec(params);
- curve.writeCSV(System.out);
}
+ KeyPairGenerator kpg = ident.getInstance(lib.getProvider());
+ if (cli.hasOption("export.bits")) {
+ int bits = Integer.parseInt(cli.getOptionValue("export.bits"));
+ kpg.initialize(bits);
+ }
+ KeyPair kp = kpg.genKeyPair();
+ ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
+ ECParameterSpec params = privateKey.getParams();
+ System.out.println(params);
+ EC_Curve curve = EC_Curve.fromSpec(params);
+ curve.writeCSV(System.out);
}
public static void main(String[] args) {
--
cgit v1.2.3-70-g09d2