From: Krzysztof Jackiewicz Date: Wed, 25 May 2016 12:04:35 +0000 (+0200) Subject: Add support for multiple threads X-Git-Tag: accepted/tizen/common/20160810.161523~109 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6a81623a26e1d8c08b355570dab8ad64ed89326a;p=platform%2Fcore%2Fsecurity%2Fyaca.git Add support for multiple threads Change-Id: I76451bc5ea76fd2277eb62f79aa435f4b4fbe64d --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e21ca95..a2e511e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,9 +47,13 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## PKG_CHECK_MODULES(YACA_DEPS REQUIRED openssl capi-base-common) +FIND_PACKAGE (Threads) + INCLUDE_DIRECTORIES(${API_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${YACA_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${YACA_DEPS_LIBRARIES}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} + ${YACA_DEPS_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT}) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/src/crypto.c b/src/crypto.c index ec1d35b..d52468d 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -34,19 +35,83 @@ #include "internal.h" +static pthread_mutex_t *mutexes = NULL; + +static void locking_callback(int mode, int type, const char* file, int line) +{ + /* Ignore NULL mutexes and lock/unlock error codes as we can't do anything + * about them. */ + + if (mutexes == NULL) + return; + + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&mutexes[type]); + else if (mode & CRYPTO_UNLOCK) + pthread_mutex_unlock(&mutexes[type]); +} + +static unsigned long thread_id_callback() +{ + return pthread_self(); +} + +static void destroy_mutexes(int count) +{ + if (mutexes != NULL) { + for (int i = 0; i < count; i++) { + /* Ignore returned value as we can't do anything about it */ + pthread_mutex_destroy(&mutexes[i]); + } + yaca_free(mutexes); + mutexes = NULL; + } +} + API int yaca_init(void) { + if (mutexes != NULL) + return YACA_ERROR_INTERNAL; // TODO introduce new one? OPENSSL_init(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); + + /* enable threads support */ + mutexes = yaca_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + if (mutexes == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + for (int i = 0; i < CRYPTO_num_locks(); i++) { + if (pthread_mutex_init(&mutexes[i], NULL) != 0) { + int ret = 0; + switch (errno) { + case ENOMEM: + ret = YACA_ERROR_OUT_OF_MEMORY; + break; + case EAGAIN: + case EPERM: + case EBUSY: + case EINVAL: + default: + ret = YACA_ERROR_INTERNAL; + } + destroy_mutexes(i); + + return ret; + } + } + + CRYPTO_set_id_callback(thread_id_callback); + CRYPTO_set_locking_callback(locking_callback); + /* TODO: - We should prepare for multithreading. Either we or the user should setup static locks. We should also decide on Openssl config. Here's a good tutorial for initalization and cleanup: https://wiki.openssl.org/index.php/Library_Initialization We should also initialize the entropy for random number generator: https://wiki.openssl.org/index.php/Random_Numbers#Initialization */ + return 0; } @@ -56,6 +121,12 @@ API void yaca_exit(void) ERR_remove_thread_state(NULL); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); + + /* threads support cleanup */ + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); + + destroy_mutexes(CRYPTO_num_locks()); } API void *yaca_malloc(size_t size)