summaryrefslogtreecommitdiff
path: root/src/cz
diff options
context:
space:
mode:
authorJ08nY2018-07-24 22:46:49 +0200
committerJ08nY2018-07-25 21:52:29 +0200
commit713b14add9496ae5b3df5bb51b02d449f4ca0cef (patch)
tree0aaf253c03792ed80c1740002f4be73212302eb6 /src/cz
parent2e91b252aa7ce4400c0fb6b586e78216717147e5 (diff)
downloadECTester-713b14add9496ae5b3df5bb51b02d449f4ca0cef.tar.gz
ECTester-713b14add9496ae5b3df5bb51b02d449f4ca0cef.tar.zst
ECTester-713b14add9496ae5b3df5bb51b02d449f4ca0cef.zip
Diffstat (limited to 'src/cz')
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java2
-rw-r--r--src/cz/crcs/ectester/standalone/libs/MscngLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/Makefile5
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java6
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java7
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java40
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java10
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/mscng.c324
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h125
9 files changed, 535 insertions, 4 deletions
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<String> 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 <windows.h>
+#include <bcrypt.h>
+
+#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, "<init>", "(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, "<init>", "()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, "<init>", "(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, "<init>", "(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, "<init>", "(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, "<init>", "(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, "<init>", "(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, &paramsSize, 0))) {
+ //err
+ }
+ if (paramsSize == 0) {
+ //TODO: what now?
+ }
+
+ BYTE params[paramsSize];
+ if (NT_FAILURE(BCryptGetProperty(kaHandle, BCRYPT_ECC_PARAMETERS, params, paramsSize, &paramsSize, 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, "<init>", "([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, "<init>", "([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, "<init>", "(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