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(-) 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.2.3-70-g09d2