diff options
| author | J08nY | 2019-07-11 22:14:55 +0200 |
|---|---|---|
| committer | J08nY | 2019-07-11 22:14:55 +0200 |
| commit | 46c0a874e494d2311148700058f61b5d8d426f3c (patch) | |
| tree | 31e80bf96cd168adb9f3cce40a9c0d8d1193a105 /src | |
| parent | f57fc9e3f61cf108016c10558f102f52728f1d3a (diff) | |
| download | ECTester-46c0a874e494d2311148700058f61b5d8d426f3c.tar.gz ECTester-46c0a874e494d2311148700058f61b5d8d426f3c.tar.zst ECTester-46c0a874e494d2311148700058f61b5d8d426f3c.zip | |
Diffstat (limited to 'src')
4 files changed, 245 insertions, 147 deletions
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat index 9b0d6f7..a5fe78e 100755 --- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat +++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile.bat @@ -157,7 +157,7 @@ if defined DEBUG ( 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% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c c_timing.c bcrypt.lib jvm.lib kernel32.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo
echo.
-%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 +%CC% /W2 /EHsc %OTHER_CLI% %INCLUDE_CLI% mscng.c c_utils.c c_timing.c bcrypt.lib jvm.lib kernel32.lib /Femscng_provider.dll /LD /link %LIBPATH% /nologo
\ No newline at end of file diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c index 81c30ec..a6ffc7e 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c @@ -1,8 +1,10 @@ #include "c_timing.h" -#include <time.h> #if _POSIX_TIMERS > 0 +#include <time.h> + + static struct timespec start = {0}; static struct timespec end = {0}; static jlong partial = 0; @@ -44,6 +46,51 @@ jlong native_timing_last() { } } +#elif defined(__WIN32__) || defined(_MSC_VER) + +#include <Windows.h> + +static LARGE_INTEGER start = {0}; +static LARGE_INTEGER end = {0}; +static jlong partial = 0; + +jboolean native_timing_supported() { + return JNI_TRUE; +} + +jlong native_timing_resolution() { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return 1000000000 / freq.QuadPart; +} + +void native_timing_start() { + partial = 0; + QueryPerformanceCounter(&start); +} + +void native_timing_pause() { + QueryPerformanceCounter(&end); + partial = (end.QuadPart - start.QuadPart) * native_timing_resolution(); +} + +void native_timing_restart() { + QueryPerformanceCounter(&start); +} + +void native_timing_stop() { + QueryPerformanceCounter(&end); +} + +jlong native_timing_last() { + jlong res = (end.QuadPart - start.QuadPart) * native_timing_resolution() + partial; + if (res < 0) { + return 0; + } else { + return res; + } +} + #else jboolean native_timing_supported() { diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h index ae650d7..3325c06 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h +++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h @@ -1,7 +1,6 @@ #pragma once #include <jni.h> -#include <unistd.h> #ifdef __cplusplus extern "C" diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c index 568e924..2b38860 100644 --- a/src/cz/crcs/ectester/standalone/libs/jni/mscng.c +++ b/src/cz/crcs/ectester/standalone/libs/jni/mscng.c @@ -1,37 +1,37 @@ -#include "native.h"
-#include <windows.h>
#include <bcrypt.h>
+#include <windows.h>
+#include "native.h"
+#include "c_timing.h"
#include "c_utils.h"
#include <stdio.h>
-
-
// BCRYPT and NT things.
-#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
-#define NT_FAILURE(status) !NT_SUCCESS(status)
+#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
- 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.
+ 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;
-//Provider things
+// Provider things
static jclass provider_class;
-#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
+#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");
@@ -70,54 +70,17 @@ typedef struct { } 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) {
+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];
@@ -141,7 +104,7 @@ static ULONG utf_8to16(NWPSTR *out_buf, LPCSTR in_str) { /**
* 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);
@@ -196,7 +159,9 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getCurv return result;
}
-JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env, jobject self, jint keysize) {
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Mscng_keysizeSupported(JNIEnv *env,
+ jobject self,
+ jint keysize) {
switch (keysize) {
case 256:
case 384:
@@ -207,7 +172,9 @@ 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) {
+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;
}
@@ -268,26 +235,27 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLe // h[cbCofactor] Cofactor of G in E.
// S[cbSeed] Seed of the curve.
- BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB*)eccParams;
+ BCRYPT_ECCFULLKEY_BLOB *header = (BCRYPT_ECCFULLKEY_BLOB *)eccParams;
PBYTE paramsStart = &eccParams[sizeof(BCRYPT_ECCFULLKEY_BLOB)];
- //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
+ // cbSubgroupOrder
PBYTE N = GY + header->cbFieldLength;
- //cbCofactor
+ // cbCofactor
PBYTE H = N + header->cbSubgroupOrder;
- //cbSeed
+ // cbSeed
PBYTE S = H + header->cbCofactor;
- *paramLength = sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed;
+ *paramLength =
+ sizeof(BCRYPT_ECCFULLKEY_BLOB) + 5 * header->cbFieldLength + header->cbSubgroupOrder + header->cbCofactor + header->cbSeed;
jobject p_int = bytes_to_biginteger(env, P, header->cbFieldLength);
@@ -297,7 +265,8 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLe 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");
+ 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);
@@ -312,7 +281,8 @@ static jobject create_ec_param_spec(JNIEnv *env, PBYTE eccParams, PULONG paramLe 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");
+ 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);
}
@@ -358,9 +328,9 @@ static ULONG create_curve(JNIEnv *env, jobject params, PBYTE *curve) { // 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;
+ 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->dwCurveType = 1; // 1 -> Prime short Weierstrass, 2 -> Prime Twisted Edwards, 3 -> Montgomery
header->dwCurveGenerationAlgId = 0;
header->cbFieldLength = bytes;
header->cbSubgroupOrder = order_bytes;
@@ -461,12 +431,11 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPC // 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;
+ 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 meta_bytes = NULL;
jbyteArray header_bytes = NULL;
switch (flag) {
@@ -538,7 +507,8 @@ static jobject key_to_privkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPC free(fullBuf);
jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "(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);
+ 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, jint flag, LPCWSTR curve) {
@@ -574,7 +544,7 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCW // 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;
+ BCRYPT_ECCFULLKEY_BLOB *pubHeader = (BCRYPT_ECCFULLKEY_BLOB *)fullBuf;
PBYTE pub_x = &fullBuf[paramLength];
PBYTE pub_y = pub_x + pubHeader->cbFieldLength;
@@ -644,14 +614,18 @@ static jobject key_to_pubkey(JNIEnv *env, BCRYPT_KEY_HANDLE key, jint flag, LPCW 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) {
+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) {
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);
+ const char *type_data = (*env)->GetStringUTFChars(env, type, NULL);
LPCWSTR algo;
if (strcmp(type_data, "ECDH") == 0) {
switch (keysize) {
@@ -665,7 +639,7 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai algo = BCRYPT_ECDH_P521_ALGORITHM;
break;
default:
- //unreachable
+ // unreachable
return NULL;
}
} else if (strcmp(type_data, "ECDSA") == 0) {
@@ -680,11 +654,11 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai algo = BCRYPT_ECDSA_P521_ALGORITHM;
break;
default:
- //unreachable
+ // unreachable
return NULL;
}
} else {
- //unreachable
+ // unreachable
return NULL;
}
(*env)->ReleaseStringUTFChars(env, type, type_data);
@@ -696,13 +670,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai BCRYPT_KEY_HANDLE key = NULL;
- if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, keysize, 0))) {
+ native_timing_start();
+ status = BCryptGenerateKeyPair(handle, &key, keysize, 0);
+ native_timing_pause();
+
+ if (NT_FAILURE(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))) {
+ native_timing_restart();
+ status = BCryptFinalizeKeyPair(key, 0);
+ native_timing_stop();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
BCryptCloseAlgorithmProvider(handle, 0);
return NULL;
@@ -718,7 +700,9 @@ 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;
@@ -726,14 +710,14 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai 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);
+ 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
+ // unreachable
return NULL;
}
(*env)->ReleaseStringUTFChars(env, type, type_data);
@@ -746,13 +730,21 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai return NULL;
}
- if (NT_FAILURE(status = BCryptGenerateKeyPair(handle, &key, bits, 0))) {
+ native_timing_start();
+ status = BCryptGenerateKeyPair(handle, &key, bits, 0);
+ native_timing_pause();
+
+ if (NT_FAILURE(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))) {
+ native_timing_restart();
+ status = BCryptFinalizeKeyPair(key, 0);
+ native_timing_stop();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptFinalizeKeyPair\n", status);
BCryptCloseAlgorithmProvider(handle, 0);
return NULL;
@@ -773,18 +765,8 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai }
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 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;
@@ -793,7 +775,7 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty } else if (lstrcmpW(type, BCRYPT_ECDSA_ALGORITHM) == 0) {
algos = ecdsa_algos;
} else {
- //unreachable
+ // unreachable
return STATUS_INVALID_PARAMETER;
}
@@ -829,7 +811,7 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty }
}
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;
@@ -839,8 +821,9 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty 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))) {
- // throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(curve name)\n", status);
+ // 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;
//}
@@ -852,7 +835,8 @@ static NTSTATUS init_use_algo(JNIEnv *env, BCRYPT_ALG_HANDLE *handle, LPCWSTR ty 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);
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSetProperty(parameters)\n",
+ status);
free(curve);
return status;
}
@@ -883,13 +867,15 @@ static jbyteArray get_meta(JNIEnv *env, jobject key) { }
}
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret__Ljava_security_interfaces_ECPublicKey_2Ljava_security_interfaces_ECPrivateKey_2Ljava_security_spec_AlgorithmParameterSpec_2(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params) {
+JNIEXPORT jbyteArray JNICALL
+Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret__Ljava_security_interfaces_ECPublicKey_2Ljava_security_interfaces_ECPrivateKey_2Ljava_security_spec_AlgorithmParameterSpec_2(
+ 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");
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);
+ const char *type_data = (*env)->GetStringUTFChars(env, type, NULL);
LPCWSTR kdf_algo;
if (strcmp(type_data, "ECDHwithSHA1KDF(CNG)") == 0) {
kdf_algo = BCRYPT_SHA1_ALGORITHM;
@@ -900,7 +886,7 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey } else if (strcmp(type_data, "ECDHwithSHA512KDF(CNG)") == 0) {
kdf_algo = BCRYPT_SHA512_ALGORITHM;
} else {
- //unreachable
+ // unreachable
return NULL;
}
(*env)->ReleaseStringUTFChars(env, type, type_data);
@@ -956,7 +942,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey BCRYPT_SECRET_HANDLE ka = NULL;
- if (NT_FAILURE(status = BCryptSecretAgreement(skey, pkey, &ka, 0))) {
+ native_timing_start();
+ status = BCryptSecretAgreement(skey, pkey, &ka, 0);
+ native_timing_stop();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSecretAgreement\n", status);
BCryptCloseAlgorithmProvider(kaHandle, 0);
BCryptDestroyKey(pkey);
@@ -964,8 +954,8 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey return NULL;
}
- BCryptBufferDesc paramList = { 0 };
- BCryptBuffer kdfParams[1] = { 0 };
+ 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;
@@ -998,16 +988,18 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey return result;
}
-JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret__Ljava_security_interfaces_ECPublicKey_2Ljava_security_interfaces_ECPrivateKey_2Ljava_security_spec_AlgorithmParameterSpec_2Ljava_lang_String_2(JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params, jstring algorithm) {
- throw_new(env, "java/lang/UnsupportedOperationException", "Not supported.");
- return NULL;
+JNIEXPORT jobject JNICALL
+Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Mscng_generateSecret__Ljava_security_interfaces_ECPublicKey_2Ljava_security_interfaces_ECPrivateKey_2Ljava_security_spec_AlgorithmParameterSpec_2Ljava_lang_String_2(
+ JNIEnv *env, jobject self, jobject pubkey, jobject privkey, jobject params, jstring algorithm) {
+ throw_new(env, "java/lang/UnsupportedOperationException", "Not supported.");
+ return NULL;
}
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);
+ const char *type_data = (*env)->GetStringUTFChars(env, type, NULL);
LPCWSTR hash_algo;
if (strcmp(type_data, "SHA1withECDSA") == 0) {
hash_algo = BCRYPT_SHA1_ALGORITHM;
@@ -1018,14 +1010,16 @@ static LPCWSTR get_sighash_algo(JNIEnv *env, jobject self) { } else if (strcmp(type_data, "SHA512withECDSA") == 0) {
hash_algo = BCRYPT_SHA512_ALGORITHM;
} else {
- //unreachable
+ // 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, jobject 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);
@@ -1068,7 +1062,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig 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))) {
+ native_timing_start();
+ status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len);
+ native_timing_pause();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
BCryptCloseAlgorithmProvider(sigHandle, 0);
BCryptCloseAlgorithmProvider(hashHandle, 0);
@@ -1083,7 +1081,6 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig 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))) {
@@ -1097,7 +1094,11 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig (*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))) {
+ native_timing_restart();
+ status = BCryptSignHash(skey, NULL, hash, hash_len, NULL, 0, &sig_len, 0);
+ native_timing_pause();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptSignHash(len only)\n", status);
BCryptCloseAlgorithmProvider(sigHandle, 0);
BCryptCloseAlgorithmProvider(hashHandle, 0);
@@ -1105,20 +1106,26 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSig 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))) {
+ PBYTE sig_buf = calloc(sig_len, 1);
+
+ native_timing_restart();
+ status = BCryptSignHash(skey, NULL, hash, hash_len, sig_buf, sig_len, &sig_len, 0);
+ native_timing_stop();
+
+ if (NT_FAILURE(status)) {
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);
+ free(sig_buf);
return NULL;
}
- (*env)->ReleaseByteArrayElements(env, sig, sig_data, 0);
- free(hash);
+ DWORD half_len = sig_len / 2;
+ jobject sig = asn1_der_encode(env, sig_buf, half_len, sig_buf + half_len, half_len);
+ free(hash);
+ free(sig_buf);
BCryptDestroyKey(skey);
BCryptCloseAlgorithmProvider(hashHandle, 0);
BCryptCloseAlgorithmProvider(sigHandle, 0);
@@ -1126,14 +1133,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, jobject 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;
jint keyflag = get_keyflag(env, pubkey);
- if (keyflag == KEYFLAG_OTHER) { // TODO: This is not necessary
+ if (keyflag == KEYFLAG_OTHER) { // TODO: This is not necessary
throw_new(env, "java/security/InvalidAlgorithmParameterException", "Cannot import non-native public key.");
return JNI_FALSE;
}
@@ -1164,7 +1173,11 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna 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))) {
+ native_timing_start();
+ status = BCryptHash(hashHandle, NULL, 0, data_bytes, data_len, hash, hash_len);
+ native_timing_pause();
+
+ if (NT_FAILURE(status)) {
throw_new_var(env, "java/security/GeneralSecurityException", "Error 0x%x returned by BCryptHash\n", status);
BCryptCloseAlgorithmProvider(sigHandle, 0);
BCryptCloseAlgorithmProvider(hashHandle, 0);
@@ -1179,7 +1192,6 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna 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))) {
@@ -1194,11 +1206,51 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna 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);
+ jbyte *r;
+ size_t rlen;
+ jbyte *s;
+ size_t slen;
+ bool decode = asn1_der_decode(env, sig, &r, &rlen, &s, &slen);
(*env)->ReleaseByteArrayElements(env, sig, sig_data, JNI_ABORT);
- free(hash);
+ if (!decode) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error decoding sig.");
+ BCryptDestroyKey(pkey);
+ BCryptCloseAlgorithmProvider(sigHandle, 0);
+ BCryptCloseAlgorithmProvider(hashHandle, 0);
+ free(hash);
+ return JNI_FALSE;
+ }
+ jbyte *r_cpy = r;
+ jbyte *s_cpy = s;
+ if (rlen > slen) {
+ r_cpy += rlen - slen;
+ rlen = slen;
+ } else if (slen > rlen) {
+ s_cpy += slen - rlen;
+ slen = rlen;
+ } else {
+ if (r[0] == 0 && s[0] == 0) {
+ r_cpy++;
+ s_cpy++;
+ rlen--;
+ slen--;
+ }
+ }
+
+ UCHAR *sig_full = calloc(rlen + slen, 1);
+ memcpy(sig_full, r_cpy, rlen);
+ memcpy(sig_full + rlen, s_cpy, slen);
+ free(r);
+ free(s);
+
+ native_timing_restart();
+ NTSTATUS result = BCryptVerifySignature(pkey, NULL, hash, hash_len, sig_full, rlen + slen, 0);
+ native_timing_stop();
+
+ free(hash);
+ free(sig_full);
BCryptDestroyKey(pkey);
BCryptCloseAlgorithmProvider(hashHandle, 0);
BCryptCloseAlgorithmProvider(sigHandle, 0);
@@ -1214,13 +1266,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna }
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_supportsNativeTiming(JNIEnv *env, jobject self) {
- return JNI_FALSE;
+ return native_timing_supported();
}
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getNativeTimingResolution(JNIEnv *env, jobject self) {
- return 0;
+ return native_timing_resolution();
}
JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MscngLib_getLastNativeTiming(JNIEnv *env, jobject self) {
- return 0;
+ return native_timing_last();
}
\ No newline at end of file |
