diff options
13 files changed, 594 insertions, 65 deletions
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index d9525e9..c3dfbbe 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -96,6 +96,7 @@ public class ECTesterStandalone { System.err.println("Invalid algorithm parameter: " + e.getMessage()); } catch (NoSuchAlgorithmException nsaex) { System.err.println("Algorithm not supported by the selected library: " + nsaex.getMessage()); + nsaex.printStackTrace(); } catch (InvalidKeyException | SignatureException | TestException e) { e.printStackTrace(); } @@ -208,9 +209,12 @@ public class ECTesterStandalone { .filter((ident) -> ident.contains(algo)) .findFirst() .orElse(lib.getKPGs().stream() - .filter((ident) -> ident.contains("EC")) + .filter((ident) -> ident.contains("ECDH")) .findFirst() - .orElse(null)); + .orElse(lib.getKPGs().stream() + .filter((ident) -> ident.contains("EC")) + .findFirst() + .orElse(null))); if (kaIdent == null || kpIdent == null) { @@ -231,7 +235,7 @@ public class ECTesterStandalone { } spec = curve.toSpec(); kpg.initialize(spec); - } + }//TODO: allow ECGenNamedSpec System.out.println("index;nanotime;pubW;privS;secret"); diff --git a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java index 724f3c6..a5d3578 100644 --- a/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java +++ b/src/cz/crcs/ectester/standalone/consts/KeyAgreementIdent.java @@ -28,13 +28,13 @@ public class KeyAgreementIdent extends Ident { ALL.add(new KeyAgreementIdent("ECCDHwithSHA384KDF", "1.3.132.1.14.2")); ALL.add(new KeyAgreementIdent("ECDHwithSHA512KDF", "1.3.132.1.11.3")); ALL.add(new KeyAgreementIdent("ECCDHwithSHA512KDF", "1.3.132.1.14.3")); - // ECMQV - ALL.add(new KeyAgreementIdent("ECMQV")); - ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", "1.3.133.16.840.63.0.16")); - ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", "1.3.132.1.15.0")); - ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", "1.3.132.1.15.1")); - ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", "1.3.132.1.15.2")); - ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", "1.3.132.1.15.3")); + // ECMQV - Disable for now as it needs diferent params(too different from DH) + //ALL.add(new KeyAgreementIdent("ECMQV")); + //ALL.add(new KeyAgreementIdent("ECMQVwithSHA1CKDF", "1.3.133.16.840.63.0.16")); + //ALL.add(new KeyAgreementIdent("ECMQVwithSHA224CKDF", "1.3.132.1.15.0")); + //ALL.add(new KeyAgreementIdent("ECMQVwithSHA256CKDF", "1.3.132.1.15.1")); + //ALL.add(new KeyAgreementIdent("ECMQVwithSHA384CKDF", "1.3.132.1.15.2")); + //ALL.add(new KeyAgreementIdent("ECMQVwithSHA512CKDF", "1.3.132.1.15.3")); // ECVKO ALL.add(new KeyAgreementIdent("ECVKO", "ECGOST3410", "1.2.643.2.2.19", "GOST-3410-2001", "1.2.643.2.2.96")); ALL.add(new KeyAgreementIdent("ECVKO256", "ECGOST3410-2012-256", "1.2.643.7.1.1.6.1", "1.2.643.7.1.1.1.1")); diff --git a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java index 50b7135..8e67967 100644 --- a/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java +++ b/src/cz/crcs/ectester/standalone/consts/KeyPairGeneratorIdent.java @@ -17,6 +17,10 @@ public class KeyPairGeneratorIdent extends Ident { ALL.add(new KeyPairGeneratorIdent("ECMQV")); ALL.add(new KeyPairGeneratorIdent("ECGOST3410")); ALL.add(new KeyPairGeneratorIdent("ECGOST3410-2012")); + // ECKCDSA? Botan provides. + ALL.add(new KeyPairGeneratorIdent("ECKCDSA")); + // ECGDSA? Botan provides. + ALL.add(new KeyPairGeneratorIdent("ECGDSA")); } public static KeyPairGeneratorIdent get(String ident) { diff --git a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java index f322cc5..d2f9f00 100644 --- a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java +++ b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java @@ -63,6 +63,20 @@ public class SignatureIdent extends Ident { ALL.add(new SignatureIdent("SHA3-256withECDDSA", "SHA3-256withDETECDSA")); ALL.add(new SignatureIdent("SHA3-384withECDDSA", "SHA3-384withDETECDSA")); ALL.add(new SignatureIdent("SHA3-512withECDDSA", "SHA3-512withDETECDSA")); + // ECKCDSA? Botan provides. + ALL.add(new SignatureIdent("ECKCDSA")); + ALL.add(new SignatureIdent("SHA1withECKCDSA", "1.2.410.200004.1.100.4.3")); + ALL.add(new SignatureIdent("SHA224withECKCDSA", "1.2.410.200004.1.100.4.4")); + ALL.add(new SignatureIdent("SHA256withECKCDSA", "1.2.410.200004.1.100.4.5")); + // ECGDSA? Botan provides. + ALL.add(new SignatureIdent("ECGDSA")); + ALL.add(new SignatureIdent("RIPEMD160withECGDSA", "1.3.36.3.3.2.5.4.1")); + ALL.add(new SignatureIdent("SHA1withECGDSA", "1.3.36.3.3.2.5.4.2")); + ALL.add(new SignatureIdent("SHA224withECGDSA", "1.3.36.3.3.2.5.4.3")); + ALL.add(new SignatureIdent("SHA224withECGDSA", "1.3.36.3.3.2.5.4.4")); + ALL.add(new SignatureIdent("SHA384withECGDSA", "1.3.36.3.3.2.5.4.5")); + ALL.add(new SignatureIdent("SHA512withECGDSA", "1.3.36.3.3.2.5.4.6")); + } public static SignatureIdent get(String ident) { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile index c6df032..3530499 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -37,20 +37,31 @@ LOCAL_LIBS = /usr/local/lib CC?=gcc CXX?=g++ +CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. +CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. + all: tomcrypt_provider.so botan_provider.so -tomcrypt_provider.so: tomcrypt.o - $(CC) -fPIC -g -shared -o $@ $< -L. -ltommath -ltomcrypt +c_utils.o: c_utils.c + $(CC) $(CFLAGS) -c $< + +cpp_utils.o: cpp_utils.cpp + $(CXX) $(CXXFLAGS) -c $< + + +tomcrypt_provider.so: tomcrypt.o c_utils.o + $(CC) -fPIC -g -shared -o $@ $^ -L. -ltommath -ltomcrypt tomcrypt.o: tomcrypt.c - $(CC) -DLTM_DESC -fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -c $< + $(CC) -DLTM_DESC $(CFLAGS) -c $< + -botan_provider.so: botan.o - $(CXX) -fPIC -g -shared -o $@ $< -L. -L"$(LOCAL_LIBS)" -lbotan-2 -fstack-protector -m64 -pthread +botan_provider.so: botan.o cpp_utils.o + $(CXX) -fPIC -g -shared -o $@ $^ -L. -L"$(LOCAL_LIBS)" -lbotan-2 -fstack-protector -m64 -pthread botan.o: botan.cpp - $(CXX) -fPIC -g -I"$(LOCAL_INCLUDES)/botan-2" -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -c $< + $(CXX) -I"$(LOCAL_INCLUDES)/botan-2" $(CFLAGS) -c $< clean: rm -rf *.o diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index 8875948..37c9add 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -89,9 +89,49 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); } - public static class Botan extends NativeKeyAgreementSpi { + public abstract static class Botan extends NativeKeyAgreementSpi { + private String type; + public Botan(String type) { + this.type = type; + } @Override native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); } + + public static class BotanECDH extends Botan { + public BotanECDH() { + super("ECDH"); + } + } + + public static class BotanECDHwithSHA1KDF extends Botan { + public BotanECDHwithSHA1KDF() { + super("ECDHwithSHA1KDF"); + } + } + + public static class BotanECDHwithSHA224KDF extends Botan { + public BotanECDHwithSHA224KDF() { + super("ECDHwithSHA224KDF"); + } + } + + public static class BotanECDHwithSHA256KDF extends Botan { + public BotanECDHwithSHA256KDF() { + super("ECDHwithSHA256KDF"); + } + } + + public static class BotanECDHwithSHA384KDF extends Botan { + public BotanECDHwithSHA384KDF() { + super("ECDHwithSHA384KDF"); + } + } + + public static class BotanECDHwithSHA512KDF extends Botan { + public BotanECDHwithSHA512KDF() { + super("ECDHwithSHA512KDF"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index 5b8a54b..9461251 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -72,9 +72,11 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); } - public static class Botan extends NativeKeyPairGeneratorSpi { + public static abstract class Botan extends NativeKeyPairGeneratorSpi { + private String type; - public Botan() { + public Botan(String type) { + this.type = type; initialize(256, new SecureRandom()); } @@ -90,4 +92,32 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { @Override native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); } + + public static class BotanECDH extends Botan { + + public BotanECDH() { + super("ECDH"); + } + } + + public static class BotanECDSA extends Botan { + + public BotanECDSA() { + super("ECDSA"); + } + } + + public static class BotanECKCDSA extends Botan { + + public BotanECKCDSA() { + super("ECKCDSA"); + } + } + + public static class BotanECGDSA extends Botan { + + public BotanECGDSA() { + super("ECGDSA"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp index 9c2394f..0b2928d 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp +++ b/src/cz/crcs/ectester/standalone/libs/jni/botan.cpp @@ -1,6 +1,14 @@ #include "native.h" #include <string> #include <botan/botan.h> +#include <botan/ec_group.h> +#include <botan/ecc_key.h> +#include <botan/ecdsa.h> +#include <botan/eckcdsa.h> +#include <botan/ecgdsa.h> +#include <botan/ecdh.h> +#include <botan/pubkey.h> +#include "cpp_utils.hpp" static jclass provider_class; @@ -34,7 +42,49 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createP * Signature: ()V */ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup(JNIEnv *env, jobject self){ + jmethodID provider_put = env->GetMethodID(provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + jstring ecdh = env->NewStringUTF("KeyPairGenerator.ECDH"); + jstring ecdh_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDH"); + env->CallObjectMethod(self, provider_put, ecdh, ecdh_value); + + jstring ecdsa = env->NewStringUTF("KeyPairGenerator.ECDSA"); + jstring ecdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECDSA"); + env->CallObjectMethod(self, provider_put, ecdsa, ecdsa_value); + + jstring eckcdsa = env->NewStringUTF("KeyPairGenerator.ECKCDSA"); + jstring eckcdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECKCDSA"); + env->CallObjectMethod(self, provider_put, eckcdsa, eckcdsa_value); + + jstring ecgdsa = env->NewStringUTF("KeyPairGenerator.ECGDSA"); + jstring ecgdsa_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$BotanECGDSA"); + env->CallObjectMethod(self, provider_put, ecgdsa, ecgdsa_value); + + jstring ecdh_ka = env->NewStringUTF("KeyAgreement.ECDH"); + jstring ecdh_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDH"); + env->CallObjectMethod(self, provider_put, ecdh_ka, ecdh_ka_value); + + jstring ecdh_sha1_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA1KDF"); + jstring ecdh_sha1_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA1KDF"); + env->CallObjectMethod(self, provider_put, ecdh_sha1_ka, ecdh_sha1_ka_value); + + jstring ecdh_sha224_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA224KDF"); + jstring ecdh_sha224_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA224KDF"); + env->CallObjectMethod(self, provider_put, ecdh_sha224_ka, ecdh_sha224_ka_value); + + jstring ecdh_sha256_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA256KDF"); + jstring ecdh_sha256_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA256KDF"); + env->CallObjectMethod(self, provider_put, ecdh_sha256_ka, ecdh_sha256_ka_value); + + jstring ecdh_sha384_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA384KDF"); + jstring ecdh_sha384_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA384KDF"); + env->CallObjectMethod(self, provider_put, ecdh_sha384_ka, ecdh_sha384_ka_value); + + jstring ecdh_sha512_ka = env->NewStringUTF("KeyAgreement.ECDHwithSHA512KDF"); + jstring ecdh_sha512_ka_value = env->NewStringUTF("cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$BotanECDHwithSHA512KDF"); + env->CallObjectMethod(self, provider_put, ecdh_sha512_ka, ecdh_sha512_ka_value); + + init_classes(env, "Botan"); } /* @@ -43,7 +93,21 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ * Signature: ()Ljava/util/Set; */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves(JNIEnv *env, jobject self){ + jclass hash_set_class = env->FindClass("java/util/TreeSet"); + + jmethodID hash_set_ctr = env->GetMethodID(hash_set_class, "<init>", "()V"); + jmethodID hash_set_add = env->GetMethodID(hash_set_class, "add", "(Ljava/lang/Object;)Z"); + + jobject result = env->NewObject(hash_set_class, hash_set_ctr); + + const std::set<std::string>& curves = Botan::EC_Group::known_named_groups(); + for (auto it = curves.begin(); it != curves.end(); ++it) { + std::string curve_name = *it; + jstring name_str = env->NewStringUTF(curve_name.c_str()); + env->CallBooleanMethod(result, hash_set_add, name_str); + } + return result; } /* @@ -52,7 +116,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported(JNIEnv *env, jobject self, jint keysize){ - + return JNI_TRUE; } /* @@ -61,7 +125,195 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported(JNIEnv *env, jobject self, jobject params){ + if (params == NULL) { + return JNI_FALSE; + } + + if (env->IsInstanceOf(params, ec_parameter_spec_class)) { + jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject curve = env->CallObjectMethod(params, get_curve); + + jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = env->CallObjectMethod(curve, get_field); + + if (env->IsInstanceOf(field, fp_field_class)) { + return JNI_TRUE; + } + } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) { + const std::set<std::string>& curves = Botan::EC_Group::known_named_groups(); + jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); + jstring name = (jstring) env->CallObjectMethod(params, get_name); + const char *utf_name = env->GetStringUTFChars(name, NULL); + std::string str_name(utf_name); + env->ReleaseStringUTFChars(name, utf_name); + if (curves.find(str_name) != curves.end()) { + return JNI_TRUE; + } + } + return JNI_FALSE; +} + +static jobject biginteger_from_bigint(JNIEnv *env, const Botan::BigInt& bigint) { + std::vector<uint8_t> bigint_data = Botan::BigInt::encode(bigint); + jbyteArray bigint_array = env->NewByteArray(bigint_data.size()); + jbyte * bigint_bytes = env->GetByteArrayElements(bigint_array, NULL); + std::copy(bigint_data.begin(), bigint_data.end(), bigint_bytes); + env->ReleaseByteArrayElements(bigint_array, bigint_bytes, JNI_COMMIT); + + jmethodID biginteger_init = env->GetMethodID(biginteger_class, "<init>", "(I[B)V"); + return env->NewObject(biginteger_class, biginteger_init, (jint) 1, bigint_array); +} + +static Botan::BigInt bigint_from_biginteger(JNIEnv *env, jobject biginteger) { + jmethodID to_byte_array = env->GetMethodID(biginteger_class, "toByteArray", "()[B"); + jbyteArray byte_array = (jbyteArray) env->CallObjectMethod(biginteger, to_byte_array); + jsize byte_length = env->GetArrayLength(byte_array); + jbyte *byte_data = env->GetByteArrayElements(byte_array, NULL); + Botan::BigInt result((unsigned uint8_t*) byte_data, byte_length); + env->ReleaseByteArrayElements(byte_array, byte_data, JNI_ABORT); + return result; +} + +static Botan::EC_Group group_from_params(JNIEnv *env, jobject params) { + if (env->IsInstanceOf(params, ec_parameter_spec_class)) { + jmethodID get_curve = env->GetMethodID(ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = env->CallObjectMethod(params, get_curve); + + jmethodID get_field = env->GetMethodID(elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = env->CallObjectMethod(elliptic_curve, get_field); + + jmethodID get_bits = env->GetMethodID(fp_field_class, "getFieldSize", "()I"); + jint bits = env->CallIntMethod(field, get_bits); + jint bytes = (bits + 7) / 8; + + jmethodID get_a = env->GetMethodID(elliptic_curve_class, "getA", "()Ljava/math/BigInteger;"); + jobject a = env->CallObjectMethod(elliptic_curve, get_a); + + jmethodID get_b = env->GetMethodID(elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject b = env->CallObjectMethod(elliptic_curve, get_b); + + jmethodID get_p = env->GetMethodID(fp_field_class, "getP", "()Ljava/math/BigInteger;"); + jobject p = env->CallObjectMethod(field, get_p); + + jmethodID get_g = env->GetMethodID(ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); + jobject g = env->CallObjectMethod(params, get_g); + + jmethodID get_x = env->GetMethodID(point_class, "getAffineX", "()Ljava/math/BigInteger;"); + jobject gx = env->CallObjectMethod(g, get_x); + + jmethodID get_y = env->GetMethodID(point_class, "getAffineY", "()Ljava/math/BigInteger;"); + jobject gy = env->CallObjectMethod(g, get_y); + + jmethodID get_n = env->GetMethodID(ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); + jobject n = env->CallObjectMethod(params, get_n); + + jmethodID get_h = env->GetMethodID(ec_parameter_spec_class, "getCofactor", "()I"); + jint h = env->CallIntMethod(params, get_h); + + Botan::BigInt pi = bigint_from_biginteger(env, p); + Botan::BigInt ai = bigint_from_biginteger(env, a); + Botan::BigInt bi = bigint_from_biginteger(env, b); + Botan::CurveGFp curve(pi, ai, bi); + + Botan::BigInt gxi = bigint_from_biginteger(env, gx); + Botan::BigInt gyi = bigint_from_biginteger(env, gy); + Botan::PointGFp generator(curve, gxi, gyi); + + Botan::BigInt ni = bigint_from_biginteger(env, n); + Botan::BigInt hi(h); + + return Botan::EC_Group(curve, generator, ni, hi); + } else if (env->IsInstanceOf(params, ecgen_parameter_spec_class)) { + jmethodID get_name = env->GetMethodID(ecgen_parameter_spec_class, "getName", "()Ljava/lang/String;"); + jstring name = (jstring) env->CallObjectMethod(params, get_name); + const char *utf_name = env->GetStringUTFChars(name, NULL); + std::string curve_name(utf_name); + env->ReleaseStringUTFChars(name, utf_name); + return Botan::EC_Group(curve_name); + } + return Botan::EC_Group(); +} + +static jobject params_from_group(JNIEnv *env, Botan::EC_Group group) { + const Botan::CurveGFp& curve = group.get_curve(); + jobject p = biginteger_from_bigint(env, curve.get_p()); + jmethodID fp_field_init = env->GetMethodID(fp_field_class, "<init>", "(Ljava/math/BigInteger;)V"); + jobject fp_field = env->NewObject(fp_field_class, fp_field_init, p); + + jobject a = biginteger_from_bigint(env, curve.get_a()); + jobject b = biginteger_from_bigint(env, curve.get_b()); + + jmethodID elliptic_curve_init = env->GetMethodID(elliptic_curve_class, "<init>", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject elliptic_curve = env->NewObject(elliptic_curve_class, elliptic_curve_init, fp_field, a, b); + + const Botan::PointGFp& generator = group.get_base_point(); + jobject gx = biginteger_from_bigint(env, generator.get_affine_x()); + jobject gy = biginteger_from_bigint(env, generator.get_affine_y()); + + jmethodID point_init = env->GetMethodID(point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject g = env->NewObject(point_class, point_init, gx, gy); + + const Botan::BigInt& order = group.get_order(); + jobject n = biginteger_from_bigint(env, order); + + const Botan::BigInt& cofactor = group.get_cofactor(); + jint h = (jint) cofactor.to_u32bit(); + + jmethodID ec_parameter_spec_init = env->GetMethodID(ec_parameter_spec_class, "<init>", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V"); + return env->NewObject(ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n, h); +} + +static jobject generate_from_group(JNIEnv* env, jobject self, Botan::EC_Group group) { + Botan::AutoSeeded_RNG rng; + + jclass botan_kpg_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Botan"); + jfieldID type_id = env->GetFieldID(botan_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) env->GetObjectField(self, type_id); + const char* type_data = env->GetStringUTFChars(type, NULL); + std::string type_str(type_data); + env->ReleaseStringUTFChars(type, type_data); + + std::unique_ptr<Botan::EC_PrivateKey> skey; + if (type_str == "ECDH") { + skey = std::make_unique<Botan::ECDH_PrivateKey>(rng, group); + } else if (type_str == "ECDSA") { + skey = std::make_unique<Botan::ECDSA_PrivateKey>(rng, group); + } else if (type_str == "ECKCDSA") { + skey = std::make_unique<Botan::ECKCDSA_PrivateKey>(rng, group); + } else if (type_str == "ECGDSA") { + skey = std::make_unique<Botan::ECGDSA_PrivateKey>(rng, group); + } + + jobject ec_param_spec = params_from_group(env, group); + + const Botan::PointGFp& pub_point = skey->public_point(); + std::vector<uint8_t> pub_data = Botan::unlock(Botan::EC2OSP(pub_point, Botan::PointGFp::UNCOMPRESSED)); + + jbyteArray pub_bytearray = env->NewByteArray(pub_data.size()); + jbyte *pub_bytes = env->GetByteArrayElements(pub_bytearray, NULL); + std::copy(pub_data.begin(), pub_data.end(), pub_bytes); + env->ReleaseByteArrayElements(pub_bytearray, pub_bytes, JNI_COMMIT); + + jobject ec_pub_param_spec = env->NewLocalRef(ec_param_spec); + jmethodID ec_pub_init = env->GetMethodID(pubkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V"); + jobject pubkey = env->NewObject(pubkey_class, ec_pub_init, pub_bytearray, ec_pub_param_spec); + + const Botan::BigInt& priv_scalar = skey->private_value(); + std::vector<uint8_t> priv_data = Botan::BigInt::encode(priv_scalar); + + jbyteArray priv_bytearray = env->NewByteArray(priv_data.size()); + jbyte *priv_bytes = env->GetByteArrayElements(priv_bytearray, NULL); + std::copy(priv_data.begin(), priv_data.end(), priv_bytes); + env->ReleaseByteArrayElements(priv_bytearray, priv_bytes, JNI_COMMIT); + + jobject ec_priv_param_spec = env->NewLocalRef(ec_param_spec); + jmethodID ec_priv_init = env->GetMethodID(privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V"); + jobject privkey = env->NewObject(privkey_class, ec_priv_init, priv_bytearray, ec_priv_param_spec); + + jmethodID keypair_init = env->GetMethodID(keypair_class, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + return env->NewObject(keypair_class, keypair_init, pubkey, privkey); } /* @@ -70,7 +322,17 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random){ - + const std::set<std::string>& curves = Botan::EC_Group::known_named_groups(); + for (auto it = curves.begin(); it != curves.end(); ++it) { + Botan::EC_Group curve_group = Botan::EC_Group(*it); + size_t curve_size = curve_group.get_curve().get_p().bits(); + if (curve_size == keysize) { + //generate on this group. Even thou no default groups are present... + return generate_from_group(env, self, curve_group); + } + } + //TODO throw an exception here? InvalidAlgorithmParameters one? + return NULL; } /* @@ -79,7 +341,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; */ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ - + Botan::EC_Group curve_group = group_from_params(env, params); + return generate_from_group(env, self, curve_group); } /* @@ -88,7 +351,65 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params){ + Botan::EC_Group curve_group = group_from_params(env, params); + + jsize privkey_length = env->GetArrayLength(privkey); + jbyte *privkey_data = env->GetByteArrayElements(privkey, NULL); + Botan::BigInt privkey_scalar((unsigned uint8_t*) privkey_data, privkey_length); + env->ReleaseByteArrayElements(privkey, privkey_data, JNI_ABORT); + + Botan::AutoSeeded_RNG rng; + + Botan::ECDH_PrivateKey skey(rng, curve_group, privkey_scalar); + + jsize pubkey_length = env->GetArrayLength(pubkey); + jbyte *pubkey_data = env->GetByteArrayElements(pubkey, NULL); + Botan::PointGFp public_point = Botan::OS2ECP((uint8_t*) pubkey_data, pubkey_length, curve_group.get_curve()); + env->ReleaseByteArrayElements(pubkey, pubkey_data, JNI_ABORT); + + Botan::ECDH_PublicKey pkey(curve_group, public_point); + //TODO: do check_key here? + + jclass botan_ka_class = env->FindClass("cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Botan"); + jfieldID type_id = env->GetFieldID(botan_ka_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) env->GetObjectField(self, type_id); + const char *type_data = env->GetStringUTFChars(type, NULL); + std::string type_str(type_data); + env->ReleaseStringUTFChars(type, type_data); + + std::string kdf; + size_t key_len = 0; + if (type_str == "ECDH") { + kdf = "Raw"; + //key len unused + } else if (type_str == "ECDHwithSHA1KDF") { + kdf = "KDF1(SHA-1)"; + key_len = 20; + } else if (type_str == "ECDHwithSHA224KDF") { + kdf = "KDF1(SHA-224)"; + key_len = 28; + } else if (type_str == "ECDHwithSHA256KDF") { + kdf = "KDF1(SHA-256)"; + key_len = 32; + } else if (type_str == "ECDHwithSHA384KDF") { + kdf = "KDF1(SHA-384)"; + key_len = 48; + } else if (type_str == "ECDHwithSHA512KDF") { + kdf = "KDF1(SHA-512)"; + key_len = 64; + } else { + //TODO what? + } + + Botan::PK_Key_Agreement ka(skey, rng, kdf); + + std::vector<uint8_t> derived = Botan::unlock(ka.derive_key(key_len, pkey.public_value()).bits_of()); + jbyteArray result = env->NewByteArray(derived.size()); + jbyte *result_data = env->GetByteArrayElements(result, NULL); + std::copy(derived.begin(), derived.end(), result_data); + env->ReleaseByteArrayElements(result, result_data, JNI_COMMIT); + return result; } /* diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c new file mode 100644 index 0000000..230f516 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c @@ -0,0 +1,61 @@ +#include "c_utils.h" +#include <string.h> + +jclass ec_parameter_spec_class; +jclass ecgen_parameter_spec_class; +jclass pubkey_class; +jclass privkey_class; +jclass keypair_class; +jclass elliptic_curve_class; +jclass fp_field_class; +jclass f2m_field_class; +jclass point_class; +jclass biginteger_class; +jclass illegal_state_exception_class; + +void init_classes(JNIEnv *env, const char* lib_name) { + jclass local_ec_parameter_spec_class = (*env)->FindClass(env, "java/security/spec/ECParameterSpec"); + ec_parameter_spec_class = (*env)->NewGlobalRef(env, local_ec_parameter_spec_class); + + jclass local_ecgen_parameter_spec_class = (*env)->FindClass(env, "java/security/spec/ECGenParameterSpec"); + ecgen_parameter_spec_class = (*env)->NewGlobalRef(env, local_ecgen_parameter_spec_class); + + const char *pubkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey$"; + char pubkey_class_name[strlen(pubkey_base) + strlen(lib_name) + 1]; + pubkey_class_name[0] = 0; + strcat(pubkey_class_name, pubkey_base); + strcat(pubkey_class_name, lib_name); + + jclass local_pubkey_class = (*env)->FindClass(env, pubkey_class_name); + pubkey_class = (*env)->NewGlobalRef(env, local_pubkey_class); + + const char *privkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$"; + char privkey_class_name[strlen(privkey_base) + strlen(lib_name) + 1]; + privkey_class_name[0] = 0; + strcat(privkey_class_name, privkey_base); + strcat(privkey_class_name, lib_name); + + jclass local_privkey_class = (*env)->FindClass(env, privkey_class_name); + privkey_class = (*env)->NewGlobalRef(env, local_privkey_class); + + jclass local_keypair_class = (*env)->FindClass(env, "java/security/KeyPair"); + keypair_class = (*env)->NewGlobalRef(env, local_keypair_class); + + jclass local_elliptic_curve_class = (*env)->FindClass(env, "java/security/spec/EllipticCurve"); + elliptic_curve_class = (*env)->NewGlobalRef(env, local_elliptic_curve_class); + + jclass local_fp_field_class = (*env)->FindClass(env, "java/security/spec/ECFieldFp"); + fp_field_class = (*env)->NewGlobalRef(env, local_fp_field_class); + + jclass local_f2m_field_class = (*env)->FindClass(env, "java/security/spec/ECFieldF2m"); + f2m_field_class = (*env)->NewGlobalRef(env, local_f2m_field_class); + + jclass local_biginteger_class = (*env)->FindClass(env, "java/math/BigInteger"); + biginteger_class = (*env)->NewGlobalRef(env, local_biginteger_class); + + jclass local_point_class = (*env)->FindClass(env, "java/security/spec/ECPoint"); + point_class = (*env)->NewGlobalRef(env, local_point_class); + + jclass local_illegal_state_exception_class = (*env)->FindClass(env, "java/lang/IllegalStateException"); + illegal_state_exception_class = (*env)->NewGlobalRef(env, local_illegal_state_exception_class); +}
\ 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 new file mode 100644 index 0000000..edd0bda --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h @@ -0,0 +1,15 @@ +#include "native.h" + +extern jclass ec_parameter_spec_class; +extern jclass ecgen_parameter_spec_class; +extern jclass pubkey_class; +extern jclass privkey_class; +extern jclass keypair_class; +extern jclass elliptic_curve_class; +extern jclass fp_field_class; +extern jclass f2m_field_class; +extern jclass point_class; +extern jclass biginteger_class; +extern jclass illegal_state_exception_class; + +void init_classes(JNIEnv *env, const char* lib_name);
\ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp new file mode 100644 index 0000000..ed59d51 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.cpp @@ -0,0 +1,54 @@ +#include "cpp_utils.hpp" + +jclass ec_parameter_spec_class; +jclass ecgen_parameter_spec_class; +jclass pubkey_class; +jclass privkey_class; +jclass keypair_class; +jclass elliptic_curve_class; +jclass fp_field_class; +jclass f2m_field_class; +jclass point_class; +jclass biginteger_class; +jclass illegal_state_exception_class; + +void init_classes(JNIEnv *env, std::string lib_name) { + jclass local_ec_parameter_spec_class = env->FindClass("java/security/spec/ECParameterSpec"); + ec_parameter_spec_class = (jclass) env->NewGlobalRef(local_ec_parameter_spec_class); + + jclass local_ecgen_parameter_spec_class = env->FindClass("java/security/spec/ECGenParameterSpec"); + ecgen_parameter_spec_class = (jclass) env->NewGlobalRef(local_ecgen_parameter_spec_class); + + std::string pubkey_class_name("cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey$"); + pubkey_class_name += lib_name; + + jclass local_pubkey_class = env->FindClass(pubkey_class_name.c_str()); + pubkey_class = (jclass) env->NewGlobalRef(local_pubkey_class); + + std::string privkey_class_name("cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$"); + privkey_class_name += lib_name; + + jclass local_privkey_class = env->FindClass(privkey_class_name.c_str()); + privkey_class = (jclass) env->NewGlobalRef(local_privkey_class); + + jclass local_keypair_class = env->FindClass("java/security/KeyPair"); + keypair_class = (jclass) env->NewGlobalRef(local_keypair_class); + + jclass local_elliptic_curve_class = env->FindClass("java/security/spec/EllipticCurve"); + elliptic_curve_class = (jclass) env->NewGlobalRef(local_elliptic_curve_class); + + jclass local_fp_field_class = env->FindClass("java/security/spec/ECFieldFp"); + fp_field_class = (jclass) env->NewGlobalRef(local_fp_field_class); + + jclass local_f2m_field_class = env->FindClass("java/security/spec/ECFieldF2m"); + f2m_field_class = (jclass) env->NewGlobalRef(local_f2m_field_class); + + jclass local_biginteger_class = env->FindClass("java/math/BigInteger"); + biginteger_class = (jclass) env->NewGlobalRef(local_biginteger_class); + + jclass local_point_class = env->FindClass("java/security/spec/ECPoint"); + point_class = (jclass) env->NewGlobalRef(local_point_class); + + jclass local_illegal_state_exception_class = env->FindClass("java/lang/IllegalStateException"); + illegal_state_exception_class = (jclass) env->NewGlobalRef(local_illegal_state_exception_class); +}
\ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp new file mode 100644 index 0000000..d0bf8f2 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/cpp_utils.hpp @@ -0,0 +1,16 @@ +#include "native.h" +#include <string> + +extern jclass ec_parameter_spec_class; +extern jclass ecgen_parameter_spec_class; +extern jclass pubkey_class; +extern jclass privkey_class; +extern jclass keypair_class; +extern jclass elliptic_curve_class; +extern jclass fp_field_class; +extern jclass f2m_field_class; +extern jclass point_class; +extern jclass biginteger_class; +extern jclass illegal_state_exception_class; + +void init_classes(JNIEnv *env, std::string lib_name);
\ 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 629ffc1..0fb69a3 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c @@ -2,20 +2,10 @@ #include <stdio.h> #include <string.h> #include <tomcrypt.h> +#include "c_utils.h" static prng_state ltc_prng; static jclass provider_class; -static jclass ec_parameter_spec_class; -static jclass ecgen_parameter_spec_class; -static jclass pubkey_class; -static jclass privkey_class; -static jclass keypair_class; -static jclass elliptic_curve_class; -static jclass fp_field_class; -static jclass f2m_field_class; -static jclass point_class; -static jclass biginteger_class; -static jclass illegal_state_exception_class; JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider(JNIEnv *env, jobject this) { /* Create the custom provider. */ @@ -60,38 +50,7 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ fprintf(stderr, "Error setting up PRNG, %s\n", error_to_string(err)); } - jclass local_ec_parameter_spec_class = (*env)->FindClass(env, "java/security/spec/ECParameterSpec"); - ec_parameter_spec_class = (*env)->NewGlobalRef(env, local_ec_parameter_spec_class); - - jclass local_ecgen_parameter_spec_class = (*env)->FindClass(env, "java/security/spec/ECGenParameterSpec"); - ecgen_parameter_spec_class = (*env)->NewGlobalRef(env, local_ecgen_parameter_spec_class); - - jclass local_pubkey_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey$TomCrypt"); - pubkey_class = (*env)->NewGlobalRef(env, local_pubkey_class); - - jclass local_privkey_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$TomCrypt"); - privkey_class = (*env)->NewGlobalRef(env, local_privkey_class); - - jclass local_keypair_class = (*env)->FindClass(env, "java/security/KeyPair"); - keypair_class = (*env)->NewGlobalRef(env, local_keypair_class); - - jclass local_elliptic_curve_class = (*env)->FindClass(env, "java/security/spec/EllipticCurve"); - elliptic_curve_class = (*env)->NewGlobalRef(env, local_elliptic_curve_class); - - jclass local_fp_field_class = (*env)->FindClass(env, "java/security/spec/ECFieldFp"); - fp_field_class = (*env)->NewGlobalRef(env, local_fp_field_class); - - jclass local_f2m_field_class = (*env)->FindClass(env, "java/security/spec/ECFieldF2m"); - f2m_field_class = (*env)->NewGlobalRef(env, local_f2m_field_class); - - jclass local_biginteger_class = (*env)->FindClass(env, "java/math/BigInteger"); - biginteger_class = (*env)->NewGlobalRef(env, local_biginteger_class); - - jclass local_point_class = (*env)->FindClass(env, "java/security/spec/ECPoint"); - point_class = (*env)->NewGlobalRef(env, local_point_class); - - jclass local_illegal_state_exception_class = (*env)->FindClass(env, "java/lang/IllegalStateException"); - illegal_state_exception_class = (*env)->NewGlobalRef(env, local_illegal_state_exception_class); + init_classes(env, "TomCrypt"); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves(JNIEnv *env, jobject this) { |
