From 713b14add9496ae5b3df5bb51b02d449f4ca0cef Mon Sep 17 00:00:00 2001 From: J08nY Date: Tue, 24 Jul 2018 22:46:49 +0200 Subject: WIP: Microsoft CryptoAPI Next Generation support. --- .../ectester/standalone/ECTesterStandalone.java | 2 +- src/cz/crcs/ectester/standalone/libs/MscngLib.java | 20 ++ src/cz/crcs/ectester/standalone/libs/jni/Makefile | 5 +- .../standalone/libs/jni/NativeECPrivateKey.java | 6 + .../standalone/libs/jni/NativeECPublicKey.java | 7 + .../libs/jni/NativeKeyPairGeneratorSpi.java | 40 ++- .../standalone/libs/jni/NativeProvider.java | 10 + src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 324 +++++++++++++++++++++ src/cz/crcs/ectester/standalone/libs/jni/native.h | 125 ++++++++ 9 files changed, 535 insertions(+), 4 deletions(-) create mode 100644 src/cz/crcs/ectester/standalone/libs/MscngLib.java create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/mscng.c (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index c3d42dc..2897d20 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.2.0 */ public class ECTesterStandalone { - private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib()}; + private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new MscngLib()}; private Config cfg; private Options opts = new Options(); diff --git a/src/cz/crcs/ectester/standalone/libs/MscngLib.java b/src/cz/crcs/ectester/standalone/libs/MscngLib.java new file mode 100644 index 0000000..527a65b --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/MscngLib.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 MscngLib extends NativeECLibrary { + + public MscngLib() { + super("mscng_provider", "bcrypt"); + } + + @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 22e41cb..6fe6857 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -43,7 +43,7 @@ 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 cryptopp_provider.so openssl_provider.so +all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so mscng_provider.dll # Common utils c_utils.o: c_utils.c @@ -85,6 +85,9 @@ cryptopp.o: cryptopp.cpp $(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $< +mscng_provider.dll: mscng.c + + clean: rm -rf *.o rm -rf *.so diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 39539df..277ffa7 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -77,4 +77,10 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { super(keyData, params); } } + + public static class Mscng extends Raw { + public Mscng(byte[] keyData, ECParameterSpec params) { + super(keyData, params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index 1085083..18cc2cb 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -1,5 +1,6 @@ package cz.crcs.ectester.standalone.libs.jni; +import cz.crcs.ectester.common.util.ByteUtil; import cz.crcs.ectester.common.util.ECUtil; import org.bouncycastle.util.Arrays; @@ -79,4 +80,10 @@ public abstract class NativeECPublicKey implements ECPublicKey { super(keyData, params); } } + + public static class Mscng extends ANSIX962 { + public Mscng(byte[] x, byte[] y, ECParameterSpec params) { + super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index 6e441e5..f7e7653 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -27,7 +27,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { @Override public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (!paramsSupported(params)) { - throw new InvalidAlgorithmParameterException("not supported."); + throw new InvalidAlgorithmParameterException("Not supported."); } this.params = params; this.random = random; @@ -41,8 +41,9 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { return generate(keysize, random); } else if (useParams) { return generate(params, random); + } else { + throw new IllegalStateException("Uninitialized KeyPair."); } - return null; } abstract boolean keysizeSupported(int keysize); @@ -173,4 +174,39 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { @Override native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); } + + public static abstract class Mscng extends NativeKeyPairGeneratorSpi { + private String type; + + public Mscng(String type) { + this.type = type; + initialize(256, new SecureRandom());//TODO: maybe remove this default init? + } + + @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 class MscngECDH extends Cryptopp { + + public MscngECDH() { + super("ECDH"); + } + } + + public static class MscngECDSA extends Cryptopp { + + public MscngECDSA() { + super("ECDSA"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java index a4967e5..f580d74 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java @@ -59,4 +59,14 @@ public abstract class NativeProvider extends Provider { @Override native void setup(); } + + public static class Mscng extends NativeProvider { + + public Mscng(String name, double version, String info) { + super(name, version, info); + } + + @Override + native void setup(); + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c new file mode 100644 index 0000000..94a0f60 --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -0,0 +1,324 @@ +#include "native.h" +#include +#include + +#include "c_utils.h" + +static jclass provider_class; + +#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) +#define NT_FAILURE(status) !NT_SUCCESS(status) + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self){ + jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); + provider_class = (*env)->NewGlobalRef(env, local_provider_class); + + jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); + + jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); + double version = 1.0; + return (*env)->NewObject(env, provider_class, init, name, version, name); +} + +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) { + INIT_PROVIDER(env, provider_class); + + init_classes(env, "Mscng"); +} + +typedef struct { + const char *name; + ULONG bits; +} named_curve_t; + +static named_curve_t named_curves[] = { + {"curve25519", 256}, + {"brainpoolP160r1", 160}, + {"brainpoolP160t1", 160}, + {"brainpoolP192r1", 192}, + {"brainpoolP192t1", 192}, + {"brainpoolP224r1", 224}, + {"brainpoolP224t1", 224}, + {"brainpoolP256r1", 256}, + {"brainpoolP256t1", 256}, + {"brainpoolP320r1", 320}, + {"brainpoolP320t1", 320}, + {"brainpoolP384r1", 384}, + {"brainpoolP384t1", 384}, + {"brainpoolP512r1", 512}, + {"brainpoolP512t1", 512}, + {"ec192wapi", 192}, + {"nistP192", 192}, + {"nistP224", 224}, + {"nistP256", 256}, + {"nistP384", 384}, + {"nistP521", 521}, + {"numsP256t1", 256}, + {"numsP384t1", 384}, + {"numsP512t1", 512}, + {"secP160k1", 160}, + {"secP160r1", 160}, + {"secP160r2", 160}, + {"secP192k1", 192}, + {"secP192r1", 192}, + {"secP224k1", 224}, + {"secP224r1", 224}, + {"secP256k1", 256}, + {"secP256r1", 256}, + {"secP384r1", 384}, + {"secP521r1", 521}, + {"wtls12", 224}, + {"wtls7", 160}, + {"wtls9", 160}, + {"x962P192v1", 192}, + {"x962P192v2", 192}, + {"x962P192v3", 192}, + {"x962P239v1", 239}, + {"x962P239v2", 239}, + {"x962P239v3", 239}, + {"x962P256v1", 256} +}; + +static const named_curve_t* lookup_curve(const char *name) { + for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { + if (strcasecmp(name, named_curves[i].name) == 0) { + return &named_curves[i]; + } + } + return NULL; +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { + 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); + + for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { + jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); + (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); + } + return result; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { + if (params == NULL) { + return JNI_FALSE; + } + + 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); + const named_curve_t *curve = lookup_curve(utf_name); + (*env)->ReleaseStringUTFChars(env, name, utf_name); + return curve == NULL ? JNI_FALSE : JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return NULL; +} + +static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { + jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); + jbyteArray bytes = (*env)->NewByteArray(env, len); + jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL); + memcpy(data, bytes, len); + (*env)->ReleaseByteArrayElements(env, bytes, data, 0); + jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes); + return result; +} + +static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { + // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. + // + // BCRYPT_ECC_PARAMETER_HEADER header + // byte[cbFieldLength] P + // byte[cbFieldLength] A + // byte[cbFieldLength] B + // byte[cbFieldLength] G.X + // byte[cbFieldLength] G.Y + // byte[cbSubgroupOrder] Order (n) + // byte[cbCofactor] Cofactor (h) + // byte[cbSeed] Seed + + // BCRYPT_ECC_PARAMETER_HEADER + // internal int Version; //Version of the structure + // internal ECC_CURVE_TYPE_ENUM CurveType; //Supported curve types. + // internal ECC_CURVE_ALG_ID_ENUM CurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. + // internal int cbFieldLength; //Byte length of the fields P, A, B, X, Y. + // internal int cbSubgroupOrder; //Byte length of the subgroup. + // internal int cbCofactor; //Byte length of cofactor of G in E. + // internal int cbSeed; //Byte length of the seed used to generate the curve. + + // internal enum ECC_CURVE_TYPE_ENUM : int + // { + // BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, + // BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, + // BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3, + // } + + // internal enum ECC_CURVE_ALG_ID_ENUM : int + // { + // BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, + // } + BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)eccParams; + PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + + //cbFieldLength + PBYTE P = paramsStart; + PBYTE A = p + header->cbFieldLength; + PBYTE B = A + header->cbFieldLength; + PBYTE GX = B + header->cbFieldLength; + PBYTE GY = GX + header->cbFieldLength; + + //cbSubgroupOrder + PBYTE N = GY + header->cbFieldLength; + + //cbCofactor + PBYTE H = N + header->cbSubgroupOrder; + + //cbSeed + PBYTE S = H + header->cbCofactor; + + jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); + + 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, p_int); + + jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength); + jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength); + + 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); + + jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength); + jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength); + + jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); + + jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder); + + jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor); + jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I"); + jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int); + + 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"); + return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ + BCRYPT_ALG_HANDLE kaHandle = NULL; + BCRYPT_KEY_HANDLE key = NULL; + + //TODO: CUSTOM curve with BCRYPT_ECC_PARAMETERS?? + + jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR algo; + if (strcmp(type_data, "ECDH") == 0) { + algo = BCRYPT_ECDH_ALGORITHM; + } else if (strcmp(type_data, "ECDSA") == 0) { + algo = BCRYPT_ECDSA_ALGORITHM; + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&kaHandle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + //err + } + + 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); + const named_curve_t *curve = lookup_curve(utf_name); + if (NT_FAILURE(BCryptSetProperty(kaHandle, BCRYPT_ECC_CURVE_NAME, utf_name, strlen(utf_name), 0))) { + //err + } + (*env)->ReleaseStringUTFChars(env, name, utf_name); + + ULONG paramsSize; + if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { + //err + } + if (paramsSize == 0) { + //TODO: what now? + } + + BYTE params[paramsSize]; + if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, params, paramsSize, ¶msSize, 0))) { + //err + } + + jobject ec_param_spec = create_ec_param_spec(env, params, paramsSize); + + if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, curve.bits, 0)) { + //err + } + + if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { + //err + } + + ULONG bufSize; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + //err + } + + BYTE privBuf[bufSize]; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufsize, &bufSize, 0))) { + //err + } + + // privBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] Q.X + // byte[cbKey] Q.Y + // byte[cbKey] D + BCRYPT_ECCKEY_BLOB *header = (BCRYPT_ECCKEY_BLOB*)privBuf; + PBYTE x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; + PBYTE y = x + header->cbKey; + PBYTE priv = y + header->cbKey; + + jbyteArray priv_bytes = (*env)->NewByteArray(env, header->cbKey); + jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); + memcpy(key_priv, priv, header->cbKey); + (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); + + 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); + + jbyteArray x_bytes = (*env)->NewByteArray(env, header->cbKey); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, x, header->cbKey); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + jbyteArray y_bytes = (*env)->NewByteArray(env, header->cbKey); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, y, header->cbKey); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); + jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, x_bytes, y_bytes, ec_pub_param_spec); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(kaHandle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); +} \ 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 af68fd4..6e2b2bf 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -684,3 +684,128 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_MscngLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_MscngLib +#define _Included_cz_crcs_ectester_standalone_libs_MscngLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_MscngLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_MscngLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840LL +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739LL +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.3.1 From 7f7d6503589c50c2990556a550c7a5f252d7d789 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 25 Jul 2018 19:38:03 +0200 Subject: Add KeyAgreement support to Mscng. --- build-standalone.xml | 1 + .../standalone/libs/jni/NativeECPrivateKey.java | 45 ++- .../standalone/libs/jni/NativeECPublicKey.java | 44 ++- .../standalone/libs/jni/NativeKeyAgreementSpi.java | 49 ++- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 333 ++++++++++++++++++--- src/cz/crcs/ectester/standalone/libs/jni/native.h | 19 ++ 6 files changed, 424 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/build-standalone.xml b/build-standalone.xml index 1e6a3d5..62b66de 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -134,6 +134,7 @@ + diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 277ffa7..7980773 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -1,5 +1,6 @@ package cz.crcs.ectester.standalone.libs.jni; +import cz.crcs.ectester.common.util.ByteUtil; import org.bouncycastle.util.Arrays; import java.math.BigInteger; @@ -12,10 +13,12 @@ import java.security.spec.ECParameterSpec; public abstract class NativeECPrivateKey implements ECPrivateKey { private String algorithm; private String format; + ECParameterSpec params; - public NativeECPrivateKey(String algorithm, String format) { + public NativeECPrivateKey(String algorithm, String format, ECParameterSpec params) { this.algorithm = algorithm; this.format = format; + this.params = params; } @Override @@ -28,14 +31,19 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { return format; } + @Override + public ECParameterSpec getParams() { + return params; + } + + public abstract byte[] getData(); + private static class Raw extends NativeECPrivateKey { - private byte[] keyData; - private ECParameterSpec params; + byte[] keyData; public Raw(byte[] keyData, ECParameterSpec params) { - super("EC", "raw"); + super("EC", "raw", params); this.keyData = keyData; - this.params = params; } @Override @@ -48,9 +56,8 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { return Arrays.clone(keyData); } - @Override - public ECParameterSpec getParams() { - return params; + public byte[] getData() { + return getEncoded(); } } @@ -79,8 +86,28 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { } public static class Mscng extends Raw { - public Mscng(byte[] keyData, ECParameterSpec params) { + private byte[] header; + private byte[] x; + private byte[] y; + + public Mscng(byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) { super(keyData, params); + this.header = header; + this.x = x; + this.y = y; + } + + public byte[] getHeader() { + return Arrays.clone(header); + } + + public byte[] getBlob() { + return ByteUtil.concatenate(header, x, y, keyData); + } + + @Override + public byte[] getData() { + return getBlob(); } } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index 18cc2cb..e44ff49 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -15,10 +15,12 @@ import java.security.spec.ECPoint; public abstract class NativeECPublicKey implements ECPublicKey { private String algorithm; private String format; + ECParameterSpec params; - public NativeECPublicKey(String algorithm, String format) { + public NativeECPublicKey(String algorithm, String format, ECParameterSpec params) { this.algorithm = algorithm; this.format = format; + this.params = params; } @Override @@ -31,14 +33,19 @@ public abstract class NativeECPublicKey implements ECPublicKey { return format; } + @Override + public ECParameterSpec getParams() { + return params; + } + + public abstract byte[] getData(); + private static class ANSIX962 extends NativeECPublicKey { - private byte[] keyData; - private ECParameterSpec params; + byte[] keyData; public ANSIX962(byte[] keyData, ECParameterSpec params) { - super("EC", "ANSI X9.62"); + super("EC", "ANSI X9.62", params); this.keyData = keyData; - this.params = params; } @Override @@ -51,9 +58,8 @@ public abstract class NativeECPublicKey implements ECPublicKey { return Arrays.clone(keyData); } - @Override - public ECParameterSpec getParams() { - return params; + public byte[] getData() { + return ECUtil.toX962Uncompressed(getW(), params); } } @@ -82,8 +88,28 @@ public abstract class NativeECPublicKey implements ECPublicKey { } public static class Mscng extends ANSIX962 { - public Mscng(byte[] x, byte[] y, ECParameterSpec params) { + private byte[] header; + private byte[] x; + private byte[] y; + + public Mscng(byte[] header, byte[] x, byte[] y, ECParameterSpec params) { super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params); + this.header = header; + this.x = x; + this.y = y; + } + + public byte[] getHeader() { + return Arrays.clone(header); + } + + public byte[] getBlob() { + return ByteUtil.concatenate(header, x, y); + } + + @Override + public byte[] getData() { + return getBlob(); } } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index 47d1fcc..1211519 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -61,8 +61,18 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { @Override protected byte[] engineGenerateSecret() throws IllegalStateException { - byte[] pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve()); - byte[] privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize()); + byte[] pubkey; + if (publicKey instanceof NativeECPublicKey) { + pubkey = ((NativeECPublicKey) publicKey).getData(); + } else { + pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve()); + } + byte[] privkey; + if (privateKey instanceof NativeECPrivateKey) { + privkey = ((NativeECPrivateKey) privateKey).getData(); + } else { + privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize()); + } return generateSecret(pubkey, privkey, params); } @@ -171,4 +181,39 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { super("ECDH"); } } + + public abstract static class Mscng extends NativeKeyAgreementSpi { + private String type; + + public Mscng(String type) { + this.type = type; + } + + @Override + native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + } + + public static class MscngECDHwithSHA1KDF extends Mscng { + public MscngECDHwithSHA1KDF() { + super("ECDHwithSHA1KDF"); + } + } + + public static class MscngECDHwithSHA256KDF extends Mscng { + public MscngECDHwithSHA256KDF() { + super("ECDHwithSHA256KDF"); + } + } + + public static class MscngECDHwithSHA384KDF extends Mscng { + public MscngECDHwithSHA384KDF() { + super("ECDHwithSHA384KDF"); + } + } + + public static class MscngECDHwithSHA512KDF extends Mscng { + public MscngECDHwithSHA512KDF() { + super("ECDHwithSHA512KDF"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 94a0f60..aa986d1 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -23,6 +23,14 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createP JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) { INIT_PROVIDER(env, provider_class); + ADD_KPG(env, self, "ECDH", "MscngECDH"); + ADD_KPG(env, self, "ECDSA", "MscngECDSA"); + + ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF"); + ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF"); + ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); + ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); + init_classes(env, "Mscng"); } @@ -119,6 +127,18 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa const named_curve_t *curve = lookup_curve(utf_name); (*env)->ReleaseStringUTFChars(env, name, utf_name); return curve == NULL ? JNI_FALSE : JNI_TRUE; + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject curve = (*env)->CallObjectMethod(env, params, get_curve); + + jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = (*env)->CallObjectMethod(env, curve, get_field); + + if ((*env)->IsInstanceOf(env, field, fp_field_class)) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } } else { return JNI_FALSE; } @@ -139,6 +159,16 @@ static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { return result; } +static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) { + 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); + memcpy(bytes, &byte_data[byte_length - len], len); + (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); +} + static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. // @@ -218,12 +248,190 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLen return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); } +static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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, "getB", "()Ljava/math/BigInteger;"); + jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); + + jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); + + jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); + jobject p = (*env)->CallObjectMethod(env, field, get_p); + + jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); + jobject g = (*env)->CallObjectMethod(env, params, get_g); + + jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); + jobject gx = (*env)->CallObjectMethod(env, g, get_x); + + jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); + jobject gy = (*env)->CallObjectMethod(env, g, get_y); + + jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); + jobject n = (*env)->CallObjectMethod(env, params, get_n); + + jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); + jint h = (*env)->CallIntMethod(env, params, get_h); + + jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I"); + jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength); + jint order_bytes = (order_bits + 7) / 8; + + // header_size + 5*bytes + order_bytes + cof_size + 0 + ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + sizeof(jint) + 0; + *curve = calloc(buSize, 1); + BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; + header->Version = 1; + header->CurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery + header->CurveGenerationAlgId = 0; + header->cbFieldLength = bytes; + header->cbSubgroupOrder = order_bytes; + header->cbCofactor = sizeof(jint); + header->cbSeed = 0; + + PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + + biginteger_to_bytes(env, p, paramsStart, bytes); + biginteger_to_bytes(env, a, paramsStart + bytes, bytes); + biginteger_to_bytes(env, b, paramsStart + 2*bytes, bytes); + biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); + biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); + biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); + jint *cof_ptr = (jint *) (paramsStart + 5*bytes + order_bytes); + *cof_ptr = h; + return bufSize; +} + +static bool init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + //err + return false; + } + + 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); + const named_curve_t *curve = lookup_curve(utf_name); + if (NT_FAILURE(BCryptSetProperty(handle, BCRYPT_ECC_CURVE_NAME, utf_name, strlen(utf_name), 0))) { + //err + return false; + } + (*env)->ReleaseStringUTFChars(env, name, utf_name); + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + PBYTE curve; + ULONG curveLen = create_curve(env, params, &curve); + if (NT_FAILURE(BCryptSetProperty(handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { + //err + return false; + } + free(curve); + } + return true; +} + +static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { + ULONG bufSize = 0; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + //err + } + if (bufSize == 0) { + //err + } + + BYTE privBuf[bufSize]; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufsize, &bufSize, 0))) { + //err + } + + // privBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] Q.X + // byte[cbKey] Q.Y + // byte[cbKey] D + BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; + PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; + PBYTE priv_y = priv_x + privHeader->cbKey; + PBYTE priv = priv_y + privHeader->cbKey; + + jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, privHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, priv_x, privHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + + jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, priv_y, privHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); + memcpy(key_priv, priv, header->cbKey); + (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); + + jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); +} + +static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { + ULONG bufSize = 0; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + //err + } + + BYTE pubBuf[bufSize]; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + //err + } + + // pubBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] Q.X + // byte[cbKey] Q.Y + BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; + PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; + PBYTE pub_y = pub_x + pubHeader->cbKey; + + jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, pubHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, pub_x, pubHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + + jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, pub_y, pubHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); +} + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ BCRYPT_ALG_HANDLE kaHandle = NULL; BCRYPT_KEY_HANDLE key = NULL; - //TODO: CUSTOM curve with BCRYPT_ECC_PARAMETERS?? - jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -238,25 +446,16 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai } (*env)->ReleaseStringUTFChars(env, type, type_data); - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&kaHandle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + if (!init_algo(env, &kaHandle, algo, params)) { //err } - 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); - const named_curve_t *curve = lookup_curve(utf_name); - if (NT_FAILURE(BCryptSetProperty(kaHandle, BCRYPT_ECC_CURVE_NAME, utf_name, strlen(utf_name), 0))) { - //err - } - (*env)->ReleaseStringUTFChars(env, name, utf_name); - ULONG paramsSize; if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { //err } if (paramsSize == 0) { - //TODO: what now? + //err } BYTE params[paramsSize]; @@ -274,51 +473,91 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai //err } - ULONG bufSize; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + jobject privkey = key_to_privkey(env, key, ec_param_spec); + jobject pubkey = key_to_pubkey(env, key, ec_param_spec); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(kaHandle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); +} + +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR kdf_algo; + if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) { + kdf_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) { + kdf_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) { + kdf_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) { + kdf_algo = BCRYPT_SHA512_ALGORITHM; + } else { //err } + (*env)->ReleaseStringUTFChars(env, type, type_data); - BYTE privBuf[bufSize]; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufsize, &bufSize, 0))) { + BCRYPT_ALG_HANDLE kaHandle = NULL; + + if (!init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params)) { //err } - // privBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - // byte[cbKey] D - BCRYPT_ECCKEY_BLOB *header = (BCRYPT_ECCKEY_BLOB*)privBuf; - PBYTE x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; - PBYTE y = x + header->cbKey; - PBYTE priv = y + header->cbKey; + BCRYPT_KEY_HANDLE pkey = NULL; + BCRYPT_KEY_HANDLE skey = NULL; - jbyteArray priv_bytes = (*env)->NewByteArray(env, header->cbKey); - jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); - memcpy(key_priv, priv, header->cbKey); - (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); - 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); + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + //err + } - jbyteArray x_bytes = (*env)->NewByteArray(env, header->cbKey); - jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, x, header->cbKey); - (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - jbyteArray y_bytes = (*env)->NewByteArray(env, header->cbKey); - jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, y, header->cbKey); - (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + BCRYPT_SECRET_HANDLE ka = NULL; - jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); - jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); - jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, x_bytes, y_bytes, ec_pub_param_spec); + if (NT_FAILURE(BCryptSecretAgreement(skey, pkey, &ka, 0))) { + //err + } - jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + BCryptBufferDesc paramList = {0}; + BCryptBuffer kdfParams[1] = {0}; + kdfParams[0].BufferType = KDF_HASH_ALGORITHM; + kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR)); + kdfParams[0].pvBuffer = (PVOID)kdf_algo; + paramList.cBuffers = 1; + paramList.pBuffers = kdfParams; + paramList.ulVersion = BCRYPTBUFFER_VERSION; + + //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* + ULONG bufSize = 0; + if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { + //err + } - BCryptDestroyKey(key); + BYTE derived[bufSize]; + if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { + //err + } + + jbyteArray result = (*env)->NewByteArray(env, bufSize); + jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); + memcpy(result_data, derived, bufSize); + (*env)->ReleaseByteArrayElements(env, result, result_data, 0); + + BCryptDestroyKey(pkey); + BCryptDestroyKey(skey); + BCryptDestroySecret(ka); BCryptCloseAlgorithmProvider(kaHandle, 0); - return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); + 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 6e2b2bf..a4b5915 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -809,3 +809,22 @@ extern "C" { } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.3.1 From fb3daa0163127efa94c147618d40547f506398f1 Mon Sep 17 00:00:00 2001 From: J08nY Date: Wed, 25 Jul 2018 21:37:28 +0200 Subject: Add Signature support to Mscng. --- build-standalone.xml | 1 + .../standalone/libs/jni/NativeSignatureSpi.java | 58 +++++++- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 152 +++++++++++++++++++++ src/cz/crcs/ectester/standalone/libs/jni/native.h | 27 ++++ 4 files changed, 236 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/build-standalone.xml b/build-standalone.xml index 62b66de..692b02b 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -135,6 +135,7 @@ + diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java index 86cc95b..e347120 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java @@ -52,12 +52,24 @@ public abstract class NativeSignatureSpi extends SignatureSpi { @Override protected byte[] engineSign() throws SignatureException { - return sign(buffer.toByteArray(), ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()), params); + byte[] privkey; + if (signKey instanceof NativeECPrivateKey) { + privkey = ((NativeECPrivateKey) signKey).getData(); + } else { + privkey = ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()); + } + return sign(buffer.toByteArray(), privkey, params); } @Override protected boolean engineVerify(byte[] sigBytes) throws SignatureException { - return verify(sigBytes, buffer.toByteArray(), ECUtil.toX962Uncompressed(verifyKey.getW(), params), params); + byte[] pubkey; + if (verifyKey instanceof NativeECPublicKey) { + pubkey = ((NativeECPublicKey) verifyKey).getData(); + } else { + pubkey = ECUtil.toX962Uncompressed(verifyKey.getW(), params); + } + return verify(sigBytes, buffer.toByteArray(), pubkey, params); } @Override @@ -294,4 +306,46 @@ public abstract class NativeSignatureSpi extends SignatureSpi { super("NONEwithECDSA"); } } + + public abstract static class Mscng extends NativeSignatureSpi { + private String type; + + public Mscng(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 MscngECDSAwithSHA1 extends Mscng { + + public MscngECDSAwithSHA1() { + super("SHA1withECDSA"); + } + } + + public static class MscngECDSAwithSHA256 extends Mscng { + + public MscngECDSAwithSHA256() { + super("SHA256withECDSA"); + } + } + + public static class MscngECDSAwithSHA384 extends Mscng { + + public MscngECDSAwithSHA384() { + super("SHA384withECDSA"); + } + } + + public static class MscngECDSAwithSHA512 extends Mscng { + + public MscngECDSAwithSHA512() { + super("SHA512withECDSA"); + } + } } diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index aa986d1..5b35cae 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -31,6 +31,11 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); + ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1"); + ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256"); + ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); + ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); + init_classes(env, "Mscng"); } @@ -523,6 +528,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { //err } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); BCRYPT_SECRET_HANDLE ka = NULL; @@ -560,4 +566,150 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey BCryptDestroySecret(ka); BCryptCloseAlgorithmProvider(kaHandle, 0); return result; +} + +static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { + jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR hash_algo; + if (strcmp(type_data, "SHA1withECDSA") == 0) { + hash_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "SHA256withECDSA") == 0) { + hash_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "SHA384withECDSA") == 0) { + hash_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "SHA512withECDSA") == 0) { + hash_algo = BCRYPT_SHA512_ALGORITHM; + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + return hash_algo; +} + +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + LPCWSTR hash_algo = get_sighash_algo(env, self); + + BCRYPT_ALG_HANDLE sigHandle = NULL; + + if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { + //err + } + + BCRYPT_ALG_HANDLE hashHandle = NULL; + + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + //err + } + + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + //err + } + + BYTE hash[hash_len]; + + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + //err + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE skey = NULL; + + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + + DWORD sig_len = 0; + if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { + //err + } + + jbyteArray sig = (*env)->NewByteArray(env, sig_len); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); + + BCryptDestroyKey(skey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); + + return sig; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { + LPCWSTR hash_algo = get_sighash_algo(env, self); + + BCRYPT_ALG_HANDLE sigHandle = NULL; + + if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { + //err + } + + BCRYPT_ALG_HANDLE hashHandle = NULL; + + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + //err + } + + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + //err + } + + BYTE hash[hash_len]; + + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + //err + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BYTE hash[hash_len]; + + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + //err + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE pkey = NULL; + + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, pub_data, pub_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + + jint sig_len = (*env)->GetArrayLength(env, sig); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0); + (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); + + BCryptDestroyKey(pkey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); + + if (result == STATUS_SUCCESS) { + return JNI_TRUE; + } else if (result == STATUS_INVALID_SIGNATURE) { + return JNI_FALSE; + } else { + //err + return JNI_FALSE; + } } \ 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 a4b5915..a2dedae 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -828,3 +828,30 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } #endif #endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng + * Method: sign + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.3.1 From da8812b55dac70882f88870afe9877dd2927fa31 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 26 Jul 2018 19:59:33 +0200 Subject: Add Mscng build files to build on windows --- build-standalone.xml | 13 ++ .../crcs/ectester/standalone/libs/jni/Makefile.bat | 136 +++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100755 src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat (limited to 'src') diff --git a/build-standalone.xml b/build-standalone.xml index 692b02b..fc135a0 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -84,11 +84,19 @@ + + + + + + + + @@ -97,6 +105,11 @@ osfamily="unix"> + + + + + diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat new file mode 100755 index 0000000..04b785e --- /dev/null +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -0,0 +1,136 @@ +@if not defined _echo echo off +setlocal EnableDelayedExpansion + +:: See if we are cleaning. +if "%1" == "clean" ( + echo ** cleaning + del mscng_provider.dll + exit +) + + +:: Determine arch. +reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && (set ARCH=32& set ARCH_S=x86& set ARCH_VS=x86) || (set ARCH=64& set ARCH_S=x64& set ARCH_VS=amd64) + +echo ** ARCH %ARCH_S% + + +:: Find a working visual studio environment. +set found=0 +set vsw_path="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" + +set vs_path= +for /f "usebackq delims=" %%i in (`%vsw_path% -nologo -prerelease -latest -property installationPath`) do ( + if exist "%%i\Common7\Tools\vsdevcmd.bat" ( + echo ** VsDevCmd at %%i\Common7\Tools\vsdevcmd.bat + call "%%i\Common7\Tools\vsdevcmd.bat" -no_logo -arch=%ARCH_VS% + if ERRORLEVEL 1 ( + echo nope. + ) else ( + set found=1 + set vs_path=%%i + break + ) + ) +) + +:: Test if we have a visual studio env. +if %found% EQU 0 ( + echo Working VsDevCmd not found. + exit /b 2 +) + +echo ** VS_PATH %vs_path% + + +:: Try to find vcruntime. +set vc_base=%vs_path%\VC\Tools\MSVC\ +if exist %vc_base% ( + set vc_version= + for /f "delims=" %%i in ('dir /b /on "!vc_base!"') do ( + set vc_version=%%i + ) + echo ** VC_VERSION !vc_version! + set vc_include=%vc_base%!vc_version!\include + set vc_lib=%vc_base%!vc_version!\lib\%ARCH_S% +) + + +:: Get the paths to Microsoft CNG SDK. +set root_rel=..\..\..\..\..\..\..\ +set mscng_rel_include=ext\mscng\Include +set mscng_rel_lib=ext\mscng\Lib + +pushd %root_rel% +pushd %mscng_rel_include% +set mscng_include=%CD% +popd +pushd %mscng_rel_lib% +set mscng_lib=%CD% +popd +popd + +set mscng_lib_arch=%mscng_lib%\X%ARCH% + +echo ** CNG_INCLUDE !mscng_include! +echo ** CNG_LIB !mscng_lib! + + +:: Get the paths to Java JNI. +if not defined JAVA_HOME ( + set jva= + for /f "delims=" %%i in ('where javac') do ( + set jva=%%~dpi + ) + pushd !jva!\.. + set JAVA_HOME=!CD! + popd +) + +echo ** JAVA_HOME !JAVA_HOME! + +set JNI_INCLUDEDIR=%JAVA_HOME%\include +set JNI_PLATFORMINCLUDEDIR=%JNI_INCLUDEDIR%\win32 +set JNI_LIBDIR=%JAVA_HOME%\lib + + +:: Setup binaries. +if not defined CC ( + set CC=cl.exe +) +if not defined LINK ( + set LINK=link.exe +) + +echo ** CC !CC! +echo ** LINK !LINK! + + +:: Try to find uCRT. +set ucrt_base=%ProgramFiles(x86)%\Windows Kits\10\ +if exist %ucrt_base% ( + set ucrt_version= + for /f "delims=" %%i in ('dir /b /on "!ucrt_base!\Include"') do ( + set ucrt_version=%%i + ) + echo ** uCRT !ucrt_version! + set ucrt_include=%ucrt_base%Include\!ucrt_version!\ucrt + set ucrt_lib=%ucrt_base%Lib\!ucrt_version! + set ucrt_lib_arch=!ucrt_lib!\ucrt\%ARCH_S% +) + +:: Setup INCLUDE paths. +set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%" /I"%mscng_include%" + +echo ** INCLUDE %INCLUDE% +echo ** INCLUDE_CLI %INCLUDE_CLI% + +:: Setup LIB paths. +set LIBPATH=/LIBPATH:"%JNI_LIBDIR%" /I"%mscng_lib_arch%" + +echo ** LIB %LIB% +echo ** LIBPATH %LIBPATH% +echo. + + +%CC% /EHsc %INCLUDE_CLI% mscng.c /LD /Femscng_provider.dll \ No newline at end of file -- cgit v1.3.1 From 1a97e9c0070899bab201a2a14c9bb90ca1ca5e69 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 26 Jul 2018 23:06:40 +0200 Subject: Fix Mscng, finally! --- .gitignore | 4 + src/cz/crcs/ectester/standalone/libs/jni/Makefile | 24 +- .../crcs/ectester/standalone/libs/jni/Makefile.bat | 10 +- src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 4 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 1458 ++++++++++---------- 5 files changed, 769 insertions(+), 731 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index af8dbf7..90700ba 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,8 @@ # Built binaries in /src. /src/**/*.a /src/**/*.o +/src/**/*.obj /src/**/*.so +/src/**/*.dll +/src/**/*.exp +/src/**/*.lib diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile index 6fe6857..006a3b1 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile @@ -38,12 +38,23 @@ CC?=gcc CXX?=g++ STRIP?=strip -LFLAGS+=-fPIC -g -shared -CFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. -CXXFLAGS+=-fPIC -g -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I. - +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 mscng_provider.dll +all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so # Common utils c_utils.o: c_utils.c @@ -85,9 +96,6 @@ cryptopp.o: cryptopp.cpp $(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $< -mscng_provider.dll: mscng.c - - clean: rm -rf *.o rm -rf *.so diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index 04b785e..a279750 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -98,12 +98,8 @@ set JNI_LIBDIR=%JAVA_HOME%\lib if not defined CC ( set CC=cl.exe ) -if not defined LINK ( - set LINK=link.exe -) echo ** CC !CC! -echo ** LINK !LINK! :: Try to find uCRT. @@ -120,17 +116,17 @@ if exist %ucrt_base% ( ) :: Setup INCLUDE paths. -set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%" /I"%mscng_include%" +set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%" echo ** INCLUDE %INCLUDE% echo ** INCLUDE_CLI %INCLUDE_CLI% :: Setup LIB paths. -set LIBPATH=/LIBPATH:"%JNI_LIBDIR%" /I"%mscng_lib_arch%" +set LIBPATH=/LIBPATH:"%JNI_LIBDIR%" echo ** LIB %LIB% echo ** LIBPATH %LIBPATH% echo. -%CC% /EHsc %INCLUDE_CLI% mscng.c /LD /Femscng_provider.dll \ No newline at end of file +%CC% /EHsc %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% \ No newline at end of file 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 336f4a1..9fee530 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c @@ -21,7 +21,7 @@ void init_classes(JNIEnv *env, const char* lib_name) { 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]; + char pubkey_class_name[1024]; //strlen(pubkey_base) + strlen(lib_name) + 1 pubkey_class_name[0] = 0; strcat(pubkey_class_name, pubkey_base); strcat(pubkey_class_name, lib_name); @@ -30,7 +30,7 @@ void init_classes(JNIEnv *env, const char* lib_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]; + char privkey_class_name[1024]; //strlen(privkey_base) + strlen(lib_name) + 1 privkey_class_name[0] = 0; strcat(privkey_class_name, privkey_base); strcat(privkey_class_name, lib_name); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 5b35cae..5dfee55 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -1,715 +1,745 @@ -#include "native.h" -#include -#include - -#include "c_utils.h" - -static jclass provider_class; - -#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) -#define NT_FAILURE(status) !NT_SUCCESS(status) - -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self){ - jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); - provider_class = (*env)->NewGlobalRef(env, local_provider_class); - - jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); - - jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); - double version = 1.0; - return (*env)->NewObject(env, provider_class, init, name, version, name); -} - -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) { - INIT_PROVIDER(env, provider_class); - - ADD_KPG(env, self, "ECDH", "MscngECDH"); - ADD_KPG(env, self, "ECDSA", "MscngECDSA"); - - ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF"); - ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF"); - ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); - ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); - - ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1"); - ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256"); - ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); - ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); - - init_classes(env, "Mscng"); -} - -typedef struct { - const char *name; - ULONG bits; -} named_curve_t; - -static named_curve_t named_curves[] = { - {"curve25519", 256}, - {"brainpoolP160r1", 160}, - {"brainpoolP160t1", 160}, - {"brainpoolP192r1", 192}, - {"brainpoolP192t1", 192}, - {"brainpoolP224r1", 224}, - {"brainpoolP224t1", 224}, - {"brainpoolP256r1", 256}, - {"brainpoolP256t1", 256}, - {"brainpoolP320r1", 320}, - {"brainpoolP320t1", 320}, - {"brainpoolP384r1", 384}, - {"brainpoolP384t1", 384}, - {"brainpoolP512r1", 512}, - {"brainpoolP512t1", 512}, - {"ec192wapi", 192}, - {"nistP192", 192}, - {"nistP224", 224}, - {"nistP256", 256}, - {"nistP384", 384}, - {"nistP521", 521}, - {"numsP256t1", 256}, - {"numsP384t1", 384}, - {"numsP512t1", 512}, - {"secP160k1", 160}, - {"secP160r1", 160}, - {"secP160r2", 160}, - {"secP192k1", 192}, - {"secP192r1", 192}, - {"secP224k1", 224}, - {"secP224r1", 224}, - {"secP256k1", 256}, - {"secP256r1", 256}, - {"secP384r1", 384}, - {"secP521r1", 521}, - {"wtls12", 224}, - {"wtls7", 160}, - {"wtls9", 160}, - {"x962P192v1", 192}, - {"x962P192v2", 192}, - {"x962P192v3", 192}, - {"x962P239v1", 239}, - {"x962P239v2", 239}, - {"x962P239v3", 239}, - {"x962P256v1", 256} -}; - -static const named_curve_t* lookup_curve(const char *name) { - for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { - if (strcasecmp(name, named_curves[i].name) == 0) { - return &named_curves[i]; - } - } - return NULL; -} - -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { - 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); - - for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { - jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); - (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); - } - return result; -} - -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { - return JNI_FALSE; -} - -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { - if (params == NULL) { - return JNI_FALSE; - } - - 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); - const named_curve_t *curve = lookup_curve(utf_name); - (*env)->ReleaseStringUTFChars(env, name, utf_name); - return curve == NULL ? JNI_FALSE : JNI_TRUE; - } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { - jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); - jobject curve = (*env)->CallObjectMethod(env, params, get_curve); - - jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); - jobject field = (*env)->CallObjectMethod(env, curve, get_field); - - if ((*env)->IsInstanceOf(env, field, fp_field_class)) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } - } else { - return JNI_FALSE; - } -} - -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { - throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; -} - -static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { - jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); - jbyteArray bytes = (*env)->NewByteArray(env, len); - jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL); - memcpy(data, bytes, len); - (*env)->ReleaseByteArrayElements(env, bytes, data, 0); - jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes); - return result; -} - -static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) { - 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); - memcpy(bytes, &byte_data[byte_length - len], len); - (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); -} - -static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { - // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. - // - // BCRYPT_ECC_PARAMETER_HEADER header - // byte[cbFieldLength] P - // byte[cbFieldLength] A - // byte[cbFieldLength] B - // byte[cbFieldLength] G.X - // byte[cbFieldLength] G.Y - // byte[cbSubgroupOrder] Order (n) - // byte[cbCofactor] Cofactor (h) - // byte[cbSeed] Seed - - // BCRYPT_ECC_PARAMETER_HEADER - // internal int Version; //Version of the structure - // internal ECC_CURVE_TYPE_ENUM CurveType; //Supported curve types. - // internal ECC_CURVE_ALG_ID_ENUM CurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. - // internal int cbFieldLength; //Byte length of the fields P, A, B, X, Y. - // internal int cbSubgroupOrder; //Byte length of the subgroup. - // internal int cbCofactor; //Byte length of cofactor of G in E. - // internal int cbSeed; //Byte length of the seed used to generate the curve. - - // internal enum ECC_CURVE_TYPE_ENUM : int - // { - // BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, - // BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, - // BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3, - // } - - // internal enum ECC_CURVE_ALG_ID_ENUM : int - // { - // BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, - // } - BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)eccParams; - PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; - - //cbFieldLength - PBYTE P = paramsStart; - PBYTE A = p + header->cbFieldLength; - PBYTE B = A + header->cbFieldLength; - PBYTE GX = B + header->cbFieldLength; - PBYTE GY = GX + header->cbFieldLength; - - //cbSubgroupOrder - PBYTE N = GY + header->cbFieldLength; - - //cbCofactor - PBYTE H = N + header->cbSubgroupOrder; - - //cbSeed - PBYTE S = H + header->cbCofactor; - - jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); - - 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, p_int); - - jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength); - jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength); - - 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); - - jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength); - jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength); - - jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); - jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); - - jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder); - - jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor); - jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I"); - jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int); - - 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"); - return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); -} - -static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { - jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); - jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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, "getB", "()Ljava/math/BigInteger;"); - jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); - - jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); - jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); - - jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); - jobject p = (*env)->CallObjectMethod(env, field, get_p); - - jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); - jobject g = (*env)->CallObjectMethod(env, params, get_g); - - jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); - jobject gx = (*env)->CallObjectMethod(env, g, get_x); - - jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); - jobject gy = (*env)->CallObjectMethod(env, g, get_y); - - jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); - jobject n = (*env)->CallObjectMethod(env, params, get_n); - - jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); - jint h = (*env)->CallIntMethod(env, params, get_h); - - jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I"); - jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength); - jint order_bytes = (order_bits + 7) / 8; - - // header_size + 5*bytes + order_bytes + cof_size + 0 - ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + sizeof(jint) + 0; - *curve = calloc(buSize, 1); - BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; - header->Version = 1; - header->CurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery - header->CurveGenerationAlgId = 0; - header->cbFieldLength = bytes; - header->cbSubgroupOrder = order_bytes; - header->cbCofactor = sizeof(jint); - header->cbSeed = 0; - - PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; - - biginteger_to_bytes(env, p, paramsStart, bytes); - biginteger_to_bytes(env, a, paramsStart + bytes, bytes); - biginteger_to_bytes(env, b, paramsStart + 2*bytes, bytes); - biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); - biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); - biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); - jint *cof_ptr = (jint *) (paramsStart + 5*bytes + order_bytes); - *cof_ptr = h; - return bufSize; -} - -static bool init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { - //err - return false; - } - - 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); - const named_curve_t *curve = lookup_curve(utf_name); - if (NT_FAILURE(BCryptSetProperty(handle, BCRYPT_ECC_CURVE_NAME, utf_name, strlen(utf_name), 0))) { - //err - return false; - } - (*env)->ReleaseStringUTFChars(env, name, utf_name); - } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { - PBYTE curve; - ULONG curveLen = create_curve(env, params, &curve); - if (NT_FAILURE(BCryptSetProperty(handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { - //err - return false; - } - free(curve); - } - return true; -} - -static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { - ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { - //err - } - if (bufSize == 0) { - //err - } - - BYTE privBuf[bufSize]; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufsize, &bufSize, 0))) { - //err - } - - // privBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - // byte[cbKey] D - BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; - PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; - PBYTE priv_y = priv_x + privHeader->cbKey; - PBYTE priv = priv_y + privHeader->cbKey; - - jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, privHeader, sizeof(BCRYPT_ECCKEY_BLOB)); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - - jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbKey); - jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, priv_x, privHeader->cbKey); - (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - - jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbKey); - jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, priv_y, privHeader->cbKey); - (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); - - jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbKey); - jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); - memcpy(key_priv, priv, header->cbKey); - (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); - - jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); - jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); -} - -static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { - ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { - //err - } - - BYTE pubBuf[bufSize]; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { - //err - } - - // pubBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; - PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; - PBYTE pub_y = pub_x + pubHeader->cbKey; - - jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, pubHeader, sizeof(BCRYPT_ECCKEY_BLOB)); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - - jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); - jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, pub_x, pubHeader->cbKey); - (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - - jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); - jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, pub_y, pubHeader->cbKey); - (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); - - jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); - jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); -} - -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ - BCRYPT_ALG_HANDLE kaHandle = NULL; - BCRYPT_KEY_HANDLE key = NULL; - - jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR algo; - if (strcmp(type_data, "ECDH") == 0) { - algo = BCRYPT_ECDH_ALGORITHM; - } else if (strcmp(type_data, "ECDSA") == 0) { - algo = BCRYPT_ECDSA_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); - - if (!init_algo(env, &kaHandle, algo, params)) { - //err - } - - ULONG paramsSize; - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { - //err - } - if (paramsSize == 0) { - //err - } - - BYTE params[paramsSize]; - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, params, paramsSize, ¶msSize, 0))) { - //err - } - - jobject ec_param_spec = create_ec_param_spec(env, params, paramsSize); - - if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, curve.bits, 0)) { - //err - } - - if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { - //err - } - - jobject privkey = key_to_privkey(env, key, ec_param_spec); - jobject pubkey = key_to_pubkey(env, key, ec_param_spec); - - jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); - - BCryptDestroyKey(key); - BCryptCloseAlgorithmProvider(kaHandle, 0); - return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); -} - -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { - jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR kdf_algo; - if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) { - kdf_algo = BCRYPT_SHA1_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) { - kdf_algo = BCRYPT_SHA256_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) { - kdf_algo = BCRYPT_SHA384_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) { - kdf_algo = BCRYPT_SHA512_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); - - BCRYPT_ALG_HANDLE kaHandle = NULL; - - if (!init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params)) { - //err - } - - BCRYPT_KEY_HANDLE pkey = NULL; - BCRYPT_KEY_HANDLE skey = NULL; - - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { - //err - } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); - - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err - } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); - - BCRYPT_SECRET_HANDLE ka = NULL; - - if (NT_FAILURE(BCryptSecretAgreement(skey, pkey, &ka, 0))) { - //err - } - - BCryptBufferDesc paramList = {0}; - BCryptBuffer kdfParams[1] = {0}; - kdfParams[0].BufferType = KDF_HASH_ALGORITHM; - kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR)); - kdfParams[0].pvBuffer = (PVOID)kdf_algo; - paramList.cBuffers = 1; - paramList.pBuffers = kdfParams; - paramList.ulVersion = BCRYPTBUFFER_VERSION; - - //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* - ULONG bufSize = 0; - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { - //err - } - - BYTE derived[bufSize]; - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { - //err - } - - jbyteArray result = (*env)->NewByteArray(env, bufSize); - jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - memcpy(result_data, derived, bufSize); - (*env)->ReleaseByteArrayElements(env, result, result_data, 0); - - BCryptDestroyKey(pkey); - BCryptDestroyKey(skey); - BCryptDestroySecret(ka); - BCryptCloseAlgorithmProvider(kaHandle, 0); - return result; -} - -static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { - jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR hash_algo; - if (strcmp(type_data, "SHA1withECDSA") == 0) { - hash_algo = BCRYPT_SHA1_ALGORITHM; - } else if (strcmp(type_data, "SHA256withECDSA") == 0) { - hash_algo = BCRYPT_SHA256_ALGORITHM; - } else if (strcmp(type_data, "SHA384withECDSA") == 0) { - hash_algo = BCRYPT_SHA384_ALGORITHM; - } else if (strcmp(type_data, "SHA512withECDSA") == 0) { - hash_algo = BCRYPT_SHA512_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); - return hash_algo; -} - -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { - LPCWSTR hash_algo = get_sighash_algo(env, self); - - BCRYPT_ALG_HANDLE sigHandle = NULL; - - if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { - //err - } - - BCRYPT_ALG_HANDLE hashHandle = NULL; - - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err - } - - DWORD dummy = 0; - DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err - } - - BYTE hash[hash_len]; - - jint data_len = (*env)->GetArrayLength(env, data); - jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err - } - (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); - - BCRYPT_KEY_HANDLE skey = NULL; - - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err - } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); - - DWORD sig_len = 0; - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { - //err - } - - jbyteArray sig = (*env)->NewByteArray(env, sig_len); - jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { - //err - } - (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); - - BCryptDestroyKey(skey); - BCryptCloseAlgorithmProvider(hashHandle, 0); - BCryptCloseAlgorithmProvider(sigHandle, 0); - - return sig; -} - -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { - LPCWSTR hash_algo = get_sighash_algo(env, self); - - BCRYPT_ALG_HANDLE sigHandle = NULL; - - if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { - //err - } - - BCRYPT_ALG_HANDLE hashHandle = NULL; - - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err - } - - DWORD dummy = 0; - DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err - } - - BYTE hash[hash_len]; - - jint data_len = (*env)->GetArrayLength(env, data); - jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err - } - (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); - - BYTE hash[hash_len]; - - jint data_len = (*env)->GetArrayLength(env, data); - jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err - } - (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); - - BCRYPT_KEY_HANDLE pkey = NULL; - - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, pub_data, pub_length, 0))) { - //err - } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); - - jint sig_len = (*env)->GetArrayLength(env, sig); - jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0); - (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); - - BCryptDestroyKey(pkey); - BCryptCloseAlgorithmProvider(hashHandle, 0); - BCryptCloseAlgorithmProvider(sigHandle, 0); - - if (result == STATUS_SUCCESS) { - return JNI_TRUE; - } else if (result == STATUS_INVALID_SIGNATURE) { - return JNI_FALSE; - } else { - //err - return JNI_FALSE; - } +#include "native.h" +#include +#include + +#include "c_utils.h" + +static jclass provider_class; + +#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) +#define NT_FAILURE(status) !NT_SUCCESS(status) + +#define STATUS_SUCCESS 0x00000000 +#define STATUS_INVALID_SIGNATURE 0xC000A000 + +typedef struct { + ULONG dwVersion; //Version of the structure + ECC_CURVE_TYPE_ENUM dwCurveType; //Supported curve types. + ECC_CURVE_ALG_ID_ENUM dwCurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. + ULONG cbFieldLength; //Byte length of the fields P, A, B, X, Y. + ULONG cbSubgroupOrder; //Byte length of the subgroup. + ULONG cbCofactor; //Byte length of cofactor of G in E. + ULONG cbSeed; //Byte length of the seed used to generate the curve. +} BCRYPT_ECC_PARAMETER_HEADER; + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self){ + jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); + provider_class = (*env)->NewGlobalRef(env, local_provider_class); + + jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); + + jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); + double version = 1.0; + return (*env)->NewObject(env, provider_class, init, name, version, name); +} + +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) { + INIT_PROVIDER(env, provider_class); + + ADD_KPG(env, self, "ECDH", "MscngECDH"); + ADD_KPG(env, self, "ECDSA", "MscngECDSA"); + + ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF"); + ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF"); + ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); + ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); + + ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1"); + ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256"); + ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); + ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); + + init_classes(env, "Mscng"); +} + +typedef struct { + const char *name; + ULONG bits; +} named_curve_t; + +static named_curve_t named_curves[] = { + {"curve25519", 256}, + {"brainpoolP160r1", 160}, + {"brainpoolP160t1", 160}, + {"brainpoolP192r1", 192}, + {"brainpoolP192t1", 192}, + {"brainpoolP224r1", 224}, + {"brainpoolP224t1", 224}, + {"brainpoolP256r1", 256}, + {"brainpoolP256t1", 256}, + {"brainpoolP320r1", 320}, + {"brainpoolP320t1", 320}, + {"brainpoolP384r1", 384}, + {"brainpoolP384t1", 384}, + {"brainpoolP512r1", 512}, + {"brainpoolP512t1", 512}, + {"ec192wapi", 192}, + {"nistP192", 192}, + {"nistP224", 224}, + {"nistP256", 256}, + {"nistP384", 384}, + {"nistP521", 521}, + {"numsP256t1", 256}, + {"numsP384t1", 384}, + {"numsP512t1", 512}, + {"secP160k1", 160}, + {"secP160r1", 160}, + {"secP160r2", 160}, + {"secP192k1", 192}, + {"secP192r1", 192}, + {"secP224k1", 224}, + {"secP224r1", 224}, + {"secP256k1", 256}, + {"secP256r1", 256}, + {"secP384r1", 384}, + {"secP521r1", 521}, + {"wtls12", 224}, + {"wtls7", 160}, + {"wtls9", 160}, + {"x962P192v1", 192}, + {"x962P192v2", 192}, + {"x962P192v3", 192}, + {"x962P239v1", 239}, + {"x962P239v2", 239}, + {"x962P239v3", 239}, + {"x962P256v1", 256} +}; + +static const named_curve_t* lookup_curve(const char *name) { + for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { + if (strcmp(name, named_curves[i].name) == 0) { + return &named_curves[i]; + } + } + return NULL; +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { + 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); + + for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { + jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); + (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); + } + return result; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { + if (params == NULL) { + return JNI_FALSE; + } + + 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); + const named_curve_t *curve = lookup_curve(utf_name); + (*env)->ReleaseStringUTFChars(env, name, utf_name); + return curve == NULL ? JNI_FALSE : JNI_TRUE; + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject curve = (*env)->CallObjectMethod(env, params, get_curve); + + jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = (*env)->CallObjectMethod(env, curve, get_field); + + if ((*env)->IsInstanceOf(env, field, fp_field_class)) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } + } else { + return JNI_FALSE; + } +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return NULL; +} + +static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { + jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); + jbyteArray byte_array = (*env)->NewByteArray(env, len); + jbyte *data = (*env)->GetByteArrayElements(env, byte_array, NULL); + memcpy(data, bytes, len); + (*env)->ReleaseByteArrayElements(env, byte_array, data, 0); + jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, byte_array); + return result; +} + +static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) { + 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); + memcpy(bytes, &byte_data[byte_length - len], len); + (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); +} + +static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { + // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. + // + // BCRYPT_ECC_PARAMETER_HEADER header + // byte[cbFieldLength] P + // byte[cbFieldLength] A + // byte[cbFieldLength] B + // byte[cbFieldLength] G.X + // byte[cbFieldLength] G.Y + // byte[cbSubgroupOrder] Order (n) + // byte[cbCofactor] Cofactor (h) + // byte[cbSeed] Seed + + // BCRYPT_ECC_PARAMETER_HEADER + // internal int Version; //Version of the structure + // internal ECC_CURVE_TYPE_ENUM CurveType; //Supported curve types. + // internal ECC_CURVE_ALG_ID_ENUM CurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. + // internal int cbFieldLength; //Byte length of the fields P, A, B, X, Y. + // internal int cbSubgroupOrder; //Byte length of the subgroup. + // internal int cbCofactor; //Byte length of cofactor of G in E. + // internal int cbSeed; //Byte length of the seed used to generate the curve. + + // internal enum ECC_CURVE_TYPE_ENUM : int + // { + // BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, + // BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, + // BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3, + // } + + // internal enum ECC_CURVE_ALG_ID_ENUM : int + // { + // BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, + // } + BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)eccParams; + PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + + //cbFieldLength + PBYTE P = paramsStart; + PBYTE A = P + header->cbFieldLength; + PBYTE B = A + header->cbFieldLength; + PBYTE GX = B + header->cbFieldLength; + PBYTE GY = GX + header->cbFieldLength; + + //cbSubgroupOrder + PBYTE N = GY + header->cbFieldLength; + + //cbCofactor + PBYTE H = N + header->cbSubgroupOrder; + + //cbSeed + PBYTE S = H + header->cbCofactor; + + jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); + + 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, p_int); + + jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength); + jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength); + + 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); + + jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength); + jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength); + + jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); + + jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder); + + jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor); + jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I"); + jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int); + + 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"); + return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); +} + +static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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, "getB", "()Ljava/math/BigInteger;"); + jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); + + jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); + + jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); + jobject p = (*env)->CallObjectMethod(env, field, get_p); + + jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); + jobject g = (*env)->CallObjectMethod(env, params, get_g); + + jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); + jobject gx = (*env)->CallObjectMethod(env, g, get_x); + + jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); + jobject gy = (*env)->CallObjectMethod(env, g, get_y); + + jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); + jobject n = (*env)->CallObjectMethod(env, params, get_n); + + jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); + jint h = (*env)->CallIntMethod(env, params, get_h); + + jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I"); + jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength); + jint order_bytes = (order_bits + 7) / 8; + + // header_size + 5*bytes + order_bytes + cof_size + 0 + ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + sizeof(jint) + 0; + *curve = calloc(bufSize, 1); + BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; + header->dwVersion = 1; + header->dwCurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery + header->dwCurveGenerationAlgId = 0; + header->cbFieldLength = bytes; + header->cbSubgroupOrder = order_bytes; + header->cbCofactor = sizeof(jint); + header->cbSeed = 0; + + PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + + biginteger_to_bytes(env, p, paramsStart, bytes); + biginteger_to_bytes(env, a, paramsStart + bytes, bytes); + biginteger_to_bytes(env, b, paramsStart + 2*bytes, bytes); + biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); + biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); + biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); + jint *cof_ptr = (jint *) (paramsStart + 5*bytes + order_bytes); + *cof_ptr = h; + return bufSize; +} + +static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { + if (NT_FAILURE(BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + //err + return 0; + } + ULONG result = 0; + 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); + jint utf_length = (*env)->GetStringUTFLength(env, name); + PUCHAR chars = calloc(utf_length + 1, 1); + (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars); + const named_curve_t *curve = lookup_curve(chars); + if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, chars, strlen(chars), 0))) { + //err + return 0; + } + free(chars); + result = curve->bits; + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + PBYTE curve; + ULONG curveLen = create_curve(env, params, &curve); + if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { + //err + return 0; + } + free(curve); + + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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); + result = (bits + 7) / 8; + } + return result; +} + +static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { + ULONG bufSize = 0; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + //err + } + if (bufSize == 0) { + //err + } + + PBYTE privBuf = calloc(bufSize, 1); + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { + //err + } + + // privBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] Q.X + // byte[cbKey] Q.Y + // byte[cbKey] D + BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; + PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; + PBYTE priv_y = priv_x + privHeader->cbKey; + PBYTE priv = priv_y + privHeader->cbKey; + + jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, privHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, priv_x, privHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + + jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, priv_y, privHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); + memcpy(key_priv, priv, privHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); + + free(privBuf); + + jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); +} + +static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { + ULONG bufSize = 0; + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + //err + } + + PBYTE pubBuf = calloc(bufSize, 1); + if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + //err + } + + // pubBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] Q.X + // byte[cbKey] Q.Y + BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; + PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; + PBYTE pub_y = pub_x + pubHeader->cbKey; + + jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, pubHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, pub_x, pubHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + + jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, pub_y, pubHeader->cbKey); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + free(pubBuf); + + jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); +} + +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ + BCRYPT_ALG_HANDLE kaHandle = NULL; + BCRYPT_KEY_HANDLE key = NULL; + + jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR algo; + if (strcmp(type_data, "ECDH") == 0) { + algo = BCRYPT_ECDH_ALGORITHM; + } else if (strcmp(type_data, "ECDSA") == 0) { + algo = BCRYPT_ECDSA_ALGORITHM; + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + ULONG bits = init_algo(env, &kaHandle, algo, params); + if (bits == 0) { + //err + } + + ULONG paramsSize; + if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { + //err + } + if (paramsSize == 0) { + //err + } + + PBYTE eccParams = calloc(paramsSize, 1); + if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, eccParams, paramsSize, ¶msSize, 0))) { + //err + } + + jobject ec_param_spec = create_ec_param_spec(env, eccParams, paramsSize); + + free(eccParams); + + if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, bits, 0))) { + //err + } + + if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { + //err + } + + jobject privkey = key_to_privkey(env, key, ec_param_spec); + jobject pubkey = key_to_pubkey(env, key, ec_param_spec); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(kaHandle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); +} + +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR kdf_algo; + if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) { + kdf_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) { + kdf_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) { + kdf_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) { + kdf_algo = BCRYPT_SHA512_ALGORITHM; + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + BCRYPT_ALG_HANDLE kaHandle = NULL; + + if (!init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params)) { + //err + } + + BCRYPT_KEY_HANDLE pkey = NULL; + BCRYPT_KEY_HANDLE skey = NULL; + + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + + BCRYPT_SECRET_HANDLE ka = NULL; + + if (NT_FAILURE(BCryptSecretAgreement(skey, pkey, &ka, 0))) { + //err + } + + BCryptBufferDesc paramList = {0}; + BCryptBuffer kdfParams[1] = {0}; + kdfParams[0].BufferType = KDF_HASH_ALGORITHM; + kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR)); + kdfParams[0].pvBuffer = (PVOID)kdf_algo; + paramList.cBuffers = 1; + paramList.pBuffers = kdfParams; + paramList.ulVersion = BCRYPTBUFFER_VERSION; + + //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* + ULONG bufSize = 0; + if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { + //err + } + + PBYTE derived = calloc(bufSize, 1); + if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { + //err + } + + jbyteArray result = (*env)->NewByteArray(env, bufSize); + jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); + memcpy(result_data, derived, bufSize); + (*env)->ReleaseByteArrayElements(env, result, result_data, 0); + + free(derived); + + BCryptDestroyKey(pkey); + BCryptDestroyKey(skey); + BCryptDestroySecret(ka); + BCryptCloseAlgorithmProvider(kaHandle, 0); + return result; +} + +static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { + jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;"); + jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR hash_algo; + if (strcmp(type_data, "SHA1withECDSA") == 0) { + hash_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "SHA256withECDSA") == 0) { + hash_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "SHA384withECDSA") == 0) { + hash_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "SHA512withECDSA") == 0) { + hash_algo = BCRYPT_SHA512_ALGORITHM; + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + return hash_algo; +} + +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + LPCWSTR hash_algo = get_sighash_algo(env, self); + + BCRYPT_ALG_HANDLE sigHandle = NULL; + + if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { + //err + } + + BCRYPT_ALG_HANDLE hashHandle = NULL; + + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + //err + } + + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + //err + } + + PBYTE hash = calloc(hash_len, 1); + + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + //err + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE skey = NULL; + + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + + DWORD sig_len = 0; + if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { + //err + } + + jbyteArray sig = (*env)->NewByteArray(env, sig_len); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); + + free(hash); + + BCryptDestroyKey(skey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); + + return sig; +} + +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { + LPCWSTR hash_algo = get_sighash_algo(env, self); + + BCRYPT_ALG_HANDLE sigHandle = NULL; + + if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { + //err + } + + BCRYPT_ALG_HANDLE hashHandle = NULL; + + if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + //err + } + + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + //err + } + + PBYTE hash = calloc(hash_len, 1); + + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + //err + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE pkey = NULL; + + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &pkey, pub_data, pub_length, 0))) { + //err + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + + jint sig_len = (*env)->GetArrayLength(env, sig); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0); + (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); + + free(hash); + + BCryptDestroyKey(pkey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); + + if (result == STATUS_SUCCESS) { + return JNI_TRUE; + } else if (result == STATUS_INVALID_SIGNATURE) { + return JNI_FALSE; + } else { + //err + return JNI_FALSE; + } } \ No newline at end of file -- cgit v1.3.1 From eef13a358a3e45b3abbb2a11016cd1243b0b2b6a Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 27 Jul 2018 00:13:56 +0200 Subject: WIP: Fix mscng according to new API. --- .../libs/jni/NativeKeyPairGeneratorSpi.java | 6 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 84 +++++++++++++++++----- 2 files changed, 68 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java index f7e7653..7ca013a 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java @@ -180,7 +180,7 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { public Mscng(String type) { this.type = type; - initialize(256, new SecureRandom());//TODO: maybe remove this default init? + initialize(256, new SecureRandom()); } @Override @@ -196,14 +196,14 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi { native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random); } - public static class MscngECDH extends Cryptopp { + public static class MscngECDH extends Mscng { public MscngECDH() { super("ECDH"); } } - public static class MscngECDSA extends Cryptopp { + public static class MscngECDSA extends Mscng { public MscngECDSA() { super("ECDSA"); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 5dfee55..56502da 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -4,13 +4,15 @@ #include "c_utils.h" +#include + static jclass provider_class; #define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) #define NT_FAILURE(status) !NT_SUCCESS(status) -#define STATUS_SUCCESS 0x00000000 -#define STATUS_INVALID_SIGNATURE 0xC000A000 +#define STATUS_SUCCESS 0x00000000 +#define STATUS_INVALID_SIGNATURE 0xC000A000 typedef struct { ULONG dwVersion; //Version of the structure @@ -30,6 +32,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createP jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); double version = 1.0; + + printf("createProvider\n"); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -49,6 +53,7 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); + printf("setup\n"); init_classes(env, "Mscng"); } @@ -106,7 +111,7 @@ static named_curve_t named_curves[] = { }; static const named_curve_t* lookup_curve(const char *name) { - for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { + for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { if (strcmp(name, named_curves[i].name) == 0) { return &named_curves[i]; } @@ -114,6 +119,18 @@ static const named_curve_t* lookup_curve(const char *name) { return NULL; } +static const named_curve_t* lookup_curve_bits(jint bitsize) { + printf("looking up %i\n", bitsize); + for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { + printf("trying (%s, %i)\n", named_curves[i].name, named_curves[i].bits); + if (bitsize == named_curves[i].bits) { + printf("got it!\n"); + return &named_curves[i]; + } + } + return NULL; +} + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet"); @@ -126,15 +143,19 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurv jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); } + printf("getCurves\n"); return result; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { - return JNI_FALSE; + printf("keysizeSupported\n"); + return (lookup_curve_bits(keysize) == NULL) ? JNI_FALSE : JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { - if (params == NULL) { + printf("paramsSupported\n"); + if (params == NULL) { + printf("theyNull\n"); return JNI_FALSE; } @@ -162,11 +183,6 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa } } -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { - throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; -} - static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); jbyteArray byte_array = (*env)->NewByteArray(env, len); @@ -463,10 +479,17 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_para return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); } +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); + return NULL; +} + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ BCRYPT_ALG_HANDLE kaHandle = NULL; BCRYPT_KEY_HANDLE key = NULL; - + + fprintf(stderr, "1\n"); + fflush(stderr); jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -477,47 +500,70 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai } else if (strcmp(type_data, "ECDSA") == 0) { algo = BCRYPT_ECDSA_ALGORITHM; } else { - //err + fprintf(stderr, "err\n"); + fflush(stderr); } (*env)->ReleaseStringUTFChars(env, type, type_data); + fprintf(stderr, "2\n"); + fflush(stderr); ULONG bits = init_algo(env, &kaHandle, algo, params); if (bits == 0) { - //err + fprintf(stderr, "err0\n"); + fflush(stderr); } + fprintf(stderr, "3\n"); + fflush(stderr); ULONG paramsSize; if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { - //err + fprintf(stderr, "err\n"); + fflush(stderr); } if (paramsSize == 0) { - //err + fprintf(stderr, "err0\n"); + fflush(stderr); } + fprintf(stderr, "4\n"); + fflush(stderr); PBYTE eccParams = calloc(paramsSize, 1); if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, eccParams, paramsSize, ¶msSize, 0))) { - //err + fprintf(stderr, "err\n"); + fflush(stderr); } - jobject ec_param_spec = create_ec_param_spec(env, eccParams, paramsSize); + jobject ec_param_spec = create_ec_param_spec(env, eccParams, paramsSize); free(eccParams); + fprintf(stderr, "5\n"); + fflush(stderr); if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, bits, 0))) { - //err + fprintf(stderr, "err\n"); + fflush(stderr); } + fprintf(stderr, "6\n"); + fflush(stderr); if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { - //err + fprintf(stderr, "err\n"); + fflush(stderr); } jobject privkey = key_to_privkey(env, key, ec_param_spec); jobject pubkey = key_to_pubkey(env, key, ec_param_spec); + fprintf(stderr, "7\n"); + fflush(stderr); jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + fprintf(stderr, "8\n"); + fflush(stderr); BCryptDestroyKey(key); BCryptCloseAlgorithmProvider(kaHandle, 0); + fprintf(stderr, "9\n"); + fflush(stderr); return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } -- cgit v1.3.1 From 0d961f0c0bdc5a0ace91bc7b2289055b26d4fbe7 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 27 Jul 2018 21:02:27 +0200 Subject: WIP: Mscng keygen works. --- .gitignore | 1 + docs/LIBS.md | 9 +- .../crcs/ectester/standalone/libs/jni/Makefile.bat | 19 +- .../standalone/libs/jni/NativeECPrivateKey.java | 10 +- .../standalone/libs/jni/NativeECPublicKey.java | 10 +- src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 4 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 478 +++++++++++++-------- 7 files changed, 346 insertions(+), 185 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index 90700ba..f40221d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Built artifacts in /dist and /applet. +/build/ /dist/lib/ /dist/ECTesterReader.jar /dist/ECTesterReader-dist.jar diff --git a/docs/LIBS.md b/docs/LIBS.md index 3d5e5e8..d1a68d0 100644 --- a/docs/LIBS.md +++ b/docs/LIBS.md @@ -79,4 +79,11 @@ Popular libraries with at least some ECC support: - Uses affine coordinates and sliding window scalar multiplication algorithm. - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx) - C API. - - Closed source, uses whatever. \ No newline at end of file + - Closed source. + - For prime field curves(only supports): + - Uses Short Weierstrass model. + - Uses Twisted Edwards model. + - Uses Montgomery model. + - Uses fixed window scalar multiplication. + - Uses Wnaf multi-scalar multiplication with interleaving. + - Uses Montgomery ladder. \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index a279750..e337e70 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -1,6 +1,11 @@ @if not defined _echo echo off setlocal EnableDelayedExpansion +:: ENV variables respected: +:: - JAVA_HOME +:: - CC +:: - USE_EXT_MSCNG + :: See if we are cleaning. if "%1" == "clean" ( echo ** cleaning @@ -58,8 +63,8 @@ if exist %vc_base% ( :: Get the paths to Microsoft CNG SDK. set root_rel=..\..\..\..\..\..\..\ -set mscng_rel_include=ext\mscng\Include -set mscng_rel_lib=ext\mscng\Lib +set mscng_rel_include=ext\mscng\10\Include +set mscng_rel_lib=ext\mscng\10\Lib pushd %root_rel% pushd %mscng_rel_include% @@ -115,15 +120,25 @@ if exist %ucrt_base% ( set ucrt_lib_arch=!ucrt_lib!\ucrt\%ARCH_S% ) + :: Setup INCLUDE paths. set INCLUDE_CLI=/I. /I"%JNI_INCLUDEDIR%" /I"%JNI_PLATFORMINCLUDEDIR%" +if defined USE_EXT_MSCNG ( + set INCLUDE_CLI=!INCLUDE_CLI! /I"%mscng_include%" +) + echo ** INCLUDE %INCLUDE% echo ** INCLUDE_CLI %INCLUDE_CLI% + :: Setup LIB paths. set LIBPATH=/LIBPATH:"%JNI_LIBDIR%" +if defined USE_EXT_MSCNG ( + set LIBPATH=!LIBPATH! /LIBPATH:"%mscng_lib_arch%" +) + echo ** LIB %LIB% echo ** LIBPATH %LIBPATH% echo. diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 7980773..76786fe 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -43,7 +43,7 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { public Raw(byte[] keyData, ECParameterSpec params) { super("EC", "raw", params); - this.keyData = keyData; + this.keyData = Arrays.clone(keyData); } @Override @@ -92,9 +92,9 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { public Mscng(byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) { super(keyData, params); - this.header = header; - this.x = x; - this.y = y; + this.header = Arrays.clone(header); + this.x = Arrays.clone(x); + this.y = Arrays.clone(y); } public byte[] getHeader() { @@ -102,7 +102,7 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y, keyData); + return ByteUtil.concatenate(header, x, y, keyData); } @Override diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index e44ff49..e55ed33 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -45,7 +45,7 @@ public abstract class NativeECPublicKey implements ECPublicKey { public ANSIX962(byte[] keyData, ECParameterSpec params) { super("EC", "ANSI X9.62", params); - this.keyData = keyData; + this.keyData = Arrays.clone(keyData); } @Override @@ -94,9 +94,9 @@ public abstract class NativeECPublicKey implements ECPublicKey { public Mscng(byte[] header, byte[] x, byte[] y, ECParameterSpec params) { super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params); - this.header = header; - this.x = x; - this.y = y; + this.header = Arrays.clone(header); + this.x = Arrays.clone(x); + this.y = Arrays.clone(y); } public byte[] getHeader() { @@ -104,7 +104,7 @@ public abstract class NativeECPublicKey implements ECPublicKey { } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y); + return ByteUtil.concatenate(header, x, y); } @Override 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 9fee530..f920fc4 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c @@ -21,7 +21,7 @@ void init_classes(JNIEnv *env, const char* lib_name) { 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[1024]; //strlen(pubkey_base) + strlen(lib_name) + 1 + char pubkey_class_name[2048] = { 0 }; //strlen(pubkey_base) + strlen(lib_name) + 1 pubkey_class_name[0] = 0; strcat(pubkey_class_name, pubkey_base); strcat(pubkey_class_name, lib_name); @@ -30,7 +30,7 @@ void init_classes(JNIEnv *env, const char* lib_name) { pubkey_class = (*env)->NewGlobalRef(env, local_pubkey_class); const char *privkey_base = "cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey$"; - char privkey_class_name[1024]; //strlen(privkey_base) + strlen(lib_name) + 1 + char privkey_class_name[2048] = { 0 }; //strlen(privkey_base) + strlen(lib_name) + 1 privkey_class_name[0] = 0; strcat(privkey_class_name, privkey_base); strcat(privkey_class_name, lib_name); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 56502da..b0b71be 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -33,7 +33,6 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createP jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); double version = 1.0; - printf("createProvider\n"); return (*env)->NewObject(env, provider_class, init, name, version, name); } @@ -53,12 +52,11 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_ ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); - printf("setup\n"); init_classes(env, "Mscng"); } typedef struct { - const char *name; + LPCSTR name; ULONG bits; } named_curve_t; @@ -120,42 +118,94 @@ static const named_curve_t* lookup_curve(const char *name) { } static const named_curve_t* lookup_curve_bits(jint bitsize) { - printf("looking up %i\n", bitsize); for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { - printf("trying (%s, %i)\n", named_curves[i].name, named_curves[i].bits); if (bitsize == named_curves[i].bits) { - printf("got it!\n"); return &named_curves[i]; } } return NULL; } +static ULONG utf_16to8(NPSTR *out_buf, LPCWSTR in_str) { + INT result = WideCharToMultiByte(CP_UTF8, 0, in_str, -1, NULL, 0, NULL, NULL); + *out_buf = calloc(result, 1); + return WideCharToMultiByte(CP_UTF8, 0, in_str, -1, *out_buf, result, NULL, NULL); +} + +static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) { + INT result = MultiByteToWideChar(CP_UTF8, 0, in_str, -1, NULL, 0); + *out_buf = calloc(result * sizeof(WCHAR), 1); + return MultiByteToWideChar(CP_UTF8, 0, in_str, -1, *out_buf, result); +} + +// Convert Java String to UTF-16 LPCWSTR null-terminated. +// Returns: Length of LPCWSTR in bytes! +static ULONG utf_strto16(NWPSTR *out_buf, JNIEnv *env, jobject str) { + jsize len = (*env)->GetStringLength(env, str); + *out_buf = calloc(len * sizeof(jchar) + 1, 1); + const jchar *chars = (*env)->GetStringChars(env, str, NULL); + memcpy(*out_buf, chars, len * sizeof(jchar)); + (*env)->ReleaseStringChars(env, str, chars); + return len * sizeof(jchar); +} + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves(JNIEnv *env, jobject self) { - jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet"); + 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"); + 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); + jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr); - for (size_t i = 0; i < sizeof(named_curves)/sizeof(named_curve_t); ++i) { - jstring curve_name = (*env)->NewStringUTF(env, named_curves[i].name); - (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name); - } - printf("getCurves\n"); + NTSTATUS status; + BCRYPT_ALG_HANDLE handle; + + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_ECDH_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return 0; + } + + ULONG bufSize; + if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(length only)\n", status); + return 0; + } + + BCRYPT_ECC_CURVE_NAMES *curves = (BCRYPT_ECC_CURVE_NAMES *)calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, (PBYTE) curves, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(whole)\n", status); + return 0; + } + for (size_t i = 0; i < curves->dwEccCurveNames; ++i) { + NPSTR curve_name; + ULONG len = utf_16to8(&curve_name, curves->pEccCurveNames[i]); + jstring c_name = (*env)->NewStringUTF(env, curve_name); + (*env)->CallBooleanMethod(env, result, hash_set_add, c_name); + free(curve_name); + } + + free(curves); + + BCryptCloseAlgorithmProvider(handle, 0); return result; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { - printf("keysizeSupported\n"); - return (lookup_curve_bits(keysize) == NULL) ? JNI_FALSE : JNI_TRUE; + switch (keysize) { + case 256: + case 384: + case 521: + return JNI_TRUE; + default: + return JNI_FALSE; + } } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { - printf("paramsSupported\n"); if (params == NULL) { - printf("theyNull\n"); return JNI_FALSE; } @@ -203,41 +253,20 @@ static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); } -static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLength) { - // Taken from https://github.com/dotnet/corefx, thanks! This API is nowhere to be found. +static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLength) { // - // BCRYPT_ECC_PARAMETER_HEADER header - // byte[cbFieldLength] P - // byte[cbFieldLength] A - // byte[cbFieldLength] B - // byte[cbFieldLength] G.X - // byte[cbFieldLength] G.Y - // byte[cbSubgroupOrder] Order (n) - // byte[cbCofactor] Cofactor (h) - // byte[cbSeed] Seed - - // BCRYPT_ECC_PARAMETER_HEADER - // internal int Version; //Version of the structure - // internal ECC_CURVE_TYPE_ENUM CurveType; //Supported curve types. - // internal ECC_CURVE_ALG_ID_ENUM CurveGenerationAlgId; //For X.592 verification purposes, if we include Seed we will need to include the algorithm ID. - // internal int cbFieldLength; //Byte length of the fields P, A, B, X, Y. - // internal int cbSubgroupOrder; //Byte length of the subgroup. - // internal int cbCofactor; //Byte length of cofactor of G in E. - // internal int cbSeed; //Byte length of the seed used to generate the curve. - - // internal enum ECC_CURVE_TYPE_ENUM : int - // { - // BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, - // BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, - // BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3, - // } - - // internal enum ECC_CURVE_ALG_ID_ENUM : int - // { - // BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, - // } - BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)eccParams; - PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + // BCRYPT_ECCFULLKEY_BLOB header + // P[cbFieldLength] Prime specifying the base field. + // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p + // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p + // Gx[cbFieldLength] X-coordinate of the base point. + // Gy[cbFieldLength] Y-coordinate of the base point. + // n[cbSubgroupOrder] Order of the group generated by G = (x,y) + // h[cbCofactor] Cofactor of G in E. + // S[cbSeed] Seed of the curve. + + BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB*)eccParams; + PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)]; //cbFieldLength PBYTE P = paramsStart; @@ -255,6 +284,8 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, ULONG paramLen //cbSeed PBYTE S = H + header->cbCofactor; + *paramLength = sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed; + jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V"); @@ -322,7 +353,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { jint order_bytes = (order_bits + 7) / 8; // header_size + 5*bytes + order_bytes + cof_size + 0 - ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + sizeof(jint) + 0; + ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + 1 + 0; *curve = calloc(bufSize, 1); BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; header->dwVersion = 1; @@ -330,7 +361,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { header->dwCurveGenerationAlgId = 0; header->cbFieldLength = bytes; header->cbSubgroupOrder = order_bytes; - header->cbCofactor = sizeof(jint); + header->cbCofactor = 1; header->cbSeed = 0; PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; @@ -341,14 +372,16 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); - jint *cof_ptr = (jint *) (paramsStart + 5*bytes + order_bytes); - *cof_ptr = h; + PBYTE cof_ptr = (PBYTE) (paramsStart + 5*bytes + order_bytes); + *cof_ptr = (BYTE)h; return bufSize; } static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { - if (NT_FAILURE(BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + NTSTATUS status; + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); return 0; } ULONG result = 0; @@ -359,17 +392,22 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job PUCHAR chars = calloc(utf_length + 1, 1); (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars); const named_curve_t *curve = lookup_curve(chars); - if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, chars, strlen(chars), 0))) { + NWPSTR curve_utf16; + ULONG ret = utf_8to16(&curve_utf16, chars); + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR) curve_utf16, ret * sizeof(WCHAR), 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); return 0; } free(chars); + free(curve_utf16); result = curve->bits; } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { PBYTE curve; ULONG curveLen = create_curve(env, params, &curve); - if (NT_FAILURE(BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); return 0; } free(curve); @@ -382,31 +420,62 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I"); jint bits = (*env)->CallIntMethod(env, field, get_bits); - result = (bits + 7) / 8; + result = bits; } return result; } -static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { +static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { + NTSTATUS status; ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); + return NULL; } if (bufSize == 0) { //err + printf("err0\n"); + return NULL; } - PBYTE privBuf = calloc(bufSize, 1); - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { + PBYTE fullBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) { //err - } + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); + return NULL; + } + + ULONG paramLength; + jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); + free(fullBuf); + + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); + return NULL; + } + + PBYTE privBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); + return NULL; + } + + printf("generate length %lu\n", bufSize); + printf("generated privkey: "); + for (size_t i = 0; i < bufSize; ++i) { + printf("%02x", (unsigned)privBuf[i] & 0xffU); + } + printf("\n"); // privBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - // byte[cbKey] D - BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; + // BCRYPT_ECCKEY_BLOB header + // Qx[cbKey] X-coordinate of the public point. + // Qy[cbKey] Y-coordinate of the public point. + // d[cbKey] Private key. + BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; PBYTE priv_y = priv_x + privHeader->cbKey; PBYTE priv = priv_y + privHeader->cbKey; @@ -432,28 +501,54 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_par (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); free(privBuf); - - jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec); - jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[BLjava/security/spec/ECParameterSpec;)V"); + + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); } -static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_param_spec) { +static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { + NTSTATUS status; ULONG bufSize = 0; - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); + return NULL; } + if (bufSize == 0) { + //err + printf("err0\n"); + return NULL; + } - PBYTE pubBuf = calloc(bufSize, 1); - if (NT_FAILURE(BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + PBYTE fullBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) { //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); + return NULL; } - // pubBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] Q.X - // byte[cbKey] Q.Y - BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; + ULONG paramLength; + jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); + free(fullBuf); + + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); + return NULL; + } + + PBYTE pubBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); + return NULL; + } + + // pubBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // Qx[cbKey] X-coordinate of the public point. + // Qy[cbKey] Y-coordinate of the public point. + BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; PBYTE pub_y = pub_x + pubHeader->cbKey; @@ -474,22 +569,85 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jobject ec_para free(pubBuf); - jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec); jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { - throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found."); - return NULL; + NTSTATUS status; + BCRYPT_ALG_HANDLE handle = NULL; + + jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring)(*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR algo; + if (strcmp(type_data, "ECDH") == 0) { + switch (keysize) { + case 256: + algo = BCRYPT_ECDH_P256_ALGORITHM; + break; + case 384: + algo = BCRYPT_ECDH_P384_ALGORITHM; + break; + case 521: + algo = BCRYPT_ECDH_P521_ALGORITHM; + break; + default: + //err + break; + } + } else if (strcmp(type_data, "ECDSA") == 0) { + switch (keysize) { + case 256: + algo = BCRYPT_ECDSA_P256_ALGORITHM; + break; + case 384: + algo = BCRYPT_ECDSA_P384_ALGORITHM; + break; + case 521: + algo = BCRYPT_ECDSA_P521_ALGORITHM; + break; + default: + //err + break; + } + } else { + //err + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return NULL; + } + + BCRYPT_KEY_HANDLE key = NULL; + + if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); + } + + if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); + } + + jobject privkey = key_to_privkey(env, key); + jobject pubkey = key_to_pubkey(env, key); + + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(handle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ - BCRYPT_ALG_HANDLE kaHandle = NULL; + NTSTATUS status; + BCRYPT_ALG_HANDLE handle = NULL; BCRYPT_KEY_HANDLE key = NULL; - fprintf(stderr, "1\n"); - fflush(stderr); jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -500,74 +658,37 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai } else if (strcmp(type_data, "ECDSA") == 0) { algo = BCRYPT_ECDSA_ALGORITHM; } else { - fprintf(stderr, "err\n"); - fflush(stderr); + //err } (*env)->ReleaseStringUTFChars(env, type, type_data); - fprintf(stderr, "2\n"); - fflush(stderr); - ULONG bits = init_algo(env, &kaHandle, algo, params); + ULONG bits = init_algo(env, &handle, algo, params); if (bits == 0) { - fprintf(stderr, "err0\n"); - fflush(stderr); - } - - fprintf(stderr, "3\n"); - fflush(stderr); - ULONG paramsSize; - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, NULL, 0, ¶msSize, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); - } - if (paramsSize == 0) { - fprintf(stderr, "err0\n"); - fflush(stderr); - } - - fprintf(stderr, "4\n"); - fflush(stderr); - PBYTE eccParams = calloc(paramsSize, 1); - if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, eccParams, paramsSize, ¶msSize, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + //err } - jobject ec_param_spec = create_ec_param_spec(env, eccParams, paramsSize); - - free(eccParams); - - fprintf(stderr, "5\n"); - fflush(stderr); - if (NT_FAILURE(BCryptGenerateKeyPair(kaHandle, &key, bits, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); } - fprintf(stderr, "6\n"); - fflush(stderr); - if (NT_FAILURE(BCryptFinalizeKeyPair(key, 0))) { - fprintf(stderr, "err\n"); - fflush(stderr); + if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); } - jobject privkey = key_to_privkey(env, key, ec_param_spec); - jobject pubkey = key_to_pubkey(env, key, ec_param_spec); + jobject privkey = key_to_privkey(env, key); + jobject pubkey = key_to_pubkey(env, key); - fprintf(stderr, "7\n"); - fflush(stderr); jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); - fprintf(stderr, "8\n"); - fflush(stderr); BCryptDestroyKey(key); - BCryptCloseAlgorithmProvider(kaHandle, 0); - fprintf(stderr, "9\n"); - fflush(stderr); + BCryptCloseAlgorithmProvider(handle, 0); return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { + NTSTATUS status; + printf("generateSecret!\n"); + jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); @@ -597,22 +718,22 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { - //err + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); BCRYPT_SECRET_HANDLE ka = NULL; - if (NT_FAILURE(BCryptSecretAgreement(skey, pkey, &ka, 0))) { - //err + if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSecretAgreement\n", status); } BCryptBufferDesc paramList = {0}; @@ -626,13 +747,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* ULONG bufSize = 0; - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(length only)\n", status); } PBYTE derived = calloc(bufSize, 1); - if (NT_FAILURE(BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(whole)\n", status); } jbyteArray result = (*env)->NewByteArray(env, bufSize); @@ -671,32 +792,34 @@ static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { + NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { //err + printf("init err!\n"); } BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); } DWORD dummy = 0; DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); } PBYTE hash = calloc(hash_len, 1); jint data_len = (*env)->GetArrayLength(env, data); jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); } (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); @@ -704,20 +827,27 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - //err + + printf("priv_length %i\n", priv_length); + printf("using privkey: "); + for (size_t i = 0; i < priv_length; ++i) { + printf("%02x", (unsigned)priv_data[i] & 0xffU); + } + printf("\n"); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); DWORD sig_len = 0; - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { - //err + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSignHash(len only)\n", status); } jbyteArray sig = (*env)->NewByteArray(env, sig_len); jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - if (NT_FAILURE(BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { - //err + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptSignHash(do)\n", status); } (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); @@ -731,6 +861,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { + NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; @@ -741,22 +872,22 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - //err + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); } DWORD dummy = 0; DWORD hash_len = 0; - if (NT_FAILURE(BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - //err + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); } PBYTE hash = calloc(hash_len, 1); jint data_len = (*env)->GetArrayLength(env, data); jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - //err + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); } (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); @@ -764,8 +895,15 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &pkey, pub_data, pub_length, 0))) { - //err + + printf("pub_length %i\n", pub_length); + printf("using pubkey: "); + for (size_t i = 0; i < pub_length; ++i) { + printf("%02x", (unsigned)pub_data[i] & 0xffU); + } + printf("\n"); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); @@ -785,7 +923,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna } else if (result == STATUS_INVALID_SIGNATURE) { return JNI_FALSE; } else { - //err + wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status); return JNI_FALSE; } } \ No newline at end of file -- cgit v1.3.1 From 9bc30bf9727cda5a6a78668843b01c689e25bc18 Mon Sep 17 00:00:00 2001 From: J08nY Date: Fri, 27 Jul 2018 22:37:53 +0200 Subject: Get Mscng signatures to work (partially). --- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 156 +++++++++-------------- 1 file changed, 63 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index b0b71be..04b0fcf 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -448,59 +448,46 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { ULONG paramLength; jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); - free(fullBuf); - - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); - return NULL; - } - - PBYTE privBuf = calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, privBuf, bufSize, &bufSize, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); - return NULL; - } - printf("generate length %lu\n", bufSize); - printf("generated privkey: "); - for (size_t i = 0; i < bufSize; ++i) { - printf("%02x", (unsigned)privBuf[i] & 0xffU); - } - printf("\n"); - - // privBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // Qx[cbKey] X-coordinate of the public point. - // Qy[cbKey] Y-coordinate of the public point. - // d[cbKey] Private key. - BCRYPT_ECCKEY_BLOB *privHeader = (BCRYPT_ECCKEY_BLOB*)privBuf; - PBYTE priv_x = &privBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; - PBYTE priv_y = priv_x + privHeader->cbKey; - PBYTE priv = priv_y + privHeader->cbKey; - - jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + // fullBuf looks like: + // BCRYPT_ECCFULLKEY_BLOB header + // P[cbFieldLength] Prime specifying the base field. + // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p + // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p + // Gx[cbFieldLength] X-coordinate of the base point. + // Gy[cbFieldLength] Y-coordinate of the base point. + // n[cbSubgroupOrder] Order of the group generated by G = (x,y) + // h[cbCofactor] Cofactor of G in E. + // S[cbSeed] Seed of the curve. + // Qx[cbFieldLength] X-coordinate of the public point. + // Qy[cbFieldLength] Y-coordinate of the public point. + // d[cbSubgroupOrder] Private key. + BCRYPT_ECCFULLKEY_BLOB *privHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf; + PBYTE priv_x = &fullBuf[paramLength]; + PBYTE priv_y = priv_x + privHeader->cbFieldLength; + PBYTE priv = priv_y + privHeader->cbFieldLength; + + jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, privHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + memcpy(header_data, privHeader, paramLength); (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, priv_x, privHeader->cbKey); + memcpy(x_data, priv_x, privHeader->cbFieldLength); (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, priv_y, privHeader->cbKey); + memcpy(y_data, priv_y, privHeader->cbFieldLength); (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); - jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbKey); + jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbSubgroupOrder); jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); - memcpy(key_priv, priv, privHeader->cbKey); + memcpy(key_priv, priv, privHeader->cbSubgroupOrder); (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); - free(privBuf); + free(fullBuf); jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); @@ -529,45 +516,39 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { ULONG paramLength; jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); - free(fullBuf); - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptExportKey(length only)\n", status); - return NULL; - } - - PBYTE pubBuf = calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, pubBuf, bufSize, &bufSize, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptExportKey(whole)\n", status); - return NULL; - } - - // pubBuf looks like: - // BCRYPT_ECCKEY_BLOB header - // Qx[cbKey] X-coordinate of the public point. - // Qy[cbKey] Y-coordinate of the public point. - BCRYPT_ECCKEY_BLOB *pubHeader = (BCRYPT_ECCKEY_BLOB*)pubBuf; - PBYTE pub_x = &pubBuf[sizeof(BCRYPT_ECCKEY_BLOB)]; - PBYTE pub_y = pub_x + pubHeader->cbKey; + // fullBuf looks like: + // BCRYPT_ECCFULLKEY_BLOB header + // P[cbFieldLength] Prime specifying the base field. + // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p + // B[cbFieldLength] Coefficient B of the equation y^2 = x^3 + A*x + B mod p + // Gx[cbFieldLength] X-coordinate of the base point. + // Gy[cbFieldLength] Y-coordinate of the base point. + // n[cbSubgroupOrder] Order of the group generated by G = (x,y) + // h[cbCofactor] Cofactor of G in E. + // S[cbSeed] Seed of the curve. + // Qx[cbFieldLength] X-coordinate of the public point. + // Qy[cbFieldLength] Y-coordinate of the public point. + BCRYPT_ECCFULLKEY_BLOB *pubHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf; + PBYTE pub_x = &fullBuf[paramLength]; + PBYTE pub_y = pub_x + pubHeader->cbFieldLength; - jbyteArray header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, pubHeader, sizeof(BCRYPT_ECCKEY_BLOB)); + memcpy(header_data, pubHeader, paramLength); (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, pub_x, pubHeader->cbKey); + memcpy(x_data, pub_x, pubHeader->cbFieldLength); (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbKey); + jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, pub_y, pubHeader->cbKey); + memcpy(y_data, pub_y, pubHeader->cbFieldLength); (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); - free(pubBuf); + free(fullBuf); jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); @@ -718,14 +699,14 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); @@ -797,10 +778,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig BCRYPT_ALG_HANDLE sigHandle = NULL; - if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { - //err - printf("init err!\n"); - } + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return 0; + } BCRYPT_ALG_HANDLE hashHandle = NULL; @@ -827,14 +809,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - - printf("priv_length %i\n", priv_length); - printf("using privkey: "); - for (size_t i = 0; i < priv_length; ++i) { - printf("%02x", (unsigned)priv_data[i] & 0xffU); - } - printf("\n"); - if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); @@ -866,9 +841,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna BCRYPT_ALG_HANDLE sigHandle = NULL; - if (!init_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, params)) { - //err - } + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { + //err + wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return 0; + } BCRYPT_ALG_HANDLE hashHandle = NULL; @@ -895,14 +872,7 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna jint pub_length = (*env)->GetArrayLength(env, pubkey); jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - - printf("pub_length %i\n", pub_length); - printf("using pubkey: "); - for (size_t i = 0; i < pub_length; ++i) { - printf("%02x", (unsigned)pub_data[i] & 0xffU); - } - printf("\n"); - if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); -- cgit v1.3.1 From 0582131bbcabea050f6a43643b7e81e922e3acd0 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 28 Jul 2018 11:45:49 +0200 Subject: Proper error handling in Mscng. --- src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 10 + src/cz/crcs/ectester/standalone/libs/jni/c_utils.h | 5 + src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 1054 +++++++++++--------- 3 files changed, 570 insertions(+), 499 deletions(-) (limited to 'src') 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 f920fc4..6954c36 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c @@ -1,4 +1,5 @@ #include "c_utils.h" +#define _ISOC99_SOURCE #include jclass ec_parameter_spec_class; @@ -64,3 +65,12 @@ void throw_new(JNIEnv *env, const char *class, const char *message) { jclass clazz = (*env)->FindClass(env, class); (*env)->ThrowNew(env, clazz, message); } + +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); + va_end(args); + throw_new(env, class, buffer); +} \ 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 3ef8f86..2e5fa1a 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h @@ -27,6 +27,11 @@ void init_classes(JNIEnv *env, const char* lib_name); */ void throw_new(JNIEnv *env, const char *class, const char *message); +/** + * Throw a new exception of class, with formatted message. + */ +void throw_new_var(JNIEnv *env, const char *class, const char *format, ...); + /** * Some useful defines to init the provider. */ diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 04b0fcf..12cc13d 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -24,97 +24,97 @@ typedef struct { ULONG cbSeed; //Byte length of the seed used to generate the curve. } BCRYPT_ECC_PARAMETER_HEADER; -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self){ - jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); - provider_class = (*env)->NewGlobalRef(env, local_provider_class); +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self) { + jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); + provider_class = (*env)->NewGlobalRef(env, local_provider_class); - jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); + jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V"); - jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); - double version = 1.0; + jstring name = (*env)->NewStringUTF(env, "Microsoft CNG"); + double version = 1.0; - return (*env)->NewObject(env, provider_class, init, name, version, name); + return (*env)->NewObject(env, provider_class, init, name, version, name); } JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup(JNIEnv *env, jobject self) { - INIT_PROVIDER(env, provider_class); + INIT_PROVIDER(env, provider_class); - ADD_KPG(env, self, "ECDH", "MscngECDH"); - ADD_KPG(env, self, "ECDSA", "MscngECDSA"); + ADD_KPG(env, self, "ECDH", "MscngECDH"); + ADD_KPG(env, self, "ECDSA", "MscngECDSA"); - ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF"); - ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF"); - ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); - ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); + ADD_KA(env, self, "ECDHwithSHA1KDF", "MscngECDHwithSHA1KDF"); + ADD_KA(env, self, "ECDHwithSHA256KDF", "MscngECDHwithSHA256KDF"); + ADD_KA(env, self, "ECDHwithSHA384KDF", "MscngECDHwithSHA384KDF"); + ADD_KA(env, self, "ECDHwithSHA512KDF", "MscngECDHwithSHA512KDF"); - ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1"); - ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256"); - ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); - ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); + ADD_SIG(env, self, "SHA1withECDSA", "MscngECDSAwithSHA1"); + ADD_SIG(env, self, "SHA256withECDSA", "MscngECDSAwithSHA256"); + ADD_SIG(env, self, "SHA384withECDSA", "MscngECDSAwithSHA384"); + ADD_SIG(env, self, "SHA512withECDSA", "MscngECDSAwithSHA112"); - init_classes(env, "Mscng"); + init_classes(env, "Mscng"); } typedef struct { - LPCSTR name; - ULONG bits; + LPCSTR name; + ULONG bits; } named_curve_t; static named_curve_t named_curves[] = { - {"curve25519", 256}, - {"brainpoolP160r1", 160}, - {"brainpoolP160t1", 160}, - {"brainpoolP192r1", 192}, - {"brainpoolP192t1", 192}, - {"brainpoolP224r1", 224}, - {"brainpoolP224t1", 224}, - {"brainpoolP256r1", 256}, - {"brainpoolP256t1", 256}, - {"brainpoolP320r1", 320}, - {"brainpoolP320t1", 320}, - {"brainpoolP384r1", 384}, - {"brainpoolP384t1", 384}, - {"brainpoolP512r1", 512}, - {"brainpoolP512t1", 512}, - {"ec192wapi", 192}, - {"nistP192", 192}, - {"nistP224", 224}, - {"nistP256", 256}, - {"nistP384", 384}, - {"nistP521", 521}, - {"numsP256t1", 256}, - {"numsP384t1", 384}, - {"numsP512t1", 512}, - {"secP160k1", 160}, - {"secP160r1", 160}, - {"secP160r2", 160}, - {"secP192k1", 192}, - {"secP192r1", 192}, - {"secP224k1", 224}, - {"secP224r1", 224}, - {"secP256k1", 256}, - {"secP256r1", 256}, - {"secP384r1", 384}, - {"secP521r1", 521}, - {"wtls12", 224}, - {"wtls7", 160}, - {"wtls9", 160}, - {"x962P192v1", 192}, - {"x962P192v2", 192}, - {"x962P192v3", 192}, - {"x962P239v1", 239}, - {"x962P239v2", 239}, - {"x962P239v3", 239}, - {"x962P256v1", 256} + {"curve25519", 256}, + {"brainpoolP160r1", 160}, + {"brainpoolP160t1", 160}, + {"brainpoolP192r1", 192}, + {"brainpoolP192t1", 192}, + {"brainpoolP224r1", 224}, + {"brainpoolP224t1", 224}, + {"brainpoolP256r1", 256}, + {"brainpoolP256t1", 256}, + {"brainpoolP320r1", 320}, + {"brainpoolP320t1", 320}, + {"brainpoolP384r1", 384}, + {"brainpoolP384t1", 384}, + {"brainpoolP512r1", 512}, + {"brainpoolP512t1", 512}, + {"ec192wapi", 192}, + {"nistP192", 192}, + {"nistP224", 224}, + {"nistP256", 256}, + {"nistP384", 384}, + {"nistP521", 521}, + {"numsP256t1", 256}, + {"numsP384t1", 384}, + {"numsP512t1", 512}, + {"secP160k1", 160}, + {"secP160r1", 160}, + {"secP160r2", 160}, + {"secP192k1", 192}, + {"secP192r1", 192}, + {"secP224k1", 224}, + {"secP224r1", 224}, + {"secP256k1", 256}, + {"secP256r1", 256}, + {"secP384r1", 384}, + {"secP521r1", 521}, + {"wtls12", 224}, + {"wtls7", 160}, + {"wtls9", 160}, + {"x962P192v1", 192}, + {"x962P192v2", 192}, + {"x962P192v3", 192}, + {"x962P239v1", 239}, + {"x962P239v2", 239}, + {"x962P239v3", 239}, + {"x962P256v1", 256} }; static const named_curve_t* lookup_curve(const char *name) { - for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { - if (strcmp(name, named_curves[i].name) == 0) { - return &named_curves[i]; - } - } - return NULL; + for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { + if (strcmp(name, named_curves[i].name) == 0) { + return &named_curves[i]; + } + } + return NULL; } static const named_curve_t* lookup_curve_bits(jint bitsize) { @@ -161,24 +161,25 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurv BCRYPT_ALG_HANDLE handle; if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, BCRYPT_ECDH_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { - //err wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - return 0; + return result; } ULONG bufSize; if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, NULL, 0, &bufSize, 0))) { - //err wprintf(L"**** Error 0x%x returned by BCryptGetProperty(length only)\n", status); - return 0; + BCryptCloseAlgorithmProvider(handle, 0); + return result; } BCRYPT_ECC_CURVE_NAMES *curves = (BCRYPT_ECC_CURVE_NAMES *)calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, (PBYTE) curves, bufSize, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptGetProperty(handle, BCRYPT_ECC_CURVE_NAME_LIST, (PBYTE)curves, bufSize, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptGetProperty(whole)\n", status); - return 0; + BCryptCloseAlgorithmProvider(handle, 0); + free(curves); + return result; } + for (size_t i = 0; i < curves->dwEccCurveNames; ++i) { NPSTR curve_name; ULONG len = utf_16to8(&curve_name, curves->pEccCurveNames[i]); @@ -190,7 +191,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurv free(curves); BCryptCloseAlgorithmProvider(handle, 0); - return result; + return result; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) { @@ -206,55 +207,55 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPa JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported(JNIEnv *env, jobject self, jobject params) { if (params == NULL) { - return JNI_FALSE; - } - - 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); - const named_curve_t *curve = lookup_curve(utf_name); - (*env)->ReleaseStringUTFChars(env, name, utf_name); - return curve == NULL ? JNI_FALSE : JNI_TRUE; - } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { - jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); - jobject curve = (*env)->CallObjectMethod(env, params, get_curve); - - jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); - jobject field = (*env)->CallObjectMethod(env, curve, get_field); - - if ((*env)->IsInstanceOf(env, field, fp_field_class)) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } - } else { - return JNI_FALSE; - } + return JNI_FALSE; + } + + 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); + const named_curve_t *curve = lookup_curve(utf_name); + (*env)->ReleaseStringUTFChars(env, name, utf_name); + return curve == NULL ? JNI_FALSE : JNI_TRUE; + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject curve = (*env)->CallObjectMethod(env, params, get_curve); + + jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;"); + jobject field = (*env)->CallObjectMethod(env, curve, get_field); + + if ((*env)->IsInstanceOf(env, field, fp_field_class)) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } + } else { + return JNI_FALSE; + } } static jobject bytes_to_biginteger(JNIEnv *env, PBYTE bytes, int len) { - jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); - jbyteArray byte_array = (*env)->NewByteArray(env, len); - jbyte *data = (*env)->GetByteArrayElements(env, byte_array, NULL); - memcpy(data, bytes, len); - (*env)->ReleaseByteArrayElements(env, byte_array, data, 0); - jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, byte_array); - return result; + jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V"); + jbyteArray byte_array = (*env)->NewByteArray(env, len); + jbyte *data = (*env)->GetByteArrayElements(env, byte_array, NULL); + memcpy(data, bytes, len); + (*env)->ReleaseByteArrayElements(env, byte_array, data, 0); + jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, byte_array); + return result; } static void biginteger_to_bytes(JNIEnv *env, jobject bigint, PBYTE bytes, ULONG len) { - jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B"); + 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); - memcpy(bytes, &byte_data[byte_length - len], len); - (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); + 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); + memcpy(bytes, &byte_data[byte_length - len], len); + (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT); } static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLength) { - // + // // BCRYPT_ECCFULLKEY_BLOB header // P[cbFieldLength] Prime specifying the base field. // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p @@ -266,151 +267,148 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLe // S[cbSeed] Seed of the curve. BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB*)eccParams; - PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)]; + PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)]; - //cbFieldLength - PBYTE P = paramsStart; - PBYTE A = P + header->cbFieldLength; - PBYTE B = A + header->cbFieldLength; - PBYTE GX = B + header->cbFieldLength; - PBYTE GY = GX + header->cbFieldLength; + //cbFieldLength + PBYTE P = paramsStart; + PBYTE A = P + header->cbFieldLength; + PBYTE B = A + header->cbFieldLength; + PBYTE GX = B + header->cbFieldLength; + PBYTE GY = GX + header->cbFieldLength; - //cbSubgroupOrder - PBYTE N = GY + header->cbFieldLength; + //cbSubgroupOrder + PBYTE N = GY + header->cbFieldLength; - //cbCofactor - PBYTE H = N + header->cbSubgroupOrder; + //cbCofactor + PBYTE H = N + header->cbSubgroupOrder; - //cbSeed - PBYTE S = H + header->cbCofactor; + //cbSeed + PBYTE S = H + header->cbCofactor; *paramLength = sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed; - jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); + jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength); - 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, p_int); + 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, p_int); - jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength); - jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength); + jobject a_int = bytes_to_biginteger(env, A, header->cbFieldLength); + jobject b_int = bytes_to_biginteger(env, B, header->cbFieldLength); - 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); + 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); - jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength); - jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength); + jobject gx_int = bytes_to_biginteger(env, GX, header->cbFieldLength); + jobject gy_int = bytes_to_biginteger(env, GY, header->cbFieldLength); - jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); - jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); + jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + jobject g = (*env)->NewObject(env, point_class, point_init, gx_int, gy_int); - jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder); + jobject n_int = bytes_to_biginteger(env, N, header->cbSubgroupOrder); - jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor); - jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I"); - jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int); + jobject h_int = bytes_to_biginteger(env, H, header->cbCofactor); + jmethodID bigint_to_int = (*env)->GetMethodID(env, biginteger_class, "intValue", "()I"); + jint cof = (*env)->CallIntMethod(env, h_int, bigint_to_int); - 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"); - return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); + 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"); + return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n_int, cof); } static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { - jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); - jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve); + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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_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_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, "getB", "()Ljava/math/BigInteger;"); - jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); + jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); - jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); - jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); + jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b); - jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); - jobject p = (*env)->CallObjectMethod(env, field, get_p); + jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;"); + jobject p = (*env)->CallObjectMethod(env, field, get_p); - jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); - jobject g = (*env)->CallObjectMethod(env, params, get_g); + jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;"); + jobject g = (*env)->CallObjectMethod(env, params, get_g); - jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); - jobject gx = (*env)->CallObjectMethod(env, g, get_x); + jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;"); + jobject gx = (*env)->CallObjectMethod(env, g, get_x); - jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); - jobject gy = (*env)->CallObjectMethod(env, g, get_y); + jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;"); + jobject gy = (*env)->CallObjectMethod(env, g, get_y); - jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); - jobject n = (*env)->CallObjectMethod(env, params, get_n); + jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;"); + jobject n = (*env)->CallObjectMethod(env, params, get_n); - jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); - jint h = (*env)->CallIntMethod(env, params, get_h); + jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I"); + jint h = (*env)->CallIntMethod(env, params, get_h); - jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I"); - jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength); - jint order_bytes = (order_bits + 7) / 8; + jmethodID get_bitlength = (*env)->GetMethodID(env, biginteger_class, "bitLength", "()I"); + jint order_bits = (*env)->CallIntMethod(env, n, get_bitlength); + jint order_bytes = (order_bits + 7) / 8; - // header_size + 5*bytes + order_bytes + cof_size + 0 - ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5*bytes + order_bytes + 1 + 0; - *curve = calloc(bufSize, 1); - BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; - header->dwVersion = 1; - header->dwCurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery - header->dwCurveGenerationAlgId = 0; - header->cbFieldLength = bytes; - header->cbSubgroupOrder = order_bytes; + // header_size + 5*bytes + order_bytes + cof_size + 0 + ULONG bufSize = sizeof(BCRYPT_ECC_PARAMETER_HEADER) + 5 * bytes + order_bytes + 1 + 0; + *curve = calloc(bufSize, 1); + BCRYPT_ECC_PARAMETER_HEADER *header = (BCRYPT_ECC_PARAMETER_HEADER*)*curve; + header->dwVersion = 1; + header->dwCurveType = 1; //1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery + header->dwCurveGenerationAlgId = 0; + header->cbFieldLength = bytes; + header->cbSubgroupOrder = order_bytes; header->cbCofactor = 1; - header->cbSeed = 0; + header->cbSeed = 0; - PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; + PBYTE paramsStart = &(*curve)[sizeof(BCRYPT_ECC_PARAMETER_HEADER)]; - biginteger_to_bytes(env, p, paramsStart, bytes); - biginteger_to_bytes(env, a, paramsStart + bytes, bytes); - biginteger_to_bytes(env, b, paramsStart + 2*bytes, bytes); - biginteger_to_bytes(env, gx, paramsStart + 3*bytes, bytes); - biginteger_to_bytes(env, gy, paramsStart + 4*bytes, bytes); - biginteger_to_bytes(env, n, paramsStart + 5*bytes, order_bytes); - PBYTE cof_ptr = (PBYTE) (paramsStart + 5*bytes + order_bytes); + biginteger_to_bytes(env, p, paramsStart, bytes); + biginteger_to_bytes(env, a, paramsStart + bytes, bytes); + biginteger_to_bytes(env, b, paramsStart + 2 * bytes, bytes); + biginteger_to_bytes(env, gx, paramsStart + 3 * bytes, bytes); + biginteger_to_bytes(env, gy, paramsStart + 4 * bytes, bytes); + biginteger_to_bytes(env, n, paramsStart + 5 * bytes, order_bytes); + PBYTE cof_ptr = (PBYTE)(paramsStart + 5 * bytes + order_bytes); *cof_ptr = (BYTE)h; - return bufSize; + return bufSize; } static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { NTSTATUS status; - if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { - //err + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - return 0; - } + return 0; + } ULONG result = 0; - 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); + 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); jint utf_length = (*env)->GetStringUTFLength(env, name); PUCHAR chars = calloc(utf_length + 1, 1); (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars); - const named_curve_t *curve = lookup_curve(chars); + const named_curve_t *curve = lookup_curve(chars); NWPSTR curve_utf16; ULONG ret = utf_8to16(&curve_utf16, chars); - if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR) curve_utf16, ret * sizeof(WCHAR), 0))) { - //err + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR)curve_utf16, ret * sizeof(WCHAR), 0))) { wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); - return 0; - } + return 0; + } free(chars); free(curve_utf16); result = curve->bits; - } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { - PBYTE curve; - ULONG curveLen = create_curve(env, params, &curve); - if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { - //err + } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { + PBYTE curve; + ULONG curveLen = create_curve(env, params, &curve); + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curveLen, 0))) { wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); - return 0; - } - free(curve); + return 0; + } + free(curve); jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve); @@ -421,27 +419,24 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I"); jint bits = (*env)->CallIntMethod(env, field, get_bits); result = bits; - } - return result; + } + return result; } static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { NTSTATUS status; - ULONG bufSize = 0; - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { - //err + ULONG bufSize = 0; + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); return NULL; - } - if (bufSize == 0) { - //err - printf("err0\n"); + } + if (bufSize == 0) { + printf("buf 0\n"); return NULL; - } + } PBYTE fullBuf = calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); return NULL; } @@ -449,7 +444,7 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { ULONG paramLength; jobject ec_priv_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); - // fullBuf looks like: + // fullBuf looks like: // BCRYPT_ECCFULLKEY_BLOB header // P[cbFieldLength] Prime specifying the base field. // A[cbFieldLength] Coefficient A of the equation y^2 = x^3 + A*x + B mod p @@ -463,56 +458,53 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { // Qy[cbFieldLength] Y-coordinate of the public point. // d[cbSubgroupOrder] Private key. BCRYPT_ECCFULLKEY_BLOB *privHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf; - PBYTE priv_x = &fullBuf[paramLength]; - PBYTE priv_y = priv_x + privHeader->cbFieldLength; - PBYTE priv = priv_y + privHeader->cbFieldLength; - - jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, privHeader, paramLength); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - - jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); - jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, priv_x, privHeader->cbFieldLength); - (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - - jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); - jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, priv_y, privHeader->cbFieldLength); - (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); - - jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbSubgroupOrder); - jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); - memcpy(key_priv, priv, privHeader->cbSubgroupOrder); - (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); + PBYTE priv_x = &fullBuf[paramLength]; + PBYTE priv_y = priv_x + privHeader->cbFieldLength; + PBYTE priv = priv_y + privHeader->cbFieldLength; + + jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, privHeader, paramLength); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, priv_x, privHeader->cbFieldLength); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + + jbyteArray y_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, priv_y, privHeader->cbFieldLength); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + + jbyteArray priv_bytes = (*env)->NewByteArray(env, privHeader->cbSubgroupOrder); + jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL); + memcpy(key_priv, priv, privHeader->cbSubgroupOrder); + (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0); free(fullBuf); - - jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); + + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); } static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { NTSTATUS status; - ULONG bufSize = 0; - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { - //err + ULONG bufSize = 0; + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, length only)\n", status); return NULL; - } + } if (bufSize == 0) { - //err printf("err0\n"); return NULL; } PBYTE fullBuf = calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) { - //err + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, fullBuf, bufSize, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); return NULL; - } + } ULONG paramLength; jobject ec_pub_param_spec = create_ec_param_spec(env, fullBuf, ¶mLength); @@ -530,28 +522,28 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { // Qx[cbFieldLength] X-coordinate of the public point. // Qy[cbFieldLength] Y-coordinate of the public point. BCRYPT_ECCFULLKEY_BLOB *pubHeader = (BCRYPT_ECCFULLKEY_BLOB*)fullBuf; - PBYTE pub_x = &fullBuf[paramLength]; - PBYTE pub_y = pub_x + pubHeader->cbFieldLength; + PBYTE pub_x = &fullBuf[paramLength]; + PBYTE pub_y = pub_x + pubHeader->cbFieldLength; - jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, pubHeader, paramLength); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, pubHeader, paramLength); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); - jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); - jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); - memcpy(x_data, pub_x, pubHeader->cbFieldLength); - (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); + jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); + jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); + memcpy(x_data, pub_x, pubHeader->cbFieldLength); + (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0); - jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); - jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); - memcpy(y_data, pub_y, pubHeader->cbFieldLength); - (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); + jbyteArray y_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); + jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL); + memcpy(y_data, pub_y, pubHeader->cbFieldLength); + (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0); free(fullBuf); - jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { @@ -575,8 +567,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai algo = BCRYPT_ECDH_P521_ALGORITHM; break; default: - //err - break; + //unreachable + return NULL; } } else if (strcmp(type_data, "ECDSA") == 0) { switch (keysize) { @@ -590,28 +582,32 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai algo = BCRYPT_ECDSA_P521_ALGORITHM; break; default: - //err - break; + //unreachable + return NULL; } } else { - //err + //unreachable + return NULL; } (*env)->ReleaseStringUTFChars(env, type, type_data); if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider", status); return NULL; } BCRYPT_KEY_HANDLE key = NULL; if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status); + BCryptCloseAlgorithmProvider(handle, 0); + return NULL; } if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status); + BCryptCloseAlgorithmProvider(handle, 0); + return NULL; } jobject privkey = key_to_privkey(env, key); @@ -624,276 +620,336 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random){ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject self, jobject params, jobject random) { NTSTATUS status; - BCRYPT_ALG_HANDLE handle = NULL; - BCRYPT_KEY_HANDLE key = NULL; - - jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR algo; - if (strcmp(type_data, "ECDH") == 0) { - algo = BCRYPT_ECDH_ALGORITHM; - } else if (strcmp(type_data, "ECDSA") == 0) { - algo = BCRYPT_ECDSA_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); + BCRYPT_ALG_HANDLE handle = NULL; + BCRYPT_KEY_HANDLE key = NULL; + + jclass mscng_kpg_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_kpg_class, "type", "Ljava/lang/String;"); + jstring type = (jstring)(*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR algo; + if (strcmp(type_data, "ECDH") == 0) { + algo = BCRYPT_ECDH_ALGORITHM; + } else if (strcmp(type_data, "ECDSA") == 0) { + algo = BCRYPT_ECDSA_ALGORITHM; + } else { + //unreachable + return NULL; + } + (*env)->ReleaseStringUTFChars(env, type, type_data); ULONG bits = init_algo(env, &handle, algo, params); - if (bits == 0) { - //err - } + if (bits == 0) { + throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo."); + return NULL; + } - if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptGenerateKeyPair\n", status); - } + if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGenerateKeyPair\n", status); + BCryptCloseAlgorithmProvider(handle, 0); + return NULL; + } - if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptFinalizeKeyPair\n", status); - } + if (NT_FAILURE(status = BCryptFinalizeKeyPair(key, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status); + BCryptCloseAlgorithmProvider(handle, 0); + return NULL; + } - jobject privkey = key_to_privkey(env, key); - jobject pubkey = key_to_pubkey(env, key); + jobject privkey = key_to_privkey(env, key); + jobject pubkey = key_to_pubkey(env, key); - jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); + jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); - BCryptDestroyKey(key); - BCryptCloseAlgorithmProvider(handle, 0); - return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); + BCryptDestroyKey(key); + BCryptCloseAlgorithmProvider(handle, 0); + return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { NTSTATUS status; printf("generateSecret!\n"); - jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR kdf_algo; - if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) { - kdf_algo = BCRYPT_SHA1_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) { - kdf_algo = BCRYPT_SHA256_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) { - kdf_algo = BCRYPT_SHA384_ALGORITHM; - } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) { - kdf_algo = BCRYPT_SHA512_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); - - BCRYPT_ALG_HANDLE kaHandle = NULL; - - if (!init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params)) { - //err - } - - BCRYPT_KEY_HANDLE pkey = NULL; - BCRYPT_KEY_HANDLE skey = NULL; - - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); - } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); - - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); - } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); - - BCRYPT_SECRET_HANDLE ka = NULL; - - if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptSecretAgreement\n", status); - } - - BCryptBufferDesc paramList = {0}; - BCryptBuffer kdfParams[1] = {0}; - kdfParams[0].BufferType = KDF_HASH_ALGORITHM; - kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR)); - kdfParams[0].pvBuffer = (PVOID)kdf_algo; - paramList.cBuffers = 1; - paramList.pBuffers = kdfParams; - paramList.ulVersion = BCRYPTBUFFER_VERSION; - - //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* - ULONG bufSize = 0; - if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(length only)\n", status); - } + jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); + jstring type = (jstring)(*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR kdf_algo; + if (strcmp(type_data, "ECDHwithSHA1KDF") == 0) { + kdf_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA256KDF") == 0) { + kdf_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA384KDF") == 0) { + kdf_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "ECDHwithSHA512KDF") == 0) { + kdf_algo = BCRYPT_SHA512_ALGORITHM; + } else { + //unreachable + return NULL; + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + + BCRYPT_ALG_HANDLE kaHandle = NULL; + + ULONG bits = init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params); + if (bits == 0) { + throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo."); + return NULL; + } + + BCRYPT_KEY_HANDLE pkey = NULL; + BCRYPT_KEY_HANDLE skey = NULL; + + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); + BCryptCloseAlgorithmProvider(kaHandle, 0); + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + return NULL; + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); + BCryptCloseAlgorithmProvider(kaHandle, 0); + BCryptDestroyKey(pkey); + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + return NULL; + } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + + BCRYPT_SECRET_HANDLE ka = NULL; + + if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSecretAgreement\n", status); + BCryptCloseAlgorithmProvider(kaHandle, 0); + BCryptDestroyKey(pkey); + BCryptDestroyKey(skey); + return NULL; + } + + BCryptBufferDesc paramList = { 0 }; + BCryptBuffer kdfParams[1] = { 0 }; + kdfParams[0].BufferType = KDF_HASH_ALGORITHM; + kdfParams[0].cbBuffer = (DWORD)((wcslen(kdf_algo) + 1) * sizeof(WCHAR)); + kdfParams[0].pvBuffer = (PVOID)kdf_algo; + paramList.cBuffers = 1; + paramList.pBuffers = kdfParams; + paramList.ulVersion = BCRYPTBUFFER_VERSION; + + //TODO: Is this the actual KDF-1 or KDF-2 algo or something completely different? *This does not use the counter!!!* + ULONG bufSize = 0; + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, NULL, 0, &bufSize, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(length only)\n", status); + return NULL; + } PBYTE derived = calloc(bufSize, 1); - if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptDeriveKey(whole)\n", status); - } + if (NT_FAILURE(status = BCryptDeriveKey(ka, BCRYPT_KDF_HASH, ¶mList, derived, bufSize, &bufSize, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptDeriveKey(whole)\n", status); + return NULL; + } - jbyteArray result = (*env)->NewByteArray(env, bufSize); - jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); - memcpy(result_data, derived, bufSize); - (*env)->ReleaseByteArrayElements(env, result, result_data, 0); + jbyteArray result = (*env)->NewByteArray(env, bufSize); + jbyte *result_data = (*env)->GetByteArrayElements(env, result, NULL); + memcpy(result_data, derived, bufSize); + (*env)->ReleaseByteArrayElements(env, result, result_data, 0); free(derived); - BCryptDestroyKey(pkey); - BCryptDestroyKey(skey); - BCryptDestroySecret(ka); - BCryptCloseAlgorithmProvider(kaHandle, 0); - return result; + BCryptDestroyKey(pkey); + BCryptDestroyKey(skey); + BCryptDestroySecret(ka); + BCryptCloseAlgorithmProvider(kaHandle, 0); + return result; } static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { - jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng"); - jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;"); - jstring type = (jstring) (*env)->GetObjectField(env, self, type_id); - const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); - LPCWSTR hash_algo; - if (strcmp(type_data, "SHA1withECDSA") == 0) { - hash_algo = BCRYPT_SHA1_ALGORITHM; - } else if (strcmp(type_data, "SHA256withECDSA") == 0) { - hash_algo = BCRYPT_SHA256_ALGORITHM; - } else if (strcmp(type_data, "SHA384withECDSA") == 0) { - hash_algo = BCRYPT_SHA384_ALGORITHM; - } else if (strcmp(type_data, "SHA512withECDSA") == 0) { - hash_algo = BCRYPT_SHA512_ALGORITHM; - } else { - //err - } - (*env)->ReleaseStringUTFChars(env, type, type_data); - return hash_algo; + jclass mscng_sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Mscng"); + jfieldID type_id = (*env)->GetFieldID(env, mscng_sig_class, "type", "Ljava/lang/String;"); + jstring type = (jstring)(*env)->GetObjectField(env, self, type_id); + const char* type_data = (*env)->GetStringUTFChars(env, type, NULL); + LPCWSTR hash_algo; + if (strcmp(type_data, "SHA1withECDSA") == 0) { + hash_algo = BCRYPT_SHA1_ALGORITHM; + } else if (strcmp(type_data, "SHA256withECDSA") == 0) { + hash_algo = BCRYPT_SHA256_ALGORITHM; + } else if (strcmp(type_data, "SHA384withECDSA") == 0) { + hash_algo = BCRYPT_SHA384_ALGORITHM; + } else if (strcmp(type_data, "SHA512withECDSA") == 0) { + hash_algo = BCRYPT_SHA512_ALGORITHM; + } else { + //unreachable + return NULL; + } + (*env)->ReleaseStringUTFChars(env, type, type_data); + return hash_algo; } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { NTSTATUS status; - LPCWSTR hash_algo = get_sighash_algo(env, self); + LPCWSTR hash_algo = get_sighash_algo(env, self); - BCRYPT_ALG_HANDLE sigHandle = NULL; + BCRYPT_ALG_HANDLE sigHandle = NULL; if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - return 0; + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return NULL; } - BCRYPT_ALG_HANDLE hashHandle = NULL; + BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - } + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + return NULL; + } - DWORD dummy = 0; - DWORD hash_len = 0; - if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); - } + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + return NULL; + } PBYTE hash = calloc(hash_len, 1); - jint data_len = (*env)->GetArrayLength(env, data); - jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); - } - (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); - - BCRYPT_KEY_HANDLE skey = NULL; - - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); - } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); - - DWORD sig_len = 0; - if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptSignHash(len only)\n", status); - } - - jbyteArray sig = (*env)->NewByteArray(env, sig_len); - jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptSignHash(do)\n", status); - } - (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + return NULL; + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE skey = NULL; + + jint priv_length = (*env)->GetArrayLength(env, privkey); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + return NULL; + } + (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + + DWORD sig_len = 0; + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(len only)\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + return NULL; + } + + jbyteArray sig = (*env)->NewByteArray(env, sig_len); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, sig_data, sig_len, &sig_len, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(do)\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); + return NULL; + } + (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0); free(hash); - BCryptDestroyKey(skey); - BCryptCloseAlgorithmProvider(hashHandle, 0); - BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptDestroyKey(skey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); - return sig; + return sig; } JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { NTSTATUS status; - LPCWSTR hash_algo = get_sighash_algo(env, self); + LPCWSTR hash_algo = get_sighash_algo(env, self); - BCRYPT_ALG_HANDLE sigHandle = NULL; + BCRYPT_ALG_HANDLE sigHandle = NULL; if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { - //err - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - return 0; + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return JNI_FALSE; } - BCRYPT_ALG_HANDLE hashHandle = NULL; + BCRYPT_ALG_HANDLE hashHandle = NULL; - if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); - } + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&hashHandle, hash_algo, NULL, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + return JNI_FALSE; + } - DWORD dummy = 0; - DWORD hash_len = 0; - if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptGetProperty(hash len)\n", status); - } + DWORD dummy = 0; + DWORD hash_len = 0; + if (NT_FAILURE(status = BCryptGetProperty(hashHandle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_len, sizeof(DWORD), &dummy, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptGetProperty(hash len)\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + return JNI_FALSE; + } PBYTE hash = calloc(hash_len, 1); - jint data_len = (*env)->GetArrayLength(env, data); - jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); - if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { - wprintf(L"**** Error 0x%x returned by BCryptHash\n", status); - } - (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); - - BCRYPT_KEY_HANDLE pkey = NULL; - - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); - if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { - wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status); - } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + jint data_len = (*env)->GetArrayLength(env, data); + jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL); + if (NT_FAILURE(status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + return JNI_FALSE; + } + (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT); + + BCRYPT_KEY_HANDLE pkey = NULL; + + jint pub_length = (*env)->GetArrayLength(env, pubkey); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status); + BCryptCloseAlgorithmProvider(sigHandle, 0); + BCryptCloseAlgorithmProvider(hashHandle, 0); + free(hash); + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + return JNI_FALSE; + } + (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); - jint sig_len = (*env)->GetArrayLength(env, sig); - jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); - NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0); - (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); + jint sig_len = (*env)->GetArrayLength(env, sig); + jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); + NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_data, sig_len, 0); + (*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT); free(hash); - BCryptDestroyKey(pkey); - BCryptCloseAlgorithmProvider(hashHandle, 0); - BCryptCloseAlgorithmProvider(sigHandle, 0); - - if (result == STATUS_SUCCESS) { - return JNI_TRUE; - } else if (result == STATUS_INVALID_SIGNATURE) { - return JNI_FALSE; - } else { - wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status); - return JNI_FALSE; - } + BCryptDestroyKey(pkey); + BCryptCloseAlgorithmProvider(hashHandle, 0); + BCryptCloseAlgorithmProvider(sigHandle, 0); + + if (result == STATUS_SUCCESS) { + return JNI_TRUE; + } else if (result == STATUS_INVALID_SIGNATURE) { + return JNI_FALSE; + } else { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptVerifySignature\n", status); + return JNI_FALSE; + } } \ No newline at end of file -- cgit v1.3.1 From 4399ba5e724763675ddda41a9f9380fa565f5584 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 28 Jul 2018 12:39:25 +0200 Subject: Add Simple and Extended native KeyAgreement and Signature SPIs. --- .../standalone/libs/jni/NativeKeyAgreementSpi.java | 65 ++++++++++++--------- .../standalone/libs/jni/NativeSignatureSpi.java | 68 ++++++++++++---------- 2 files changed, 75 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index 1211519..31886cf 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -16,9 +16,9 @@ import java.security.spec.ECParameterSpec; * @author Jan Jancar johny@neuromancer.sk */ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { - private ECPrivateKey privateKey; - private ECPublicKey publicKey; - private ECParameterSpec params; + ECPrivateKey privateKey; + ECPublicKey publicKey; + ECParameterSpec params; @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { @@ -59,23 +59,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { return null; } - @Override - protected byte[] engineGenerateSecret() throws IllegalStateException { - byte[] pubkey; - if (publicKey instanceof NativeECPublicKey) { - pubkey = ((NativeECPublicKey) publicKey).getData(); - } else { - pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve()); - } - byte[] privkey; - if (privateKey instanceof NativeECPrivateKey) { - privkey = ((NativeECPrivateKey) privateKey).getData(); - } else { - privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize()); - } - return generateSecret(pubkey, privkey, params); - } - @Override protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException { byte[] secret = engineGenerateSecret(); @@ -92,16 +75,46 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { return new SecretKeySpec(engineGenerateSecret(), algorithm); } - abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi { + + @Override + protected byte[] engineGenerateSecret() throws IllegalStateException { + byte[] pubkey; + if (publicKey instanceof NativeECPublicKey) { + pubkey = ((NativeECPublicKey) publicKey).getData(); + } else { + pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve()); + } + byte[] privkey; + if (privateKey instanceof NativeECPrivateKey) { + privkey = ((NativeECPrivateKey) privateKey).getData(); + } else { + privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize()); + } + return generateSecret(pubkey, privkey, params); + } + + abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + } + + private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { + + @Override + protected byte[] engineGenerateSecret() throws IllegalStateException { + return generateSecret(publicKey, privateKey, params); + } + + abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, ECParameterSpec params); + } - public static class TomCrypt extends NativeKeyAgreementSpi { + public static class TomCrypt extends SimpleKeyAgreementSpi { @Override native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); } - public abstract static class Botan extends NativeKeyAgreementSpi { + public abstract static class Botan extends SimpleKeyAgreementSpi { private String type; public Botan(String type) { @@ -148,7 +161,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } } - public abstract static class Cryptopp extends NativeKeyAgreementSpi { + public abstract static class Cryptopp extends SimpleKeyAgreementSpi { private String type; public Cryptopp(String type) { @@ -165,7 +178,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } } - public abstract static class Openssl extends NativeKeyAgreementSpi { + public abstract static class Openssl extends SimpleKeyAgreementSpi { private String type; public Openssl(String type) { @@ -182,7 +195,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } } - public abstract static class Mscng extends NativeKeyAgreementSpi { + public abstract static class Mscng extends SimpleKeyAgreementSpi { private String type; public Mscng(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 e347120..81c7948 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java @@ -12,11 +12,11 @@ import java.security.spec.ECParameterSpec; * @author Jan Jancar johny@neuromancer.sk */ public abstract class NativeSignatureSpi extends SignatureSpi { - private ECPublicKey verifyKey; - private ECPrivateKey signKey; - private ECParameterSpec params; + ECPublicKey verifyKey; + ECPrivateKey signKey; + ECParameterSpec params; - private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @Override protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { @@ -50,27 +50,6 @@ public abstract class NativeSignatureSpi extends SignatureSpi { buffer.write(b, off, len); } - @Override - protected byte[] engineSign() throws SignatureException { - byte[] privkey; - if (signKey instanceof NativeECPrivateKey) { - privkey = ((NativeECPrivateKey) signKey).getData(); - } else { - privkey = ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()); - } - return sign(buffer.toByteArray(), privkey, params); - } - - @Override - protected boolean engineVerify(byte[] sigBytes) throws SignatureException { - byte[] pubkey; - if (verifyKey instanceof NativeECPublicKey) { - pubkey = ((NativeECPublicKey) verifyKey).getData(); - } else { - pubkey = ECUtil.toX962Uncompressed(verifyKey.getW(), params); - } - return verify(sigBytes, buffer.toByteArray(), pubkey, params); - } @Override @Deprecated @@ -84,11 +63,36 @@ public abstract class NativeSignatureSpi extends SignatureSpi { throw new UnsupportedOperationException("getParameter() not supported"); } - abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params); + private abstract static class SimpleSignatureSpi extends NativeSignatureSpi { - abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params); + @Override + protected byte[] engineSign() throws SignatureException { + byte[] privkey; + if (signKey instanceof NativeECPrivateKey) { + privkey = ((NativeECPrivateKey) signKey).getData(); + } else { + privkey = ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()); + } + return sign(buffer.toByteArray(), privkey, params); + } + + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + byte[] pubkey; + if (verifyKey instanceof NativeECPublicKey) { + pubkey = ((NativeECPublicKey) verifyKey).getData(); + } else { + pubkey = ECUtil.toX962Uncompressed(verifyKey.getW(), params); + } + return verify(sigBytes, buffer.toByteArray(), pubkey, params); + } + + abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params); + + abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params); + } - public static class TomCryptRaw extends NativeSignatureSpi { + public static class TomCryptRaw extends SimpleSignatureSpi { @Override native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params); @@ -97,7 +101,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi { native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params); } - public abstract static class Botan extends NativeSignatureSpi { + public abstract static class Botan extends SimpleSignatureSpi { private String type; public Botan(String type) { @@ -237,7 +241,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi { } } - public abstract static class Cryptopp extends NativeSignatureSpi { + public abstract static class Cryptopp extends SimpleSignatureSpi { private String type; public Cryptopp(String type) { @@ -286,7 +290,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi { } } - public abstract static class Openssl extends NativeSignatureSpi { + public abstract static class Openssl extends SimpleSignatureSpi { private String type; public Openssl(String type) { @@ -307,7 +311,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi { } } - public abstract static class Mscng extends NativeSignatureSpi { + public abstract static class Mscng extends SimpleSignatureSpi { private String type; public Mscng(String type) { -- cgit v1.3.1 From f7cd2f14fec676fedc6484eff9a64ebc41d3d910 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sat, 28 Jul 2018 18:34:09 +0200 Subject: Redo Mscng key storage. --- .../ectester/standalone/ECTesterStandalone.java | 1 - .../standalone/libs/jni/NativeECPrivateKey.java | 19 +- .../standalone/libs/jni/NativeECPublicKey.java | 19 +- .../standalone/libs/jni/NativeSignatureSpi.java | 23 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 315 ++++++++++++++++++--- src/cz/crcs/ectester/standalone/libs/jni/native.h | 38 +-- 6 files changed, 345 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index 2897d20..2f132fa 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -275,7 +275,6 @@ public class ECTesterStandalone { .findFirst() .orElse(null))); - if (kaIdent == null || kpIdent == null) { throw new NoSuchAlgorithmException(algo); } else { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java index 76786fe..4cd4a9d 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java @@ -86,23 +86,38 @@ public abstract class NativeECPrivateKey implements ECPrivateKey { } public static class Mscng extends Raw { + // 0 -> implicit (meta = curveName UTF16, header = full); + // 1 -> explicit (meta = null, header = full); + // 2 -> nist (meta = null, header = full) + private int flag; + private byte[] meta = null; private byte[] header; private byte[] x; private byte[] y; - public Mscng(byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) { + public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, byte[] keyData, ECParameterSpec params) { super(keyData, params); + this.flag = flag; + this.meta = Arrays.clone(meta); this.header = Arrays.clone(header); this.x = Arrays.clone(x); this.y = Arrays.clone(y); } + public int getFlag() { + return flag; + } + + public byte[] getMeta() { + return Arrays.clone(meta); + } + public byte[] getHeader() { return Arrays.clone(header); } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y, keyData); + return ByteUtil.concatenate(header, x, y, keyData); } @Override diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java index e55ed33..ccf21c0 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java @@ -88,23 +88,38 @@ public abstract class NativeECPublicKey implements ECPublicKey { } public static class Mscng extends ANSIX962 { + // 0 -> implicit (meta = curveName UTF16, header = full); + // 1 -> explicit (meta = null, header = full); + // 2 -> nist (meta = null, header = full) + private int flag; + private byte[] meta = null; private byte[] header; private byte[] x; private byte[] y; - public Mscng(byte[] header, byte[] x, byte[] y, ECParameterSpec params) { + public Mscng(int flag, byte[] meta, byte[] header, byte[] x, byte[] y, ECParameterSpec params) { super(ByteUtil.concatenate(new byte[]{0x04}, x, y), params); + this.flag = flag; + this.meta = Arrays.clone(meta); this.header = Arrays.clone(header); this.x = Arrays.clone(x); this.y = Arrays.clone(y); } + public int getFlag() { + return flag; + } + + public byte[] getMeta() { + return Arrays.clone(meta); + } + public byte[] getHeader() { return Arrays.clone(header); } public byte[] getBlob() { - return ByteUtil.concatenate(header, x, y); + return ByteUtil.concatenate(header, x, y); } @Override diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java index 81c7948..b60f2c6 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java @@ -92,6 +92,23 @@ public abstract class NativeSignatureSpi extends SignatureSpi { abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params); } + private abstract static class ExtendedSignatureSpi extends NativeSignatureSpi { + + @Override + protected byte[] engineSign() throws SignatureException { + return sign(buffer.toByteArray(), signKey, params); + } + + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + return verify(sigBytes, buffer.toByteArray(), verifyKey, params); + } + + abstract byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params); + + abstract boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params); + } + public static class TomCryptRaw extends SimpleSignatureSpi { @Override @@ -311,7 +328,7 @@ public abstract class NativeSignatureSpi extends SignatureSpi { } } - public abstract static class Mscng extends SimpleSignatureSpi { + public abstract static class Mscng extends ExtendedSignatureSpi { private String type; public Mscng(String type) { @@ -319,10 +336,10 @@ public abstract class NativeSignatureSpi extends SignatureSpi { } @Override - native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params); + native byte[] sign(byte[] data, ECPrivateKey privkey, ECParameterSpec params); @Override - native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params); + native boolean verify(byte[] signature, byte[] data, ECPublicKey pubkey, ECParameterSpec params); } public static class MscngECDSAwithSHA1 extends Mscng { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 12cc13d..8cd96fc 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -6,8 +6,9 @@ #include -static jclass provider_class; + +// BCRYPT and NT things. #define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) #define NT_FAILURE(status) !NT_SUCCESS(status) @@ -24,6 +25,13 @@ typedef struct { ULONG cbSeed; //Byte length of the seed used to generate the curve. } BCRYPT_ECC_PARAMETER_HEADER; +//Provider things +static jclass provider_class; + +#define KEYFLAG_IMPLICIT 0 +#define KEYFLAG_EXPLICIT 1 +#define KEYFLAG_NIST 2 + JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self) { jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); provider_class = (*env)->NewGlobalRef(env, local_provider_class); @@ -138,8 +146,8 @@ static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) { return MultiByteToWideChar(CP_UTF8, 0, in_str, -1, *out_buf, result); } -// Convert Java String to UTF-16 LPCWSTR null-terminated. -// Returns: Length of LPCWSTR in bytes! +// Convert Java String to UTF-16 NWPSTR null-terminated. +// Returns: Length of NWPSTR in bytes! static ULONG utf_strto16(NWPSTR *out_buf, JNIEnv *env, jobject str) { jsize len = (*env)->GetStringLength(env, str); *out_buf = calloc(len * sizeof(jchar) + 1, 1); @@ -378,7 +386,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { return bufSize; } -static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, jobject params) { +static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, jint *keyflag, NWPSTR *curve_name, LPCWSTR algo, jobject params) { NTSTATUS status; if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); @@ -392,15 +400,14 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job PUCHAR chars = calloc(utf_length + 1, 1); (*env)->GetStringUTFRegion(env, name, 0, utf_length, chars); const named_curve_t *curve = lookup_curve(chars); - NWPSTR curve_utf16; - ULONG ret = utf_8to16(&curve_utf16, chars); - if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR)curve_utf16, ret * sizeof(WCHAR), 0))) { + ULONG ret = utf_8to16(curve_name, chars); + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, (PUCHAR)*curve_name, ret * sizeof(WCHAR), 0))) { wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status); return 0; } free(chars); - free(curve_utf16); result = curve->bits; + *keyflag = KEYFLAG_IMPLICIT; } else if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) { PBYTE curve; ULONG curveLen = create_curve(env, params, &curve); @@ -419,11 +426,13 @@ static ULONG init_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR algo, job jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I"); jint bits = (*env)->CallIntMethod(env, field, get_bits); result = bits; + *keyflag = KEYFLAG_EXPLICIT; + *curve_name = NULL; } return result; } -static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { +static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) { NTSTATUS status; ULONG bufSize = 0; if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { @@ -438,6 +447,7 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { PBYTE fullBuf = calloc(bufSize, 1); if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, fullBuf, bufSize, &bufSize, 0))) { wprintf(L"**** Error 0x%x returned by BCryptExportKey(full, whole)\n", status); + free(fullBuf); return NULL; } @@ -462,10 +472,59 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { PBYTE priv_y = priv_x + privHeader->cbFieldLength; PBYTE priv = priv_y + privHeader->cbFieldLength; - jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, privHeader, paramLength); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + + jbyteArray meta_bytes = NULL; + jbyteArray header_bytes = NULL; + switch (flag) { + case 0: { + // meta = curve + jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR); + meta_bytes = (*env)->NewByteArray(env, meta_len); + jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL); + memcpy(meta_data, curve, meta_len); + (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0); + } + case 1: + case 2: { + // meta = null + // header = full + header_bytes = (*env)->NewByteArray(env, paramLength); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, fullBuf, paramLength); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + break; + } + default: + // header = small + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, NULL, 0, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status); + free(fullBuf); + return NULL; + } + if (bufSize == 0) { + printf("buf 0\n"); + free(fullBuf); + return NULL; + } + PBYTE smallBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, smallBuf, bufSize, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status); + free(fullBuf); + free(smallBuf); + return NULL; + } + // smallBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // Qx[cbFieldLength] X-coordinate of the public point. + // Qy[cbFieldLength] Y-coordinate of the public point. + // d[cbSubgroupOrder] Private key. + header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + free(smallBuf); + break; + } jbyteArray x_bytes = (*env)->NewByteArray(env, privHeader->cbFieldLength); jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); @@ -484,11 +543,11 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { free(fullBuf); - jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([B[B[B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, privkey_class, ec_priv_init, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); + jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "(I[B[B[B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, privkey_class, ec_priv_init, flag, meta_bytes, header_bytes, x_bytes, y_bytes, priv_bytes, ec_priv_param_spec); } -static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { +static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCWSTR curve) { NTSTATUS status; ULONG bufSize = 0; if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { @@ -525,10 +584,55 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { PBYTE pub_x = &fullBuf[paramLength]; PBYTE pub_y = pub_x + pubHeader->cbFieldLength; - jbyteArray header_bytes = (*env)->NewByteArray(env, paramLength); - jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); - memcpy(header_data, pubHeader, paramLength); - (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + jbyteArray meta_bytes = NULL; + jbyteArray header_bytes = NULL; + switch (flag) { + case 0: { + // meta = curve + jint meta_len = (wcslen(curve) + 1) * sizeof(WCHAR); + meta_bytes = (*env)->NewByteArray(env, meta_len); + jbyte *meta_data = (*env)->GetByteArrayElements(env, meta_bytes, NULL); + memcpy(meta_data, curve, meta_len); + (*env)->ReleaseByteArrayElements(env, meta_bytes, meta_data, 0); + } + case 1: + case 2: { + header_bytes = (*env)->NewByteArray(env, paramLength); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, pubHeader, paramLength); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + break; + } + default: + // header = small + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, length only)\n", status); + free(fullBuf); + return NULL; + } + if (bufSize == 0) { + printf("buf 0\n"); + free(fullBuf); + return NULL; + } + PBYTE smallBuf = calloc(bufSize, 1); + if (NT_FAILURE(status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, smallBuf, bufSize, &bufSize, 0))) { + wprintf(L"**** Error 0x%x returned by BCryptExportKey(small, whole)\n", status); + free(fullBuf); + free(smallBuf); + return NULL; + } + // smallBuf looks like: + // BCRYPT_ECCKEY_BLOB header + // Qx[cbFieldLength] X-coordinate of the public point. + // Qy[cbFieldLength] Y-coordinate of the public point. + header_bytes = (*env)->NewByteArray(env, sizeof(BCRYPT_ECCKEY_BLOB)); + jbyte *header_data = (*env)->GetByteArrayElements(env, header_bytes, NULL); + memcpy(header_data, smallBuf, sizeof(BCRYPT_ECCKEY_BLOB)); + (*env)->ReleaseByteArrayElements(env, header_bytes, header_data, 0); + free(smallBuf); + break; + } jbyteArray x_bytes = (*env)->NewByteArray(env, pubHeader->cbFieldLength); jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL); @@ -542,8 +646,8 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key) { free(fullBuf); - jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([B[B[BLjava/security/spec/ECParameterSpec;)V"); - return (*env)->NewObject(env, pubkey_class, ec_pub_init, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); + jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "(I[B[B[B[BLjava/security/spec/ECParameterSpec;)V"); + return (*env)->NewObject(env, pubkey_class, ec_pub_init, flag, meta_bytes, header_bytes, x_bytes, y_bytes, ec_pub_param_spec); } JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject self, jint keysize, jobject random) { @@ -610,8 +714,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL; } - jobject privkey = key_to_privkey(env, key); - jobject pubkey = key_to_pubkey(env, key); + jobject privkey = key_to_privkey(env, key, KEYFLAG_NIST, NULL); + jobject pubkey = key_to_pubkey(env, key, KEYFLAG_NIST, NULL); jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); @@ -640,7 +744,9 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai } (*env)->ReleaseStringUTFChars(env, type, type_data); - ULONG bits = init_algo(env, &handle, algo, params); + jint keyflag; + NWPSTR curveName; + ULONG bits = init_algo(env, &handle, &keyflag, &curveName, algo, params); if (bits == 0) { throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo."); return NULL; @@ -658,8 +764,12 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL; } - jobject privkey = key_to_privkey(env, key); - jobject pubkey = key_to_pubkey(env, key); + jobject privkey = key_to_privkey(env, key, keyflag, curveName); + jobject pubkey = key_to_pubkey(env, key, keyflag, curveName); + + if (curveName) { + free(curveName); + } jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V"); @@ -668,9 +778,109 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey); } +static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR type, jint keyflag, jbyteArray meta, jobject params) { + LPCWSTR ecdh_algos[] = { + BCRYPT_ECDH_ALGORITHM, + BCRYPT_ECDH_P256_ALGORITHM, + BCRYPT_ECDH_P384_ALGORITHM, + BCRYPT_ECDH_P521_ALGORITHM + }; + LPCWSTR ecdsa_algos[] = { + BCRYPT_ECDSA_ALGORITHM, + BCRYPT_ECDSA_P256_ALGORITHM, + BCRYPT_ECDSA_P384_ALGORITHM, + BCRYPT_ECDSA_P521_ALGORITHM + }; + + LPCWSTR *algos; + LPCWSTR algo; + if (lstrcmpW(type, BCRYPT_ECDH_ALGORITHM) == 0) { + algos = ecdh_algos; + } else if (lstrcmpW(type, BCRYPT_ECDSA_ALGORITHM) == 0) { + algos = ecdsa_algos; + } else { + //unreachable + return STATUS_INVALID_PARAMETER; + } + + switch (keyflag) { + case 0: + case 1: + algo = algos[0]; + break; + case 2: { + jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); + jobject elliptic_curve = (*env)->CallObjectMethod(env, params, 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); + switch (bits) { + case 256: + algo = algos[1]; + break; + case 384: + algo = algos[2]; + break; + case 521: + algo = algos[3]; + break; + default: + return STATUS_INVALID_PARAMETER; + } + break; + } + } + NTSTATUS status; + + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(handle, algo, MS_PRIMITIVE_PROVIDER, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + return status; + } + + switch (keyflag) { + case 0: { + jint meta_len = (*env)->GetArrayLength(env, meta); + jbyte *meta_data = (*env)->GetByteArrayElements(env, meta, NULL); + //if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, meta_data, meta_len, 0))) { + // throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(curve name)\n", status); + // (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT); + // return status; + //} + (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT); + break; + } + case 1: { + PBYTE curve; + ULONG curve_len = create_curve(env, params, &curve); + if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curve_len, 0))) { + throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(parameters)\n", status); + free(curve); + return status; + } + free(curve); + break; + } + } + return STATUS_SUCCESS; +} + +static jint get_keyflag(JNIEnv *env, jobject key) { + jclass key_class = (*env)->GetObjectClass(env, key); + jmethodID get_flag = (*env)->GetMethodID(env, key_class, "getFlag", "()I"); + return (*env)->CallIntMethod(env, key, get_flag); +} + +static jbyteArray get_meta(JNIEnv *env, jobject key) { + jclass key_class = (*env)->GetObjectClass(env, key); + jmethodID get_meta = (*env)->GetMethodID(env, key_class, "getMeta", "()[B"); + return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta); +} + JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { NTSTATUS status; - printf("generateSecret!\n"); jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); jfieldID type_id = (*env)->GetFieldID(env, mscng_ka_class, "type", "Ljava/lang/String;"); @@ -693,9 +903,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey BCRYPT_ALG_HANDLE kaHandle = NULL; - ULONG bits = init_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, params); - if (bits == 0) { - throw_new(env, "java/security/GeneralSecurityException", "Couldn't initialize algo."); + jint pub_flag = get_keyflag(env, pubkey); + jbyteArray meta = get_meta(env, pubkey); + + if (NT_FAILURE(status = init_use_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, pub_flag, meta, params))) { return NULL; } @@ -712,6 +923,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + jint priv_flag = get_keyflag(env, privkey); jint priv_length = (*env)->GetArrayLength(env, privkey); jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { @@ -791,12 +1003,19 @@ static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { return hash_algo; } -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jbyteArray privkey, jobject params) { +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign(JNIEnv *env, jobject self, jbyteArray data, jobject privkey, jobject params) { NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; + jint keyflag = get_keyflag(env, privkey); + jbyteArray meta = get_meta(env, privkey); + + if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) { + return NULL; + } + if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); return NULL; @@ -835,17 +1054,21 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig BCRYPT_KEY_HANDLE skey = NULL; - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + jmethodID get_data = (*env)->GetMethodID(env, privkey_class, "getData", "()[B"); + jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data); + + + jint priv_length = (*env)->GetArrayLength(env, privkey_barray); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL); if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status); BCryptCloseAlgorithmProvider(sigHandle, 0); BCryptCloseAlgorithmProvider(hashHandle, 0); free(hash); - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT); return NULL; } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT); DWORD sig_len = 0; if (NT_FAILURE(status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0))) { @@ -877,14 +1100,16 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig return sig; } -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) { +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify(JNIEnv *env, jobject self, jbyteArray sig, jbyteArray data, jobject pubkey, jobject params) { NTSTATUS status; LPCWSTR hash_algo = get_sighash_algo(env, self); BCRYPT_ALG_HANDLE sigHandle = NULL; - if (NT_FAILURE(status = BCryptOpenAlgorithmProvider(&sigHandle, BCRYPT_ECDSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0))) { - throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + jint keyflag = get_keyflag(env, pubkey); + jbyteArray meta = get_meta(env, pubkey); + + if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) { return JNI_FALSE; } @@ -921,17 +1146,21 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna BCRYPT_KEY_HANDLE pkey = NULL; - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + jmethodID get_data = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B"); + jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data); + + + jint pub_length = (*env)->GetArrayLength(env, pubkey_barray); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL); if (NT_FAILURE(status = BCryptImportKeyPair(sigHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair\n", status); BCryptCloseAlgorithmProvider(sigHandle, 0); BCryptCloseAlgorithmProvider(hashHandle, 0); free(hash); - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT); return JNI_FALSE; } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT); jint sig_len = (*env)->GetArrayLength(env, sig); jbyte *sig_data = (*env)->GetByteArrayElements(env, sig, NULL); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h index a2dedae..e8dff88 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -35,7 +35,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getC extern "C" { #endif #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS @@ -45,9 +45,9 @@ extern "C" { #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739i64 /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt * Method: setup @@ -206,7 +206,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurv extern "C" { #endif #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS @@ -216,9 +216,9 @@ extern "C" { #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739i64 /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan * Method: setup @@ -377,7 +377,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getC extern "C" { #endif #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE 2147483639L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS @@ -387,9 +387,9 @@ extern "C" { #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES 2L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739i64 /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp * Method: setup @@ -548,7 +548,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCu extern "C" { #endif #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE 2147483639L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS @@ -558,9 +558,9 @@ extern "C" { #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES 2L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739i64 /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl * Method: setup @@ -719,7 +719,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurv extern "C" { #endif #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS @@ -729,9 +729,9 @@ extern "C" { #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES #define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840i64 #undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739LL +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739i64 /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng * Method: setup @@ -838,18 +838,18 @@ extern "C" { /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + * Signature: ([BLjava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + (JNIEnv *, jobject, jbyteArray, jobject, jobject); /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + * Signature: ([B[BLjava/security/interfaces/ECPublicKey;Ljava/security/spec/ECParameterSpec;)Z */ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jobject); #ifdef __cplusplus } -- cgit v1.3.1 From 25cb7f41a871b890a194ff4ccdf6230c4bc22a99 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 29 Jul 2018 14:00:55 +0200 Subject: Try to fix ECDH with KDF loading. --- .../ectester/standalone/libs/jni/NativeKeyAgreementSpi.java | 12 ++++++++++++ src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java | 10 +++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index 31886cf..aa053bf 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -20,6 +20,10 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { ECPublicKey publicKey; ECParameterSpec params; + public NativeKeyAgreementSpi() { + + } + @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { if (!(key instanceof ECPrivateKey)) { @@ -77,6 +81,10 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi { + public SimpleKeyAgreementSpi() { + + } + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { byte[] pubkey; @@ -99,6 +107,10 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { + public ExtendedKeyAgreementSpi() { + + } + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { return generateSecret(publicKey, privateKey, params); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java index f580d74..fef2930 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java @@ -12,10 +12,14 @@ public abstract class NativeProvider extends Provider { public NativeProvider(String name, double version, String info) { super(name, version, info); - AccessController.doPrivileged((PrivilegedAction) () -> { + if (System.getSecurityManager() == null) { setup(); - return null; - }); + } else { + AccessController.doPrivileged((PrivilegedAction) () -> { + setup(); + return null; + }); + } } abstract void setup(); -- cgit v1.3.1 From 7e7d2d3bb67750702d5476fc9e05b31015cec7fc Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 29 Jul 2018 13:54:13 +0200 Subject: Fix Mscng ECDH. --- build-standalone.xml | 8 + nbproject/keystore | Bin 0 -> 3987 bytes .../crcs/ectester/standalone/libs/jni/Makefile.bat | 2 +- .../standalone/libs/jni/NativeKeyAgreementSpi.java | 16 +- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 20 +- src/cz/crcs/ectester/standalone/libs/jni/native.h | 1714 ++++++++++---------- 6 files changed, 874 insertions(+), 886 deletions(-) create mode 100755 nbproject/keystore (limited to 'src') diff --git a/build-standalone.xml b/build-standalone.xml index fc135a0..685f791 100644 --- a/build-standalone.xml +++ b/build-standalone.xml @@ -80,6 +80,14 @@ + + + + + + + + diff --git a/nbproject/keystore b/nbproject/keystore new file mode 100755 index 0000000..7c9c8e4 Binary files /dev/null and b/nbproject/keystore differ diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index e337e70..3530fe9 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -9,7 +9,7 @@ setlocal EnableDelayedExpansion :: See if we are cleaning. if "%1" == "clean" ( echo ** cleaning - del mscng_provider.dll + del *.dll *.exp *.lib *.obj exit ) diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index aa053bf..c11c803 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -20,10 +20,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { ECPublicKey publicKey; ECParameterSpec params; - public NativeKeyAgreementSpi() { - - } - @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { if (!(key instanceof ECPrivateKey)) { @@ -81,10 +77,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi { - public SimpleKeyAgreementSpi() { - - } - @Override protected byte[] engineGenerateSecret() throws IllegalStateException { byte[] pubkey; @@ -107,10 +99,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { - public ExtendedKeyAgreementSpi() { - - } - @Override protected byte[] engineGenerateSecret() throws IllegalStateException { return generateSecret(publicKey, privateKey, params); @@ -207,7 +195,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } } - public abstract static class Mscng extends SimpleKeyAgreementSpi { + public abstract static class Mscng extends ExtendedKeyAgreementSpi { private String type; public Mscng(String type) { @@ -215,7 +203,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } @Override - native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); + native byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, ECParameterSpec params); } public static class MscngECDHwithSHA1KDF extends Mscng { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 8cd96fc..a284901 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -125,15 +125,6 @@ static const named_curve_t* lookup_curve(const char *name) { return NULL; } -static const named_curve_t* lookup_curve_bits(jint bitsize) { - for (size_t i = 0; i < sizeof(named_curves) / sizeof(named_curve_t); ++i) { - if (bitsize == named_curves[i].bits) { - return &named_curves[i]; - } - } - return NULL; -} - static ULONG utf_16to8(NPSTR *out_buf, LPCWSTR in_str) { INT result = WideCharToMultiByte(CP_UTF8, 0, in_str, -1, NULL, 0, NULL, NULL); *out_buf = calloc(result, 1); @@ -146,8 +137,10 @@ static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) { return MultiByteToWideChar(CP_UTF8, 0, in_str, -1, *out_buf, result); } -// Convert Java String to UTF-16 NWPSTR null-terminated. -// Returns: Length of NWPSTR in bytes! +/** + * Convert Java String to UTF-16 NWPSTR null-terminated. + * Returns: Length of NWPSTR in bytes! + */ static ULONG utf_strto16(NWPSTR *out_buf, JNIEnv *env, jobject str) { jsize len = (*env)->GetStringLength(env, str); *out_buf = calloc(len * sizeof(jchar) + 1, 1); @@ -333,7 +326,7 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { jint bits = (*env)->CallIntMethod(env, field, get_bits); jint bytes = (bits + 7) / 8; - jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); + jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;"); jobject a = (*env)->CallObjectMethod(env, elliptic_curve, get_a); jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;"); @@ -879,7 +872,7 @@ static jbyteArray get_meta(JNIEnv *env, jobject key) { return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta); } -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jbyteArray pubkey, jbyteArray privkey, jobject params) { +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params) { NTSTATUS status; jclass mscng_ka_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi$Mscng"); @@ -973,7 +966,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey (*env)->ReleaseByteArrayElements(env, result, result_data, 0); free(derived); - BCryptDestroyKey(pkey); BCryptDestroyKey(skey); BCryptDestroySecret(ka); diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h index e8dff88..b5cde43 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -1,857 +1,857 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib -#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_TomcryptLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider - (JNIEnv *, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_TomcryptLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739i64 -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2 - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib -#define _Included_cz_crcs_ectester_standalone_libs_BotanLib -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_BotanLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider - (JNIEnv *, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_BotanLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739i64 -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: generate - * 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 *, jobject, jint, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan - * Method: generate - * 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 *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_CryptoppLib */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_CryptoppLib -#define _Included_cz_crcs_ectester_standalone_libs_CryptoppLib -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_CryptoppLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider - (JNIEnv *, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_CryptoppLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739i64 -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2 - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp - * Method: sign - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_sign - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp - * Method: verify - * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_OpensslLib */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_OpensslLib -#define _Included_cz_crcs_ectester_standalone_libs_OpensslLib -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_OpensslLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider - (JNIEnv *, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_OpensslLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739i64 -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2 - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#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 -/* Header for class cz_crcs_ectester_standalone_libs_MscngLib */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_MscngLib -#define _Included_cz_crcs_ectester_standalone_libs_MscngLib -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_MscngLib - * Method: createProvider - * Signature: ()Ljava/security/Provider; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider - (JNIEnv *, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_MscngLib - * Method: getCurves - * Signature: ()Ljava/util/Set; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng -#ifdef __cplusplus -extern "C" { -#endif -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS 0L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES 1L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840i64 -#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739i64 -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng - * Method: setup - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng - * Method: keysizeSupported - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported - (JNIEnv *, jobject, jint); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng - * Method: paramsSupported - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported - (JNIEnv *, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng - * Method: generate - * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2 - (JNIEnv *, jobject, jint, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng - * Method: generate - * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; - */ -JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng - * Method: generateSecret - * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng */ - -#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng -#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng - * Method: sign - * Signature: ([BLjava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B - */ -JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign - (JNIEnv *, jobject, jbyteArray, jobject, jobject); - -/* - * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng - * Method: verify - * Signature: ([B[BLjava/security/interfaces/ECPublicKey;Ljava/security/spec/ECParameterSpec;)Z - */ -JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify - (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class cz_crcs_ectester_standalone_libs_TomcryptLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_TomcryptLib +#define _Included_cz_crcs_ectester_standalone_libs_TomcryptLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_TomcryptLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 1421746759512286392i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID 4112578634029874840i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt_serialVersionUID -4298000515446427739i64 +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_TomCrypt + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024TomCrypt_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_TomCrypt + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_TomCrypt +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_TomCrypt +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_TomCrypt + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw + * Method: sign + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_BotanLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_BotanLib +#define _Included_cz_crcs_ectester_standalone_libs_BotanLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_BotanLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_BotanLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_BotanLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 1421746759512286392i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID 4112578634029874840i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan_serialVersionUID -4298000515446427739i64 +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Botan + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Botan_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Botan_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan + * Method: generate + * 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 *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Botan + * Method: generate + * 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 *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Botan +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Botan +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Botan + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Botan_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan + * Method: sign + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Botan + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Botan_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_CryptoppLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_CryptoppLib +#define _Included_cz_crcs_ectester_standalone_libs_CryptoppLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_CryptoppLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_CryptoppLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 1421746759512286392i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID 4112578634029874840i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp_serialVersionUID -4298000515446427739i64 +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Cryptopp + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Cryptopp_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Cryptopp + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Cryptopp_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Cryptopp + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Cryptopp_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp + * Method: sign + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_sign + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Cryptopp + * Method: verify + * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Cryptopp_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_OpensslLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_OpensslLib +#define _Included_cz_crcs_ectester_standalone_libs_OpensslLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_OpensslLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_OpensslLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 1421746759512286392i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID 4112578634029874840i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl_serialVersionUID -4298000515446427739i64 +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Openssl + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Openssl_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Openssl + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Openssl_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Openssl +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Openssl + * Method: generateSecret + * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Openssl_generateSecret + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject); + +#ifdef __cplusplus +} +#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 +/* Header for class cz_crcs_ectester_standalone_libs_MscngLib */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_MscngLib +#define _Included_cz_crcs_ectester_standalone_libs_MscngLib +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_MscngLib + * Method: createProvider + * Signature: ()Ljava/security/Provider; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider + (JNIEnv *, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_MscngLib + * Method: getCurves + * Signature: ()Ljava/util/Set; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurves + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 1421746759512286392i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_MAX_ARRAY_SIZE 2147483639L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_KEYS 0L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_VALUES 1L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_ENTRIES 2L +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID 4112578634029874840i64 +#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID +#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng_serialVersionUID -4298000515446427739i64 +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Mscng + * Method: setup + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Mscng_setup + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: keysizeSupported + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported + (JNIEnv *, jobject, jint); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: paramsSupported + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_paramsSupported + (JNIEnv *, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: generate + * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__ILjava_security_SecureRandom_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Mscng + * Method: generate + * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair; + */ +JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2 + (JNIEnv *, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Mscng +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng + * Method: generateSecret + * Signature: (Ljava/security/interfaces/ECPublicKey;Ljava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret + (JNIEnv *, jobject, jobject, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng */ + +#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng +#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng + * Method: sign + * Signature: ([BLjava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_sign + (JNIEnv *, jobject, jbyteArray, jobject, jobject); + +/* + * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Mscng + * Method: verify + * Signature: ([B[BLjava/security/interfaces/ECPublicKey;Ljava/security/spec/ECParameterSpec;)Z + */ +JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Mscng_verify + (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif -- cgit v1.3.1 From 8d21a87b25550215a4c59ff4ef8d32e2f0736b3f Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 29 Jul 2018 14:07:04 +0200 Subject: Update docs on Standalone testing. --- README.md | 78 ++++++++++++++-------- .../ectester/standalone/ECTesterStandalone.java | 2 +- 2 files changed, 53 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 7121027..b18ebbd 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,11 @@ For more information on ECC libraries see [LIBS](docs/LIBS.md). ### Setup +OpenJDK JRE is required to test ECDH on Windows properly, as Oracle JRE requires the Java Cryptography Providers +for certain classes (such as a [KeyAgreement](https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyAgreement.html)) +to be signed by keys that are signed by their JCA Code Signing Authority. ECTester internally uses Java Cryptography Provider +API to expose and test native libraries. OpenJDK for Windows can be obtained from [ojdkbuild/ojdkbuild](https://github.com/ojdkbuild/ojdkbuild). + Installing the Java Cryptography Extension Unlimited Strength policy files is necessary to do testing with quite a lot of practical key sizes, they are available for download: @@ -243,49 +248,70 @@ To install, place them in `${java.home}/jre/lib/security/`. ### Options ``` -usage: ECTesterStandalone.jar [-V] [-h] [ (ecdh [-t ] [-n ] [-b ] [-nc ]) | -(ecdsa [-t ] [-n ] [-b ] [-nc ] [-f ]) | -(export [-t ] [-b ]) | (generate [-nc ] [-n ] [-t -] [-b ]) | (list-data [what]) | (list-libs) | (test [-gt ] -[-kt ] [-st ] [-b ] [-nc ]) ] [lib] - - -V,--version Print version info. - -h,--help Print help. - [lib] What library to use. - - ecdh: +usage: ECTesterStandalone.jar [-V] [-h] [-C] + [ (ecdh [-b ] [-nc ] [-cn ] [-t ] [--key-type ] [-n ]) | + (ecdsa [-b ] [-nc ] [-cn ] [-t ] [-n ] [-f ]) | + (export [-b ] [-t ]) | + (generate [-b ] [-nc ] [-cn ] [-n ] [-t ]) | + (list-data [what]) | + (list-libs) | + (list-suites) | + (test [-b ] [-nc ] [-cn ] [-gt ] [-kt ] [-st ] [-f ] [--key-type ] + ) ] + [lib] + + ecdh: | Perform EC based KeyAgreement. | + -b,--bits What size of curve to use. + -nc,--named-curve Use a named curve, from CurveDB: + -cn,--curve-name Use a named curve, search from curves + supported by the library: -t,--type Set KeyAgreement object [type]. + --key-type Set the key [algorithm] for which the key + should be derived in KeyAgreements with + KDF. Default is "AES". -n,--amount Do ECDH [amount] times. + + ecdsa: | Perform EC based Signature. | -b,--bits What size of curve to use. -nc,--named-curve Use a named curve, from CurveDB: - - ecdsa: + -cn,--curve-name Use a named curve, search from curves + supported by the library: -t,--type Set Signature object [type]. -n,--amount Do ECDSA [amount] times. - -b,--bits What size of curve to use. - -nc,--named-curve Use a named curve, from CurveDB: -f,--file Input [file] to sign. - export: - -t,--type Set KeyPair object [type]. - -b,--bits What size of curve to use. + export: | Export default curve parameters. | + -b,--bits What size of curve to use. + -t,--type Set KeyPair object [type]. - generate: + generate: | Generate EC keypairs. | + -b,--bits What size of curve to use. -nc,--named-curve Use a named curve, from CurveDB: + -cn,--curve-name Use a named curve, search from curves + supported by the library: -n,--amount Generate [amount] of EC keys. -t,--type Set KeyPairGenerator object [type]. - -b,--bits What size of curve to use. - list-data: - [what] what to list. + list-data: | List/show contained EC domain parameters/keys. | + [what] what to list. + + list-libs: | List supported libraries. | - list-libs: + list-suites: | List supported test suites. | - test: + test: | Test a library. | + -b,--bits What size of curve to use. + -nc,--named-curve Use a named curve, from CurveDB: + -cn,--curve-name Use a named curve, search from curves + supported by the library: -gt,--kpg-type Set the KeyPairGenerator object [type]. -kt,--ka-type Set the KeyAgreement object [type]. -st,--sig-type Set the Signature object [type]. - -b,--bits What size of curve to use. - -nc,--named-curve Use a named curve, from CurveDB: + -f,--format Set the output format, one of + text,yaml,xml. + --key-type Set the key [algorithm] for which the key + should be derived in KeyAgreements with + KDF. Default is "AES". + The test suite to run. ``` diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java index 2f132fa..31d291c 100644 --- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java +++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java @@ -180,8 +180,8 @@ public class ECTesterStandalone { actions.put("generate", generate); Options exportOpts = new Options(); - exportOpts.addOption(Option.builder("t").longOpt("type").hasArg().argName("type").optionalArg(false).desc("Set KeyPair object [type].").build()); exportOpts.addOption(bits); + 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); -- cgit v1.3.1 From 21ecc7501145b5e9b239dd5a62ccbefdcaa3a160 Mon Sep 17 00:00:00 2001 From: J08nY Date: Sun, 29 Jul 2018 17:21:04 +0200 Subject: Somewhat finished Mscng implementation. --- .gitignore | 1 + README.md | 6 +- .../crcs/ectester/standalone/libs/jni/Makefile.bat | 46 ++++++++----- .../standalone/libs/jni/NativeKeyAgreementSpi.java | 42 +++++++----- src/cz/crcs/ectester/standalone/libs/jni/mscng.c | 78 ++++++++++++++++------ src/cz/crcs/ectester/standalone/libs/jni/native.h | 2 +- 6 files changed, 118 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index f40221d..8f7585a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ /src/**/*.dll /src/**/*.exp /src/**/*.lib +/src/**/*.pdb diff --git a/README.md b/README.md index b18ebbd..2b331ff 100644 --- a/README.md +++ b/README.md @@ -239,9 +239,9 @@ API to expose and test native libraries. OpenJDK for Windows can be obtained fro Installing the Java Cryptography Extension Unlimited Strength policy files is necessary to do testing with quite a lot of practical key sizes, they are available for download: - * [Java 6](http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html) - * [Java 7](http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html) - * [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) + - [Java 6](http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html) + - [Java 7](http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html) + - [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) To install, place them in `${java.home}/jre/lib/security/`. diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index 3530fe9..9b0d6f7 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -5,6 +5,7 @@ setlocal EnableDelayedExpansion :: - JAVA_HOME :: - CC :: - USE_EXT_MSCNG +:: - DEBUG :: See if we are cleaning. if "%1" == "clean" ( @@ -13,11 +14,13 @@ if "%1" == "clean" ( exit ) +set TAB= + :: Determine arch. -reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && (set ARCH=32& set ARCH_S=x86& set ARCH_VS=x86) || (set ARCH=64& set ARCH_S=x64& set ARCH_VS=amd64) +reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL 2>&1 && (set ARCH=32& set ARCH_S=x86& set ARCH_VS=x86) || (set ARCH=64& set ARCH_S=x64& set ARCH_VS=amd64) -echo ** ARCH %ARCH_S% +echo ** ARCH%TAB%%TAB%%ARCH_S% :: Find a working visual studio environment. @@ -27,7 +30,7 @@ set vsw_path="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" set vs_path= for /f "usebackq delims=" %%i in (`%vsw_path% -nologo -prerelease -latest -property installationPath`) do ( if exist "%%i\Common7\Tools\vsdevcmd.bat" ( - echo ** VsDevCmd at %%i\Common7\Tools\vsdevcmd.bat + echo ** VsDevCmd%TAB%%TAB%%%i\Common7\Tools\vsdevcmd.bat call "%%i\Common7\Tools\vsdevcmd.bat" -no_logo -arch=%ARCH_VS% if ERRORLEVEL 1 ( echo nope. @@ -45,7 +48,7 @@ if %found% EQU 0 ( exit /b 2 ) -echo ** VS_PATH %vs_path% +echo ** VS_PATH%TAB%%TAB%%vs_path% :: Try to find vcruntime. @@ -55,7 +58,7 @@ if exist %vc_base% ( for /f "delims=" %%i in ('dir /b /on "!vc_base!"') do ( set vc_version=%%i ) - echo ** VC_VERSION !vc_version! + echo ** VC_VERSION%TAB%!vc_version! set vc_include=%vc_base%!vc_version!\include set vc_lib=%vc_base%!vc_version!\lib\%ARCH_S% ) @@ -77,8 +80,8 @@ popd set mscng_lib_arch=%mscng_lib%\X%ARCH% -echo ** CNG_INCLUDE !mscng_include! -echo ** CNG_LIB !mscng_lib! +echo ** CNG_INCLUDE%TAB%%mscng_include% +echo ** CNG_LIB%TAB%%TAB%%mscng_lib_arch% :: Get the paths to Java JNI. @@ -92,7 +95,7 @@ if not defined JAVA_HOME ( popd ) -echo ** JAVA_HOME !JAVA_HOME! +echo ** JAVA_HOME%TAB%%JAVA_HOME% set JNI_INCLUDEDIR=%JAVA_HOME%\include set JNI_PLATFORMINCLUDEDIR=%JNI_INCLUDEDIR%\win32 @@ -104,7 +107,7 @@ if not defined CC ( set CC=cl.exe ) -echo ** CC !CC! +echo ** CC%TAB%%TAB%%CC% :: Try to find uCRT. @@ -114,7 +117,7 @@ if exist %ucrt_base% ( for /f "delims=" %%i in ('dir /b /on "!ucrt_base!\Include"') do ( set ucrt_version=%%i ) - echo ** uCRT !ucrt_version! + echo ** uCRT%TAB%%TAB%!ucrt_version! set ucrt_include=%ucrt_base%Include\!ucrt_version!\ucrt set ucrt_lib=%ucrt_base%Lib\!ucrt_version! set ucrt_lib_arch=!ucrt_lib!\ucrt\%ARCH_S% @@ -128,8 +131,8 @@ if defined USE_EXT_MSCNG ( set INCLUDE_CLI=!INCLUDE_CLI! /I"%mscng_include%" ) -echo ** INCLUDE %INCLUDE% -echo ** INCLUDE_CLI %INCLUDE_CLI% +echo ** INCLUDE%TAB%%TAB%%INCLUDE% +echo ** INCLUDE_CLI%TAB%%INCLUDE_CLI% :: Setup LIB paths. @@ -139,9 +142,22 @@ if defined USE_EXT_MSCNG ( set LIBPATH=!LIBPATH! /LIBPATH:"%mscng_lib_arch%" ) -echo ** LIB %LIB% -echo ** LIBPATH %LIBPATH% +echo ** LIB%TAB%%TAB%%LIB% +echo ** LIBPATH%TAB%%TAB%%LIBPATH% + + +:: Setup DEBUB options. +set OTHER_CLI= +if defined DEBUG ( + set OTHER_CLI=/Od /Z7 +) else ( + set OTHER_CLI=/O2 +) + +echo ** OTHER_CLI%TAB%%OTHER_CLI% echo. +echo ^>^> %CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo +echo. -%CC% /EHsc %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% \ No newline at end of file +%CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c bcrypt.lib jvm.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo \ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java index c11c803..4ed3469 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java +++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java @@ -11,6 +11,7 @@ import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECParameterSpec; +import java.security.spec.ECGenParameterSpec; /** * @author Jan Jancar johny@neuromancer.sk @@ -18,7 +19,7 @@ import java.security.spec.ECParameterSpec; public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { ECPrivateKey privateKey; ECPublicKey publicKey; - ECParameterSpec params; + AlgorithmParameterSpec params; @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { @@ -30,15 +31,6 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { this.params = privateKey.getParams(); } - @Override - protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - if (!(params instanceof ECParameterSpec)) { - throw new InvalidAlgorithmParameterException(); - } - engineInit(key, random); - this.params = (ECParameterSpec) params; - } - @Override protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException { if (privateKey == null) { @@ -71,27 +63,36 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { @Override protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { - // TODO: This is dangerous/not correct ! Need to actually implement KDF1 and KDF2 here probably. + // TODO: This is dangerous/not correct ! Need to actually implement KDF1 and KDF2 here probably. Or just pass it off to the libs through some different interface. return new SecretKeySpec(engineGenerateSecret(), algorithm); } private abstract static class SimpleKeyAgreementSpi extends NativeKeyAgreementSpi { + @Override + protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + if (!(params instanceof ECParameterSpec)) { + throw new InvalidAlgorithmParameterException(); + } + engineInit(key, random); + this.params = params; + } + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { byte[] pubkey; if (publicKey instanceof NativeECPublicKey) { pubkey = ((NativeECPublicKey) publicKey).getData(); } else { - pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve()); + pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), ((ECParameterSpec) params).getCurve()); } byte[] privkey; if (privateKey instanceof NativeECPrivateKey) { privkey = ((NativeECPrivateKey) privateKey).getData(); } else { - privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize()); + privkey = ECUtil.toByteArray(privateKey.getS(), ((ECParameterSpec) params).getCurve().getField().getFieldSize()); } - return generateSecret(pubkey, privkey, params); + return generateSecret(pubkey, privkey, (ECParameterSpec) params); } abstract byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params); @@ -99,12 +100,21 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { private abstract static class ExtendedKeyAgreementSpi extends NativeKeyAgreementSpi { + @Override + protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + if (!(params instanceof ECParameterSpec || params instanceof ECGenParameterSpec)) { + throw new InvalidAlgorithmParameterException(); + } + engineInit(key, random); + this.params = params; + } + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { return generateSecret(publicKey, privateKey, params); } - abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, ECParameterSpec params); + abstract byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params); } @@ -203,7 +213,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi { } @Override - native byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, ECParameterSpec params); + native byte[] generateSecret(ECPublicKey pubkey, ECPrivateKey privkey, AlgorithmParameterSpec params); } public static class MscngECDHwithSHA1KDF extends Mscng { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index a284901..16736d7 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -28,9 +28,10 @@ typedef struct { //Provider things static jclass provider_class; -#define KEYFLAG_IMPLICIT 0 -#define KEYFLAG_EXPLICIT 1 -#define KEYFLAG_NIST 2 +#define KEYFLAG_IMPLICIT 0 //Mscng native key, over named curve +#define KEYFLAG_EXPLICIT 1 //Mscng native key, over explicit ecc parameters +#define KEYFLAG_NIST 2 //Mscng native key, over NIST parameters, custom ECDH/ECDSA_P* algo +#define KEYFLAG_OTHER 3 //Other key, explicit ecc parameters JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_createProvider(JNIEnv *env, jobject self) { jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Mscng"); @@ -797,11 +798,12 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty } switch (keyflag) { - case 0: - case 1: + case KEYFLAG_IMPLICIT: + case KEYFLAG_EXPLICIT: + case KEYFLAG_OTHER: algo = algos[0]; break; - case 2: { + case KEYFLAG_NIST: { jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;"); jobject elliptic_curve = (*env)->CallObjectMethod(env, params, get_curve); @@ -834,7 +836,7 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty } switch (keyflag) { - case 0: { + case KEYFLAG_IMPLICIT: { jint meta_len = (*env)->GetArrayLength(env, meta); jbyte *meta_data = (*env)->GetByteArrayElements(env, meta, NULL); //if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_CURVE_NAME, meta_data, meta_len, 0))) { @@ -845,7 +847,8 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty (*env)->ReleaseByteArrayElements(env, meta, meta_data, JNI_ABORT); break; } - case 1: { + case KEYFLAG_EXPLICIT: + case KEYFLAG_OTHER: { PBYTE curve; ULONG curve_len = create_curve(env, params, &curve); if (NT_FAILURE(status = BCryptSetProperty(*handle, BCRYPT_ECC_PARAMETERS, curve, curve_len, 0))) { @@ -861,15 +864,23 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty } static jint get_keyflag(JNIEnv *env, jobject key) { - jclass key_class = (*env)->GetObjectClass(env, key); - jmethodID get_flag = (*env)->GetMethodID(env, key_class, "getFlag", "()I"); - return (*env)->CallIntMethod(env, key, get_flag); + if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) { + jclass key_class = (*env)->GetObjectClass(env, key); + jmethodID get_flag = (*env)->GetMethodID(env, key_class, "getFlag", "()I"); + return (*env)->CallIntMethod(env, key, get_flag); + } else { + return KEYFLAG_OTHER; + } } static jbyteArray get_meta(JNIEnv *env, jobject key) { - jclass key_class = (*env)->GetObjectClass(env, key); - jmethodID get_meta = (*env)->GetMethodID(env, key_class, "getMeta", "()[B"); - return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta); + if ((*env)->IsInstanceOf(env, key, pubkey_class) || (*env)->IsInstanceOf(env, key, privkey_class)) { + jclass key_class = (*env)->GetObjectClass(env, key); + jmethodID get_meta = (*env)->GetMethodID(env, key_class, "getMeta", "()[B"); + return (jbyteArray)(*env)->CallObjectMethod(env, key, get_meta); + } else { + return NULL; + } } JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params) { @@ -897,6 +908,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey BCRYPT_ALG_HANDLE kaHandle = NULL; jint pub_flag = get_keyflag(env, pubkey); + if (pub_flag == KEYFLAG_OTHER) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key."); + return NULL; + } jbyteArray meta = get_meta(env, pubkey); if (NT_FAILURE(status = init_use_algo(env, &kaHandle, BCRYPT_ECDH_ALGORITHM, pub_flag, meta, params))) { @@ -906,27 +921,38 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey BCRYPT_KEY_HANDLE pkey = NULL; BCRYPT_KEY_HANDLE skey = NULL; - jint pub_length = (*env)->GetArrayLength(env, pubkey); - jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL); + jmethodID get_data_priv = (*env)->GetMethodID(env, pubkey_class, "getData", "()[B"); + jbyteArray pubkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, pubkey, get_data_priv); + + jint pub_length = (*env)->GetArrayLength(env, pubkey_barray); + jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey_barray, NULL); if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPUBLIC_BLOB, &pkey, pub_data, pub_length, 0))) { throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(pub)\n", status); BCryptCloseAlgorithmProvider(kaHandle, 0); - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT); return NULL; } - (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, pubkey_barray, pub_data, JNI_ABORT); jint priv_flag = get_keyflag(env, privkey); - jint priv_length = (*env)->GetArrayLength(env, privkey); - jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL); + if (priv_flag == KEYFLAG_OTHER) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key."); + return NULL; + } + + jmethodID get_data_pub = (*env)->GetMethodID(env, privkey_class, "getData", "()[B"); + jbyteArray privkey_barray = (jbyteArray)(*env)->CallObjectMethod(env, privkey, get_data_pub); + + jint priv_length = (*env)->GetArrayLength(env, privkey_barray); + jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey_barray, NULL); if (NT_FAILURE(status = BCryptImportKeyPair(kaHandle, NULL, BCRYPT_ECCFULLPRIVATE_BLOB, &skey, priv_data, priv_length, 0))) { throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptImportKeyPair(priv)\n", status); BCryptCloseAlgorithmProvider(kaHandle, 0); BCryptDestroyKey(pkey); - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT); return NULL; } - (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, privkey_barray, priv_data, JNI_ABORT); BCRYPT_SECRET_HANDLE ka = NULL; @@ -1002,6 +1028,10 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig BCRYPT_ALG_HANDLE sigHandle = NULL; jint keyflag = get_keyflag(env, privkey); + if (keyflag == KEYFLAG_OTHER) { + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native private key."); + return NULL; + } jbyteArray meta = get_meta(env, privkey); if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) { @@ -1099,6 +1129,10 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna BCRYPT_ALG_HANDLE sigHandle = NULL; jint keyflag = get_keyflag(env, pubkey); + if (keyflag == KEYFLAG_OTHER) { // TODO: This is not necessary + throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key."); + return JNI_FALSE; + } jbyteArray meta = get_meta(env, pubkey); if (NT_FAILURE(status = init_use_algo(env, &sigHandle, BCRYPT_ECDSA_ALGORITHM, keyflag, meta, params))) { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h index b5cde43..dcdaa1b 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/native.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h @@ -819,7 +819,7 @@ extern "C" { /* * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Mscng * Method: generateSecret - * Signature: (Ljava/security/interfaces/ECPublicKey;Ljava/security/interfaces/ECPrivateKey;Ljava/security/spec/ECParameterSpec;)[B + * Signature: (Ljava/security/interfaces/ECPublicKey;Ljava/security/interfaces/ECPrivateKey;Ljava/security/spec/AlgorithmParameterSpec;)[B */ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret (JNIEnv *, jobject, jobject, jobject, jobject); -- cgit v1.3.1