File fix-segfault-during-multithread-keygen.patch of Package libica2

Index: src/s390_rsa.c
===================================================================
--- a/src/s390_rsa.c
+++ b/src/s390_rsa.c
@@ -18,6 +18,9 @@
 #include <errno.h>
 #include <stdint.h>
 #include <openssl/rsa.h>
+#include <openssl/crypto.h>
+#include <pthread.h>
+#include <semaphore.h>
 
 #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 <stdlib.h>
 #include <string.h>
 #include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <semaphore.h>
+#include <pthread.h>
 #include <syslog.h>
 
 #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 <openssl/bn.h>
 #include <asm/zcrypt.h>
+#include <semaphore.h>
 #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
 
openSUSE Build Service is sponsored by