From ce8de7c163d6a5586f0f3584ed7f8e171f61c249 Mon Sep 17 00:00:00 2001 From: Chao Shan Date: Wed, 25 Mar 2020 12:12:55 -0400 Subject: [PATCH] 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 | 309 ++++++++++++++---- 1 file changed, 252 insertions(+), 57 deletions(-) diff --git a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c index 2f01e1aee91..d8e06689e43 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,31 @@ 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(); +static void pthreads_thread_id(CRYPTO_THREADID *tid); +static void pthreads_locking_callback(int mode, int type, const char *file, int line); +static void win32_locking_callback(int mode, int type, const char *file, int line); + /* 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 +198,7 @@ static void printErrors(void) { fflush(stderr); } +static void *crypto_library = NULL; /* * Class: jdk_crypto_jniprovider_NativeCrypto * Method: loadCrypto @@ -178,7 +207,6 @@ static void printErrors(void) { JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto (JNIEnv *env, jclass thisObj){ - void *handle; char *error; typedef const char* OSSL_version_t(int); @@ -188,8 +216,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 (crypto_library == NULL) { /* fprintf(stderr, " :FAILED TO LOAD OPENSSL CRYPTO LIBRARY\n"); */ /* fflush(stderr); */ return -1; @@ -201,15 +229,16 @@ 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"); + OSSL_version = (OSSL_version_t*)find_crypto_symbol(crypto_library, "SSLeay_version"); if (OSSL_version == NULL) { /* fprintf(stderr, "Only openssl 1.0.x and 1.1.x are supported\n"); */ /* fflush(stderr); */ - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } else { openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */ @@ -217,7 +246,8 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto if (0 != strncmp(openssl_version, OPENSSL_VERSION_1_0, strlen(OPENSSL_VERSION_1_0))) { /* fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); */ /* fflush(stderr); */ - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } ossl_ver = 0; @@ -228,84 +258,95 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto if (0 != strncmp(openssl_version, OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1))) { /* fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); */ /* fflush(stderr); */ - 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 (ossl_ver == 0) { + 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"); + 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 (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_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"); + 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"); + 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"); + 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 ((OSSL_error_string == NULL) || (OSSL_error_string_n == NULL) || @@ -349,16 +390,170 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto (OSSL_BN_set_negative == NULL) || (OSSL_BN_free == NULL) || /* Check symbols that are only available in OpenSSL 1.1.x and above */ - ((ossl_ver == 1) && ((OSSL_chacha20 == NULL) || (OSSL_chacha20_poly1305 == NULL)))) { + ((ossl_ver == 1) && ((OSSL_chacha20 == NULL) || (OSSL_chacha20_poly1305 == NULL))) || + /* Check symbols that are only available in OpenSSL 1.0.x and above */ + ((OSSL_CRYPTO_num_locks == NULL) && (ossl_ver == 0)) || + ((OSSL_CRYPTO_THREADID_set_numeric == NULL) && (ossl_ver == 0)) || + ((OSSL_OPENSSL_malloc == NULL) && (ossl_ver == 0)) || + ((OSSL_OPENSSL_free == NULL) && (ossl_ver == 0)) || + ((OSSL_CRYPTO_THREADID_set_callback == NULL) && (ossl_ver == 0)) || + ((OSSL_CRYPTO_set_locking_callback == NULL) && (ossl_ver == 0))) { /* fprintf(stderr, "One or more of the required symbols are missing in the crypto library\n"); */ /* fflush(stderr); */ - unload_crypto_library(handle); + unload_crypto_library(crypto_library); + crypto_library = NULL; return -1; } else { + if (ossl_ver == 0) { + if (thread_setup() != 0) { + 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\n"); + for (j = 0; j < i; j++) { + int destroyResult = pthread_mutex_destroy(&(lock_cs[j])); + if (0 == destroyResult) { + fprintf(stderr, "pthread_mutex_destroy error\n"); + } + } + (*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\n"); + } +#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