This is an automated email from the ASF dual-hosted git repository. vanzin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-crypto.git
The following commit(s) were added to refs/heads/master by this push: new 2875340 OpenSSL 1.1.0 updates with backward compatibility for OpenSSL 1.0.2 and 1.0.1 (#92) 2875340 is described below commit 2875340ca3f9f5b19cd14939d9c0fbba500687f1 Author: aremily <arem...@users.noreply.github.com> AuthorDate: Tue Feb 19 13:40:39 2019 -0500 OpenSSL 1.1.0 updates with backward compatibility for OpenSSL 1.0.2 and 1.0.1 (#92) --- Makefile.common | 6 +- .../java/org/apache/commons/crypto/Crypto.java | 8 +- .../apache/commons/crypto/OpenSslInfoNative.java | 19 +- ...nSslNativeJna.java => OpenSsl10XNativeJna.java} | 180 ++++---- ...nSslNativeJna.java => OpenSsl11XNativeJna.java} | 212 ++++----- .../org/apache/commons/crypto/jna/OpenSslJna.java | 10 + .../commons/crypto/jna/OpenSslJnaCryptoRandom.java | 2 +- .../commons/crypto/jna/OpenSslNativeJna.java | 477 ++++++++++----------- .../org/apache/commons/crypto/OpenSslInfoNative.c | 83 ++-- .../apache/commons/crypto/cipher/OpenSslNative.c | 163 +++---- .../commons/crypto/org_apache_commons_crypto.h | 22 + .../crypto/random/OpenSslCryptoRandomNative.c | 86 ++-- .../commons/crypto/jna/OpenSslNativeJnaTest.java | 2 +- 13 files changed, 638 insertions(+), 632 deletions(-) diff --git a/Makefile.common b/Makefile.common index 96a53b8..f5ce5b7 100644 --- a/Makefile.common +++ b/Makefile.common @@ -179,10 +179,10 @@ Mac-x86_LIBNAME := libcommons-crypto.jnilib Mac-x86_COMMONS_CRYPTO_FLAGS := Mac-x86_64_CC := gcc -arch $(OS_ARCH) -Mac-x86_64_CXX := g++ -arch $(OS_ARCH) +Mac-x86_64_CXX := gcc -arch $(OS_ARCH) Mac-x86_64_STRIP := strip -x -Mac-x86_64_CFLAGS := -Ilib/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.5 -fvisibility=hidden -I/usr/local/include -I/usr/local/opt/openssl/include -Mac-x86_64_CXXFLAGS := -Ilib/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.5 -fvisibility=hidden -I/usr/local/include -I/usr/local/opt/openssl/include +Mac-x86_64_CFLAGS := -Ilib/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.7 -fvisibility=hidden -I/usr/local/include -I/usr/local/opt/openssl/include +Mac-x86_64_CXXFLAGS := -Ilib/inc_mac -I$(JAVA_HOME)/include -O2 -fPIC -mmacosx-version-min=10.7 -fvisibility=hidden -I/usr/local/include -I/usr/local/opt/openssl/include Mac-x86_64_LINKFLAGS := -dynamiclib -L/usr/local/lib Mac-x86_64_LIBNAME := libcommons-crypto.jnilib Mac-x86_64_COMMONS_CRYPTO_FLAGS := diff --git a/src/main/java/org/apache/commons/crypto/Crypto.java b/src/main/java/org/apache/commons/crypto/Crypto.java index 48069f4..b6fc886 100644 --- a/src/main/java/org/apache/commons/crypto/Crypto.java +++ b/src/main/java/org/apache/commons/crypto/Crypto.java @@ -132,8 +132,8 @@ public final class Crypto { System.out.println("Native code loaded OK " + OpenSslInfoNative.NativeVersion()); System.out.println("Native Name " + OpenSslInfoNative.NativeName()); System.out.println("Native Built " + OpenSslInfoNative.NativeTimeStamp()); - System.out.println("OpenSSL library loaded OK, version: 0x" + Long.toHexString(OpenSslInfoNative.SSLeay())); - System.out.println(OpenSslInfoNative.SSLeayVersion(0)); + System.out.println("OpenSSL library loaded OK, version: 0x" + Long.toHexString(OpenSslInfoNative.OpenSSL())); + System.out.println("OpenSSL library info " + OpenSslInfoNative.OpenSSLVersion(0)); { Properties props = new Properties(); props.setProperty(CryptoRandomFactory.CLASSES_KEY, CryptoRandomFactory.RandomProvider.OPENSSL.getClassName()); @@ -146,9 +146,9 @@ public final class Crypto { CryptoCipherFactory.getCryptoCipher("AES/CTR/NoPadding", props); System.out.println("Cipher instance created OK"); } - System.out.println("Additional SSLeay_version(n) details:"); + System.out.println("Additional OpenSSL_version(n) details:"); for(int j=1;j<6;j++) { - System.out.println(j+": "+ OpenSslInfoNative.SSLeayVersion(j)); + System.out.println(j+": "+ OpenSslInfoNative.OpenSSLVersion(j)); } } else { System.out.println("Native load failed: " + getLoadingError()); diff --git a/src/main/java/org/apache/commons/crypto/OpenSslInfoNative.java b/src/main/java/org/apache/commons/crypto/OpenSslInfoNative.java index 8ca2fde..85a3687 100644 --- a/src/main/java/org/apache/commons/crypto/OpenSslInfoNative.java +++ b/src/main/java/org/apache/commons/crypto/OpenSslInfoNative.java @@ -18,7 +18,7 @@ package org.apache.commons.crypto; /** - * JNI interface of {@see CryptoRandom} implementation for OpenSSL. + * JNI interface of {@link CryptoRandom} implementation for OpenSSL. * The native method in this class is defined in * OpenSslCryptoRandomNative.h (generated at build time by javah) * and implemented in the file @@ -26,6 +26,9 @@ package org.apache.commons.crypto; */ class OpenSslInfoNative { + public static final long VERSION_1_0_2X = 0x10002000; + public static final long VERSION_1_1_0X = 0x10100000; + /** * Makes the constructor private. */ @@ -46,16 +49,18 @@ class OpenSslInfoNative { * @return timestamp of native */ public static native String NativeTimeStamp(); - + + /** - * @return the value of SSLEAY_VERSION_NUMBER. + * @return the value of OPENSSL_VERSION_NUMBER. */ - public static native long SSLeay(); - + public static native long OpenSSL(); + /** - * Returns SSLeay_version according the version type. + * Returns OpenSSL_version according the version type. + * * @param type The version type * @return The text variant of the version number and the release date. */ - public static native String SSLeayVersion(int type); + public static native String OpenSSLVersion(int type); } diff --git a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java b/src/main/java/org/apache/commons/crypto/jna/OpenSsl10XNativeJna.java similarity index 69% copy from src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java copy to src/main/java/org/apache/commons/crypto/jna/OpenSsl10XNativeJna.java index 099c049..ed050b2 100644 --- a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java +++ b/src/main/java/org/apache/commons/crypto/jna/OpenSsl10XNativeJna.java @@ -24,12 +24,7 @@ import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.ptr.PointerByReference; -class OpenSslNativeJna { - - static final int OPENSSL_INIT_ENGINE_RDRAND = 0x00000200; - - static final int OOSL_JNA_ENCRYPT_MODE = 1; - static final int OOSL_JNA_DECRYPT_MODE = 0; +class OpenSsl10XNativeJna { static final boolean INIT_OK; @@ -40,7 +35,6 @@ class OpenSslNativeJna { Throwable thrown = null; try { Native.register("crypto"); - ERR_load_crypto_strings(); ok = true; } catch (Exception e) { thrown = e; @@ -52,19 +46,18 @@ class OpenSslNativeJna { } } - //misc /** - * @return OPENSSL_VERSION_NUMBER which is a numeric release version - * * identifier + * @return OPENSSL_VERSION_NUMBER which is a numeric release version identifier */ public static native NativeLong SSLeay(); /** * Retrieves version/build information about OpenSSL library. * - * @param type type can be SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON... - * @return A pointer to a constant string describing the version of the - * OpenSSL library or giving information about the library build. + * @param type + * type can be SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON... + * @return A pointer to a constant string describing the version of the OpenSSL library or + * giving information about the library build. */ public static native String SSLeay_version(int type); @@ -74,45 +67,45 @@ class OpenSslNativeJna { public static native void ERR_load_crypto_strings(); /** - * @return the earliest error code from the thread's error queue without - * modifying it. + * @return the earliest error code from the thread's error queue without modifying it. */ public static native NativeLong ERR_peek_error(); - - /** * Generates a human-readable string representing the error code e. + * * @see <a>https://www.openssl.org/docs/manmaster/crypto/ERR_error_string.html</a> * - * @param err the error code - * @param null_ buf is NULL, the error string is placed in a static buffer + * @param err + * the error code + * @param null_ + * buf is NULL, the error string is placed in a static buffer * @return the human-readable error messages. */ public static native String ERR_error_string(NativeLong err, char[] null_); - //String ERR_lib_error_string(NativeLong err); - //String ERR_func_error_string(NativeLong err); - //en-/decryption /** * Creates a cipher context. * - * @return a pointer to a newly created EVP_CIPHER_CTX for success and - * NULL for failure. + * @return a pointer to a newly created EVP_CIPHER_CTX for success and NULL for failure. */ public static native PointerByReference EVP_CIPHER_CTX_new(); - /** * EVP_CIPHER_CTX_init() remains as an alias for EVP_CIPHER_CTX_reset - * @param p cipher context + * + * @param p + * cipher context */ public static native void EVP_CIPHER_CTX_init(PointerByReference p); /** * Enables or disables padding - * @param c cipher context - * @param pad If the pad parameter is zero then no padding is performed + * + * @param c + * cipher context + * @param pad + * If the pad parameter is zero then no padding is performed * @return always returns 1 */ public static native int EVP_CIPHER_CTX_set_padding(PointerByReference c, int pad); @@ -149,70 +142,96 @@ class OpenSslNativeJna { /** * Init a cipher. - * @param ctx cipher context - * @param cipher evp cipher instance - * @param impl engine - * @param key key - * @param iv iv - * @param enc 1 for encryption, 0 for decryption + * + * @param ctx + * cipher context + * @param cipher + * evp cipher instance + * @param impl + * engine + * @param key + * key + * @param iv + * iv + * @param enc + * 1 for encryption, 0 for decryption * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherInit_ex(PointerByReference ctx, PointerByReference cipher, PointerByReference impl, byte key[], byte iv[], int enc); - + public static native int EVP_CipherInit_ex(PointerByReference ctx, PointerByReference cipher, + PointerByReference impl, byte key[], byte iv[], int enc); /** * Continues a multiple-part encryption/decryption operation. * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length - * @param in input byte buffer - * @param inl input length + * @param ctx + * cipher context + * @param bout + * output byte buffer + * @param outl + * output length + * @param in + * input byte buffer + * @param inl + * input length * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherUpdate(PointerByReference ctx, ByteBuffer bout, int[] outl, ByteBuffer in, int inl); + public static native int EVP_CipherUpdate(PointerByReference ctx, ByteBuffer bout, int[] outl, + ByteBuffer in, int inl); /** * Finishes a multiple-part operation. * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length + * @param ctx + * cipher context + * @param bout + * output byte buffer + * @param outl + * output length * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherFinal_ex(PointerByReference ctx, ByteBuffer bout, int[] outl); + public static native int EVP_CipherFinal_ex(PointerByReference ctx, ByteBuffer bout, + int[] outl); /** - * Clears all information from a cipher context and free up any allocated - * memory associate with it, including ctx itself. - * @param c openssl evp cipher + * Clears all information from a cipher context and free up any allocated memory associate with + * it, including ctx itself. + * + * @param c + * openssl evp cipher */ public static native void EVP_CIPHER_CTX_free(PointerByReference c); /** - * Clears all information from a cipher context and free up any allocated - * * memory associate with it. - * @param c openssl evp cipher + * Clears all information from a cipher context and free up any allocated * memory associate + * with it. + * + * @param c + * openssl evp cipher */ public static native void EVP_CIPHER_CTX_cleanup(PointerByReference c); - //Random generator + // Random generator /** * OpenSSL uses for random number generation + * * @return pointers to the respective methods */ public static native PointerByReference RAND_get_rand_method(); /** * OpenSSL uses for random number generation. + * * @return pointers to the respective methods */ public static native PointerByReference RAND_SSLeay(); /** * Generates random data - * @param buf the bytes for generated random. - * @param num buffer length + * + * @param buf + * the bytes for generated random. + * @param num + * buffer length * @return 1 on success, 0 otherwise. */ public static native int RAND_bytes(ByteBuffer buf, int num); @@ -220,42 +239,54 @@ class OpenSslNativeJna { /** * Releases all functional references. * - * @param e engine reference. + * @param e + * engine reference. * @return 0 on success, 1 otherwise. */ public static native int ENGINE_finish(PointerByReference e); /** * Frees the structural reference - * @param e engine reference. + * + * @param e + * engine reference. * @return 0 on success, 1 otherwise. */ public static native int ENGINE_free(PointerByReference e); /** * Cleanups before program exit, it will avoid memory leaks. + * * @return 0 on success, 1 otherwise. */ public static native int ENGINE_cleanup(); /** * Obtains a functional reference from an existing structural reference. - * @param e engine reference - * @return zero if the ENGINE was not already operational and couldn't be successfully initialised + * + * @param e + * engine reference + * @return zero if the ENGINE was not already operational and couldn't be successfully + * initialised */ public static native int ENGINE_init(PointerByReference e); /** * Sets the engine as the default for random number generation. - * @param e engine reference - * @param flags ENGINE_METHOD_RAND + * + * @param e + * engine reference + * @param flags + * ENGINE_METHOD_RAND * @return zero if failed. */ public static native int ENGINE_set_default(PointerByReference e, int flags); /** * Gets engine by id - * @param id engine id + * + * @param id + * engine id * @return engine instance */ public static native PointerByReference ENGINE_by_id(String id); @@ -264,27 +295,4 @@ class OpenSslNativeJna { * Initializes the engine. */ public static native void ENGINE_load_rdrand(); - - //TODO callback multithreading - /*public interface Id_function_cb extends Callback { - long invoke (); - } - - public interface Locking_function_cb extends Callback { - void invoke(int mode, int n, String file, int line); - } - - public static final Id_function_cb default_id_function = new Id_function_cb() { - - @Override - public long invoke() { - //id always positive - long id = Thread.currentThread().getId(); - return id; - } - }; - - int CRYPTO_num_locks(); - void CRYPTO_set_id_callback(Id_function_cb id_function); - void CRYPTO_set_locking_callback(Locking_function_cb locking_function);*/ -} \ No newline at end of file +} diff --git a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java b/src/main/java/org/apache/commons/crypto/jna/OpenSsl11XNativeJna.java similarity index 58% copy from src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java copy to src/main/java/org/apache/commons/crypto/jna/OpenSsl11XNativeJna.java index 099c049..b9c4c0e 100644 --- a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java +++ b/src/main/java/org/apache/commons/crypto/jna/OpenSsl11XNativeJna.java @@ -24,12 +24,7 @@ import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.ptr.PointerByReference; -class OpenSslNativeJna { - - static final int OPENSSL_INIT_ENGINE_RDRAND = 0x00000200; - - static final int OOSL_JNA_ENCRYPT_MODE = 1; - static final int OOSL_JNA_DECRYPT_MODE = 0; +class OpenSsl11XNativeJna { static final boolean INIT_OK; @@ -40,7 +35,6 @@ class OpenSslNativeJna { Throwable thrown = null; try { Native.register("crypto"); - ERR_load_crypto_strings(); ok = true; } catch (Exception e) { thrown = e; @@ -52,67 +46,38 @@ class OpenSslNativeJna { } } - //misc - /** - * @return OPENSSL_VERSION_NUMBER which is a numeric release version - * * identifier - */ - public static native NativeLong SSLeay(); - - /** - * Retrieves version/build information about OpenSSL library. - * - * @param type type can be SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON... - * @return A pointer to a constant string describing the version of the - * OpenSSL library or giving information about the library build. - */ - public static native String SSLeay_version(int type); - /** - * Registers the error strings for all libcrypto functions. - */ - public static native void ERR_load_crypto_strings(); - - /** - * @return the earliest error code from the thread's error queue without - * modifying it. + * @return the earliest error code from the thread's error queue without modifying it. */ public static native NativeLong ERR_peek_error(); - - /** * Generates a human-readable string representing the error code e. + * * @see <a>https://www.openssl.org/docs/manmaster/crypto/ERR_error_string.html</a> * - * @param err the error code - * @param null_ buf is NULL, the error string is placed in a static buffer + * @param err + * the error code + * @param null_ + * buf is NULL, the error string is placed in a static buffer * @return the human-readable error messages. */ public static native String ERR_error_string(NativeLong err, char[] null_); - //String ERR_lib_error_string(NativeLong err); - //String ERR_func_error_string(NativeLong err); - //en-/decryption /** * Creates a cipher context. * - * @return a pointer to a newly created EVP_CIPHER_CTX for success and - * NULL for failure. + * @return a pointer to a newly created EVP_CIPHER_CTX for success and NULL for failure. */ public static native PointerByReference EVP_CIPHER_CTX_new(); - - /** - * EVP_CIPHER_CTX_init() remains as an alias for EVP_CIPHER_CTX_reset - * @param p cipher context - */ - public static native void EVP_CIPHER_CTX_init(PointerByReference p); - /** * Enables or disables padding - * @param c cipher context - * @param pad If the pad parameter is zero then no padding is performed + * + * @param c + * cipher context + * @param pad + * If the pad parameter is zero then no padding is performed * @return always returns 1 */ public static native int EVP_CIPHER_CTX_set_padding(PointerByReference c, int pad); @@ -149,70 +114,88 @@ class OpenSslNativeJna { /** * Init a cipher. - * @param ctx cipher context - * @param cipher evp cipher instance - * @param impl engine - * @param key key - * @param iv iv - * @param enc 1 for encryption, 0 for decryption + * + * @param ctx + * cipher context + * @param cipher + * evp cipher instance + * @param impl + * engine + * @param key + * key + * @param iv + * iv + * @param enc + * 1 for encryption, 0 for decryption * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherInit_ex(PointerByReference ctx, PointerByReference cipher, PointerByReference impl, byte key[], byte iv[], int enc); - + public static native int EVP_CipherInit_ex(PointerByReference ctx, PointerByReference cipher, + PointerByReference impl, byte key[], byte iv[], int enc); /** * Continues a multiple-part encryption/decryption operation. * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length - * @param in input byte buffer - * @param inl input length + * @param ctx + * cipher context + * @param bout + * output byte buffer + * @param outl + * output length + * @param in + * input byte buffer + * @param inl + * input length * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherUpdate(PointerByReference ctx, ByteBuffer bout, int[] outl, ByteBuffer in, int inl); + public static native int EVP_CipherUpdate(PointerByReference ctx, ByteBuffer bout, int[] outl, + ByteBuffer in, int inl); /** * Finishes a multiple-part operation. * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length + * @param ctx + * cipher context + * @param bout + * output byte buffer + * @param outl + * output length * @return 1 for success and 0 for failure. */ - public static native int EVP_CipherFinal_ex(PointerByReference ctx, ByteBuffer bout, int[] outl); + public static native int EVP_CipherFinal_ex(PointerByReference ctx, ByteBuffer bout, + int[] outl); /** - * Clears all information from a cipher context and free up any allocated - * memory associate with it, including ctx itself. - * @param c openssl evp cipher + * Clears all information from a cipher context and free up any allocated memory associate with + * it, including ctx itself. + * + * @param c + * openssl evp cipher */ public static native void EVP_CIPHER_CTX_free(PointerByReference c); /** - * Clears all information from a cipher context and free up any allocated - * * memory associate with it. - * @param c openssl evp cipher + * Clears all information from a cipher context and free up any allocated * memory associate + * with it. + * + * @param c + * openssl evp cipher */ - public static native void EVP_CIPHER_CTX_cleanup(PointerByReference c); - //Random generator + // Random generator /** * OpenSSL uses for random number generation + * * @return pointers to the respective methods */ public static native PointerByReference RAND_get_rand_method(); /** - * OpenSSL uses for random number generation. - * @return pointers to the respective methods - */ - public static native PointerByReference RAND_SSLeay(); - - /** * Generates random data - * @param buf the bytes for generated random. - * @param num buffer length + * + * @param buf + * the bytes for generated random. + * @param num + * buffer length * @return 1 on success, 0 otherwise. */ public static native int RAND_bytes(ByteBuffer buf, int num); @@ -220,71 +203,58 @@ class OpenSslNativeJna { /** * Releases all functional references. * - * @param e engine reference. + * @param e + * engine reference. * @return 0 on success, 1 otherwise. */ public static native int ENGINE_finish(PointerByReference e); /** * Frees the structural reference - * @param e engine reference. + * + * @param e + * engine reference. * @return 0 on success, 1 otherwise. */ public static native int ENGINE_free(PointerByReference e); /** - * Cleanups before program exit, it will avoid memory leaks. - * @return 0 on success, 1 otherwise. - */ - public static native int ENGINE_cleanup(); - - /** * Obtains a functional reference from an existing structural reference. - * @param e engine reference - * @return zero if the ENGINE was not already operational and couldn't be successfully initialised + * + * @param e + * engine reference + * @return zero if the ENGINE was not already operational and couldn't be successfully + * initialised */ public static native int ENGINE_init(PointerByReference e); /** * Sets the engine as the default for random number generation. - * @param e engine reference - * @param flags ENGINE_METHOD_RAND + * + * @param e + * engine reference + * @param flags + * ENGINE_METHOD_RAND * @return zero if failed. */ public static native int ENGINE_set_default(PointerByReference e, int flags); /** * Gets engine by id - * @param id engine id + * + * @param id + * engine id * @return engine instance */ public static native PointerByReference ENGINE_by_id(String id); /** - * Initializes the engine. + * Retrieves version/build information about OpenSSL library. + * + * @param type + * type can be OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON... + * @return A pointer to a constant string describing the version of the OpenSSL library or + * giving information about the library build. */ - public static native void ENGINE_load_rdrand(); - - //TODO callback multithreading - /*public interface Id_function_cb extends Callback { - long invoke (); - } - - public interface Locking_function_cb extends Callback { - void invoke(int mode, int n, String file, int line); - } - - public static final Id_function_cb default_id_function = new Id_function_cb() { - - @Override - public long invoke() { - //id always positive - long id = Thread.currentThread().getId(); - return id; - } - }; - - int CRYPTO_num_locks(); - void CRYPTO_set_id_callback(Id_function_cb id_function); - void CRYPTO_set_locking_callback(Locking_function_cb locking_function);*/ -} \ No newline at end of file + public static native String OpenSSL_version(int type); +} diff --git a/src/main/java/org/apache/commons/crypto/jna/OpenSslJna.java b/src/main/java/org/apache/commons/crypto/jna/OpenSslJna.java index 14b9d34..da66c5c 100644 --- a/src/main/java/org/apache/commons/crypto/jna/OpenSslJna.java +++ b/src/main/java/org/apache/commons/crypto/jna/OpenSslJna.java @@ -53,4 +53,14 @@ public final class OpenSslJna { return OpenSslNativeJna.INIT_ERROR; } + /** + * Retrieves version/build information about OpenSSL library. + * + * @param type type can be OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON... + * @return A pointer to a constant string describing the version of the + * OpenSSL library or giving information about the library build. + */ + static String OpenSSLVersion(int type) { + return OpenSslNativeJna.OpenSSLVersion(type); + } } diff --git a/src/main/java/org/apache/commons/crypto/jna/OpenSslJnaCryptoRandom.java b/src/main/java/org/apache/commons/crypto/jna/OpenSslJnaCryptoRandom.java index b3f4c4f..823637d 100644 --- a/src/main/java/org/apache/commons/crypto/jna/OpenSslJnaCryptoRandom.java +++ b/src/main/java/org/apache/commons/crypto/jna/OpenSslJnaCryptoRandom.java @@ -106,7 +106,7 @@ class OpenSslJnaCryptoRandom extends Random implements CryptoRandom { close(); throw new RuntimeException("rdrand should be used but default is detected"); } - + ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length); int retVal = OpenSslNativeJna.RAND_bytes(buf, bytes.length); throwOnError(retVal); diff --git a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java b/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java index 099c049..26507d7 100644 --- a/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java +++ b/src/main/java/org/apache/commons/crypto/jna/OpenSslNativeJna.java @@ -20,7 +20,8 @@ package org.apache.commons.crypto.jna; import java.nio.ByteBuffer; -import com.sun.jna.Native; +import com.sun.jna.Function; +import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLong; import com.sun.jna.ptr.PointerByReference; @@ -35,256 +36,252 @@ class OpenSslNativeJna { static final Throwable INIT_ERROR; + public static final long VERSION; + public static final long VERSION_1_0_X = 0x10000000; + public static final long VERSION_1_1_X = 0x10100000; + static { - boolean ok = false; - Throwable thrown = null; + NativeLibrary crypto = NativeLibrary.getInstance("crypto"); + Function version = null; try { - Native.register("crypto"); - ERR_load_crypto_strings(); - ok = true; - } catch (Exception e) { - thrown = e; + version = crypto.getFunction("SSLeay"); } catch (UnsatisfiedLinkError e) { - thrown = e; - } finally { - INIT_OK = ok; - INIT_ERROR = thrown; + // Swallow the Error. + } + + if (version == null) { + VERSION = VERSION_1_1_X; + } else { + VERSION = VERSION_1_0_X; + } + + if (VERSION == VERSION_1_1_X) { + INIT_OK = OpenSsl11XNativeJna.INIT_OK; + } else { + INIT_OK = OpenSsl10XNativeJna.INIT_OK; + } + + if (INIT_OK) { + INIT_ERROR = null; + } else if (VERSION == VERSION_1_1_X) { + INIT_ERROR = OpenSsl11XNativeJna.INIT_ERROR; + } else { + INIT_ERROR = OpenSsl10XNativeJna.INIT_ERROR; + } + } + + public static PointerByReference ENGINE_by_id(String string) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.ENGINE_by_id(string); + } else { + return OpenSsl10XNativeJna.ENGINE_by_id(string); } } - //misc - /** - * @return OPENSSL_VERSION_NUMBER which is a numeric release version - * * identifier - */ - public static native NativeLong SSLeay(); - - /** - * Retrieves version/build information about OpenSSL library. - * - * @param type type can be SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON... - * @return A pointer to a constant string describing the version of the - * OpenSSL library or giving information about the library build. - */ - public static native String SSLeay_version(int type); - - /** - * Registers the error strings for all libcrypto functions. - */ - public static native void ERR_load_crypto_strings(); - - /** - * @return the earliest error code from the thread's error queue without - * modifying it. - */ - public static native NativeLong ERR_peek_error(); - - - - /** - * Generates a human-readable string representing the error code e. - * @see <a>https://www.openssl.org/docs/manmaster/crypto/ERR_error_string.html</a> - * - * @param err the error code - * @param null_ buf is NULL, the error string is placed in a static buffer - * @return the human-readable error messages. - */ - public static native String ERR_error_string(NativeLong err, char[] null_); - //String ERR_lib_error_string(NativeLong err); - //String ERR_func_error_string(NativeLong err); - - //en-/decryption - /** - * Creates a cipher context. - * - * @return a pointer to a newly created EVP_CIPHER_CTX for success and - * NULL for failure. - */ - public static native PointerByReference EVP_CIPHER_CTX_new(); - - - /** - * EVP_CIPHER_CTX_init() remains as an alias for EVP_CIPHER_CTX_reset - * @param p cipher context - */ - public static native void EVP_CIPHER_CTX_init(PointerByReference p); - - /** - * Enables or disables padding - * @param c cipher context - * @param pad If the pad parameter is zero then no padding is performed - * @return always returns 1 - */ - public static native int EVP_CIPHER_CTX_set_padding(PointerByReference c, int pad); - - /** - * @return an openssl AES evp cipher instance with a 128-bit key CBC mode - */ - public static native PointerByReference EVP_aes_128_cbc(); - - /** - * @return an openssl AES evp cipher instance with a 128-bit key CTR mode - */ - public static native PointerByReference EVP_aes_128_ctr(); - - /** - * @return an openssl AES evp cipher instance with a 192-bit key CBC mode - */ - public static native PointerByReference EVP_aes_192_cbc(); - - /** - * @return an openssl AES evp cipher instance with a 192-bit key CTR mode - */ - public static native PointerByReference EVP_aes_192_ctr(); - - /** - * @return an openssl AES evp cipher instance with a 256-bit key CBC mode - */ - public static native PointerByReference EVP_aes_256_cbc(); - - /** - * @return an openssl AES evp cipher instance with a 256-bit key CTR mode - */ - public static native PointerByReference EVP_aes_256_ctr(); - - /** - * Init a cipher. - * @param ctx cipher context - * @param cipher evp cipher instance - * @param impl engine - * @param key key - * @param iv iv - * @param enc 1 for encryption, 0 for decryption - * @return 1 for success and 0 for failure. - */ - public static native int EVP_CipherInit_ex(PointerByReference ctx, PointerByReference cipher, PointerByReference impl, byte key[], byte iv[], int enc); - - - /** - * Continues a multiple-part encryption/decryption operation. - * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length - * @param in input byte buffer - * @param inl input length - * @return 1 for success and 0 for failure. - */ - public static native int EVP_CipherUpdate(PointerByReference ctx, ByteBuffer bout, int[] outl, ByteBuffer in, int inl); - - /** - * Finishes a multiple-part operation. - * - * @param ctx cipher context - * @param bout output byte buffer - * @param outl output length - * @return 1 for success and 0 for failure. - */ - public static native int EVP_CipherFinal_ex(PointerByReference ctx, ByteBuffer bout, int[] outl); - - /** - * Clears all information from a cipher context and free up any allocated - * memory associate with it, including ctx itself. - * @param c openssl evp cipher - */ - public static native void EVP_CIPHER_CTX_free(PointerByReference c); - - /** - * Clears all information from a cipher context and free up any allocated - * * memory associate with it. - * @param c openssl evp cipher - */ - public static native void EVP_CIPHER_CTX_cleanup(PointerByReference c); - - //Random generator - /** - * OpenSSL uses for random number generation - * @return pointers to the respective methods - */ - public static native PointerByReference RAND_get_rand_method(); - - /** - * OpenSSL uses for random number generation. - * @return pointers to the respective methods - */ - public static native PointerByReference RAND_SSLeay(); - - /** - * Generates random data - * @param buf the bytes for generated random. - * @param num buffer length - * @return 1 on success, 0 otherwise. - */ - public static native int RAND_bytes(ByteBuffer buf, int num); - - /** - * Releases all functional references. - * - * @param e engine reference. - * @return 0 on success, 1 otherwise. - */ - public static native int ENGINE_finish(PointerByReference e); - - /** - * Frees the structural reference - * @param e engine reference. - * @return 0 on success, 1 otherwise. - */ - public static native int ENGINE_free(PointerByReference e); - - /** - * Cleanups before program exit, it will avoid memory leaks. - * @return 0 on success, 1 otherwise. - */ - public static native int ENGINE_cleanup(); - - /** - * Obtains a functional reference from an existing structural reference. - * @param e engine reference - * @return zero if the ENGINE was not already operational and couldn't be successfully initialised - */ - public static native int ENGINE_init(PointerByReference e); - - /** - * Sets the engine as the default for random number generation. - * @param e engine reference - * @param flags ENGINE_METHOD_RAND - * @return zero if failed. - */ - public static native int ENGINE_set_default(PointerByReference e, int flags); - - /** - * Gets engine by id - * @param id engine id - * @return engine instance - */ - public static native PointerByReference ENGINE_by_id(String id); - - /** - * Initializes the engine. - */ - public static native void ENGINE_load_rdrand(); - - //TODO callback multithreading - /*public interface Id_function_cb extends Callback { - long invoke (); + public static void ENGINE_finish(PointerByReference rdrandEngine) { + if (VERSION == VERSION_1_1_X) { + OpenSsl11XNativeJna.ENGINE_finish(rdrandEngine); + } else { + OpenSsl10XNativeJna.ENGINE_finish(rdrandEngine); + } + } + + public static void ENGINE_free(PointerByReference rdrandEngine) { + if (VERSION == VERSION_1_1_X) { + OpenSsl11XNativeJna.ENGINE_free(rdrandEngine); + } else { + OpenSsl10XNativeJna.ENGINE_free(rdrandEngine); + } + } + + public static int ENGINE_init(PointerByReference rdrandEngine) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.ENGINE_init(rdrandEngine); + } else { + return OpenSsl10XNativeJna.ENGINE_init(rdrandEngine); + } } - public interface Locking_function_cb extends Callback { - void invoke(int mode, int n, String file, int line); + public static int ENGINE_set_default(PointerByReference rdrandEngine, int eNGINE_METHOD_RAND) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.ENGINE_set_default(rdrandEngine, eNGINE_METHOD_RAND); + } else { + return OpenSsl10XNativeJna.ENGINE_set_default(rdrandEngine, eNGINE_METHOD_RAND); + } } - public static final Id_function_cb default_id_function = new Id_function_cb() { + public static String ERR_error_string(NativeLong err, Object object) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.ERR_error_string(err, null); + } else { + return OpenSsl10XNativeJna.ERR_error_string(err, null); + } + } - @Override - public long invoke() { - //id always positive - long id = Thread.currentThread().getId(); - return id; + public static NativeLong ERR_peek_error() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.ERR_peek_error(); + } else { + return OpenSsl10XNativeJna.ERR_peek_error(); } - }; + } + + public static PointerByReference EVP_aes_128_cbc() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_128_cbc(); + } else { + return OpenSsl10XNativeJna.EVP_aes_128_cbc(); + } + } + + public static PointerByReference EVP_aes_128_ctr() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_128_ctr(); + } else { + return OpenSsl10XNativeJna.EVP_aes_128_ctr(); + } + } + + public static PointerByReference EVP_aes_192_cbc() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_192_cbc(); + } else { + return OpenSsl10XNativeJna.EVP_aes_192_cbc(); + } + } + + public static PointerByReference EVP_aes_192_ctr() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_192_ctr(); + } else { + return OpenSsl10XNativeJna.EVP_aes_192_ctr(); + } + } + + public static PointerByReference EVP_aes_256_cbc() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_256_cbc(); + } else { + return OpenSsl10XNativeJna.EVP_aes_256_cbc(); + } + } + + public static PointerByReference EVP_aes_256_ctr() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_aes_256_ctr(); + } else { + return OpenSsl10XNativeJna.EVP_aes_256_ctr(); + } + } - int CRYPTO_num_locks(); - void CRYPTO_set_id_callback(Id_function_cb id_function); - void CRYPTO_set_locking_callback(Locking_function_cb locking_function);*/ + public static void EVP_CIPHER_CTX_free(PointerByReference context) { + if (VERSION == VERSION_1_1_X) { + OpenSsl11XNativeJna.EVP_CIPHER_CTX_free(context); + } else { + OpenSsl10XNativeJna.EVP_CIPHER_CTX_free(context); + } + } + + public static PointerByReference EVP_CIPHER_CTX_new() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_CIPHER_CTX_new(); + } else { + return OpenSsl10XNativeJna.EVP_CIPHER_CTX_new(); + } + } + + public static void EVP_CIPHER_CTX_set_padding(PointerByReference context, int padding) { + if (VERSION == VERSION_1_1_X) { + OpenSsl11XNativeJna.EVP_CIPHER_CTX_set_padding(context, padding); + } else { + OpenSsl10XNativeJna.EVP_CIPHER_CTX_set_padding(context, padding); + } + } + + public static int EVP_CipherFinal_ex(PointerByReference context, ByteBuffer outBuffer, + int[] outlen) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_CipherFinal_ex(context, outBuffer, outlen); + } else { + return OpenSsl10XNativeJna.EVP_CipherFinal_ex(context, outBuffer, outlen); + } + } + + public static int EVP_CipherInit_ex(PointerByReference context, PointerByReference algo, + Object object, byte[] encoded, byte[] iv, int cipherMode) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_CipherInit_ex(context, algo, null, encoded, iv, + cipherMode); + } else { + return OpenSsl10XNativeJna.EVP_CipherInit_ex(context, algo, null, encoded, iv, + cipherMode); + } + } + + public static int EVP_CipherUpdate(PointerByReference context, ByteBuffer outBuffer, + int[] outlen, ByteBuffer inBuffer, int remaining) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.EVP_CipherUpdate(context, outBuffer, outlen, inBuffer, + remaining); + } else { + return OpenSsl10XNativeJna.EVP_CipherUpdate(context, outBuffer, outlen, inBuffer, + remaining); + } + } + + public static int RAND_bytes(ByteBuffer buf, int length) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.RAND_bytes(buf, length); + } else { + return OpenSsl10XNativeJna.RAND_bytes(buf, length); + } + } + + public static PointerByReference RAND_get_rand_method() { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.RAND_get_rand_method(); + } else { + return OpenSsl10XNativeJna.RAND_get_rand_method(); + } + } + + public static PointerByReference RAND_SSLeay() { + if (VERSION == VERSION_1_1_X) { + return null; + } else { + return OpenSsl10XNativeJna.RAND_SSLeay(); + } + } + + public static String OpenSSLVersion(int i) { + if (VERSION == VERSION_1_1_X) { + return OpenSsl11XNativeJna.OpenSSL_version(i); + } else { + return OpenSsl10XNativeJna.SSLeay_version(i); + } + } + + public static void ENGINE_load_rdrand() { + if (VERSION == VERSION_1_1_X) { + return; + } else { + OpenSsl10XNativeJna.ENGINE_load_rdrand(); + } + } + + public static void ENGINE_cleanup() { + if (VERSION == VERSION_1_1_X) { + return; + } else { + OpenSsl10XNativeJna.ENGINE_cleanup(); + } + } + + public static void EVP_CIPHER_CTX_cleanup(PointerByReference context) { + if (VERSION == VERSION_1_1_X) { + return; + } else { + OpenSsl10XNativeJna.EVP_CIPHER_CTX_cleanup(context); + } + } } \ No newline at end of file diff --git a/src/main/native/org/apache/commons/crypto/OpenSslInfoNative.c b/src/main/native/org/apache/commons/crypto/OpenSslInfoNative.c index bb71638..937fc28 100644 --- a/src/main/native/org/apache/commons/crypto/OpenSslInfoNative.c +++ b/src/main/native/org/apache/commons/crypto/OpenSslInfoNative.c @@ -39,38 +39,20 @@ #include "OpenSslInfoNative.h" #ifdef UNIX -static unsigned long (*dlsym_SSLeay) (void); -static char * (*dlsym_SSLeay_version) (int); +static unsigned long (*dlsym_OpenSSL_version_num) (void); +static const char * (*dlsym_OpenSSL_version) (int); static void *openssl; #endif #ifdef WINDOWS -typedef unsigned long (__cdecl *__dlsym_SSLeay) (void); -static __dlsym_SSLeay dlsym_SSLeay; -typedef char * (__cdecl *__dlsym_SSLeay_version) (int); -static __dlsym_SSLeay dlsym_SSLeay; -static __dlsym_SSLeay_version dlsym_SSLeay_version; +typedef unsigned long (__cdecl *__dlsym_OpenSSL) (void); +static __dlsym_OpenSSL dlsym_OpenSSL; +typedef char * (__cdecl *__dlsym_OpenSSL_version) (int); +static __dlsym_OpenSSL dlsym_OpenSSL; +static __dlsym_OpenSSL_version dlsym_OpenSSL_version; HMODULE openssl; #endif -#ifdef UNIX -static void get_methods(JNIEnv *env, void *openssl) -#endif -#ifdef WINDOWS -static void get_methods(JNIEnv *env, HMODULE openssl) -#endif -{ -#ifdef UNIX - dlerror(); // Clear any existing error - LOAD_DYNAMIC_SYMBOL(dlsym_SSLeay, env, openssl, "SSLeay"); - LOAD_DYNAMIC_SYMBOL(dlsym_SSLeay_version, env, openssl, "SSLeay_version"); -#endif - -#ifdef WINDOWS - LOAD_DYNAMIC_SYMBOL(__dlsym_SSLeay, dlsym_SSLeay, env, openssl, "SSLeay"); - LOAD_DYNAMIC_SYMBOL(__dlsym_SSLeay_version, dlsym_SSLeay_version, env, openssl, "SSLeay_version"); -#endif -} static int load_library(JNIEnv *env) { char msg[100]; @@ -94,30 +76,12 @@ static int load_library(JNIEnv *env) THROW(env, "java/lang/UnsatisfiedLinkError", msg); return 0; } - get_methods(env, openssl); +#ifdef UNIX + LOAD_OPENSSL_VERSION_FUNCTION(dlsym_OpenSSL_version_num, env, openssl); +#endif return 1; } -JNIEXPORT jstring JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_SSLeayVersion - (JNIEnv *env, jclass clazz, jint type) -{ - if (!load_library(env)) { - return NULL; - } - - jstring answer = (*env)->NewStringUTF(env,dlsym_SSLeay_version(type)); - return answer; -} - -JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_SSLeay - (JNIEnv *env, jobject object) -{ - if (!load_library(env)) { - return 0; - } - return dlsym_SSLeay(); -} - JNIEXPORT jstring JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_NativeVersion (JNIEnv *env, jobject object) { @@ -135,3 +99,30 @@ JNIEXPORT jstring JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_Nativ { return (*env)->NewStringUTF(env, PROJECT_NAME); } + +JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_OpenSSL + (JNIEnv *env, jclass clazz) +{ + if (!load_library(env)) { + return 0; + } + jlong version_num = (jlong)dlsym_OpenSSL_version_num(); + return version_num; +} + +JNIEXPORT jstring JNICALL Java_org_apache_commons_crypto_OpenSslInfoNative_OpenSSLVersion + (JNIEnv *env, jclass clazz, jint type) +{ + if (!load_library(env)) { + return NULL; + } + if (dlsym_OpenSSL_version_num() > VERSION_1_1_X) { + dlsym_OpenSSL_version = do_dlsym(env, openssl, "OpenSSL_version"); + } else { + dlsym_OpenSSL_version = do_dlsym(env, openssl, "SSLeay_version"); + } + jstring answer = (*env)->NewStringUTF(env,dlsym_OpenSSL_version(type)); + return answer; +} + + diff --git a/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c b/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c index ec9c945..25b4a06 100644 --- a/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c +++ b/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c @@ -32,9 +32,12 @@ #ifdef UNIX static EVP_CIPHER_CTX * (*dlsym_EVP_CIPHER_CTX_new)(void); static void (*dlsym_EVP_CIPHER_CTX_free)(EVP_CIPHER_CTX *); -static void (*dlsym_EVP_CIPHER_CTX_init)(EVP_CIPHER_CTX *); static int (*dlsym_EVP_CIPHER_CTX_set_padding)(EVP_CIPHER_CTX *, int); static int (*dlsym_EVP_CIPHER_CTX_ctrl)(EVP_CIPHER_CTX *, int, int, void *); +static int (*dlsym_EVP_CIPHER_CTX_block_size)(EVP_CIPHER_CTX *); +static EVP_CIPHER * (*dlsym_EVP_CIPHER_CTX_cipher)(EVP_CIPHER_CTX *); +static unsigned long (*dlsym_EVP_CIPHER_flags)(const EVP_CIPHER *); +static int (*dlsym_EVP_CIPHER_CTX_test_flags)(const EVP_CIPHER_CTX *, int); static int (*dlsym_EVP_CipherInit_ex)(EVP_CIPHER_CTX *, const EVP_CIPHER *, \ ENGINE *, const unsigned char *, const unsigned char *, int); static int (*dlsym_EVP_CipherUpdate)(EVP_CIPHER_CTX *, unsigned char *, \ @@ -49,12 +52,13 @@ static EVP_CIPHER * (*dlsym_EVP_aes_128_cbc)(void); static EVP_CIPHER * (*dlsym_EVP_aes_256_gcm)(void); static EVP_CIPHER * (*dlsym_EVP_aes_192_gcm)(void); static EVP_CIPHER * (*dlsym_EVP_aes_128_gcm)(void); +static void *openssl; #endif #ifdef WINDOWS typedef EVP_CIPHER_CTX * (__cdecl *__dlsym_EVP_CIPHER_CTX_new)(void); typedef void (__cdecl *__dlsym_EVP_CIPHER_CTX_free)(EVP_CIPHER_CTX *); -typedef void (__cdecl *__dlsym_EVP_CIPHER_CTX_init)(EVP_CIPHER_CTX *); +typedef int (__cdecl *__dlsym_EVP_CIPHER_CTX_reset)(EVP_CIPHER_CTX *); typedef int (__cdecl *__dlsym_EVP_CIPHER_CTX_set_padding)(EVP_CIPHER_CTX *, int); typedef int (__cdecl *__dlsym_EVP_CIPHER_CTX_ctrl)(EVP_CIPHER_CTX *, int, int, void *); typedef int (__cdecl *__dlsym_EVP_CipherInit_ex)(EVP_CIPHER_CTX *, \ @@ -75,7 +79,7 @@ typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_192_gcm)(void); typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_128_gcm)(void); static __dlsym_EVP_CIPHER_CTX_new dlsym_EVP_CIPHER_CTX_new; static __dlsym_EVP_CIPHER_CTX_free dlsym_EVP_CIPHER_CTX_free; -static __dlsym_EVP_CIPHER_CTX_init dlsym_EVP_CIPHER_CTX_init; +static __dlsym_EVP_CIPHER_CTX_reset dlsym_EVP_CIPHER_CTX_reset; static __dlsym_EVP_CIPHER_CTX_set_padding dlsym_EVP_CIPHER_CTX_set_padding; static __dlsym_EVP_CIPHER_CTX_ctrl dlsym_EVP_CIPHER_CTX_ctrl; static __dlsym_EVP_CipherInit_ex dlsym_EVP_CipherInit_ex; @@ -93,7 +97,7 @@ static __dlsym_EVP_aes_128_gcm dlsym_EVP_aes_128_gcm; #endif #ifdef UNIX -static void loadAes(JNIEnv *env, void *openssl) +static void loadAes(JNIEnv *env) #endif #ifdef WINDOWS @@ -139,7 +143,7 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initI { char msg[1000]; #ifdef UNIX - void *openssl = dlopen(COMMONS_CRYPTO_OPENSSL_LIBRARY, RTLD_LAZY | RTLD_GLOBAL); + openssl = dlopen(COMMONS_CRYPTO_OPENSSL_LIBRARY, RTLD_LAZY | RTLD_GLOBAL); #endif #ifdef WINDOWS @@ -161,22 +165,17 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initI #ifdef UNIX dlerror(); // Clear any existing error - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_new, env, openssl, \ - "EVP_CIPHER_CTX_new"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_free, env, openssl, \ - "EVP_CIPHER_CTX_free"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_init, env, openssl, \ - "EVP_CIPHER_CTX_init"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_set_padding, env, openssl, \ - "EVP_CIPHER_CTX_set_padding"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_ctrl, env, openssl, \ - "EVP_CIPHER_CTX_ctrl"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherInit_ex, env, openssl, \ - "EVP_CipherInit_ex"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherUpdate, env, openssl, \ - "EVP_CipherUpdate"); - LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherFinal_ex, env, openssl, \ - "EVP_CipherFinal_ex"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_new, env, openssl, "EVP_CIPHER_CTX_new"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_free, env, openssl, "EVP_CIPHER_CTX_free"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_set_padding, env, openssl, "EVP_CIPHER_CTX_set_padding"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_ctrl, env, openssl, "EVP_CIPHER_CTX_ctrl"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_block_size, env, openssl, "EVP_CIPHER_CTX_block_size"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_cipher, env, openssl, "EVP_CIPHER_CTX_cipher"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_flags, env, openssl, "EVP_CIPHER_flags"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CIPHER_CTX_test_flags, env, openssl, "EVP_CIPHER_CTX_test_flags"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherInit_ex, env, openssl, "EVP_CipherInit_ex"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherUpdate, env, openssl, "EVP_CipherUpdate"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_CipherFinal_ex, env, openssl, "EVP_CipherFinal_ex"); #endif #ifdef WINDOWS @@ -184,8 +183,9 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initI env, openssl, "EVP_CIPHER_CTX_new"); LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_CIPHER_CTX_free, dlsym_EVP_CIPHER_CTX_free, \ env, openssl, "EVP_CIPHER_CTX_free"); - LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_CIPHER_CTX_init, dlsym_EVP_CIPHER_CTX_init, \ - env, openssl, "EVP_CIPHER_CTX_init"); + LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_CIPHER_CTX_reset, \ + dlsym_EVP_CIPHER_CTX_reset, env, + openssl, "EVP_CIPHER_CTX_reset"); LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_CIPHER_CTX_set_padding, \ dlsym_EVP_CIPHER_CTX_set_padding, env, \ openssl, "EVP_CIPHER_CTX_set_padding"); @@ -197,7 +197,7 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initI env, openssl, "EVP_CipherFinal_ex"); #endif - loadAes(env, openssl); + loadAes(env); jthrowable jthr = (*env)->ExceptionOccurred(env); if (jthr) { (*env)->DeleteLocalRef(env, jthr); @@ -209,9 +209,14 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initI typedef struct EVP_CTX_Wrapper { int initialized; + int encrypt; // ENCRYPT_MODE or DECRYPT_MODE EVP_CIPHER_CTX *ctx; } EVP_CTX_Wrapper; +static int check_update_max_output_len(EVP_CTX_Wrapper *wrapper, int input_len, int max_output_len); +static int check_doFinal_max_output_len(JNIEnv *env, EVP_CIPHER_CTX *context, int max_output_len); +static int is_bad_tag(EVP_CTX_Wrapper *wrapper); + #define CTX_WRAPPER(addr) ((EVP_CTX_Wrapper *)(ptrdiff_t) addr) static EVP_CTX_Wrapper * new_context_wrapper(JNIEnv *env) { @@ -412,6 +417,7 @@ JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_init } // everything is OK, + wrapper->encrypt = mode; wrapper->initialized = 1; cleanup: @@ -428,31 +434,6 @@ cleanup: return JLONG(wrapper); } -// https://www.openssl.org/docs/crypto/EVP_EncryptInit.html -static int check_update_max_output_len(EVP_CIPHER_CTX *context, int input_len, - int max_output_len) -{ - if (context->flags & EVP_CIPH_NO_PADDING) { - if (max_output_len >= input_len) { - return 1; - } - return 0; - } else { - int b = context->cipher->block_size; - if (context->encrypt) { - if (max_output_len >= input_len + b - 1) { - return 1; - } - } else { - if (max_output_len >= input_len + b) { - return 1; - } - } - - return 0; - } -} - JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_update (JNIEnv *env, jclass clazz, jlong ctx, jobject input, jint input_offset, jint input_len, jobject output, jint output_offset, jint max_output_len) @@ -462,7 +443,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_updat return 0; } - if (!check_update_max_output_len(context, input_len, max_output_len)) { + if (!check_update_max_output_len(CTX_WRAPPER(ctx), input_len, max_output_len)) { THROW(env, "javax/crypto/ShortBufferException", \ "Output buffer is not sufficient."); return 0; @@ -495,10 +476,8 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_updat } // when provide AAD to EVP cipher, output is NULL. - if (output != NULL - && !check_update_max_output_len(context, input_len, max_output_len)) { - THROW(env, "javax/crypto/ShortBufferException", \ - "Output buffer is not sufficient."); + if (output != NULL && !check_update_max_output_len(CTX_WRAPPER(ctx), input_len, max_output_len)) { + THROW(env, "javax/crypto/ShortBufferException", "Output buffer is not sufficient."); return 0; } @@ -544,7 +523,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_updat return 0; } - if (!check_update_max_output_len(context, input_len, max_output_len)) { + if (!check_update_max_output_len(CTX_WRAPPER(ctx), input_len, max_output_len)) { THROW(env, "javax/crypto/ShortBufferException", \ "Output buffer is not sufficient."); return 0; @@ -572,23 +551,6 @@ cleanup: return output_len; } - -// https://www.openssl.org/docs/crypto/EVP_EncryptInit.html -static int check_doFinal_max_output_len(EVP_CIPHER_CTX *context, - int max_output_len) -{ - if (context->flags & EVP_CIPH_NO_PADDING) { - return 1; - } else { - int b = context->cipher->block_size; - if (max_output_len >= b) { - return 1; - } - - return 0; - } -} - JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_doFinal (JNIEnv *env, jclass clazz, jlong ctx, jobject output, jint offset, jint max_output_len) @@ -598,7 +560,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_doFin return 0; } - if (!check_doFinal_max_output_len(context, max_output_len)) { + if (!check_doFinal_max_output_len(env, context, max_output_len)) { THROW(env, "javax/crypto/ShortBufferException", \ "Output buffer is not sufficient."); return 0; @@ -613,8 +575,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_doFin int output_len = 0; if (!dlsym_EVP_CipherFinal_ex(context, output_bytes, &output_len)) { // validate tag in GCM mode when decrypt - if ((context->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_GCM_MODE - && context->encrypt == DECRYPT_MODE) { + if (is_bad_tag(CTX_WRAPPER(ctx))) { THROW(env, "javax/crypto/AEADBadTagException", "Tag mismatch!"); } else { THROW(env, "java/lang/InternalError", "Error in EVP_CipherFinal_ex."); @@ -633,7 +594,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_doFin return 0; } - if (!check_doFinal_max_output_len(context, max_output_len)) { + if (!check_doFinal_max_output_len(env, context, max_output_len)) { THROW(env, "javax/crypto/ShortBufferException", \ "Output buffer is not sufficient."); return 0; @@ -651,8 +612,7 @@ JNIEXPORT jint JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_doFin if (rc == 0) { // validate tag in GCM mode when decrypt - if ((context->cipher->flags & EVP_CIPH_MODE) == EVP_CIPH_GCM_MODE - && context->encrypt == DECRYPT_MODE) { + if (is_bad_tag(CTX_WRAPPER(ctx))) { THROW(env, "javax/crypto/AEADBadTagException", "Tag mismatch!"); } else { THROW(env, "java/lang/InternalError", "Error in EVP_CipherFinal_ex."); @@ -716,3 +676,50 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_clean EVP_CTX_Wrapper *wrapper = CTX_WRAPPER(ctx); free_context_wrapper(wrapper); } + +static int check_update_max_output_len(EVP_CTX_Wrapper *wrapper, int input_len, int max_output_len) +{ + if (dlsym_EVP_CIPHER_CTX_test_flags(wrapper->ctx, EVP_CIPH_NO_PADDING) == EVP_CIPH_NO_PADDING) { + if (max_output_len >= input_len) { + return 1; + } + return 0; + } else { + int b = dlsym_EVP_CIPHER_CTX_block_size(wrapper->ctx); + if (wrapper->encrypt) { + if (max_output_len >= input_len + b - 1) { + return 1; + } + } else { + if (max_output_len >= input_len + b) { + return 1; + } + } + return 0; + } +} + +static int check_doFinal_max_output_len(JNIEnv *env, EVP_CIPHER_CTX *context, int max_output_len) +{ + if (dlsym_EVP_CIPHER_CTX_test_flags(context, EVP_CIPH_NO_PADDING) == EVP_CIPH_NO_PADDING) { + return 1; + } else { + int b = dlsym_EVP_CIPHER_CTX_block_size(context); + if (max_output_len >= b) { + return 1; + } + return 0; + } +} + +static int is_bad_tag(EVP_CTX_Wrapper *wrapper) +{ + EVP_CIPHER* ciph = dlsym_EVP_CIPHER_CTX_cipher(wrapper->ctx); + unsigned long flags = dlsym_EVP_CIPHER_flags(ciph); + if ((flags & EVP_CIPH_MODE) == EVP_CIPH_GCM_MODE && wrapper->encrypt == DECRYPT_MODE) { + return 1; + } + return 0; +} + + diff --git a/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h b/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h index b980b77..d0b43ef 100644 --- a/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h +++ b/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h @@ -94,11 +94,30 @@ void *do_dlsym(JNIEnv *env, void *handle, const char *symbol) { return func_ptr; } +static __attribute__ ((unused)) +void *do_version_dlsym(JNIEnv *env, void *handle) { + if (!env || !handle) { + THROW(env, "java/lang/InternalError", NULL); + return NULL; + } + void *func_ptr = dlsym(handle, "OpenSSL_version_num"); + if (func_ptr == NULL) { + func_ptr = dlsym(handle, "SSLeay"); + } + return func_ptr; +} + /* A helper macro to dlsym the requisite dynamic symbol and bail-out on error. */ #define LOAD_DYNAMIC_SYMBOL(func_ptr, env, handle, symbol) \ if ((func_ptr = do_dlsym(env, handle, symbol)) == NULL) { \ return; \ } + +/* A macro to dlsym the appropriate OpenSSL version number function. */ +#define LOAD_OPENSSL_VERSION_FUNCTION(func_ptr, env, handle) \ + if ((func_ptr = do_version_dlsym(env, handle)) == NULL) { \ + THROW(env, "java/lang/Error", NULL); \ + } #endif // Unix part end @@ -195,6 +214,7 @@ static FARPROC WINAPI do_dlsym(JNIEnv *env, HMODULE handle, LPCSTR symbol) { #include <openssl/aes.h> #include <openssl/evp.h> #include <openssl/err.h> +#include <openssl/opensslv.h> /** * A helper macro to convert the java 'context-handle' @@ -224,6 +244,8 @@ static FARPROC WINAPI do_dlsym(JNIEnv *env, HMODULE handle, LPCSTR symbol) { #define NOPADDING 0 #define PKCS5PADDING 1 +#define VERSION_1_0_X 0x10000000 +#define VERSION_1_1_X 0x10100000 #endif diff --git a/src/main/native/org/apache/commons/crypto/random/OpenSslCryptoRandomNative.c b/src/main/native/org/apache/commons/crypto/random/OpenSslCryptoRandomNative.c index 56668cb..9f6078d 100644 --- a/src/main/native/org/apache/commons/crypto/random/OpenSslCryptoRandomNative.c +++ b/src/main/native/org/apache/commons/crypto/random/OpenSslCryptoRandomNative.c @@ -43,60 +43,51 @@ #ifdef UNIX static void * (*dlsym_CRYPTO_malloc) (int, const char *, int); static void (*dlsym_CRYPTO_free) (void *); -static int (*dlsym_CRYPTO_num_locks) (void); -static void (*dlsym_CRYPTO_set_locking_callback) (void (*)()); -static void (*dlsym_CRYPTO_set_id_callback) (unsigned long (*)()); -static void (*dlsym_ENGINE_load_rdrand) (void); static ENGINE * (*dlsym_ENGINE_by_id) (const char *); static int (*dlsym_ENGINE_init) (ENGINE *); static int (*dlsym_ENGINE_set_default) (ENGINE *, unsigned int); static int (*dlsym_ENGINE_finish) (ENGINE *); static int (*dlsym_ENGINE_free) (ENGINE *); -static void (*dlsym_ENGINE_cleanup) (void); static int (*dlsym_RAND_bytes) (unsigned char *, int); static unsigned long (*dlsym_ERR_get_error) (void); +static unsigned long (*dlsym_OpenSSL_version_num)(void); +static void *openssl; #endif #ifdef WINDOWS typedef void * (__cdecl *__dlsym_CRYPTO_malloc) (int, const char *, int); typedef void (__cdecl *__dlsym_CRYPTO_free) (void *); -typedef int (__cdecl *__dlsym_CRYPTO_num_locks) (void); -typedef void (__cdecl *__dlsym_CRYPTO_set_locking_callback) \ - (void (*)(int, int, char *, int)); -typedef void (__cdecl *__dlsym_ENGINE_load_rdrand) (void); typedef ENGINE * (__cdecl *__dlsym_ENGINE_by_id) (const char *); typedef int (__cdecl *__dlsym_ENGINE_init) (ENGINE *); typedef int (__cdecl *__dlsym_ENGINE_set_default) (ENGINE *, unsigned int); typedef int (__cdecl *__dlsym_ENGINE_finish) (ENGINE *); typedef int (__cdecl *__dlsym_ENGINE_free) (ENGINE *); -typedef void (__cdecl *__dlsym_ENGINE_cleanup) (void); typedef int (__cdecl *__dlsym_RAND_bytes) (unsigned char *, int); typedef unsigned long (__cdecl *__dlsym_ERR_get_error) (void); static __dlsym_CRYPTO_malloc dlsym_CRYPTO_malloc; static __dlsym_CRYPTO_free dlsym_CRYPTO_free; -static __dlsym_CRYPTO_num_locks dlsym_CRYPTO_num_locks; -static __dlsym_CRYPTO_set_locking_callback dlsym_CRYPTO_set_locking_callback; -static __dlsym_ENGINE_load_rdrand dlsym_ENGINE_load_rdrand; static __dlsym_ENGINE_by_id dlsym_ENGINE_by_id; static __dlsym_ENGINE_init dlsym_ENGINE_init; static __dlsym_ENGINE_set_default dlsym_ENGINE_set_default; static __dlsym_ENGINE_finish dlsym_ENGINE_finish; static __dlsym_ENGINE_free dlsym_ENGINE_free; -static __dlsym_ENGINE_cleanup dlsym_ENGINE_cleanup; static __dlsym_RAND_bytes dlsym_RAND_bytes; static __dlsym_ERR_get_error dlsym_ERR_get_error; #endif -static ENGINE * openssl_rand_init(void); -static void openssl_rand_clean(ENGINE *eng, int clean_locks); +static ENGINE * openssl_rand_init(JNIEnv *env); +static void openssl_rand_clean(JNIEnv *env, ENGINE *eng, int clean_locks); static int openssl_rand_bytes(unsigned char *buf, int num); +static void pthreads_locking_callback(int mode, int type, char *file, int line); +static unsigned long pthreads_thread_id(void); +static pthread_mutex_t *lock_cs; JNIEXPORT void JNICALL Java_org_apache_commons_crypto_random_OpenSslCryptoRandomNative_initSR (JNIEnv *env, jclass clazz) { char msg[1000]; #ifdef UNIX - void *openssl = dlopen(COMMONS_CRYPTO_OPENSSL_LIBRARY, RTLD_LAZY | RTLD_GLOBAL); + openssl = dlopen(COMMONS_CRYPTO_OPENSSL_LIBRARY, RTLD_LAZY | RTLD_GLOBAL); #endif #ifdef WINDOWS @@ -120,22 +111,15 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_random_OpenSslCryptoRandom dlerror(); // Clear any existing error LOAD_DYNAMIC_SYMBOL(dlsym_CRYPTO_malloc, env, openssl, "CRYPTO_malloc"); LOAD_DYNAMIC_SYMBOL(dlsym_CRYPTO_free, env, openssl, "CRYPTO_free"); - LOAD_DYNAMIC_SYMBOL(dlsym_CRYPTO_num_locks, env, openssl, "CRYPTO_num_locks"); - LOAD_DYNAMIC_SYMBOL(dlsym_CRYPTO_set_locking_callback, \ - env, openssl, "CRYPTO_set_locking_callback"); - LOAD_DYNAMIC_SYMBOL(dlsym_CRYPTO_set_id_callback, env, \ - openssl, "CRYPTO_set_id_callback"); - LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_load_rdrand, env, \ - openssl, "ENGINE_load_rdrand"); LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_by_id, env, openssl, "ENGINE_by_id"); LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_init, env, openssl, "ENGINE_init"); LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_set_default, env, \ openssl, "ENGINE_set_default"); LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_finish, env, openssl, "ENGINE_finish"); LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_free, env, openssl, "ENGINE_free"); - LOAD_DYNAMIC_SYMBOL(dlsym_ENGINE_cleanup, env, openssl, "ENGINE_cleanup"); LOAD_DYNAMIC_SYMBOL(dlsym_RAND_bytes, env, openssl, "RAND_bytes"); LOAD_DYNAMIC_SYMBOL(dlsym_ERR_get_error, env, openssl, "ERR_get_error"); + LOAD_OPENSSL_VERSION_FUNCTION(dlsym_OpenSSL_version_num, env, openssl); #endif #ifdef WINDOWS @@ -143,13 +127,6 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_random_OpenSslCryptoRandom env, openssl, "CRYPTO_malloc"); LOAD_DYNAMIC_SYMBOL(__dlsym_CRYPTO_free, dlsym_CRYPTO_free, \ env, openssl, "CRYPTO_free"); - LOAD_DYNAMIC_SYMBOL(__dlsym_CRYPTO_num_locks, dlsym_CRYPTO_num_locks, \ - env, openssl, "CRYPTO_num_locks"); - LOAD_DYNAMIC_SYMBOL(__dlsym_CRYPTO_set_locking_callback, \ - dlsym_CRYPTO_set_locking_callback, \ - env, openssl, "CRYPTO_set_locking_callback"); - LOAD_DYNAMIC_SYMBOL(__dlsym_ENGINE_load_rdrand, dlsym_ENGINE_load_rdrand, \ - env, openssl, "ENGINE_load_rdrand"); LOAD_DYNAMIC_SYMBOL(__dlsym_ENGINE_by_id, dlsym_ENGINE_by_id, \ env, openssl, "ENGINE_by_id"); LOAD_DYNAMIC_SYMBOL(__dlsym_ENGINE_init, dlsym_ENGINE_init, \ @@ -160,15 +137,13 @@ JNIEXPORT void JNICALL Java_org_apache_commons_crypto_random_OpenSslCryptoRandom env, openssl, "ENGINE_finish"); LOAD_DYNAMIC_SYMBOL(__dlsym_ENGINE_free, dlsym_ENGINE_free, \ env, openssl, "ENGINE_free"); - LOAD_DYNAMIC_SYMBOL(__dlsym_ENGINE_cleanup, dlsym_ENGINE_cleanup, \ - env, openssl, "ENGINE_cleanup"); LOAD_DYNAMIC_SYMBOL(__dlsym_RAND_bytes, dlsym_RAND_bytes, \ env, openssl, "RAND_bytes"); LOAD_DYNAMIC_SYMBOL(__dlsym_ERR_get_error, dlsym_ERR_get_error, \ env, openssl, "ERR_get_error"); #endif - openssl_rand_init(); + openssl_rand_init(env); } JNIEXPORT jboolean JNICALL Java_org_apache_commons_crypto_random_OpenSslCryptoRandomNative_nextRandBytes___3B @@ -246,9 +221,11 @@ static void pthreads_locking_callback(int mode, int type, char *file, int line); static unsigned long pthreads_thread_id(void); static pthread_mutex_t *lock_cs; -static void locks_setup(void) +static void locks_setup(JNIEnv *env) { int i; + static int (*dlsym_CRYPTO_num_locks) (void); + dlsym_CRYPTO_num_locks = do_dlsym(env, openssl, "CRYPTO_num_locks"); lock_cs = dlsym_CRYPTO_malloc(dlsym_CRYPTO_num_locks() * \ sizeof(pthread_mutex_t), __FILE__, __LINE__); @@ -256,13 +233,22 @@ static void locks_setup(void) pthread_mutex_init(&(lock_cs[i]), NULL); } + static void (*dlsym_CRYPTO_set_id_callback) (unsigned long (*)()); + dlsym_CRYPTO_set_id_callback = do_dlsym(env, openssl, "CRYPTO_set_id_callback"); + static void (*dlsym_CRYPTO_set_locking_callback) (void (*)()); + dlsym_CRYPTO_set_locking_callback = do_dlsym(env, openssl, "CRYPTO_set_locking_callback"); + dlsym_CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); dlsym_CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); } -static void locks_cleanup(void) +static void locks_cleanup(JNIEnv *env) { int i; + static int (*dlsym_CRYPTO_num_locks) (void); + dlsym_CRYPTO_num_locks = do_dlsym(env, openssl, "CRYPTO_num_locks"); + static void (*dlsym_CRYPTO_set_locking_callback) (void (*)()); + dlsym_CRYPTO_set_locking_callback = do_dlsym(env, openssl, "CRYPTO_set_locking_callback"); dlsym_CRYPTO_set_locking_callback(NULL); for (i = 0; i < dlsym_CRYPTO_num_locks(); i++) { @@ -294,11 +280,15 @@ static unsigned long pthreads_thread_id(void) * If using an Intel chipset with RDRAND, the high-performance hardware * random number generator will be used. */ -static ENGINE * openssl_rand_init(void) +static ENGINE * openssl_rand_init(JNIEnv *env) { - locks_setup(); + if (dlsym_OpenSSL_version_num() < VERSION_1_1_X) { + locks_setup(env); + static void (*dlsym_ENGINE_load_rdrand) (void); + dlsym_ENGINE_load_rdrand = do_dlsym(env, openssl, "ENGINE_load_rdrand"); + dlsym_ENGINE_load_rdrand(); + } - dlsym_ENGINE_load_rdrand(); ENGINE *eng = dlsym_ENGINE_by_id("rdrand"); int ret = -1; @@ -321,22 +311,28 @@ static ENGINE * openssl_rand_init(void) } while(0); if (ret == -1) { - openssl_rand_clean(eng, 0); + openssl_rand_clean(env, eng, 0); } return eng; } -static void openssl_rand_clean(ENGINE *eng, int clean_locks) +static void openssl_rand_clean(JNIEnv *env, ENGINE *eng, int clean_locks) { if (NULL != eng) { dlsym_ENGINE_finish(eng); dlsym_ENGINE_free(eng); } - dlsym_ENGINE_cleanup(); - if (clean_locks) { - locks_cleanup(); + if (dlsym_OpenSSL_version_num() < VERSION_1_1_X) { + static void (*dlsym_ENGINE_cleanup) (void); + if((dlsym_ENGINE_cleanup = do_dlsym(env, openssl, "ENGINE_cleanup")) == NULL) { + THROW(env, "java/lang/UnsatisfiedLinkError", "ENGINE_cleanup"); + } + dlsym_ENGINE_cleanup(); + if (clean_locks) { + locks_cleanup(env); + } } } diff --git a/src/test/java/org/apache/commons/crypto/jna/OpenSslNativeJnaTest.java b/src/test/java/org/apache/commons/crypto/jna/OpenSslNativeJnaTest.java index 28b3381..4857aea 100644 --- a/src/test/java/org/apache/commons/crypto/jna/OpenSslNativeJnaTest.java +++ b/src/test/java/org/apache/commons/crypto/jna/OpenSslNativeJnaTest.java @@ -25,7 +25,7 @@ public class OpenSslNativeJnaTest { @Test public void test() { if (OpenSslJna.isEnabled()) { - System.out.println("** INFO: JNA is using: " + OpenSslNativeJna.SSLeay_version(0)); + System.out.println("** INFO: JNA is using: " + OpenSslJna.OpenSSLVersion(0)); } else { System.out.println("** WARN: JNA could not be enabled: " + OpenSslJna.initialisationError().getMessage()); }