diff options
| author | J08nY | 2018-07-19 18:41:31 +0200 |
|---|---|---|
| committer | J08nY | 2018-07-19 18:41:31 +0200 |
| commit | 1c678ec14afad688e0f4913dc478394d429ad6ee (patch) | |
| tree | 8818564196768f1e9a200caf188500907836ef89 /src | |
| parent | fac4315a5402e3cabdd17d03647d1c29fac8c274 (diff) | |
| download | ECTester-1c678ec14afad688e0f4913dc478394d429ad6ee.tar.gz ECTester-1c678ec14afad688e0f4913dc478394d429ad6ee.tar.zst ECTester-1c678ec14afad688e0f4913dc478394d429ad6ee.zip | |
Diffstat (limited to 'src')
4 files changed, 210 insertions, 25 deletions
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java index 0949172..86cc95b 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java @@ -273,4 +273,25 @@ public abstract class NativeSignatureSpi extends SignatureSpi { super("SHA512withECDSA"); } } + + public abstract static class Openssl extends NativeSignatureSpi { + private String type; + + public Openssl(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 OpensslECDSAwithNONE extends Openssl { + + public OpensslECDSAwithNONE() { + super("NONEwithECDSA"); + } + } } 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 d925dfe..3ef8f86 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h @@ -25,4 +25,17 @@ void init_classes(JNIEnv *env, const char* lib_name); /** * Throw a new exception of class with message. */ -void throw_new(JNIEnv *env, const char *class, const char *message);
\ No newline at end of file +void throw_new(JNIEnv *env, const char *class, const char *message); + +/** + * Some useful defines to init the provider. + */ +#define INIT_PROVIDER(env, provider_class) jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") +#define ADD_PROPERTY(env, self, base_name, base_class, prop_name, prop_class) do { \ + jstring ec = (*env)->NewStringUTF(env, base_name prop_name); \ + jstring ec_value = (*env)->NewStringUTF(env, base_class prop_class); \ + (*env)->CallObjectMethod(env, self, provider_put, ec, ec_value); \ + } while (0) +#define ADD_KPG(env, self, kpg_name, kpg_class) ADD_PROPERTY(env, self, "KeyPairGenerator.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$", kpg_name, kpg_class) +#define ADD_KA(env, self, ka_name, ka_class) ADD_PROPERTY(env, self, "KeyAgreement.", "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$", ka_name, ka_class) +#define ADD_SIG(env, self, sig_name, sig_class) ADD_PROPERTY(env, self, "Signature.", "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$", sig_name, sig_class)
\ 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 54dc63f..af68fd4 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -657,3 +657,30 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl + * Method: sign + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Openssl + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, 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 6f92046..3916cec 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c @@ -1,14 +1,16 @@ #include "native.h" #include <string.h> +#include <stdio.h> #include <openssl/conf.h> #include <openssl/opensslv.h> #include <openssl/objects.h> +#include <openssl/obj_mac.h> +#include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/err.h> #include <openssl/ec.h> -#include <openssl/obj_mac.h> -#include <openssl/bn.h> +#include <openssl/ecdsa.h> #include "c_utils.h" @@ -23,7 +25,10 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_creat jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V"); jstring name = (*env)->NewStringUTF(env, OPENSSL_VERSION_TEXT); - double version = ((double)((OPENSSL_VERSION_NUMBER & 0xff000000L) >> 30)) + ((double)((OPENSSL_VERSION_NUMBER & 0xff0000L) >> 20)); + long ver_hi = (OPENSSL_VERSION_NUMBER & 0xff000000L) >> 28; + long ver_mid = (OPENSSL_VERSION_NUMBER & 0xff0000L) >> 20; + long ver_low = (OPENSSL_VERSION_NUMBER & 0xff00L) >> 12; + double version = (double)ver_hi + ((double)ver_mid/10) + ((double)ver_low/100); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -33,15 +38,11 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - - jstring ec = (*env)->NewStringUTF(env, "KeyPairGenerator.EC"); - jstring ec_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Openssl"); - (*env)->CallObjectMethod(env, self, provider_put, ec, ec_value); + INIT_PROVIDER(env, provider_class); - jstring ecdh = (*env)->NewStringUTF(env, "KeyAgreement.ECDH"); - jstring ecdh_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$OpensslECDH"); - (*env)->CallObjectMethod(env, self, provider_put, ecdh, ecdh_value); + ADD_KPG(env, self, "EC", "Openssl"); + ADD_KA(env, self, "ECDH", "OpensslECDH"); + ADD_SIG(env, self, "NONEwithECDSA", "OpensslECDSAwithNONE"); init_classes(env, "Openssl"); } @@ -144,20 +145,37 @@ static EC_GROUP *create_curve(JNIEnv *env, jobject params) { BIGNUM *p_bn = biginteger_to_bignum(env, p); result = EC_GROUP_new_curve_GFp(p_bn, a_bn, b_bn, NULL); BN_free(p_bn); + if (!result) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GFp."); + BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); + return NULL; + } g_point = EC_POINT_new(result); - EC_POINT_set_affine_coordinates_GFp(result, g_point, gx_bn, gy_bn, NULL); + if(!EC_POINT_set_affine_coordinates_GFp(result, g_point, gx_bn, gy_bn, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GFp."); + BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result); + return NULL; + } } else if ((*env)->IsInstanceOf(env, field, f2m_field_class)) { - jmethodID get_reduction_poly = (*env)->GetMethodID(env, f2m_field_class, "getReductionPolynomial", "()Ljava/math/BigInteger;"); jobject red_poly = (*env)->CallObjectMethod(env, field, get_reduction_poly); BIGNUM *p_bn = biginteger_to_bignum(env, red_poly); result = EC_GROUP_new_curve_GF2m(p_bn, a_bn, b_bn, NULL); BN_free(p_bn); + if (!result) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_new_curve_GF2m."); + BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); + return NULL; + } g_point = EC_POINT_new(result); - EC_POINT_set_affine_coordinates_GF2m(result, g_point, gx_bn, gy_bn, NULL); + if(!EC_POINT_set_affine_coordinates_GF2m(result, g_point, gx_bn, gy_bn, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_POINT_set_affine_coordinates_GF2m."); + BN_free(a_bn); BN_free(b_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result); + return NULL; + } } else { return NULL; } @@ -174,7 +192,11 @@ static EC_GROUP *create_curve(JNIEnv *env, jobject params) { BIGNUM *h_bn = BN_new(); BN_set_word(h_bn, h); - EC_GROUP_set_generator(result, g_point, n_bn, h_bn); + if (!EC_GROUP_set_generator(result, g_point, n_bn, h_bn)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating EC_GROUP, EC_GROUP_set_generator."); + BN_free(n_bn); BN_free(h_bn); BN_free(gx_bn); BN_free(gy_bn); EC_POINT_free(g_point); EC_GROUP_free(result); + return NULL; + } EC_POINT_free(g_point); BN_free(gx_bn); @@ -228,7 +250,11 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) { BIGNUM *p = BN_new(); a = BN_new(); b = BN_new(); - EC_GROUP_get_curve_GFp(curve, p, a, b, NULL); + if (!EC_GROUP_get_curve_GFp(curve, p, a, b, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GFp."); + BN_free(p); BN_free(a); BN_free(b); + return NULL; + } jobject p_int = bignum_to_biginteger(env, p); @@ -239,12 +265,20 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) { gx = BN_new(); gy = BN_new(); - EC_POINT_get_affine_coordinates_GFp(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL); + if (!EC_POINT_get_affine_coordinates_GFp(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GFp."); + BN_free(a); BN_free(b); BN_free(gx); BN_free(gy); + return NULL; + } } else if (field_type == NID_X9_62_characteristic_two_field) { a = BN_new(); b = BN_new(); - EC_GROUP_get_curve_GF2m(curve, NULL, a, b, NULL); + if (!EC_GROUP_get_curve_GF2m(curve, NULL, a, b, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_curve_GF2m."); + BN_free(a); BN_free(b); + return NULL; + } int basis_type = EC_GROUP_get_basis_type(curve); jintArray ks; @@ -252,11 +286,21 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) { if (basis_type == NID_X9_62_tpBasis) { ks = (*env)->NewIntArray(env, 1); ks_data = (*env)->GetIntArrayElements(env, ks, NULL); - EC_GROUP_get_trinomial_basis(curve, &ks_data[0]); + if (!EC_GROUP_get_trinomial_basis(curve, &ks_data[0])) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_trinomial_basis."); + BN_free(a); BN_free(b); + (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT); + return NULL; + } } else if (basis_type == NID_X9_62_ppBasis) { ks = (*env)->NewIntArray(env, 3); ks_data = (*env)->GetIntArrayElements(env, ks, NULL); - EC_GROUP_get_pentanomial_basis(curve, &ks_data[0], &ks_data[1], &ks_data[2]); + if (!EC_GROUP_get_pentanomial_basis(curve, &ks_data[0], &ks_data[1], &ks_data[2])) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_GROUP_get_pentanomial_basis."); + BN_free(a); BN_free(b); + (*env)->ReleaseIntArrayElements(env, ks, ks_data, JNI_ABORT); + return NULL; + } } else { return NULL; } @@ -269,7 +313,11 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) { gx = BN_new(); gy = BN_new(); - EC_POINT_get_affine_coordinates_GF2m(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL); + if (!EC_POINT_get_affine_coordinates_GF2m(curve, EC_GROUP_get0_generator(curve), gx, gy, NULL)) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Error creating ECParameterSpec, EC_POINT_get_affine_coordinates_GF2m."); + BN_free(a); BN_free(b); BN_free(gx); BN_free(gy); + return NULL; + } } else { return NULL; } @@ -306,7 +354,11 @@ static jobject generate_from_curve(JNIEnv *env, const EC_GROUP *curve) { EC_KEY *key = EC_KEY_new(); EC_KEY_set_group(key, curve); - EC_KEY_generate_key(key); + if (!EC_KEY_generate_key(key)) { + throw_new(env, "java/security/GeneralSecurityException", "Error generating key, EC_KEY_generate_key."); + EC_KEY_free(key); + return NULL; + } jbyteArray priv_bytes = (*env)->NewByteArray(env, key_bytes); jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); @@ -431,13 +483,85 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey int field_size = EC_GROUP_get_degree(curve); size_t secret_len = (field_size + 7)/8; + //TODO: Do more KeyAgreements here, but will have to do the hash-fun manually, + // 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); - ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL); + if (ECDH_compute_key(result_data, secret_len, EC_KEY_get0_public_key(pub), priv, NULL) <= 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); + return NULL; + } (*env)->ReleaseByteArrayElements(env, result, result_data, JNI_COMMIT); EC_KEY_free(pub); EC_KEY_free(priv); EC_GROUP_free(curve); return result; -}
\ No newline at end of file +} + +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + EC_GROUP *curve = create_curve(env, params); + if (!curve) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return NULL; + } + + EC_KEY *priv = barray_to_privkey(env, curve, privkey); + + 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? + ECDSA_SIG *signature = ECDSA_do_sign(data_data, data_size, priv); + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); + if (!signature) { + throw_new(env, "java/security/GeneralSecurityException", "Error signing, ECDSA_do_sign."); + EC_KEY_free(priv); EC_GROUP_free(curve); + return NULL; + } + + jsize sig_len = i2d_ECDSA_SIG(signature, NULL); + jbyteArray result = (*env)->NewByteArray(env, sig_len); + jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); + jbyte *result_data_ptr = result_data; + i2d_ECDSA_SIG(signature, (unsigned char **)&result_data_ptr); + (*env)->ReleaseByteArrayElements(env, result, result_data, JNI_COMMIT); + + ECDSA_SIG_free(signature); + EC_KEY_free(priv); + EC_GROUP_free(curve); + return result; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Openssl_verify(JNIEnv *env, jobject self, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) { + EC_GROUP *curve = create_curve(env, params); + if (!curve) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return JNI_FALSE; + } + + EC_KEY *pub = barray_to_pubkey(env, curve, pubkey); + + jsize sig_len = (*env)->GetArrayLength(env, signature); + jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL); + jbyte *sig_data_ptr = sig_data; + ECDSA_SIG *sig_obj = d2i_ECDSA_SIG(NULL, (const unsigned char **)&sig_data_ptr, sig_len); + (*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT); + + jsize data_size = (*env)->GetArrayLength(env, data); + jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL); + int result = ECDSA_do_verify(data_data, data_size, sig_obj, pub); + 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); + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); + return JNI_FALSE; + } + (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT); + + ECDSA_SIG_free(sig_obj); + EC_KEY_free(pub); + EC_GROUP_free(curve); + return (result == 1) ? JNI_TRUE : JNI_FALSE; +} |
