aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2018-10-21 13:53:28 +0200
committerJ08nY2018-10-21 13:53:28 +0200
commitb40e99c4d175e5085fa029b98709a06992873de8 (patch)
tree4539d38f2c72c3860e71f3e4de704df6c6de38b9
parent2b073e59b5e8661aac85e89b86a7fe4e657a268f (diff)
parentc3474ab145fc1975b68949f3abd40ea4ee6dd73c (diff)
downloadECTester-b40e99c4d175e5085fa029b98709a06992873de8.tar.gz
ECTester-b40e99c4d175e5085fa029b98709a06992873de8.tar.zst
ECTester-b40e99c4d175e5085fa029b98709a06992873de8.zip
-rw-r--r--README.md17
-rw-r--r--build-standalone.xml7
-rw-r--r--docs/LIBS.md31
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java4
-rw-r--r--src/cz/crcs/ectester/standalone/consts/SignatureIdent.java2
-rw-r--r--src/cz/crcs/ectester/standalone/libs/GcryptLib.java20
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/Makefile71
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java6
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java6
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java23
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java18
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java10
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java91
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/boringssl.c2
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.c101
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/c_utils.h11
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c606
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h181
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/openssl.c2
19 files changed, 1156 insertions, 53 deletions
diff --git a/README.md b/README.md
index 370f144..4112595 100644
--- a/README.md
+++ b/README.md
@@ -222,14 +222,15 @@ If you are interested in testing support for other JavaCard algorithms, please v
## Standalone library testing
Currently supported libraries include:
- - BouncyCastle
- - SunEC
- - OpenSSL
- - BoringSSL
- - Crypto++
- - libtomcrypt
- - botan
- - Microsoft CNG
+ - [BouncyCastle](https://bouncycastle.org/java.html)
+ - [Sun EC](https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunEC)
+ - [OpenSSL](https://www.openssl.org/)
+ - [BoringSSL](https://boringssl.googlesource.com/boringssl)
+ - [Crypto++](https://cryptopp.com/)
+ - [libtomcrypt](http://www.libtom.net/LibTomCrypt/)
+ - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/)
+ - [Botan](https://botan.randombit.net/)
+ - [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx)
For more information on ECC libraries see [LIBS](docs/LIBS.md).
diff --git a/build-standalone.xml b/build-standalone.xml
index c141509..9a47642 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -164,6 +164,13 @@
<class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Boringssl"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Boringssl"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Boringssl"/>
+ <class name="cz.crcs.ectester.standalone.libs.GcryptLib"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeProvider$Gcrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyPairGeneratorSpi$Gcrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPublicKey$Gcrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$Gcrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$Gcrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$Gcrypt"/>
</javah>
</target>
</project>
diff --git a/docs/LIBS.md b/docs/LIBS.md
index ad7aaf0..faab84d 100644
--- a/docs/LIBS.md
+++ b/docs/LIBS.md
@@ -3,14 +3,16 @@
Popular libraries with at least some ECC support:
- [NSS](https://hg.mozilla.org/projects/nss)
- - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/)
- [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)
- [Microsoft .NET crypto](https://docs.microsoft.com/en-us/dotnet/standard/security/cryptography-model)
# Supported libraries
+Libraries that ECTester can test.
+
- [BouncyCastle](https://bouncycastle.org/java.html)
- Java
- Works with the short Weierstrass curve model.
@@ -71,6 +73,23 @@ mkdir build && cd build
cmake -DBUILD_SHARED_LIBS=1 -GNinja ..
ninja
```
+ - [Crypto++](https://cryptopp.com/)
+ - C++
+ - For prime field curves:
+ - Uses projective coordinates and sliding window scalar multiplication algorithm.
+ - For binary field curves:
+ - Uses affine coordinates and sliding window scalar multiplication algorithm.
+ - [libtomcrypt](http://www.libtom.net/LibTomCrypt/)
+ - C
+ - Uses Jacobian coordinates.
+ - Sliding window scalar multiplication algorithm.
+ - [libgcrypt](https://www.gnupg.org/related_software/libgcrypt/)
+ - C
+ - Only supports prime field curves.
+ - Uses short Weierstrass, Montgomery and Twisted Edwards models.
+ - Uses left-to-right double-and-add always scalar multiplication and Jacobian coordinates in short Weierstrass form.
+ - Uses Montgomery ladder and X-only in Montgomery form.
+ - Uses left-to-right double-and-add always scalar multiplication in Twisted Edwards form.
- [Botan](https://botan.randombit.net/)
- C++
- Uses blinded(randomized) Montgomery ladder.
@@ -78,16 +97,6 @@ ninja
- <https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-1986-cc>
- <https://eprint.iacr.org/2015/657>
- ECTester supports v2.4.0 and up.
- - [libtomcrypt](http://www.libtom.net/LibTomCrypt/)
- - C
- - Uses Jacobian coordinates.
- - Sliding window scalar multiplication algorithm.
- - [Crypto++](https://cryptopp.com/)
- - C++
- - For prime field curves:
- - Uses projective coordinates and sliding window scalar multiplication algorithm.
- - For binary field curves:
- - Uses affine coordinates and sliding window scalar multiplication algorithm.
- [Microsoft CNG](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376210(v=vs.85).aspx)
- C API.
- Closed source.
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index cb6728b..7480215 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -66,7 +66,7 @@ import java.util.stream.Collectors;
* @version v0.3.0
*/
public class ECTesterStandalone {
- private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new MscngLib()};
+ private ProviderECLibrary[] libs = new ProviderECLibrary[]{new SunECLib(), new BouncyCastleLib(), new TomcryptLib(), new BotanLib(), new CryptoppLib(), new OpensslLib(), new BoringsslLib(), new GcryptLib(), new MscngLib()};
private Config cfg;
private Options opts = new Options();
@@ -325,7 +325,7 @@ public class ECTesterStandalone {
ECPublicKey pubkey = (ECPublicKey) other.getPublic();
long elapsed = -System.nanoTime();
- if (spec != null) {
+ if (spec instanceof ECParameterSpec) {
ka.init(privkey, spec);
} else {
ka.init(privkey);
diff --git a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
index dea8abe..93b7f99 100644
--- a/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
+++ b/src/cz/crcs/ectester/standalone/consts/SignatureIdent.java
@@ -52,7 +52,7 @@ public class SignatureIdent extends Ident {
ALL.add(new SignatureIdent("ECGOST3410-2012-512", "GOST-3410-2012-512"));
ALL.add(new SignatureIdent("GOST3411-2012-512withECGOST3410-2012-512", "GOST3411-2012-512/ECGOST3410-2012-5120", "1.2.643.7.1.1.3.3"));
ALL.add(new SignatureIdent("SM3withSM2"));
- // ECDDSA
+ // ECDDSA (rfc6979?)
ALL.add(new SignatureIdent("ECDDSA", "DETECDSA", "ECDETDSA"));
ALL.add(new SignatureIdent("SHA1withECDDSA", "SHA1withDETECDSA"));
ALL.add(new SignatureIdent("SHA224withECDDSA", "SHA224withDETECDSA"));
diff --git a/src/cz/crcs/ectester/standalone/libs/GcryptLib.java b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
new file mode 100644
index 0000000..a0a7fc8
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/GcryptLib.java
@@ -0,0 +1,20 @@
+package cz.crcs.ectester.standalone.libs;
+
+import java.security.Provider;
+import java.util.Set;
+
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
+public class GcryptLib extends NativeECLibrary {
+
+ public GcryptLib() {
+ super("gcrypt_provider", "gcrypt", "gpg-error");
+ }
+
+ @Override
+ native Provider createProvider();
+
+ @Override
+ public native Set<String> getCurves();
+}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/Makefile b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
index 189a6dd..2232e3d 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/Makefile
+++ b/src/cz/crcs/ectester/standalone/libs/jni/Makefile
@@ -1,3 +1,28 @@
+###############################################################################
+## General CC setup.
+
+CC?=gcc
+CXX?=g++
+
+LFLAGS+=-fPIC -shared
+CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
+
+DEBUG ?= 0
+
+ifeq ($(DEBUG), 1)
+ CFLAGS+=-g -Wall
+ LFLAGS+=-g
+ CXXFLAGS+=-g -Wall
+else
+ CFLAGS+=-O2
+ LFLAGS+=-O2
+ CXXFLAGS+=-O2
+endif
+
+###############################################################################
+## Java JNI setup.
+
ifeq ($(JAVA_HOME),)
ifeq ($(OS),Windows_NT)
which = $(shell where $1)
@@ -24,37 +49,16 @@ ifeq ($(JNI_PLATFORM),)
else
ifeq ($(findstring linux,$(TARGETTRIPLET)),linux)
JNI_PLATFORM:= linux
- # add more checks here
endif
endif
endif
JNI_PLATFORMINCLUDEDIR ?= $(JNI_INCLUDEDIR)/$(JNI_PLATFORM)
-LOCAL_INCLUDES = /usr/local/include
-LOCAL_LIBS = /usr/local/lib
+###############################################################################
+## Targets.
-CC?=gcc
-CXX?=g++
-STRIP?=strip
-
-LFLAGS+=-fPIC -shared
-CFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-CXXFLAGS+=-fPIC -I"$(JNI_INCLUDEDIR)" -I"$(JNI_PLATFORMINCLUDEDIR)" -I.
-
-DEBUG ?= 0
-
-ifeq ($(DEBUG), 1)
- CFLAGS+=-g
- LFLAGS+=-g
- CXXFLAGS+=-g
-else
- CFLAGS+=-O2
- LFLAGS+=-O2
- CXXFLAGS+=-O2
-endif
-
-all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so
+all: tomcrypt_provider.so botan_provider.so cryptopp_provider.so openssl_provider.so boringssl_provider.so gcrypt_provider.so
# Common utils
c_utils.o: c_utils.c
@@ -81,6 +85,14 @@ boringssl.o: boringssl.c
$(CC) -I../../../../../../../ext/boringssl/include/ $(CFLAGS) -c $<
+# libgcrypt shim
+gcrypt_provider.so: gcrypt.o c_utils.o
+ $(CC) $(LFLAGS) -o $@ $^ -L. $(shell libgcrypt-config --libs)
+
+gcrypt.o: gcrypt.c
+ $(CC) $(shell libgcrypt-config --cflags) $(CFLAGS) -c $<
+
+
# Libtomcrypt shim
tomcrypt_provider.so: tomcrypt.o c_utils.o
$(CC) $(LFLAGS) -o $@ $^ -L. -ltommath $(shell pkg-config --libs libtomcrypt)
@@ -104,9 +116,18 @@ cryptopp_provider.so: cryptopp.o cpp_utils.o
cryptopp.o: cryptopp.cpp
$(CXX) $(shell pkg-config --cflags libcrypto++) $(CXXFLAGS) -c $<
+help:
+ @echo "# This makefile builds the JNI shims necessary to test native libraries."
+ @echo "# Targets:"
+ @echo " - openssl_provider.so"
+ @echo " - boringssl_provider.so"
+ @echo " - gcrypt_provider.so"
+ @echo " - tomcrypt_provider.so"
+ @echo " - botan_provider.so"
+ @echo " - cryptopp_provider.so"
clean:
rm -rf *.o
rm -rf *.so
-.PHONY: all clean \ No newline at end of file
+.PHONY: all help clean \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
index a74c155..6d8101f 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPrivateKey.java
@@ -91,6 +91,12 @@ public abstract class NativeECPrivateKey implements ECPrivateKey {
}
}
+ public static class Gcrypt extends Raw {
+ public Gcrypt(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 7c17646..dcb8b3f 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeECPublicKey.java
@@ -92,6 +92,12 @@ public abstract class NativeECPublicKey implements ECPublicKey {
}
}
+ public static class Gcrypt extends ANSIX962 {
+ public Gcrypt(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 5fca448..7b531f5 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -65,7 +65,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
@Override
protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
if (!(params instanceof ECParameterSpec)) {
- throw new InvalidAlgorithmParameterException();
+ throw new InvalidAlgorithmParameterException(params.toString());
}
engineInit(key, random);
this.params = params;
@@ -254,6 +254,27 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
}
+ public abstract static class Gcrypt extends SimpleKeyAgreementSpi {
+ private String type;
+
+ public Gcrypt(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 GcryptECDH extends Gcrypt {
+ public GcryptECDH() {
+ super("ECDH");
+ }
+ }
+
+
public abstract static class Mscng extends ExtendedKeyAgreementSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
index 77f0d18..78656fc 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyPairGeneratorSpi.java
@@ -198,6 +198,24 @@ public abstract class NativeKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
}
+ public static class Gcrypt extends NativeKeyPairGeneratorSpi {
+
+ public Gcrypt() {
+ }
+
+ @Override
+ native boolean keysizeSupported(int keysize);
+
+ @Override
+ native boolean paramsSupported(AlgorithmParameterSpec params);
+
+ @Override
+ native KeyPair generate(int keysize, SecureRandom random);
+
+ @Override
+ native KeyPair generate(AlgorithmParameterSpec params, SecureRandom random);
+ }
+
public static abstract class Mscng extends NativeKeyPairGeneratorSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
index 1399500..99baa97 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeProvider.java
@@ -74,6 +74,16 @@ public abstract class NativeProvider extends Provider {
native void setup();
}
+ public static class Gcrypt extends NativeProvider {
+
+ public Gcrypt(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ @Override
+ native void setup();
+ }
+
public static class Mscng extends NativeProvider {
public Mscng(String name, double version, String info) {
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index 3f99771..f2b1ab9 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -349,6 +349,97 @@ public abstract class NativeSignatureSpi extends SignatureSpi {
}
}
+ public abstract static class Gcrypt extends SimpleSignatureSpi {
+ private String type;
+
+ public Gcrypt(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 GcryptECDSAwithNONE extends Gcrypt {
+
+ public GcryptECDSAwithNONE() {
+ super("NONEwithECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA1 extends Gcrypt {
+
+ public GcryptECDSAwithSHA1() {
+ super("SHA1withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA224 extends Gcrypt {
+
+ public GcryptECDSAwithSHA224() {
+ super("SHA224withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA256 extends Gcrypt {
+
+ public GcryptECDSAwithSHA256() {
+ super("SHA256withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA384 extends Gcrypt {
+
+ public GcryptECDSAwithSHA384() {
+ super("SHA384withECDSA");
+ }
+ }
+
+ public static class GcryptECDSAwithSHA512 extends Gcrypt {
+
+ public GcryptECDSAwithSHA512() {
+ super("SHA512withECDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA1 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA1() {
+ super("SHA1withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA224 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA224() {
+ super("SHA224withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA256 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA256() {
+ super("SHA256withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA384 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA384() {
+ super("SHA384withECDDSA");
+ }
+ }
+
+ public static class GcryptECDDSAwithSHA512 extends Gcrypt {
+
+ public GcryptECDDSAwithSHA512() {
+ super("SHA512withECDDSA");
+ }
+ }
+
public abstract static class Mscng extends ExtendedSignatureSpi {
private String type;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
index 0353741..965e396 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/boringssl.c
@@ -1,6 +1,5 @@
#include "native.h"
#include <string.h>
-#include <stdio.h>
#include <openssl/conf.h>
#include <openssl/opensslv.h>
@@ -256,7 +255,6 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) {
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);
- fflush(stderr);
BN_free(a);
BN_free(b);
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 49cab44..c36d3c9 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.c
@@ -75,7 +75,7 @@ void throw_new_var(JNIEnv *env, const char *class, const char *format, ...) {
char buffer[2048];
va_list args;
va_start(args, format);
- int res = vsnprintf(buffer, 2048, format, args);
+ vsnprintf(buffer, 2048, format, args);
va_end(args);
throw_new(env, class, buffer);
}
@@ -105,4 +105,103 @@ jint get_kdf_bits(JNIEnv *env, jstring algorithm) {
}
(*env)->ReleaseStringUTFChars(env, algorithm, algo_data);
return result;
+}
+
+jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyte *s, size_t s_len) {
+ jbyte r_length = (jbyte) r_len + (r[0] & 0x80 ? 1 : 0);
+ jbyte s_length = (jbyte) s_len + (s[0] & 0x80 ? 1 : 0);
+
+ // R and S are < 128 bytes, so 1 byte tag + 1 byte len + len bytes value
+ size_t seq_value_len = 2 + r_length + 2 + s_length;
+ size_t whole_len = seq_value_len;
+
+ // The SEQUENCE length might be >= 128, so more bytes of length
+ size_t seq_len_len = 0;
+ if (seq_value_len >= 128) {
+ size_t s = seq_value_len;
+ while ((s = s >> 8)) {
+ seq_len_len++;
+ }
+ }
+ // seq_len_len bytes for length and one for length of length
+ whole_len += seq_len_len + 1;
+
+ // 1 byte tag for SEQUENCE
+ whole_len += 1;
+
+ jbyteArray result = (jbyteArray) (*env)->NewByteArray(env, whole_len);
+ jbyte *data = (*env)->GetByteArrayElements(env, result, NULL);
+ size_t i = 0;
+ data[i++] = 0x30; // SEQUENCE
+ if (seq_value_len < 128) {
+ data[i++] = (jbyte) seq_value_len;
+ } 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++] = 0x02; //INTEGER
+ data[i++] = r_length;
+ if (r[0] & 0x80) {
+ data[i++] = 0;
+ }
+ memcpy(data + i, r, r_len);
+ i += r_len;
+ data[i++] = 0x02; //INTEGER
+ data[i++] = s_length;
+ if (s[0] & 0x80) {
+ data[i++] = 0;
+ }
+ memcpy(data + i, s, s_len);
+ i += s_len;
+ (*env)->ReleaseByteArrayElements(env, result, data, 0);
+
+ return result;
+}
+
+bool asn1_der_decode(JNIEnv *env, jbyteArray sig, jbyte **r_data, size_t *r_len, jbyte **s_data, size_t *s_len) {
+ size_t sig_len = (*env)->GetArrayLength(env, sig);
+ jbyte *data = (*env)->GetByteArrayElements(env, sig, NULL);
+ size_t i = 0;
+ if (data[i++] != 0x30) {//SEQUENCE
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t seq_value_len = 0;
+ if (!(data[i] & 0x80)) {
+ seq_value_len = data[i++];
+ } else {
+ size_t seq_len_len = data[i++] & 0x7f;
+ while (seq_len_len > 0) {
+ seq_value_len |= (data[i++] << (seq_len_len - 1));
+ seq_len_len--;
+ }
+ }
+
+ if (data[i++] != 0x02) {//INTEGER
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t r_length = data[i++];
+ jbyte *r_out = malloc(r_length);
+ memcpy(r_out, data + i, r_length);
+ i += r_length;
+
+ if (data[i++] != 0x02) {//INTEGER
+ free(r_out);
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return false;
+ }
+ size_t s_length = data[i++];
+ jbyte *s_out = malloc(s_length);
+ memcpy(s_out, data + i, s_length);
+ i += s_length;
+
+ *r_len = r_length;
+ *r_data = r_out;
+ *s_len = s_length;
+ *s_data = s_out;
+ (*env)->ReleaseByteArrayElements(env, sig, data, JNI_ABORT);
+ return true;
} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
index b767b61..82c3538 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/c_utils.h
@@ -1,6 +1,7 @@
#pragma once
#include "native.h"
+#include <stdbool.h>
/**
* Classes that are accessed alot are cached here, manually.
@@ -39,6 +40,16 @@ void throw_new_var(JNIEnv *env, const char *class, const char *format, ...);
jint get_kdf_bits(JNIEnv *env, jstring algorithm);
/**
+ * DER encode the r and s values.
+ */
+jbyteArray asn1_der_encode(JNIEnv *env, const jbyte *r, size_t r_len, const jbyte *s, size_t s_len);
+
+/**
+ * DER decode a signature into r and s values.
+ */
+bool asn1_der_decode(JNIEnv *env, jbyteArray sig, jbyte **r_data, size_t *r_len, jbyte **s_data, size_t *s_len);
+
+/**
* Some useful defines to init the provider.
*/
#define INIT_PROVIDER(env, provider_class) jmethodID provider_put = (*env)->GetMethodID(env, provider_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
new file mode 100644
index 0000000..0ba94c6
--- /dev/null
+++ b/src/cz/crcs/ectester/standalone/libs/jni/gcrypt.c
@@ -0,0 +1,606 @@
+#include "native.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <gcrypt.h>
+#include "c_utils.h"
+
+static jclass provider_class;
+
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_createProvider(JNIEnv *env, jobject this){
+ /* Create the custom provider. */
+ jclass local_provider_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeProvider$Gcrypt");
+ provider_class = (*env)->NewGlobalRef(env, local_provider_class);
+
+ jmethodID init = (*env)->GetMethodID(env, local_provider_class, "<init>", "(Ljava/lang/String;DLjava/lang/String;)V");
+
+ const char *running_with = gcry_check_version(GCRYPT_VERSION);
+ if (!running_with) {
+ return NULL;
+ }
+ char full_name[strlen("libgcrypt ") + strlen(running_with) + 1];
+ strcpy(full_name, "libgcrypt ");
+ strcat(full_name, running_with);
+ jstring name = (*env)->NewStringUTF(env, full_name);
+ double version = strtod(running_with, NULL);
+
+ return (*env)->NewObject(env, provider_class, init, name, version, name);
+}
+
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup(JNIEnv *env, jobject this) {
+ gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+ //gcry_control(GCRYCTL_SET_DEBUG_FLAGS, 1);
+ gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+ INIT_PROVIDER(env, provider_class);
+
+ ADD_KPG(env, this, "EC", "Gcrypt");
+ ADD_KA(env, this, "ECDH", "GcryptECDH");
+ ADD_SIG(env, this, "NONEwithECDSA", "GcryptECDSAwithNONE");
+ ADD_SIG(env, this, "SHA1withECDSA", "GcryptECDSAwithSHA1");
+ ADD_SIG(env, this, "SHA224withECDSA", "GcryptECDSAwithSHA224");
+ ADD_SIG(env, this, "SHA256withECDSA", "GcryptECDSAwithSHA256");
+ ADD_SIG(env, this, "SHA384withECDSA", "GcryptECDSAwithSHA384");
+ ADD_SIG(env, this, "SHA512withECDSA", "GcryptECDSAwithSHA512");
+ ADD_SIG(env, this, "SHA1withECDDSA", "GcryptECDDSAwithSHA1");
+ ADD_SIG(env, this, "SHA224withECDDSA", "GcryptECDDSAwithSHA224");
+ ADD_SIG(env, this, "SHA256withECDDSA", "GcryptECDDSAwithSHA256");
+ ADD_SIG(env, this, "SHA384withECDDSA", "GcryptECDDSAwithSHA384");
+ ADD_SIG(env, this, "SHA512withECDDSA", "GcryptECDDSAwithSHA512");
+
+ init_classes(env, "Gcrypt");
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_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, "<init>", "()V");
+ jmethodID hash_set_add = (*env)->GetMethodID(env, hash_set_class, "add", "(Ljava/lang/Object;)Z");
+
+ jobject result = (*env)->NewObject(env, hash_set_class, hash_set_ctr);
+
+ const char *name;
+ unsigned int nbits;
+
+ for (size_t i = 0; (name = gcry_pk_get_curve(NULL, i, &nbits)); i++){
+ jstring curve_name = (*env)->NewStringUTF(env, name);
+ (*env)->CallBooleanMethod(env, result, hash_set_add, curve_name);
+ }
+
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize) {
+ const char *name;
+ unsigned int nbits;
+
+ for (size_t i = 0; (name = gcry_pk_get_curve(NULL, i, &nbits)); i++){
+ if (nbits == keysize) {
+ return JNI_TRUE;
+ }
+ }
+
+ return JNI_FALSE;
+}
+
+static void print_sexp(gcry_sexp_t sexp) {
+ size_t len = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+ char string[len];
+ gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, string, len);
+ printf("%s\n", string);
+ fflush(stdout);
+}
+
+static void print_chrray(unsigned char *arr, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ printf("%02x,", ((unsigned char) arr[i] & 0xff));
+ }
+ printf("\n");
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_paramsSupported(JNIEnv *env, jobject this, jobject params) {
+ if (params == NULL) {
+ return JNI_FALSE;
+ }
+
+ if ((*env)->IsInstanceOf(env, params, ec_parameter_spec_class)) {
+ return JNI_FALSE;
+ } 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);
+ gcry_sexp_t curve_sexp;
+ gcry_sexp_build(&curve_sexp, NULL, "(public-key (ecc (curve %s)))", utf_name);
+ unsigned int nbits;
+ const char *ret_name = gcry_pk_get_curve(curve_sexp, 0, &nbits);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ gcry_sexp_release(curve_sexp);
+ return ret_name ? JNI_TRUE : JNI_FALSE;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+static gcry_mpi_t bytearray_to_mpi(JNIEnv *env, jbyteArray array) {
+ if (!array) {
+ return NULL;
+ }
+
+ gcry_mpi_t result;
+
+ size_t length = (*env)->GetArrayLength(env, array);
+ char data[length + 1];
+ data[0] = 0;
+ (*env)->GetByteArrayRegion(env, array, 0, length, data + 1);
+ gcry_mpi_scan(&result, GCRYMPI_FMT_USG, data, length + 1, NULL);
+ return result;
+}
+
+static jbyteArray mpi_to_bytearray0(JNIEnv *env, gcry_mpi_t mpi, size_t start, size_t len) {
+ if (!mpi) {
+ return NULL;
+ }
+
+ size_t mpi_len = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &mpi_len, mpi);
+ if (start >= mpi_len) {
+ return NULL;
+ }
+ if (start + len > mpi_len || len == 0) {
+ len = mpi_len - start;
+ }
+ unsigned char buff[mpi_len];
+ gcry_mpi_print(GCRYMPI_FMT_USG, buff, mpi_len, NULL, mpi);
+ jbyteArray bytes = (*env)->NewByteArray(env, len);
+ jbyte *data = (*env)->GetByteArrayElements(env, bytes, NULL);
+ memcpy(data, buff + start, len);
+ (*env)->ReleaseByteArrayElements(env, bytes, data, 0);
+ return bytes;
+}
+
+static jbyteArray mpi_to_bytearray(JNIEnv *env, gcry_mpi_t mpi) {
+ return mpi_to_bytearray0(env, mpi, 0, 0);
+}
+
+static jobject mpi_to_biginteger(JNIEnv *env, gcry_mpi_t mpi) {
+ if (!mpi) {
+ return NULL;
+ }
+
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "<init>", "(I[B)V");
+ jbyteArray bytes = mpi_to_bytearray(env, mpi);
+ jobject result = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, bytes);
+ return result;
+}
+
+static gcry_mpi_t biginteger_to_mpi(JNIEnv *env, jobject bigint) {
+ if (!bigint) {
+ return NULL;
+ }
+
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+ jbyteArray byte_array = (jbyteArray) (*env)->CallObjectMethod(env, bigint, to_byte_array);
+ return bytearray_to_mpi(env, byte_array);
+}
+
+static jint mpi_to_jint(gcry_mpi_t mpi) {
+ jint result = 0;
+ unsigned long nbits = gcry_mpi_get_nbits(mpi);
+ int max_bits = sizeof(jint) * 8;
+ for (size_t i = 0; i < nbits && i < max_bits; ++i) {
+ if (gcry_mpi_test_bit(mpi, nbits - i - 1)) {
+ result = ((result << 1) | 1);
+ } else {
+ result = (result << 1);
+ }
+ }
+ return result;
+}
+
+static jobject buff_to_ecpoint(JNIEnv *env, gcry_buffer_t buff) {
+ jint coord_size = (buff.len - 1) / 2;
+ jmethodID biginteger_init = (*env)->GetMethodID(env, biginteger_class, "<init>", "(I[B)V");
+
+ jbyteArray x_bytes = (*env)->NewByteArray(env, coord_size);
+ jbyte *x_data = (*env)->GetByteArrayElements(env, x_bytes, NULL);
+ memcpy(x_data, ((char *) buff.data) + 1, coord_size);
+ (*env)->ReleaseByteArrayElements(env, x_bytes, x_data, 0);
+ jobject xi = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, x_bytes);
+
+ jbyteArray y_bytes = (*env)->NewByteArray(env, coord_size);
+ jbyte *y_data = (*env)->GetByteArrayElements(env, y_bytes, NULL);
+ memcpy(y_data, ((char *) buff.data) + 1 + coord_size, coord_size);
+ (*env)->ReleaseByteArrayElements(env, y_bytes, y_data, 0);
+ jobject yi = (*env)->NewObject(env, biginteger_class, biginteger_init, 1, y_bytes);
+
+ jmethodID point_init = (*env)->GetMethodID(env, point_class, "<init>", "(Ljava/math/BigInteger;Ljava/math/BigInteger;)V");
+ return (*env)->NewObject(env, point_class, point_init, xi, yi);
+}
+
+static jobject create_ec_param_spec(JNIEnv *env, gcry_sexp_t key) {
+ jobject result = NULL;
+ gcry_mpi_t p, a, b, n, h;
+ gcry_buffer_t g = {0};
+ gcry_error_t err = gcry_sexp_extract_param(key, "ecc", "pab&g+nh", &p, &a, &b, &g, &n, &h, NULL);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error exporting domain parameters. Error: %ui", gcry_err_code(err));
+ goto end;
+ }
+
+ jobject pi = mpi_to_biginteger(env, p);
+ jmethodID fp_field_init = (*env)->GetMethodID(env, fp_field_class, "<init>", "(Ljava/math/BigInteger;)V");
+ jobject field = (*env)->NewObject(env, fp_field_class, fp_field_init, pi);
+
+ jobject ai = mpi_to_biginteger(env, a);
+ jobject bi = mpi_to_biginteger(env, b);
+
+ 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, ai, bi);
+
+ jobject gen = buff_to_ecpoint(env, g);
+
+ jobject order = mpi_to_biginteger(env, n);
+ jint cofactor = mpi_to_jint(h);
+
+ 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");
+ result = (*env)->NewObject(env, ec_parameter_spec_class, ec_parameter_spec_init, elliptic_curve, gen, order, cofactor);
+
+end:
+ gcry_mpi_release(p);
+ gcry_mpi_release(a);
+ gcry_mpi_release(b);
+ gcry_free(g.data);
+ gcry_mpi_release(n);
+ gcry_mpi_release(h);
+ return result;
+}
+
+static jobject generate_from_sexp(JNIEnv *env, gcry_sexp_t gen_sexp) {
+ jobject result = NULL;
+ gcry_sexp_t key_sexp;
+ gcry_error_t err = gcry_pk_genkey(&key_sexp, gen_sexp);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error generating key. Error: %ui", gcry_err_code(err));
+ goto release_sexp;
+ }
+ gcry_sexp_t pkey = gcry_sexp_find_token(key_sexp, "public-key", 0);
+ gcry_sexp_t skey = gcry_sexp_find_token(key_sexp, "private-key", 0);
+
+ jobject ec_param_spec = create_ec_param_spec(env, skey);
+ if (!ec_param_spec) {
+ goto release_keypair;
+ }
+
+ gcry_buffer_t q = {0};
+ gcry_mpi_t d;
+ err = gcry_sexp_extract_param(skey, "ecc", "&q+d", &q, &d, NULL);
+
+ jbyteArray pub_bytes = (*env)->NewByteArray(env, q.size);
+ jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
+ memcpy(key_pub, q.data, q.size);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
+
+ size_t priv_len = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &priv_len, d);
+ jbyteArray priv_bytes = (*env)->NewByteArray(env, priv_len);
+ jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
+ gcry_mpi_print(GCRYMPI_FMT_USG, key_priv, priv_len, NULL, d);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+
+ jobject ec_pub_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
+ jmethodID ec_pub_init = (*env)->GetMethodID(env, pubkey_class, "<init>", "([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, "<init>", "([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, "<init>", "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V");
+ result = (*env)->NewObject(env, keypair_class, keypair_init, pubkey, privkey);
+
+ gcry_mpi_release(d);
+ gcry_free(q.data);
+
+release_keypair:
+ gcry_sexp_release(pkey);
+ gcry_sexp_release(skey);
+release_sexp:
+ gcry_sexp_release(key_sexp);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject this, jint keysize, jobject random) {
+ gcry_sexp_t gen_sexp;
+ gcry_sexp_build(&gen_sexp, NULL, "(genkey (ecc (flags no-keytest param) (nbits %d)))", keysize);
+
+ jobject result = generate_from_sexp(env, gen_sexp);
+ gcry_sexp_release(gen_sexp);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_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)) {
+ return NULL;
+ } 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);
+ gcry_sexp_t gen_sexp;
+ gcry_sexp_build(&gen_sexp, NULL, "(genkey (ecc (flags no-keytest param) (curve %s)))", utf_name);
+ (*env)->ReleaseStringUTFChars(env, name, utf_name);
+ jobject result = generate_from_sexp(env, gen_sexp);
+ gcry_sexp_release(gen_sexp);
+ return result;
+ } else {
+ return NULL;
+ }
+}
+
+static gcry_sexp_t create_key(JNIEnv *env, jobject ec_param_spec, const char *key_fmt, gcry_mpi_t q, gcry_mpi_t d) {
+ gcry_sexp_t inner;
+ gcry_mpi_t p, a, b, g, n, h;
+
+ jmethodID get_curve = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCurve", "()Ljava/security/spec/EllipticCurve;");
+ jobject elliptic_curve = (*env)->CallObjectMethod(env, ec_param_spec, get_curve);
+
+ jmethodID get_field = (*env)->GetMethodID(env, elliptic_curve_class, "getField", "()Ljava/security/spec/ECField;");
+ jobject field = (*env)->CallObjectMethod(env, elliptic_curve, get_field);
+
+ jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
+ jint bits = (*env)->CallIntMethod(env, field, get_bits);
+ jint bytes = (bits + 7) / 8;
+
+ jmethodID get_a = (*env)->GetMethodID(env, elliptic_curve_class, "getA", "()Ljava/math/BigInteger;");
+ jobject big_a = (*env)->CallObjectMethod(env, elliptic_curve, get_a);
+ a = biginteger_to_mpi(env, big_a);
+
+ jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
+ jobject big_b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
+ b = biginteger_to_mpi(env, big_b);
+
+ jmethodID get_p = (*env)->GetMethodID(env, fp_field_class, "getP", "()Ljava/math/BigInteger;");
+ jobject big_p = (*env)->CallObjectMethod(env, field, get_p);
+ p = biginteger_to_mpi(env, big_p);
+
+ jmethodID get_g = (*env)->GetMethodID(env, ec_parameter_spec_class, "getGenerator", "()Ljava/security/spec/ECPoint;");
+ jobject g_point = (*env)->CallObjectMethod(env, ec_param_spec, get_g);
+
+ jmethodID get_x = (*env)->GetMethodID(env, point_class, "getAffineX", "()Ljava/math/BigInteger;");
+ jobject gx = (*env)->CallObjectMethod(env, g_point, get_x);
+
+ jmethodID get_y = (*env)->GetMethodID(env, point_class, "getAffineY", "()Ljava/math/BigInteger;");
+ jobject gy = (*env)->CallObjectMethod(env, g_point, get_y);
+
+ jmethodID to_byte_array = (*env)->GetMethodID(env, biginteger_class, "toByteArray", "()[B");
+
+ jbyteArray gx_bytes = (jbyteArray) (*env)->CallObjectMethod(env, gx, to_byte_array);
+ size_t gx_len = (*env)->GetArrayLength(env, gx_bytes);
+ jbyteArray gy_bytes = (jbyteArray) (*env)->CallObjectMethod(env, gy, to_byte_array);
+ size_t gy_len = (*env)->GetArrayLength(env, gy_bytes);
+ unsigned char g_data[1 + 2 * bytes];
+ g_data[0] = 0x04;
+ jbyte *gx_data = (*env)->GetByteArrayElements(env, gx_bytes, NULL);
+ memcpy(g_data + 1, gx_data + (gx_len - bytes), bytes);
+ (*env)->ReleaseByteArrayElements(env, gx_bytes, gx_data, JNI_ABORT);
+ jbyte *gy_data = (*env)->GetByteArrayElements(env, gy_bytes, NULL);
+ memcpy(g_data + 1 + bytes, gy_data + (gy_len - bytes), bytes);
+ (*env)->ReleaseByteArrayElements(env, gy_bytes, gy_data, JNI_ABORT);
+
+ gcry_mpi_scan(&g, GCRYMPI_FMT_USG, g_data, 1 + 2 * bytes, NULL);
+
+ jmethodID get_n = (*env)->GetMethodID(env, ec_parameter_spec_class, "getOrder", "()Ljava/math/BigInteger;");
+ jobject big_n = (*env)->CallObjectMethod(env, ec_param_spec, get_n);
+ n = biginteger_to_mpi(env, big_n);
+
+ jmethodID get_h = (*env)->GetMethodID(env, ec_parameter_spec_class, "getCofactor", "()I");
+ jint jh = (*env)->CallIntMethod(env, ec_param_spec, get_h);
+ h = gcry_mpi_set_ui(NULL, jh);
+
+ if (q && d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (q %M) (d %M))", p, a, b, g, n, h, q, d, NULL);
+ } else if (q && !d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (q %M))", p, a, b, g, n, h, q, NULL);
+ } else if (!q && d) {
+ gcry_sexp_build(&inner, NULL, "(ecc (flags param) (p %M) (a %M) (b %M) (g %M) (n %M) (h %M) (d %M))", p, a, b, g, n, h, d, NULL);
+ }
+ gcry_sexp_t result;
+ gcry_sexp_build(&result, NULL, key_fmt, inner, NULL);
+ gcry_sexp_release(inner);
+ return result;
+}
+
+static gcry_sexp_t create_pubkey(JNIEnv *env, jobject ec_param_spec, jbyteArray pubkey) {
+ gcry_mpi_t q = bytearray_to_mpi(env, pubkey);
+ gcry_sexp_t result = create_key(env, ec_param_spec, "(public-key %S)", q, NULL);
+ gcry_mpi_release(q);
+ return result;
+}
+
+static gcry_sexp_t create_privkey(JNIEnv *env, jobject ec_param_spec, jbyteArray pubkey, jbyteArray privkey) {
+ gcry_mpi_t q = bytearray_to_mpi(env, pubkey);
+ gcry_mpi_t d = bytearray_to_mpi(env, privkey);
+ gcry_sexp_t result = create_key(env, ec_param_spec, "(private-key %S)", q, d);
+ gcry_mpi_release(q);
+ gcry_mpi_release(d);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params) {
+ jbyteArray result = NULL;
+ gcry_sexp_t pub = create_pubkey(env, params, pubkey);
+ gcry_mpi_t priv = bytearray_to_mpi(env, privkey);
+
+ gcry_sexp_t enc_sexp;
+ gcry_sexp_build(&enc_sexp, NULL, "(data (flags raw) (value %M))", priv, NULL);
+ gcry_sexp_t res_sexp;
+ // TODO: figure out why ecc_encrypt_raw takes signed representation.. Nobody uses that., everybody uses unsigned reduced mod p.
+ gcry_error_t err = gcry_pk_encrypt(&res_sexp, enc_sexp, pub);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDH. Error: %ui", gcry_err_code(err));
+ goto end;
+ }
+
+ gcry_mpi_t derived;
+ err = gcry_sexp_extract_param(res_sexp, NULL, "s", &derived, NULL);
+
+ size_t derived_bytes;
+ gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &derived_bytes, derived);
+ size_t coord_bytes = (derived_bytes - 1) / 2;
+ result = mpi_to_bytearray0(env, derived, 1, coord_bytes);
+
+ gcry_mpi_release(derived);
+end:
+ gcry_sexp_release(enc_sexp);
+ gcry_sexp_release(res_sexp);
+ gcry_sexp_release(pub);
+ gcry_mpi_release(priv);
+ return result;
+}
+
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2Ljava_lang_String_2(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params, jstring algorithm) {
+ throw_new(env, "java/lang/UnsupportedOperationException", "Not supported.");
+ return NULL;
+}
+
+static int starts_with(const char *whole, const char *prefix) {
+ return !strncmp(whole, prefix, strlen(prefix));
+}
+
+static int get_hash_algo(const char *sig_type) {
+ if (starts_with(sig_type, "SHA1")) {
+ return GCRY_MD_SHA1;
+ } else if (starts_with(sig_type, "SHA224")) {
+ return GCRY_MD_SHA224;
+ } else if (starts_with(sig_type, "SHA256")) {
+ return GCRY_MD_SHA256;
+ } else if (starts_with(sig_type, "SHA384")) {
+ return GCRY_MD_SHA384;
+ } else if (starts_with(sig_type, "SHA512")) {
+ return GCRY_MD_SHA512;
+ } else {
+ return GCRY_MD_NONE;
+ }
+}
+
+static const char *get_sig_algo(const char *sig_type) {
+ const char *start = strstr(sig_type, "with") + strlen("with");
+ if (starts_with(start, "ECDSA")) {
+ return NULL;
+ } else if (starts_with(start, "ECDDSA")) {
+ return "rfc6979";
+ } else {
+ return NULL;
+ }
+}
+
+static void get_sign_data_sexp(JNIEnv *env, gcry_sexp_t *result, jobject this, jbyteArray data) {
+ jclass sig_class = (*env)->FindClass(env, "cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi$Gcrypt");
+ jfieldID type_id = (*env)->GetFieldID(env, sig_class, "type", "Ljava/lang/String;");
+ jstring type = (jstring)(*env)->GetObjectField(env, this, type_id);
+ const char* type_data = (*env)->GetStringUTFChars(env, type, NULL);
+ int hash_algo = get_hash_algo(type_data);
+ const char *sig_algo = get_sig_algo(type_data);
+ const char *with = strstr(type_data, "with");
+ char hash_name[with - type_data + 1];
+ memcpy(hash_name, type_data, with - type_data);
+ for (size_t i = 0; i < with - type_data; ++i) {
+ hash_name[i] = tolower(hash_name[i]);
+ }
+ hash_name[with - type_data] = 0;
+ (*env)->ReleaseStringUTFChars(env, type, type_data);
+
+ if (hash_algo == GCRY_MD_NONE) {
+ gcry_mpi_t data_mpi = bytearray_to_mpi(env, data);
+ gcry_sexp_build(result, NULL, "(data (flags raw param) (value %M))", data_mpi);
+ gcry_mpi_release(data_mpi);
+ } else {
+ unsigned int hash_len = gcry_md_get_algo_dlen(hash_algo);
+ size_t data_len = (*env)->GetArrayLength(env, data);
+ jbyte *data_bytes = (*env)->GetByteArrayElements(env, data, NULL);
+ unsigned char out_hash[hash_len];
+ gcry_md_hash_buffer(hash_algo, out_hash, data_bytes, data_len);
+ (*env)->ReleaseByteArrayElements(env, data, data_bytes, JNI_ABORT);
+ gcry_mpi_t hash_mpi;
+ gcry_mpi_scan(&hash_mpi, GCRYMPI_FMT_USG, out_hash, hash_len, NULL);
+ if (!sig_algo) {
+ gcry_sexp_build(result, NULL, "(data (flags raw param) (value %M))", hash_mpi);
+ } else {
+ gcry_sexp_build(result, NULL, "(data (flags %s param) (hash %s %M))", sig_algo, hash_name, hash_mpi);
+ }
+ gcry_mpi_release(hash_mpi);
+ }
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_sign(JNIEnv *env, jobject this, jbyteArray data, jbyteArray privkey, jobject params) {
+ jbyteArray result = NULL;
+ gcry_sexp_t priv_sexp = create_privkey(env, params, NULL, privkey);
+
+ gcry_sexp_t data_sexp;
+ get_sign_data_sexp(env, &data_sexp, this, data);
+
+ gcry_sexp_t res_sexp;
+ gcry_error_t err = gcry_pk_sign(&res_sexp, data_sexp, priv_sexp);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error performing ECDSA. Error: %ui", gcry_err_code(err));
+ goto release_init;
+ }
+
+ gcry_buffer_t r_buf = {0};
+ gcry_buffer_t s_buf = {0};
+ err = gcry_sexp_extract_param(res_sexp, "ecdsa", "&rs", &r_buf, &s_buf, NULL);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ throw_new_var(env, "java/security/GeneralSecurityException", "Error extracting ECDSA output. Error: %ui", gcry_err_code(err));
+ goto release_res;
+ }
+ result = asn1_der_encode(env, r_buf.data, r_buf.len, s_buf.data, s_buf.len);
+
+ gcry_free(r_buf.data);
+ gcry_free(s_buf.data);
+release_res:
+ gcry_sexp_release(res_sexp);
+release_init:
+ gcry_sexp_release(priv_sexp);
+ gcry_sexp_release(data_sexp);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_verify(JNIEnv *env, jobject this, jbyteArray sig, jbyteArray data, jbyteArray pubkey, jobject params) {
+ jboolean result = JNI_FALSE;
+ gcry_sexp_t pub_sexp = create_pubkey(env, params, pubkey);
+
+ gcry_sexp_t data_sexp;
+ get_sign_data_sexp(env, &data_sexp, this, data);
+
+ size_t r_len, s_len;
+ jbyte *r_data, *s_data;
+ bool decode = asn1_der_decode(env, sig, &r_data, &r_len, &s_data, &s_len);
+ if (!decode) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error decoding sig.");
+ goto release_init;
+ }
+
+ gcry_mpi_t r_mpi, s_mpi;
+ gcry_mpi_scan(&r_mpi, GCRYMPI_FMT_USG, r_data, r_len, NULL);
+ gcry_mpi_scan(&s_mpi, GCRYMPI_FMT_USG, s_data, s_len, NULL);
+ free(r_data);
+ free(s_data);
+
+ gcry_sexp_t sig_sexp;
+ gcry_sexp_build(&sig_sexp, NULL, "(sig-val (ecdsa (r %M) (s %M)))", r_mpi, s_mpi);
+ gcry_error_t err = gcry_pk_verify(sig_sexp, data_sexp, pub_sexp);
+ if (gcry_err_code(err) != GPG_ERR_NO_ERROR) {
+ if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) {
+ throw_new(env, "java/security/GeneralSecurityException", "Error verif sig.");
+ goto release_init;
+ }
+ } else {
+ result = JNI_TRUE;
+ }
+
+release_init:
+ gcry_sexp_release(pub_sexp);
+ gcry_sexp_release(data_sexp);
+ return result;
+} \ No newline at end of file
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h
index eb64b53..47031e4 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -1086,3 +1086,184 @@ JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSigna
}
#endif
#endif
+/* Header for class cz_crcs_ectester_standalone_libs_GcryptLib */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_GcryptLib
+#define _Included_cz_crcs_ectester_standalone_libs_GcryptLib
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: createProvider
+ * Signature: ()Ljava/security/Provider;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_createProvider
+ (JNIEnv *, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_GcryptLib
+ * Method: getCurves
+ * Signature: ()Ljava/util/Set;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_GcryptLib_getCurves
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID 1421746759512286392LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_MAX_ARRAY_SIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_MAX_ARRAY_SIZE 2147483639L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_KEYS
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_KEYS 0L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_VALUES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_VALUES 1L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_ENTRIES
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_ENTRIES 2L
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID 4112578634029874840LL
+#undef cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID
+#define cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt_serialVersionUID -4298000515446427739LL
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeProvider_Gcrypt
+ * Method: setup
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_00024Gcrypt_setup
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt_DEFAULT_KEYSIZE
+#define cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt_DEFAULT_KEYSIZE 256L
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: keysizeSupported
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_keysizeSupported
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: paramsSupported
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_paramsSupported
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: generate
+ * Signature: (ILjava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_generate__ILjava_security_SecureRandom_2
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_Gcrypt
+ * Method: generate
+ * Signature: (Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/SecureRandom;)Ljava/security/KeyPair;
+ */
+JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024Gcrypt_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_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPublicKey_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeECPrivateKey_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+ * Method: generateSecret
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024Gcrypt_generateSecret___3B_3BLjava_security_spec_ECParameterSpec_2
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_Gcrypt
+ * 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_00024Gcrypt_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_Gcrypt */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_Gcrypt
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024Gcrypt_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 255834a..4ea5f6c 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/openssl.c
@@ -1,6 +1,5 @@
#include "native.h"
#include <string.h>
-#include <stdio.h>
#include <openssl/conf.h>
#include <openssl/opensslv.h>
@@ -327,7 +326,6 @@ static jobject create_ec_param_spec(JNIEnv *env, const EC_GROUP *curve) {
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);
- fflush(stderr);
BN_free(a);
BN_free(b);