From 1c823003bfd9433c8c4f05999553ce1525a41ac0 Mon Sep 17 00:00:00 2001 From: Chao Shan Date: Wed, 25 Mar 2020 14:03:26 -0400 Subject: [PATCH 1/2] Add openssl thread synchronization to fix crashes Openssl 1.0.2 is not safely used in multi-thread application. The change adds threadid and locking callback functions to provide thread-safety when openssl 1.0.2 is used. It fixes issue 8373, test crash in openjdk, jdk_net_0, com/sun/net/httpserver/Test9a.java Signed-off-by: Chao Shan --- .../share/native/libjncrypto/NativeCrypto.c | 412 +++++++++++++----- 1 file changed, 305 insertions(+), 107 deletions(-) diff --git a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c index 578762eb37..de87f16458 100644 --- a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c +++ b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved + * (c) Copyright IBM Corp. 2018, 2020 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,14 @@ #define OPENSSL_VERSION_1_0 "OpenSSL 1.0." #define OPENSSL_VERSION_1_1 "OpenSSL 1.1." +/* needed for OpenSSL 1.0.2 Thread handling routines */ +#define CRYPTO_LOCK 1 + +#if defined(WINDOWS) +# include +#else /* defined(WINDOWS) */ +# include +#endif /* defined(WINDOWS) */ /* Header for RSA algorithm using 1.0.2 OpenSSL */ int OSSL102_RSA_set0_key(RSA *, BIGNUM *, BIGNUM *, BIGNUM *); @@ -95,11 +103,34 @@ typedef BIGNUM* OSSL_BN_bin2bn_t (const unsigned char *, int, BIGNUM *); typedef void OSSL_BN_set_negative_t (BIGNUM *, int); typedef void OSSL_BN_free_t (BIGNUM *); +typedef int OSSL_CRYPTO_num_locks_t(); +typedef void OSSL_CRYPTO_THREADID_set_numeric_t(CRYPTO_THREADID *id, unsigned long val); +typedef void* OSSL_OPENSSL_malloc_t(size_t num); +typedef void* OSSL_OPENSSL_free_t(void* addr); +typedef int OSSL_CRYPTO_THREADID_set_callback_t(void (*threadid_func)(CRYPTO_THREADID *)); +typedef void OSSL_CRYPTO_set_locking_callback_t(void (*func)(int mode, int type, const char *file, int line)); + +static int thread_setup(); +#if defined(WINDOWS) +static void win32_locking_callback(int mode, int type, const char *file, int line); +#else /* defined(WINDOWS) */ +static void pthreads_thread_id(CRYPTO_THREADID *tid); +static void pthreads_locking_callback(int mode, int type, const char *file, int line); +#endif /* defined(WINDOWS) */ + /* Define pointers for OpenSSL functions to handle Errors. */ OSSL_error_string_n_t* OSSL_error_string_n; OSSL_error_string_t* OSSL_error_string; OSSL_get_error_t* OSSL_get_error; +/* Define pointers for OpenSSL 1.0.2 threading routines */ +static OSSL_CRYPTO_num_locks_t* OSSL_CRYPTO_num_locks = NULL; +static OSSL_CRYPTO_THREADID_set_numeric_t* OSSL_CRYPTO_THREADID_set_numeric = NULL; +static OSSL_OPENSSL_malloc_t* OSSL_OPENSSL_malloc = NULL; +static OSSL_OPENSSL_free_t* OSSL_OPENSSL_free = NULL; +static OSSL_CRYPTO_THREADID_set_callback_t* OSSL_CRYPTO_THREADID_set_callback = NULL; +static OSSL_CRYPTO_set_locking_callback_t* OSSL_CRYPTO_set_locking_callback = NULL; + /* Define pointers for OpenSSL functions to handle Message Digest algorithms. */ OSSL_sha_t* OSSL_sha1; OSSL_sha_t* OSSL_sha256; @@ -170,6 +201,7 @@ static void printErrors(void) fflush(stderr); } +static void *crypto_library = NULL; /* * Class: jdk_crypto_jniprovider_NativeCrypto * Method: loadCrypto @@ -178,7 +210,6 @@ static void printErrors(void) JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto (JNIEnv *env, jclass thisObj, jboolean trace) { - void *handle; char *error; typedef const char* OSSL_version_t(int); @@ -188,8 +219,8 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto int ossl_ver; /* Load OpenSSL Crypto library */ - handle = load_crypto_library(); - if (handle == NULL) { + crypto_library = load_crypto_library(); + if (NULL == crypto_library) { if (trace) { fprintf(stderr, "Error loading OpenSSL: FAILED TO LOAD OPENSSL CRYPTO LIBRARY\n"); } @@ -202,16 +233,17 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto * the symbol "SSLeay_version" is used by OpenSSL 1.0. * Currently only openssl 1.0.x and 1.1.x are supported. */ - OSSL_version = (OSSL_version_t*)find_crypto_symbol(handle, "OpenSSL_version"); + OSSL_version = (OSSL_version_t*)find_crypto_symbol(crypto_library, "OpenSSL_version"); - if (OSSL_version == NULL) { - OSSL_version = (OSSL_version_t*)find_crypto_symbol(handle, "SSLeay_version"); + if (NULL == OSSL_version) { + OSSL_version = (OSSL_version_t*)find_crypto_symbol(crypto_library, "SSLeay_version"); - if (OSSL_version == NULL) { + if (NULL == OSSL_version) { if (trace) { fprintf(stderr, "Error loading OpenSSL: Error finding the OpenSSL version symbol in the crypto library\n"); } - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } else { openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */ @@ -220,7 +252,8 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto if (trace) { fprintf(stderr, "Error loading OpenSSL: Incompatible OpenSSL version found: %s\n", openssl_version); } - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } ossl_ver = 0; @@ -232,132 +265,151 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto if (trace) { fprintf(stderr, "Error loading OpenSSL: Incompatible OpenSSL version found: %s\n", openssl_version); } - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } ossl_ver = 1; } /* Load the function symbols for OpenSSL errors. */ - OSSL_error_string_n = (OSSL_error_string_n_t*)find_crypto_symbol(handle, "ERR_error_string_n"); - OSSL_error_string = (OSSL_error_string_t*)find_crypto_symbol(handle, "ERR_error_string"); - OSSL_get_error = (OSSL_get_error_t*)find_crypto_symbol(handle, "ERR_get_error"); + OSSL_error_string_n = (OSSL_error_string_n_t*)find_crypto_symbol(crypto_library, "ERR_error_string_n"); + OSSL_error_string = (OSSL_error_string_t*)find_crypto_symbol(crypto_library, "ERR_error_string"); + OSSL_get_error = (OSSL_get_error_t*)find_crypto_symbol(crypto_library, "ERR_get_error"); + + /* Load Threading routines for OpenSSL 1.0.2 */ + if (0 == ossl_ver) { + OSSL_CRYPTO_num_locks = (OSSL_CRYPTO_num_locks_t*)find_crypto_symbol(crypto_library, "CRYPTO_num_locks"); + OSSL_CRYPTO_THREADID_set_numeric = (OSSL_CRYPTO_THREADID_set_numeric_t*)find_crypto_symbol(crypto_library, "CRYPTO_THREADID_set_numeric"); + OSSL_OPENSSL_malloc = (OSSL_OPENSSL_malloc_t*)find_crypto_symbol(crypto_library, "CRYPTO_malloc"); + OSSL_OPENSSL_free = (OSSL_OPENSSL_free_t*)find_crypto_symbol(crypto_library, "CRYPTO_free"); + OSSL_CRYPTO_THREADID_set_callback = (OSSL_CRYPTO_THREADID_set_callback_t*)find_crypto_symbol(crypto_library, "CRYPTO_THREADID_set_callback"); + OSSL_CRYPTO_set_locking_callback = (OSSL_CRYPTO_set_locking_callback_t*)find_crypto_symbol(crypto_library, "CRYPTO_set_locking_callback"); + } /* Load the function symbols for OpenSSL Message Digest algorithms. */ - OSSL_sha1 = (OSSL_sha_t*)find_crypto_symbol(handle, "EVP_sha1"); - OSSL_sha256 = (OSSL_sha_t*)find_crypto_symbol(handle, "EVP_sha256"); - OSSL_sha224 = (OSSL_sha_t*)find_crypto_symbol(handle, "EVP_sha224"); - OSSL_sha384 = (OSSL_sha_t*)find_crypto_symbol(handle, "EVP_sha384"); - OSSL_sha512 = (OSSL_sha_t*)find_crypto_symbol(handle, "EVP_sha512"); - - if (ossl_ver == 1) { - OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(handle, "EVP_MD_CTX_new"); - OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(handle, "EVP_MD_CTX_reset"); - OSSL_MD_CTX_free = (OSSL_MD_CTX_free_t*)find_crypto_symbol(handle, "EVP_MD_CTX_free"); + OSSL_sha1 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha1"); + OSSL_sha256 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha256"); + OSSL_sha224 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha224"); + OSSL_sha384 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha384"); + OSSL_sha512 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha512"); + + if (1 == ossl_ver) { + OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_new"); + OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_reset"); + OSSL_MD_CTX_free = (OSSL_MD_CTX_free_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_free"); } else { - OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(handle, "EVP_MD_CTX_create"); - OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(handle, "EVP_MD_CTX_cleanup"); - OSSL_MD_CTX_free = (OSSL_MD_CTX_free_t*)find_crypto_symbol(handle, "EVP_MD_CTX_destroy"); + OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_create"); + OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_cleanup"); + OSSL_MD_CTX_free = (OSSL_MD_CTX_free_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_destroy"); } - OSSL_DigestInit_ex = (OSSL_DigestInit_ex_t*)find_crypto_symbol(handle, "EVP_DigestInit_ex"); - OSSL_MD_CTX_copy_ex = (OSSL_MD_CTX_copy_ex_t*)find_crypto_symbol(handle, "EVP_MD_CTX_copy_ex"); - OSSL_DigestUpdate = (OSSL_DigestUpdate_t*)find_crypto_symbol(handle, "EVP_DigestUpdate"); - OSSL_DigestFinal_ex = (OSSL_DigestFinal_ex_t*)find_crypto_symbol(handle, "EVP_DigestFinal_ex"); + OSSL_DigestInit_ex = (OSSL_DigestInit_ex_t*)find_crypto_symbol(crypto_library, "EVP_DigestInit_ex"); + OSSL_MD_CTX_copy_ex = (OSSL_MD_CTX_copy_ex_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_copy_ex"); + OSSL_DigestUpdate = (OSSL_DigestUpdate_t*)find_crypto_symbol(crypto_library, "EVP_DigestUpdate"); + OSSL_DigestFinal_ex = (OSSL_DigestFinal_ex_t*)find_crypto_symbol(crypto_library, "EVP_DigestFinal_ex"); /* Load the function symbols for OpenSSL CBC and GCM Cipher algorithms. */ - OSSL_CIPHER_CTX_new = (OSSL_CIPHER_CTX_new_t*)find_crypto_symbol(handle, "EVP_CIPHER_CTX_new"); - OSSL_CIPHER_CTX_free = (OSSL_CIPHER_CTX_free_t*)find_crypto_symbol(handle, "EVP_CIPHER_CTX_free"); - OSSL_aes_128_cbc = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_128_cbc"); - OSSL_aes_192_cbc = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_192_cbc"); - OSSL_aes_256_cbc = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_256_cbc"); - OSSL_CipherInit_ex = (OSSL_CipherInit_ex_t*)find_crypto_symbol(handle, "EVP_CipherInit_ex"); - OSSL_CIPHER_CTX_set_padding = (OSSL_CIPHER_CTX_set_padding_t*)find_crypto_symbol(handle, "EVP_CIPHER_CTX_set_padding"); - OSSL_CipherUpdate = (OSSL_CipherUpdate_t*)find_crypto_symbol(handle, "EVP_CipherUpdate"); - OSSL_CipherFinal_ex = (OSSL_CipherFinal_ex_t*)find_crypto_symbol(handle, "EVP_CipherFinal_ex"); - OSSL_aes_128_gcm = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_128_gcm"); - OSSL_aes_192_gcm = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_192_gcm"); - OSSL_aes_256_gcm = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_aes_256_gcm"); - OSSL_CIPHER_CTX_ctrl = (OSSL_CIPHER_CTX_ctrl_t*)find_crypto_symbol(handle, "EVP_CIPHER_CTX_ctrl"); - OSSL_DecryptInit_ex = (OSSL_DecryptInit_ex_t*)find_crypto_symbol(handle, "EVP_DecryptInit_ex"); - OSSL_DecryptUpdate = (OSSL_DecryptUpdate_t*)find_crypto_symbol(handle, "EVP_DecryptUpdate"); - OSSL_DecryptFinal = (OSSL_DecryptFinal_t*)find_crypto_symbol(handle, "EVP_DecryptFinal"); + OSSL_CIPHER_CTX_new = (OSSL_CIPHER_CTX_new_t*)find_crypto_symbol(crypto_library, "EVP_CIPHER_CTX_new"); + OSSL_CIPHER_CTX_free = (OSSL_CIPHER_CTX_free_t*)find_crypto_symbol(crypto_library, "EVP_CIPHER_CTX_free"); + OSSL_aes_128_cbc = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_128_cbc"); + OSSL_aes_192_cbc = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_192_cbc"); + OSSL_aes_256_cbc = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_256_cbc"); + OSSL_CipherInit_ex = (OSSL_CipherInit_ex_t*)find_crypto_symbol(crypto_library, "EVP_CipherInit_ex"); + OSSL_CIPHER_CTX_set_padding = (OSSL_CIPHER_CTX_set_padding_t*)find_crypto_symbol(crypto_library, "EVP_CIPHER_CTX_set_padding"); + OSSL_CipherUpdate = (OSSL_CipherUpdate_t*)find_crypto_symbol(crypto_library, "EVP_CipherUpdate"); + OSSL_CipherFinal_ex = (OSSL_CipherFinal_ex_t*)find_crypto_symbol(crypto_library, "EVP_CipherFinal_ex"); + OSSL_aes_128_gcm = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_128_gcm"); + OSSL_aes_192_gcm = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_192_gcm"); + OSSL_aes_256_gcm = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_aes_256_gcm"); + OSSL_CIPHER_CTX_ctrl = (OSSL_CIPHER_CTX_ctrl_t*)find_crypto_symbol(crypto_library, "EVP_CIPHER_CTX_ctrl"); + OSSL_DecryptInit_ex = (OSSL_DecryptInit_ex_t*)find_crypto_symbol(crypto_library, "EVP_DecryptInit_ex"); + OSSL_DecryptUpdate = (OSSL_DecryptUpdate_t*)find_crypto_symbol(crypto_library, "EVP_DecryptUpdate"); + OSSL_DecryptFinal = (OSSL_DecryptFinal_t*)find_crypto_symbol(crypto_library, "EVP_DecryptFinal"); /* Load the functions symbols for OpenSSL ChaCha20 algorithms. (Need OpenSSL 1.1.x or above) */ - if (ossl_ver == 1) { - OSSL_chacha20 = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_chacha20"); - OSSL_chacha20_poly1305 = (OSSL_cipher_t*)find_crypto_symbol(handle, "EVP_chacha20_poly1305"); + if (1 == ossl_ver) { + OSSL_chacha20 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20"); + OSSL_chacha20_poly1305 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20_poly1305"); } else { OSSL_chacha20 = NULL; OSSL_chacha20_poly1305 = NULL; } /* Load the functions symbols for OpenSSL RSA algorithm. */ - OSSL_RSA_new = (OSSL_RSA_new_t*)find_crypto_symbol(handle, "RSA_new"); + OSSL_RSA_new = (OSSL_RSA_new_t*)find_crypto_symbol(crypto_library, "RSA_new"); - if (ossl_ver == 1) { - OSSL_RSA_set0_key = (OSSL_RSA_set0_key_t*)find_crypto_symbol(handle, "RSA_set0_key"); - OSSL_RSA_set0_factors = (OSSL_RSA_set0_factors_t*)find_crypto_symbol(handle, "RSA_set0_factors"); - OSSL_RSA_set0_crt_params = (OSSL_RSA_set0_key_t*)find_crypto_symbol(handle, "RSA_set0_crt_params"); + if (1 == ossl_ver) { + OSSL_RSA_set0_key = (OSSL_RSA_set0_key_t*)find_crypto_symbol(crypto_library, "RSA_set0_key"); + OSSL_RSA_set0_factors = (OSSL_RSA_set0_factors_t*)find_crypto_symbol(crypto_library, "RSA_set0_factors"); + OSSL_RSA_set0_crt_params = (OSSL_RSA_set0_key_t*)find_crypto_symbol(crypto_library, "RSA_set0_crt_params"); } else { OSSL_RSA_set0_key = &OSSL102_RSA_set0_key; OSSL_RSA_set0_factors = &OSSL102_RSA_set0_factors; OSSL_RSA_set0_crt_params = &OSSL102_RSA_set0_crt_params; } - OSSL_RSA_free = (OSSL_RSA_free_t *)find_crypto_symbol(handle, "RSA_free"); - OSSL_RSA_public_decrypt = (OSSL_RSA_public_decrypt_t *)find_crypto_symbol(handle, "RSA_public_decrypt"); - OSSL_RSA_private_encrypt = (OSSL_RSA_private_encrypt_t *)find_crypto_symbol(handle, "RSA_private_decrypt"); - OSSL_BN_bin2bn = (OSSL_BN_bin2bn_t *)find_crypto_symbol(handle, "BN_bin2bn"); - OSSL_BN_set_negative = (OSSL_BN_set_negative_t *)find_crypto_symbol(handle, "BN_set_negative"); - OSSL_BN_free = (OSSL_BN_free_t *)find_crypto_symbol(handle, "BN_free"); - - if ((OSSL_error_string == NULL) || - (OSSL_error_string_n == NULL) || - (OSSL_get_error == NULL) || - (OSSL_sha1 == NULL) || - (OSSL_sha256 == NULL) || - (OSSL_sha224 == NULL) || - (OSSL_sha384 == NULL) || - (OSSL_sha512 == NULL) || - (OSSL_MD_CTX_new == NULL) || - (OSSL_MD_CTX_reset == NULL) || - (OSSL_MD_CTX_free == NULL) || - (OSSL_DigestInit_ex == NULL) || - (OSSL_MD_CTX_copy_ex == NULL) || - (OSSL_DigestUpdate == NULL) || - (OSSL_DigestFinal_ex == NULL) || - (OSSL_CIPHER_CTX_new == NULL) || - (OSSL_CIPHER_CTX_free == NULL) || - (OSSL_aes_128_cbc == NULL) || - (OSSL_aes_192_cbc == NULL) || - (OSSL_aes_256_cbc == NULL) || - (OSSL_CipherInit_ex == NULL) || - (OSSL_CIPHER_CTX_set_padding == NULL) || - (OSSL_CipherUpdate == NULL) || - (OSSL_CipherFinal_ex == NULL) || - (OSSL_aes_128_gcm == NULL) || - (OSSL_aes_192_gcm == NULL) || - (OSSL_aes_256_gcm == NULL) || - (OSSL_CIPHER_CTX_ctrl == NULL) || - (OSSL_DecryptInit_ex == NULL) || - (OSSL_DecryptUpdate == NULL) || - (OSSL_DecryptFinal == NULL) || - (OSSL_RSA_new == NULL) || - (OSSL_RSA_set0_key == NULL) || - (OSSL_RSA_set0_factors == NULL) || - (OSSL_RSA_set0_crt_params == NULL) || - (OSSL_RSA_free == NULL) || - (OSSL_RSA_public_decrypt == NULL) || - (OSSL_RSA_private_encrypt == NULL) || - (OSSL_BN_bin2bn == NULL) || - (OSSL_BN_set_negative == NULL) || - (OSSL_BN_free == NULL) || + OSSL_RSA_free = (OSSL_RSA_free_t *)find_crypto_symbol(crypto_library, "RSA_free"); + OSSL_RSA_public_decrypt = (OSSL_RSA_public_decrypt_t *)find_crypto_symbol(crypto_library, "RSA_public_decrypt"); + OSSL_RSA_private_encrypt = (OSSL_RSA_private_encrypt_t *)find_crypto_symbol(crypto_library, "RSA_private_decrypt"); + OSSL_BN_bin2bn = (OSSL_BN_bin2bn_t *)find_crypto_symbol(crypto_library, "BN_bin2bn"); + OSSL_BN_set_negative = (OSSL_BN_set_negative_t *)find_crypto_symbol(crypto_library, "BN_set_negative"); + OSSL_BN_free = (OSSL_BN_free_t *)find_crypto_symbol(crypto_library, "BN_free"); + + if ((NULL == OSSL_error_string) || + (NULL == OSSL_error_string_n) || + (NULL == OSSL_get_error) || + (NULL == OSSL_sha1) || + (NULL == OSSL_sha256) || + (NULL == OSSL_sha224) || + (NULL == OSSL_sha384) || + (NULL == OSSL_sha512) || + (NULL == OSSL_MD_CTX_new) || + (NULL == OSSL_MD_CTX_reset) || + (NULL == OSSL_MD_CTX_free) || + (NULL == OSSL_DigestInit_ex) || + (NULL == OSSL_MD_CTX_copy_ex) || + (NULL == OSSL_DigestUpdate) || + (NULL == OSSL_DigestFinal_ex) || + (NULL == OSSL_CIPHER_CTX_new) || + (NULL == OSSL_CIPHER_CTX_free) || + (NULL == OSSL_aes_128_cbc) || + (NULL == OSSL_aes_192_cbc) || + (NULL == OSSL_aes_256_cbc) || + (NULL == OSSL_CipherInit_ex) || + (NULL == OSSL_CIPHER_CTX_set_padding) || + (NULL == OSSL_CipherUpdate) || + (NULL == OSSL_CipherFinal_ex) || + (NULL == OSSL_aes_128_gcm) || + (NULL == OSSL_aes_192_gcm) || + (NULL == OSSL_aes_256_gcm) || + (NULL == OSSL_CIPHER_CTX_ctrl) || + (NULL == OSSL_DecryptInit_ex) || + (NULL == OSSL_DecryptUpdate) || + (NULL == OSSL_DecryptFinal) || + (NULL == OSSL_RSA_new) || + (NULL == OSSL_RSA_set0_key) || + (NULL == OSSL_RSA_set0_factors) || + (NULL == OSSL_RSA_set0_crt_params) || + (NULL == OSSL_RSA_free) || + (NULL == OSSL_RSA_public_decrypt) || + (NULL == OSSL_RSA_private_encrypt) || + (NULL == OSSL_BN_bin2bn) || + (NULL == OSSL_BN_set_negative) || + (NULL == OSSL_BN_free) || /* Check symbols that are only available in OpenSSL 1.1.x and above */ - ((ossl_ver == 1) && ((OSSL_chacha20 == NULL) || (OSSL_chacha20_poly1305 == NULL)))) { + ((1 == ossl_ver) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) || + /* Check symbols that are only available in OpenSSL 1.0.x and above */ + ((NULL == OSSL_CRYPTO_num_locks) && (0 == ossl_ver)) || + ((NULL == OSSL_CRYPTO_THREADID_set_numeric) && (0 == ossl_ver)) || + ((NULL == OSSL_OPENSSL_malloc) && (0 == ossl_ver)) || + ((NULL == OSSL_OPENSSL_free) && (0 == ossl_ver)) || + ((NULL == OSSL_CRYPTO_THREADID_set_callback) && (0 == ossl_ver)) || + ((NULL == OSSL_CRYPTO_set_locking_callback) && (0 == ossl_ver))) { if (trace) { fprintf(stderr, "Error loading OpenSSL: One or more of the required symbols are missing in the crypto library: %s\n", openssl_version); } - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } else { if (trace) { @@ -365,15 +417,161 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto if (NULL == library_path) { fprintf(stderr, "Using OpenSSL version: %s\n", openssl_version); } else { - get_library_path(handle, library_path); + get_library_path(crypto_library, library_path); fprintf(stderr, "Using OpenSSL version: %s (%s)\n", openssl_version, library_path); free(library_path); } } + if (0 == ossl_ver) { + if (0 != thread_setup()) { + unload_crypto_library(crypto_library); + crypto_library = NULL; + return -1; + } + } return ossl_ver; } } +#if defined(WINDOWS) +static HANDLE *lock_cs = NULL; + +int thread_setup() +{ + int i = 0; + int j = 0; + int lockNum = (*OSSL_CRYPTO_num_locks)(); + size_t size = lockNum * sizeof(HANDLE); + lock_cs = (*OSSL_OPENSSL_malloc)(size); + if (NULL == lock_cs) { + return -1; + } + for (i = 0; i < lockNum; i++) { + lock_cs[i] = CreateMutex(NULL, FALSE, NULL); + if (NULL == lock_cs[i]) { + fprintf(stderr, "CreateMutex error: %d\n", GetLastError()); + for (j = 0; j < i; j++) { + BOOL releaseResult = ReleaseMutex(lock_cs[j]); + if (FALSE == releaseResult) { + fprintf(stderr, "ReleaseMutex error: %d\n", GetLastError()); + } + } + (*OSSL_OPENSSL_free)(lock_cs); + lock_cs = NULL; + return -1; + } + } + /* + * For windows platform, OpenSSL already has an implementation to get thread id. + * So Windows do not need (*OSSL_CRYPTO_THREADID_set_callback)() here like non-Windows Platform. + */ + (*OSSL_CRYPTO_set_locking_callback)(win32_locking_callback); + return 0; +} + +void win32_locking_callback(int mode, int type, const char *file, int line) +{ + if (0 != (mode & CRYPTO_LOCK)) { + DWORD dwWaitResult = WaitForSingleObject(lock_cs[type], INFINITE); + if (WAIT_FAILED == dwWaitResult) { + fprintf(stderr, "WaitForSingleObject error: %d\n", GetLastError()); + } + } else { + BOOL releaseResult = ReleaseMutex(lock_cs[type]); + if (FALSE == releaseResult) { + fprintf(stderr, "ReleaseMutex error: %d\n", GetLastError()); + } + } +} + +#else /* defined(WINDOWS) */ +static pthread_mutex_t *lock_cs = NULL; + +int thread_setup() +{ + int i = 0; + int j = 0; + int lockNum = (*OSSL_CRYPTO_num_locks)(); + size_t size = lockNum * sizeof(pthread_mutex_t); + lock_cs = (*OSSL_OPENSSL_malloc)(size); + if (NULL == lock_cs) { + return -1; + } + for (i = 0; i < lockNum; i++) { + int initResult = pthread_mutex_init(&(lock_cs[i]), NULL); + if (0 != initResult) { + fprintf(stderr, "pthread_mutex_init error %d\n", initResult); + for (j = 0; j < i; j++) { + int destroyResult = pthread_mutex_destroy(&(lock_cs[j])); + if (0 != destroyResult) { + fprintf(stderr, "pthread_mutex_destroy error %d\n", destroyResult); + } + } + (*OSSL_OPENSSL_free)(lock_cs); + lock_cs = NULL; + return -1; + } + } + (*OSSL_CRYPTO_THREADID_set_callback)(pthreads_thread_id); + (*OSSL_CRYPTO_set_locking_callback)(pthreads_locking_callback); + return 0; +} + +void pthreads_locking_callback(int mode, int type, const char *file, int line) +{ + if (0 != (mode & CRYPTO_LOCK)) { + int lockResult = pthread_mutex_lock(&(lock_cs[type])); + if (0 != lockResult) { + fprintf(stderr, "pthread_mutex_lock error: %d\n", lockResult); + } + } else { + int unlockResult = pthread_mutex_unlock(&(lock_cs[type])); + if (0 != unlockResult) { + fprintf(stderr, "pthread_mutex_unlock error: %d\n", unlockResult); + } + } +} + +void pthreads_thread_id(CRYPTO_THREADID *tid) +{ + (*OSSL_CRYPTO_THREADID_set_numeric)(tid, (unsigned long)pthread_self()); +} +#endif /* defined(WINDOWS) */ + +/* Clean up resource from loadCrypto() and thread_setup()*/ +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void * reserved) +{ + int i = 0; + int lockNum = 0; + if (NULL == crypto_library) { + return; + } + if ((NULL == OSSL_CRYPTO_num_locks) || (NULL == lock_cs)) { + unload_crypto_library(crypto_library); + crypto_library = NULL; + return; + } + lockNum = (*OSSL_CRYPTO_num_locks)(); + (*OSSL_CRYPTO_set_locking_callback)(NULL); + for (i = 0; i < lockNum; i++) { +#if defined(WINDOWS) + BOOL destoryResult = CloseHandle(lock_cs[i]); + if (FALSE == destoryResult) { + fprintf(stderr, "destoryResult error: %d\n", GetLastError()); + } +#else /* defined(WINDOWS) */ + int destroyResult = pthread_mutex_destroy(&(lock_cs[i])); + if (0 != destroyResult) { + fprintf(stderr, "pthread_mutex_destroy error %d\n", destroyResult); + } +#endif /* defined(WINDOWS) */ + } + (*OSSL_OPENSSL_free)(lock_cs); + lock_cs = NULL; + unload_crypto_library(crypto_library); + crypto_library = NULL; +} + /* Create Digest context * * Class: jdk_crypto_jniprovider_NativeCrypto @@ -1114,7 +1312,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_GCMDecrypt } if (inLen - tagLen > 0) { - if(0 == (*OSSL_DecryptUpdate)(ctx, outputNative + outOffset, &len, inputNative + inOffset, inLen - tagLen)) { + if (0 == (*OSSL_DecryptUpdate)(ctx, outputNative + outOffset, &len, inputNative + inOffset, inLen - tagLen)) { printErrors(); (*OSSL_CIPHER_CTX_free)(ctx); (*env)->ReleasePrimitiveArrayCritical(env, key, keyNative, JNI_ABORT); From fa43f89a84e3a32abba5d552a6c2d6b9b019c5a1 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Mon, 6 Apr 2020 18:39:59 -0400 Subject: [PATCH 2/2] Use CloseHandle() to destroy a mutex on Windows Signed-off-by: Keith W. Campbell --- .../src/java.base/share/native/libjncrypto/NativeCrypto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c index de87f16458..6a6d7f8e41 100644 --- a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c +++ b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c @@ -451,9 +451,9 @@ int thread_setup() if (NULL == lock_cs[i]) { fprintf(stderr, "CreateMutex error: %d\n", GetLastError()); for (j = 0; j < i; j++) { - BOOL releaseResult = ReleaseMutex(lock_cs[j]); - if (FALSE == releaseResult) { - fprintf(stderr, "ReleaseMutex error: %d\n", GetLastError()); + BOOL closeResult = CloseHandle(lock_cs[j]); + if (FALSE == closeResult) { + fprintf(stderr, "CloseHandle error: %d\n", GetLastError()); } } (*OSSL_OPENSSL_free)(lock_cs);