Index: src/s390_rsa.c =================================================================== --- a/src/s390_rsa.c +++ b/src/s390_rsa.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include "s390_rsa.h" #include "s390_prng.h" @@ -41,9 +44,22 @@ static unsigned int mod_expo_sw(int arg_ char *exp, int mod_length, char *mod, int *res_length, char *res, BN_CTX *ctx); -RSA* rsa_key_generate(unsigned int modulus_bit_length, - unsigned long *public_exponent) +struct thread_data +{ + unsigned int mod_bit_length; + unsigned long *pub_exp; + RSA *rsa; +}; + +static void *__rsa_key_generate(void *ptr) { + struct thread_data *pth_data; + unsigned int modulus_bit_length; + unsigned long *public_exponent; + + pth_data = (struct thread_data*)ptr; + modulus_bit_length = pth_data->mod_bit_length; + public_exponent = pth_data->pub_exp; BN_GENCB cb; if (*public_exponent == 0) @@ -70,9 +86,36 @@ RSA* rsa_key_generate(unsigned int modul if (RSA_generate_key_ex(rsa, modulus_bit_length, exp, &cb)) { BN_free(exp); - return rsa; + pth_data->rsa = rsa; } + else + pth_data->rsa = NULL; + + return 0; +} +RSA* rsa_key_generate(unsigned int modulus_bit_length, + unsigned long *public_exponent) +{ + pthread_t tid; + struct thread_data th_data; + int rc; + + sem_wait(&openssl_crypto_lock_mtx); + + th_data.mod_bit_length = modulus_bit_length; + th_data.pub_exp = public_exponent; + rc = pthread_create(&(tid), NULL, (void *)&__rsa_key_generate, + (void *)(&th_data)); + if (rc) + return 0; + rc = pthread_join(tid, NULL); + + if (!rc && th_data.rsa) { + sem_post(&openssl_crypto_lock_mtx); + return th_data.rsa; + } + sem_post(&openssl_crypto_lock_mtx); return 0; } Index: src/init.c =================================================================== --- a/src/init.c +++ b/src/init.c @@ -18,10 +18,14 @@ #include #include #include +#include +#include +#include #include #include "init.h" #include "icastats.h" +#include "s390_rsa.h" #include "s390_prng.h" #include "s390_crypto.h" #include "ica_api.h" @@ -79,12 +83,60 @@ void end_sigill_section(struct sigaction sigprocmask(SIG_SETMASK, oldset, 0); } +static pthread_mutex_t *openssl_locks; + +static void openssl_lock_callback(int mode, int num, char *file, int line) +{ + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&(openssl_locks[num])); + } + else { + pthread_mutex_unlock(&(openssl_locks[num])); + } +} + +static unsigned long get_thread_id(void) +{ + return (unsigned long)pthread_self(); +} + +static void init_openssl_locks(void) +{ + int i, crypt_num_locks; + + crypt_num_locks = CRYPTO_num_locks(); + openssl_locks = (pthread_mutex_t *) + OPENSSL_malloc(crypt_num_locks * + sizeof(pthread_mutex_t)); + for (i = 0; i < CRYPTO_num_locks(); i++) { + pthread_mutex_init(&(openssl_locks[i]),NULL); + } + + CRYPTO_set_id_callback((unsigned long (*)())get_thread_id); + CRYPTO_set_locking_callback((void (*) + (int, int, const char*, int))openssl_lock_callback); + + sem_init(&openssl_crypto_lock_mtx, 0, crypt_num_locks); +} + +static void free_openssl_locks(void) +{ + int i; + + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + pthread_mutex_destroy(&(openssl_locks[i])); + + OPENSSL_free(openssl_locks); +} + void openssl_init(void) { /* initial seed the openssl random generator */ unsigned char random_data[64]; s390_prng(random_data, sizeof(random_data)); RAND_seed(random_data, sizeof(random_data)); + init_openssl_locks(); } /* Switches have to be done first. Otherwise we will not have hw support @@ -115,4 +167,5 @@ void __attribute__ ((constructor)) icain void __attribute__ ((destructor)) icaexit(void) { stats_munmap(SHM_CLOSE); + free_openssl_locks(); } Index: src/include/s390_rsa.h =================================================================== --- a/src/include/s390_rsa.h +++ b/src/include/s390_rsa.h @@ -16,6 +16,7 @@ #include #include +#include #include "ica_api.h" typedef struct ica_rsa_modexpo ica_rsa_modexpo_t; @@ -40,5 +41,7 @@ unsigned int rsa_key_generate_crt(ica_ad unsigned int rsa_crt_sw(ica_rsa_modexpo_crt_t * pCrt); unsigned int rsa_mod_mult_sw(ica_rsa_modmult_t * pMul); unsigned int rsa_mod_expo_sw(ica_rsa_modexpo_t *pMex); + +sem_t openssl_crypto_lock_mtx; #endif