From 19d09ebf00af0a09506ce3e7534bb658a8e999b9 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Thu, 4 Jul 2019 01:53:38 +0200
Subject: Add mbedTLS support.
---
.gitignore | 3 +-
build-standalone.xml | 7 +
docs/LIBS.md | 10 +-
src/cz/crcs/ectester/common/util/ECUtil.java | 6 +-
.../ectester/standalone/ECTesterStandalone.java | 30 +-
.../crcs/ectester/standalone/libs/MbedTLSLib.java | 29 ++
src/cz/crcs/ectester/standalone/libs/jni/Makefile | 11 +-
.../standalone/libs/jni/NativeECPrivateKey.java | 6 +
.../standalone/libs/jni/NativeECPublicKey.java | 6 +
.../standalone/libs/jni/NativeKeyAgreementSpi.java | 21 +
.../libs/jni/NativeKeyPairGeneratorSpi.java | 19 +
.../standalone/libs/jni/NativeProvider.java | 10 +
.../standalone/libs/jni/NativeSignatureSpi.java | 21 +
.../crcs/ectester/standalone/libs/jni/c_timing.c | 22 +-
.../crcs/ectester/standalone/libs/jni/c_timing.h | 10 +
src/cz/crcs/ectester/standalone/libs/jni/c_utils.c | 17 +-
src/cz/crcs/ectester/standalone/libs/jni/mbedtls.c | 571 +++++++++++++++++++++
src/cz/crcs/ectester/standalone/libs/jni/native.h | 205 ++++++++
src/cz/crcs/ectester/standalone/libs/jni/openssl.c | 3 +-
19 files changed, 978 insertions(+), 29 deletions(-)
create mode 100644 src/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
create mode 100644 src/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
diff --git a/.gitignore b/.gitignore
index 3162005..ff1c3c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,4 +37,5 @@
/src/**/*.pdb
# Python stuff
-/util/__pycache__/
\ No newline at end of file
+/util/__pycache__/
+/util/.ipynb_checkpoints/
\ No newline at end of file
diff --git a/build-standalone.xml b/build-standalone.xml
index 9382a8f..de01275 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -182,6 +182,13 @@
+
+
+
+
+
+
+
diff --git a/docs/LIBS.md b/docs/LIBS.md
index 8aea9be..09c82cf 100644
--- a/docs/LIBS.md
+++ b/docs/LIBS.md
@@ -3,7 +3,6 @@
Popular libraries with at least some ECC support, that ECTester does not yet support:
- [NSS](https://hg.mozilla.org/projects/nss)
- - [mbedTLS](https://tls.mbed.org/)
- [LibreSSL](https://www.libressl.org/)
- [Nettle](http://www.lysator.liu.se/~nisse/nettle/)
- [OpenSSL (FIPS mode)](https://www.openssl.org/docs/fipsnotes.html)
@@ -113,4 +112,11 @@ ninja
- Uses Montgomery model.
- Uses fixed window scalar multiplication.
- Uses Wnaf multi-scalar multiplication with interleaving.
- - Uses Montgomery ladder.
\ No newline at end of file
+ - Uses Montgomery ladder.
+ - [mbedTLS](https://tls.mbed.org/)
+ - C
+ - Only supports prime field curves.
+ - Uses short Weierstrass and Montgomery models.
+ - Uses comb method for short Weierstrass curves, using (randomized) Jacobian coordinates.
+ -
+ - Uses Montgomery ladder with xz coordinates for Montgomery curves.
\ No newline at end of file
diff --git a/src/cz/crcs/ectester/common/util/ECUtil.java b/src/cz/crcs/ectester/common/util/ECUtil.java
index ce50c21..43ccf08 100644
--- a/src/cz/crcs/ectester/common/util/ECUtil.java
+++ b/src/cz/crcs/ectester/common/util/ECUtil.java
@@ -446,16 +446,16 @@ public class ECUtil {
return result;
}
- public static ECKey loadKey(short params, String named, String file, ECParameterSpec spec) throws IOException {
+ public static ECKey loadKey(short params, String named, String file, AlgorithmParameterSpec spec) throws IOException {
if (params == EC_Consts.PARAMETERS_KEYPAIR) {
throw new IllegalArgumentException();
}
EC_Params param = loadParams(params, named, file);
if (param != null) {
if (params == EC_Consts.PARAMETER_W) {
- return new RawECPublicKey(toPoint(param), spec);
+ return new RawECPublicKey(toPoint(param), (ECParameterSpec) spec);
} else if (params == EC_Consts.PARAMETER_S) {
- return new RawECPrivateKey(toScalar(param), spec);
+ return new RawECPrivateKey(toScalar(param), (ECParameterSpec) spec);
}
}
return null;
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 6143751..8e88461 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -78,7 +78,8 @@ public class ECTesterStandalone {
new BoringsslLib(),
new GcryptLib(),
new MscngLib(),
- new WolfCryptLib()};
+ new WolfCryptLib(),
+ new MbedTLSLib()};
private Config cfg;
private Options opts = new Options();
@@ -148,20 +149,20 @@ public class ECTesterStandalone {
private TreeCommandLine parseArgs(String[] args) throws ParseException {
Map actions = new TreeMap<>();
- Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).build();
- Option namedPublic = Option.builder("npub").longOpt("named-public").desc("Use a named public key, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).build();
- Option filePublic = Option.builder("pub").longOpt("public").desc("Use a given public key from file.").hasArg().argName("pubkey").optionalArg(false).build();
+ Option namedCurve = Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).numberOfArgs(1).build();
+ Option namedPublic = Option.builder("npub").longOpt("named-public").desc("Use a named public key, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).numberOfArgs(1).build();
+ Option filePublic = Option.builder("pub").longOpt("public").desc("Use a given public key from file.").hasArg().argName("pubkey").optionalArg(false).numberOfArgs(1).build();
OptionGroup publicKey = new OptionGroup();
publicKey.addOption(namedPublic);
publicKey.addOption(filePublic);
- Option namedPrivate = Option.builder("npriv").longOpt("named-private").desc("Use a named private key, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).build();
- Option filePrivate = Option.builder("priv").longOpt("private").desc("Use a given private key from file.").hasArg().argName("privkey").optionalArg(false).build();
+ Option namedPrivate = Option.builder("npriv").longOpt("named-private").desc("Use a named private key, from CurveDB: ").hasArg().argName("cat/id").optionalArg(false).numberOfArgs(1).build();
+ Option filePrivate = Option.builder("priv").longOpt("private").desc("Use a given private key from file.").hasArg().argName("privkey").optionalArg(false).numberOfArgs(1).build();
OptionGroup privateKey = new OptionGroup();
privateKey.addOption(namedPrivate);
privateKey.addOption(filePrivate);
- Option curveName = Option.builder("cn").longOpt("curve-name").desc("Use a named curve, search from curves supported by the library: ").hasArg().argName("name").optionalArg(false).build();
- Option bits = Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").build();
- Option output = Option.builder("o").longOpt("output").desc("Output into file .").hasArgs().argName("output_file").optionalArg(false).build();
+ Option curveName = Option.builder("cn").longOpt("curve-name").desc("Use a named curve, search from curves supported by the library: ").hasArg().argName("name").optionalArg(false).numberOfArgs(1).build();
+ Option bits = Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").numberOfArgs(1).build();
+ Option output = Option.builder("o").longOpt("output").desc("Output into file .").hasArgs().argName("output_file").optionalArg(false).numberOfArgs(1).build();
Options testOpts = new Options();
testOpts.addOption(bits);
@@ -366,8 +367,8 @@ public class ECTesterStandalone {
other = kpg.genKeyPair();
}
- ECPrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdh.named-private"), cli.getOptionValue("ecdh.private"), (ECParameterSpec) spec);
- ECPublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdh.named-public"), cli.getOptionValue("ecdh.public"), (ECParameterSpec) spec);
+ ECPrivateKey privkey = (ECPrivateKey) ECUtil.loadKey(EC_Consts.PARAMETER_S, cli.getOptionValue("ecdh.named-private"), cli.getOptionValue("ecdh.private"), spec);
+ ECPublicKey pubkey = (ECPublicKey) ECUtil.loadKey(EC_Consts.PARAMETER_W, cli.getOptionValue("ecdh.named-public"), cli.getOptionValue("ecdh.public"), spec);
int amount = Integer.parseInt(cli.getOptionValue("ecdh.amount", "1"));
for (int i = 0; i < amount || amount == 0; ++i) {
@@ -496,7 +497,7 @@ public class ECTesterStandalone {
PrintStream out;
if (cli.hasOption("ecdsa.output")) {
- out = new PrintStream(FileUtil.openStream(cli.getOptionValues("ecdh.output")));
+ out = new PrintStream(FileUtil.openStream(cli.getOptionValues("ecdsa.output")));
} else {
out = System.out;
}
@@ -710,6 +711,11 @@ public class ECTesterStandalone {
System.err.println("You can only specify bitsize or a named curve/curve name, nor both.");
return false;
}
+
+ if (hasCurveName && (cli.hasOption(next + ".named-public") || cli.hasOption(next + ".named-private") || cli.hasOption(next + ".public") || cli.hasOption(next + ".private"))) {
+ System.err.println("Cannot specify key with a curve name switch, needs explicit parameteres.");
+ return false;
+ }
}
if (!cli.isNext("list-data") && !cli.isNext("list-suites")) {
diff --git a/src/cz/crcs/ectester/standalone/libs/MbedTLSLib.java b/src/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
new file mode 100644
index 0000000..bc1a6c3
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/MbedTLSLib.java
@@ -0,0 +1,29 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class MbedTLSLib extends NativeECLibrary {
+
+ public MbedTLSLib() {
+ super("mbedtls_provider", "mbedcrypto");
+ }
+
+ @Override
+ public native boolean supportsNativeTiming();
+
+ @Override
+ public native long getNativeTimingResolution();
+
+ @Override
+ public native long getLastNativeTiming();
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index c8ab47b..8b4754b 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -58,7 +58,7 @@ JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM)
###############################################################################
## Targets.
-all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so gcrypt_provider.so
+all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so gcrypt_provider.so mbedtls_provider.so
# Common utils
c_utils.o: c_utils.c
@@ -119,6 +119,14 @@ cryptopp_provider.so: cryptopp.o cpp_utils.o c_timing.o
cryptopp.o: cryptopp.cpp
$(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $<
+
+# mbedTLS shim
+mbedtls_provider.so: mbedtls.o c_utils.o c_timing.o
+ $(CC) $(LFLAGS) -o $@ $^ -L. -lmbedcrypto
+
+mbedtls.o: mbedtls.c
+ $(CC) $(CFLAGS) -c $<
+
help:
@echo "# This makefile builds the JNI shims necessary to test native libraries."
@echo "# Targets:"
@@ -128,6 +136,7 @@ help:
@echo " - tomcrypt_provider.so"
@echo " - botan_provider.so"
@echo " - cryptopp_provider.so"
+ @echo " - mbedtls_provider.so"
clean:
rm -rf *.o
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
index 6d8101f..96f19b8 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
@@ -97,6 +97,12 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
}
}
+ public static class MbedTLS extends Raw {
+ public MbedTLS(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
public static class Mscng extends Raw {
// 0 -> implicit (meta = curveName UTF16, header = full);
// 1 -> explicit (meta = null, header = full);
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
index dcb8b3f..9e29a59 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
@@ -98,6 +98,12 @@ public abstract class NativeECPublicKey implements ECPublicKey {
}
}
+ public static class MbedTLS extends ANSIX962 {
+ public MbedTLS(byte[] keyData, ECParameterSpec params) {
+ super(keyData, params);
+ }
+ }
+
public static class Mscng extends ANSIX962 {
// 0 -> implicit (meta = curveName UTF16, header = full);
// 1 -> explicit (meta = null, header = full);
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index 7b531f5..b098792 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -312,4 +312,25 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
super("ECDHwithSHA512KDF(CNG)");
}
}
+
+ public abstract static class MbedTLS extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public MbedTLS(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native SecretKey generateSecret(byte[] pubkey, byte[] privkey, ECParameterSpec params, String algorithm);
+ }
+
+ public static class MbedTLSECDH extends MbedTLS {
+ public MbedTLSECDH() {
+ super("ECDH");
+ }
+ }
+
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
index 78656fc..a3552cf 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
@@ -249,4 +249,23 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
super("ECDSA");
}
}
+
+ public static class MbedTLS extends NativeKeyPairGeneratorSpi {
+
+ public MbedTLS() {
+ initialize(256, new SecureRandom());
+ }
+
+ @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);
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
index 99baa97..7527463 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
@@ -93,4 +93,14 @@ public abstract class NativeProvider extends Provider {
@Override
native void setup();
}
+
+ public static class MbedTLS extends NativeProvider {
+
+ public MbedTLS(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index f2b1ab9..37e87bc 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -440,6 +440,27 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
}
}
+ public abstract static class MbedTLS extends SimpleSignatureSpi {
+ private String type;
+
+ public MbedTLS(String type) {
+ this.type = type;
+ }
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+ }
+
+ public static class MbedTLSECDSAwithNONE extends MbedTLS {
+
+ public MbedTLSECDSAwithNONE() {
+ super("NONEwithECDSA");
+ }
+ }
+
public abstract static class Mscng extends ExtendedSignatureSpi {
private String type;
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 be46398..81c30ec 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.c
@@ -3,8 +3,9 @@
#if _POSIX_TIMERS > 0
-struct timespec start = {0};
-struct timespec end = {0};
+static struct timespec start = {0};
+static struct timespec end = {0};
+static jlong partial = 0;
jboolean native_timing_supported() {
return JNI_TRUE;
@@ -16,19 +17,26 @@ jlong native_timing_resolution() {
return timeval.tv_nsec;
}
-
void native_timing_start() {
+ partial = 0;
clock_gettime(CLOCK_MONOTONIC, &start);
}
+void native_timing_pause() {
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ partial += (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec);
+}
+
+void native_timing_restart() {
+ clock_gettime(CLOCK_MONOTONIC, &start);
+}
void native_timing_stop() {
clock_gettime(CLOCK_MONOTONIC, &end);
}
-
jlong native_timing_last() {
- jlong res = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec);
+ jlong res = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec) + partial;
if (res < 0) {
return 0;
} else {
@@ -48,6 +56,10 @@ jlong native_timing_resolution() {
void native_timing_start() {}
+void native_timing_pause() {}
+
+void native_timing_restart() {}
+
void native_timing_stop() {}
jlong native_timing_last() {
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 bce2a19..ae650d7 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_timing.h
@@ -23,6 +23,16 @@ jlong native_timing_resolution();
*/
void native_timing_start();
+/**
+ *
+ */
+void native_timing_pause();
+
+/**
+ *
+ */
+void native_timing_restart();
+
/**
*
*/
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
index 81d1fb8..ab221a9 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
@@ -108,6 +108,17 @@ jint get_kdf_bits(JNIEnv *env, jstring algorithm) {
}
jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyte *s, size_t s_len) {
+ const jbyte *rtmp = r;
+ while (*rtmp++ == 0) {
+ r++;
+ r_len--;
+ }
+ const jbyte *stmp = s;
+ while (*stmp++ == 0) {
+ s++;
+ s_len--;
+ }
+
jbyte r_length = (jbyte) r_len + (r[0] & 0x80 ? 1 : 0);
jbyte s_length = (jbyte) s_len + (s[0] & 0x80 ? 1 : 0);
@@ -119,9 +130,9 @@ jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyt
size_t seq_len_len = 0;
if (seq_value_len >= 128) {
size_t s = seq_value_len;
- while ((s = s >> 8)) {
+ do {
seq_len_len++;
- }
+ } while ((s = s >> 8));
}
// seq_len_len bytes for length and one for length of length
whole_len += seq_len_len + 1;
@@ -138,7 +149,7 @@ jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyt
} else {
data[i++] = (jbyte) (seq_len_len | (1 << 7));
for (size_t j = 0; j < seq_len_len; ++j) {
- data[i++] = (jbyte) (seq_value_len & (0xff << (seq_len_len - j)));
+ data[i++] = (jbyte) (seq_value_len & (0xff << (8 * (seq_len_len - j - 1))));
}
}
data[i++] = 0x02; //INTEGER
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/mbedtls.c b/src/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
new file mode 100644
index 0000000..71ede19
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/mbedtls.c
@@ -0,0 +1,571 @@
+#include "native.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "c_utils.h"
+#include "c_timing.h"
+
+static mbedtls_ctr_drbg_context ctr_drbg;
+static mbedtls_entropy_context entropy;
+static jclass provider_class;
+
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_createProvider(JNIEnv *env, jobject this) {
+ /* Create the custom provider. */
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$MbedTLS");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ jstring name = (*env)->NewStringUTF(env, MBEDTLS_VERSION_STRING_FULL);
+ double version = MBEDTLS_VERSION_MAJOR + (MBEDTLS_VERSION_MINOR/10) + (MBEDTLS_VERSION_PATCH/100);
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+static int dev_urandom(void *data, unsigned char *output, size_t len, size_t *olen) {
+ FILE *file;
+ size_t ret, left = len;
+ unsigned char *p = output;
+ ((void) data);
+
+ *olen = 0;
+
+ file = fopen( "/dev/urandom", "rb" );
+ if (file == NULL) {
+ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ while (left > 0) {
+ ret = fread(p, 1, left, file);
+ if (ret == 0 && ferror(file)) {
+ fclose(file);
+ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ p += ret;
+ left -= ret;
+ sleep(1);
+ }
+ fclose(file);
+ *olen = len;
+
+ return 0;
+}
+
+static int ctr_drbg_wrapper(void *ctx, unsigned char *buf, size_t len) {
+ native_timing_pause();
+ int result = mbedtls_ctr_drbg_random(ctx, buf, len);
+ native_timing_restart();
+ return result;
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024MbedTLS_setup(JNIEnv *env, jobject this) {
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, this, "EC", "MbedTLS");
+ ADD_KA(env, this, "ECDH", "MbedTLSECDH");
+ ADD_SIG(env, this, "NONEwithECDSA", "MbedTLSECDSAwithNONE");
+
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+ mbedtls_entropy_init(&entropy);
+ mbedtls_entropy_add_source(&entropy, dev_urandom, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);
+ mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
+
+ init_classes(env, "MbedTLS");
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCurves(JNIEnv *env, jobject this) {
+ jclass hash_set_class = (*env)->FindClass(env, "java/util/TreeSet");
+
+ jmethodID hash_set_ctr = (*env)->GetMethodID(env, hash_set_class, "", "()V");
+ jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr);
+ for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
+ curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+ curve_info++) {
+
+ jstring curve_name = (*env)->NewStringUTF(env, curve_info->name);
+ (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name);
+ }
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_keysizeSupported(JNIEnv *env, jobject this, jint keysize) {
+ for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
+ curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+ curve_info++) {
+ if (keysize == curve_info->bit_size) {
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_paramsSupported(JNIEnv *env, jobject this, jobject params) {
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, curve, get_field);
+ if ((*env)->IsInstanceOf(env, field, f2m_field_class)) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+ } else 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);
+ for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
+ curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+ curve_info++) {
+ if (strcasecmp(utf_name, curve_info->name) == 0) {
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return JNI_TRUE;
+ }
+ }
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return JNI_FALSE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+const char *err_to_string(int error) {
+ switch (error) {
+ case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
+ return "Bad input parameters to function.";
+ case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
+ return "The buffer is too small to write to.";
+ case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:
+ return "The requested feature is not available, for example, the requested curve is not supported.";
+ case MBEDTLS_ERR_ECP_VERIFY_FAILED:
+ return "The signature is not valid.";
+ case MBEDTLS_ERR_ECP_ALLOC_FAILED:
+ return "Memory allocation failed.";
+ case MBEDTLS_ERR_ECP_RANDOM_FAILED:
+ return "Generation of random value, such as ephemeral key, failed.";
+ case MBEDTLS_ERR_ECP_INVALID_KEY:
+ return "Invalid private or public key.";
+ case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:
+ return "The buffer contains a valid signature followed by more data.";
+ case MBEDTLS_ERR_MPI_FILE_IO_ERROR:
+ return "An error occurred while reading from or writing to a file.";
+ case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
+ return "Bad input parameters to function.";
+ case MBEDTLS_ERR_MPI_INVALID_CHARACTER:
+ return "There is an invalid character in the digit string.";
+ case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
+ return "The buffer is too small to write to.";
+ case MBEDTLS_ERR_MPI_NEGATIVE_VALUE:
+ return "The input arguments are negative or result in illegal output.";
+ case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO:
+ return "The input argument for division is zero, which is not allowed.";
+ case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
+ return "The input arguments are not acceptable.";
+ case MBEDTLS_ERR_MPI_ALLOC_FAILED:
+ return "Memory allocation failed.";
+ default:
+ return "UNKNOWN.";
+ }
+}
+
+static jobject biginteger_from_mpi(JNIEnv *env, const mbedtls_mpi *mpi) {
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "", "(I[B)V");
+ size_t size = mbedtls_mpi_size(mpi);
+ jbyteArray bytes = (*env)->NewByteArray(env, size);
+ jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL);
+ mbedtls_mpi_write_binary(mpi, data, size);
+ (*env)->ReleaseByteArrayElements(env, bytes, data, 0);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes);
+ return result;
+}
+
+static void mpi_from_biginteger(JNIEnv* env, jobject biginteger, mbedtls_mpi *mpi) {
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, biginteger, to_byte_array);
+ jsize byte_length = (*env)->GetArrayLength(env, byte_array);
+ jbyte *byte_data = (*env)->GetByteArrayElements(env, byte_array, NULL);
+ mbedtls_mpi_read_binary(mpi, byte_data, byte_length);
+ (*env)->ReleaseByteArrayElements(env, byte_array, byte_data, JNI_ABORT);
+}
+
+static void biginteger_print(JNIEnv *env, jobject bigint) {
+ jmethodID to_string = (*env)->GetMethodID(env, biginteger_class, "toString", "(I)Ljava/lang/String;");
+ jstring big_string = (*env)->CallObjectMethod(env, bigint, to_string, (jint) 16);
+
+ jsize len = (*env)->GetStringUTFLength(env, big_string);
+ char raw_string[len + 1];
+ raw_string[len] = 0;
+ (*env)->GetStringUTFRegion(env, big_string, 0, len, raw_string);
+ printf("%s\n", raw_string);
+ fflush(stdout);
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, const mbedtls_ecp_group *group) {
+ jobject p = biginteger_from_mpi(env, &group->P);
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "", "(Ljava/math/BigInteger;)V");
+ jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, p);
+
+ jobject a;
+ if (group->A.p == NULL) {
+ jmethodID biginteger_subtract = (*env)->GetMethodID(env, biginteger_class, "subtract", "(Ljava/math/BigInteger;)Ljava/math/BigInteger;");
+ jmethodID biginteger_valueof = (*env)->GetStaticMethodID(env, biginteger_class, "valueOf", "(J)Ljava/math/BigInteger;");
+ jobject three = (*env)->CallStaticObjectMethod(env, biginteger_class, biginteger_valueof, (jlong) 3);
+ a = (*env)->CallObjectMethod(env, p, biginteger_subtract, three);
+ } else {
+ a = biginteger_from_mpi(env, &group->A);
+ }
+ jobject b = biginteger_from_mpi(env, &group->B);
+
+ jmethodID elliptic_curve_init = (*env)->GetMethodID(env, elliptic_curve_class, "", "(Ljava/security/spec/ECField;Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject elliptic_curve = (*env)->NewObject(env, elliptic_curve_class, elliptic_curve_init, field, a, b);
+
+ jobject gx = biginteger_from_mpi(env, &group->G.X);
+ jobject gy = biginteger_from_mpi(env, &group->G.Y);
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ jobject g = (*env)->NewObject(env, point_class, point_init, gx, gy);
+
+ jobject n = biginteger_from_mpi(env, &group->N);
+ jint h = 1;
+
+ jmethodID ec_parameter_spec_init = (*env)->GetMethodID(env, ec_parameter_spec_class, "", "(Ljava/security/spec/EllipticCurve;Ljava/security/spec/ECPoint;Ljava/math/BigInteger;I)V");
+ return (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, g, n, h);
+}
+
+static void create_curve(JNIEnv *env, jobject params, mbedtls_ecp_group *group) {
+ mbedtls_ecp_group_init(group);
+ group->id = 0;
+
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject curve = (*env)->CallObjectMethod(env, params, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, curve, get_field);
+
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject p = (*env)->CallObjectMethod(env, field, get_p);
+ mpi_from_biginteger(env, p, &group->P);
+
+ jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject a = (*env)->CallObjectMethod(env, curve, get_a);
+ mpi_from_biginteger(env, a, &group->A);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject b = (*env)->CallObjectMethod(env, curve, get_b);
+ mpi_from_biginteger(env, b, &group->B);
+
+ jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g = (*env)->CallObjectMethod(env, params, get_g);
+
+ jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = (*env)->CallObjectMethod(env, g, get_x);
+ mpi_from_biginteger(env, gx, &group->G.X);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g, get_y);
+ mpi_from_biginteger(env, gy, &group->G.Y);
+
+ mbedtls_mpi_lset(&group->G.Z, 1);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject n = (*env)->CallObjectMethod(env, params, get_n);
+ mpi_from_biginteger(env, n, &group->N);
+ group->pbits = group->nbits = mbedtls_mpi_bitlen(&group->P);
+ group->h = 0;
+}
+
+static jobject generate_from_curve(JNIEnv *env, mbedtls_ecp_group *group) {
+ mbedtls_mpi d;
+ mbedtls_mpi_init(&d);
+
+ mbedtls_ecp_point Q;
+ mbedtls_ecp_point_init(&Q);
+
+ if (ctr_drbg.reseed_counter >= ctr_drbg.reseed_interval) {
+ // Reseed manually, outside of the timing window, to not disturb the timing data.
+ // They are somewhat disturbed anyway, but we cannot really get rid of that easily.
+ // We also help it by using a wrapper and pausing for random gen.
+ mbedtls_ctr_drbg_reseed(&ctr_drbg, NULL, 0);
+ }
+
+ native_timing_start();
+ int error = mbedtls_ecp_gen_keypair(group, &d, &Q, ctr_drbg_wrapper, &ctr_drbg);
+ native_timing_stop();
+
+ if (error) {
+ throw_new(env, "java/security/GeneralSecurityException", err_to_string(error));
+ mbedtls_mpi_free(&d);
+ mbedtls_ecp_point_free(&Q);
+ return NULL;
+ }
+
+ jint keysize = (jint) mbedtls_mpi_bitlen(&group->N);
+ unsigned long key_bytes = (keysize + 7) / 8;
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, key_bytes);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ mbedtls_mpi_write_binary(&d, key_priv, key_bytes);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ unsigned long key_len = 2*key_bytes + 1;
+ jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len);
+ jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
+ size_t out_key_len = 0;
+ mbedtls_ecp_point_write_binary(group, &Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &out_key_len, key_pub, key_len);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
+
+ jobject ec_param_spec = create_ec_param_spec(env, group);
+
+ mbedtls_mpi_free(&d);
+ mbedtls_ecp_point_free(&Q);
+
+ jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject pubkey = (*env)->NewObject(env, pubkey_class, ec_pub_init, pub_bytes, ec_pub_param_spec);
+
+ jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "", "([BLjava/security/spec/ECParameterSpec;)V");
+ jobject privkey = (*env)->NewObject(env, privkey_class, ec_priv_init, priv_bytes, ec_priv_param_spec);
+
+ jmethodID keypair_init = (*env)->GetMethodID(env, keypair_class, "", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+ return (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+}
+
+static jobject generate_from_curve_info(JNIEnv *env, const mbedtls_ecp_curve_info *curve) {
+ mbedtls_ecp_group group;
+ mbedtls_ecp_group_init(&group);
+ mbedtls_ecp_group_load(&group, curve->grp_id);
+ jobject result = generate_from_curve(env, &group);
+ mbedtls_ecp_group_free(&group);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject this, jint keysize, jobject random) {
+ const mbedtls_ecp_curve_info *curve = NULL;
+ for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
+ curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+ curve_info++) {
+ if (keysize == curve_info->bit_size) {
+ curve = curve_info;
+ break;
+ }
+ }
+
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found.");
+ return NULL;
+ }
+
+ return generate_from_curve_info(env, curve);
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_generate__Ljava_security_spec_AlgorithmParameterSpec_2Ljava_security_SecureRandom_2(JNIEnv *env, jobject this, jobject params, jobject random) {
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ mbedtls_ecp_group curve;
+ create_curve(env, params, &curve);
+ jobject result = generate_from_curve(env, &curve);
+ mbedtls_ecp_group_free(&curve);
+ return result;
+ } else 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 mbedtls_ecp_curve_info *curve = NULL;
+ for (const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_list();
+ curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+ curve_info++) {
+ if (strcasecmp(utf_name, curve_info->name) == 0) {
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ curve = curve_info;
+ break;
+ }
+ }
+ if (!curve) {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve for given bitsize not found.");
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ return NULL;
+ }
+ return generate_from_curve_info(env, curve);
+ } else {
+ throw_new(env, "java/security/InvalidAlgorithmParameterException", "Curve not found.");
+ return NULL;
+ }
+}
+
+static void create_pubkey(JNIEnv *env, jbyteArray pubkey, mbedtls_ecp_group *curve, mbedtls_ecp_point *pub) {
+ mbedtls_ecp_point_init(pub);
+ jsize pub_size = (*env)->GetArrayLength(env, pubkey);
+ jbyte *key_pub = (*env)->GetByteArrayElements(env, pubkey, NULL);
+ mbedtls_ecp_point_read_binary(curve, pub, key_pub, pub_size);
+ (*env)->ReleaseByteArrayElements(env, pubkey, key_pub, JNI_ABORT);
+}
+
+static void create_privkey(JNIEnv *env, jbyteArray privkey, mbedtls_mpi *priv) {
+ mbedtls_mpi_init(priv);
+ jsize priv_size = (*env)->GetArrayLength(env, privkey);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, privkey, NULL);
+ mbedtls_mpi_read_binary(priv, key_priv, priv_size);
+ (*env)->ReleaseByteArrayElements(env, privkey, key_priv, JNI_ABORT);
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024MbedTLS_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ mbedtls_ecp_group curve;
+ create_curve(env, params, &curve);
+
+ mbedtls_ecp_point pub;
+ create_pubkey(env, pubkey, &curve, &pub);
+
+ mbedtls_mpi priv;
+ create_privkey(env, privkey, &priv);
+
+ mbedtls_mpi result;
+ mbedtls_mpi_init(&result);
+
+ native_timing_start();
+ int error = mbedtls_ecdh_compute_shared(&curve, &result, &pub, &priv, ctr_drbg_wrapper, &ctr_drbg);
+ native_timing_stop();
+
+ if (error) {
+ throw_new(env, "java/security/GeneralSecurityException", err_to_string(error));
+ mbedtls_mpi_free(&result);
+ mbedtls_mpi_free(&priv);
+ mbedtls_ecp_point_free(&pub);
+ mbedtls_ecp_group_free(&curve);
+ return NULL;
+ }
+
+ jint keysize = (jint) mbedtls_mpi_bitlen(&curve.N);
+ unsigned long key_bytes = (keysize + 7) / 8;
+ jbyteArray result_bytes = (*env)->NewByteArray(env, key_bytes);
+ jbyte *result_data = (*env)->GetByteArrayElements(env, result_bytes, NULL);
+ mbedtls_mpi_write_binary(&result, result_data, key_bytes);
+ (*env)->ReleaseByteArrayElements(env, result_bytes, result_data, 0);
+
+ mbedtls_mpi_free(&result);
+ mbedtls_mpi_free(&priv);
+ mbedtls_ecp_point_free(&pub);
+ mbedtls_ecp_group_free(&curve);
+
+ return result_bytes;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024MbedTLS_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params, jstring algo) {
+ throw_new(env, "java/lang/UnsupportedOperationException", "Not supported.");
+ return NULL;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024MbedTLS_sign(JNIEnv *env, jobject this, jbyteArray data, jbyteArray privkey, jobject params) {
+ mbedtls_ecp_group curve;
+ create_curve(env, params, &curve);
+
+ mbedtls_mpi priv;
+ create_privkey(env, privkey, &priv);
+
+ mbedtls_mpi r;
+ mbedtls_mpi_init(&r);
+ mbedtls_mpi s;
+ mbedtls_mpi_init(&s);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ native_timing_start();
+ int error = mbedtls_ecdsa_sign(&curve, &r, &s, &priv, data_data, data_size, ctr_drbg_wrapper, &ctr_drbg);
+ native_timing_stop();
+
+ mbedtls_mpi_free(&priv);
+ mbedtls_ecp_group_free(&curve);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ if (error) {
+ throw_new(env, "java/security/GeneralSecurityException", err_to_string(error));
+ mbedtls_mpi_free(&r);
+ mbedtls_mpi_free(&s);
+ return NULL;
+ }
+
+ jsize rlen = (mbedtls_mpi_bitlen(&r) + 7) / 8;
+ jbyte r_bytes[rlen];
+ mbedtls_mpi_write_binary(&r, r_bytes, rlen);
+ jsize slen = (mbedtls_mpi_bitlen(&s) + 7) / 8;
+ jbyte s_bytes[slen];
+ mbedtls_mpi_write_binary(&s, s_bytes, slen);
+
+ mbedtls_mpi_free(&r);
+ mbedtls_mpi_free(&s);
+ return asn1_der_encode(env, r_bytes, rlen, s_bytes, slen);
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024MbedTLS_verify(JNIEnv *env, jobject this, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) {
+ mbedtls_ecp_group curve;
+ create_curve(env, params, &curve);
+
+ mbedtls_ecp_point pub;
+ create_pubkey(env, pubkey, &curve, &pub);
+ jbyte *r_bytes;
+ size_t rlen;
+ jbyte *s_bytes;
+ size_t slen;
+ bool decode = asn1_der_decode(env, signature, &r_bytes, &rlen, &s_bytes, &slen);
+ if (!decode) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error decoding sig.");
+ mbedtls_ecp_point_free(&pub);
+ mbedtls_ecp_group_free(&curve);
+ return JNI_FALSE;
+ }
+
+ mbedtls_mpi r;
+ mbedtls_mpi_init(&r);
+ mbedtls_mpi_read_binary(&r, r_bytes, rlen);
+ mbedtls_mpi s;
+ mbedtls_mpi_init(&s);
+ mbedtls_mpi_read_binary(&s, s_bytes, slen);
+ free(r_bytes);
+ free(s_bytes);
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ native_timing_start();
+ int error = mbedtls_ecdsa_verify(&curve, data_data, data_size, &pub, &r, &s);
+ native_timing_stop();
+
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ if (error) {
+ if (error != MBEDTLS_ERR_ECP_VERIFY_FAILED) {
+ throw_new(env, "java/security/GeneralSecurityException", err_to_string(error));
+ }
+ mbedtls_ecp_point_free(&pub);
+ mbedtls_ecp_group_free(&curve);
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_supported();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getNativeTimingResolution(JNIEnv *env, jobject this) {
+ return native_timing_resolution();
+}
+
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getLastNativeTiming(JNIEnv *env, jobject this) {
+ return native_timing_last();
+}
\ 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 e410204..76268d8 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1435,3 +1435,208 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
}
#endif
#endif
+/* Header for class cz_crcs_ectester_standalone_libs_MbedTLSLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_MbedTLSLib
+#define _Included_cz_crcs_ectester_standalone_libs_MbedTLSLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: supportsNativeTiming
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_supportsNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: getNativeTimingResolution
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getNativeTimingResolution
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: getLastNativeTiming
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getLastNativeTiming
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_MbedTLSLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_MbedTLSLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID 1421746759512286392LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID 4112578634029874840LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS_serialVersionUID -4298000515446427739LL
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_MbedTLS
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024MbedTLS_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS_DEFAULT_KEYSIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS_DEFAULT_KEYSIZE 256L
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_MbedTLS
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024MbedTLS_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_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_MbedTLS
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024MbedTLS_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_MbedTLS
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;Ljava/lang/String;)Ljavax/crypto/SecretKey;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024MbedTLS_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_MbedTLS */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_MbedTLS
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_MbedTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_MbedTLS
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024MbedTLS_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_MbedTLS
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024MbedTLS_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
index a63c2fb..1e1ba02 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -570,14 +570,13 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
native_timing_start();
int result = ECDSA_do_verify((unsigned char *) data_data, data_size, sig_obj, pub);
native_timing_stop();
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
if (result < 0) {
throw_new(env, "java/security/GeneralSecurityException", "Error verifying, ECDSA_do_verify.");
EC_KEY_free(pub); EC_GROUP_free(curve); ECDSA_SIG_free(sig_obj);
- (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
return JNI_FALSE;
}
- (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
ECDSA_SIG_free(sig_obj);
EC_KEY_free(pub);
--
cgit v1.2.3-70-g09d2