@@ -45,10 +45,12 @@ typedef struct {
45
45
46
46
static unsigned int openssl_external_init = 0 ;
47
47
static unsigned int openssl_init_count = 0 ;
48
-
48
+ static sqlite3_mutex * openssl_rand_mutex = NULL ;
49
49
50
50
static int sqlciphe
8000
r_openssl_add_random (void * ctx , void * buffer , int length ) {
51
+ sqlite3_mutex_enter (openssl_rand_mutex );
51
52
RAND_add (buffer , length , 0 );
53
+ sqlite3_mutex_leave (openssl_rand_mutex );
52
54
return SQLITE_OK ;
53
55
}
54
56
@@ -59,40 +61,53 @@ static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
59
61
sqlcipher_openssl_deactivate() will free the EVP structures.
60
62
*/
61
63
static int sqlcipher_openssl_activate (void * ctx ) {
62
- /* we'll initialize openssl and increment the internal init counter
64
+ /* initialize openssl and increment the internal init counter
63
65
but only if it hasn't been initalized outside of SQLCipher by this program
64
66
e.g. on startup */
67
+ sqlite3_mutex_enter (sqlite3_mutex_alloc (SQLITE_MUTEX_STATIC_MASTER ));
68
+
65
69
if (openssl_init_count == 0 && EVP_get_cipherbyname (CIPHER ) != NULL ) {
70
+ /* if openssl has not yet been initialized by this library, but
71
+ a call to get_cipherbyname works, then the openssl library
72
+ has been initialized externally already. */
66
73
openssl_external_init = 1 ;
67
74
}
68
75
69
- if (openssl_external_init == 0 ) {
70
- if (openssl_init_count == 0 ) {
71
- OpenSSL_add_all_algorithms ();
72
- }
73
- openssl_init_count ++ ;
76
+ if (openssl_init_count == 0 && openssl_external_init == 0 ) {
77
+ /* if the library was not externally initialized, then should be now */
78
+ OpenSSL_add_all_algorithms ();
74
79
}
80
+
81
+ if (openssl_rand_mutex == NULL ) {
82
+ /* allocate a mutex to guard against concurrent calls to RAND_bytes() */
83
+ openssl_rand_mutex = sqlite3_mutex_alloc (SQLITE_MUTEX_FAST );
84
+ }
85
+
86
+ openssl_init_count ++ ;
87
+ sqlite3_mutex_leave (sqlite3_mutex_alloc (SQLITE_MUTEX_STATIC_MASTER ));
75
88
return SQLITE_OK ;
76
89
}
77
90
78
91
/* deactivate SQLCipher, most imporantly decremeting the activation count and
79
92
freeing the EVP structures on the final deactivation to ensure that
80
93
OpenSSL memory is cleaned up */
81
94
static int sqlcipher_openssl_deactivate (void * ctx ) {
82
- sqlite3_mutex_enter (sqlite3MutexAlloc (SQLITE_MUTEX_STATIC_MASTER ));
83
- /* If it is initialized externally, then the init counter should never be greater than zero.
84
- This should prevent SQLCipher from "cleaning up" openssl
85
- when something else in the program might be using it. */
86
- if (openssl_external_init == 0 ) {
87
- openssl_init_count -- ;
88
- /* if the counter reaches zero after it's decremented release EVP memory
95
+ sqlite3_mutex_enter (sqlite3_mutex_alloc (SQLITE_MUTEX_STATIC_MASTER ));
96
+ openssl_init_count -- ;
97
+
98
+ if ( openssl_init_count == 0 ) {
99
+ if (openssl_external_init == 0 ) {
100
+ /* if OpenSSL hasn't be initialized externally, and the counter reaches zero
101
+ after it's decremented, release EVP memory
89
102
Note: this code will only be reached if OpensSSL_add_all_algorithms()
90
- is called by SQLCipher internally. */
91
- if ( openssl_init_count == 0 ) {
103
+ is called by SQLCipher internally. This should prevent SQLCipher from
104
+ "cleaning up" openssl when it was initialized externally by the program */
92
105
EVP_cleanup ();
93
106
}
107
+ sqlite3_mutex_free (openssl_rand_mutex );
108
+ openssl_rand_mutex = NULL ;
94
109
}
95
- sqlite3_mutex_leave (sqlite3MutexAlloc (SQLITE_MUTEX_STATIC_MASTER ));
110
+ sqlite3_mutex_leave (sqlite3_mutex_alloc (SQLITE_MUTEX_STATIC_MASTER ));
96
111
return SQLITE_OK ;
97
112
}
98
113
@@ -102,7 +117,17 @@ static const char* sqlcipher_openssl_get_provider_name(void *ctx) {
102
117
103
118
/* generate a defined number of random bytes */
104
119
static int sqlcipher_openssl_random (void * ctx , void * buffer , int length ) {
105
- return (RAND_bytes ((unsigned char * )buffer , length ) == 1 ) ? SQLITE_OK : SQLITE_ERROR ;
120
+ int rc = 0 ;
121
+ /* concurrent calls to RAND_bytes can cause a crash under some openssl versions when a
122
+ naive application doesn't use CRYPTO_set_locking_callback and
123
+ CRYPTO_THREADID_set_callback to ensure openssl thread safety.
124
+ This is simple workaround to prevent this common crash
125
+ but a more proper solution is that applications setup platform-appropriate
126
+ thread saftey in openssl externally */
127
+ sqlite3_mutex_enter (openssl_rand_mutex );
128
+ rc = RAND_bytes ((unsigned char * )buffer , length );
129
+ sqlite3_mutex_leave (openssl_rand_mutex );
130
+ return (rc == 1 ) ? SQLITE_OK : SQLITE_ERROR ;
106
131
}
107
132
108
133
static int sqlcipher_openssl_hmac (void * ctx , unsigned char * hmac_key , int key_sz , unsigned char * in , int in_sz , unsigned char * in2 , int in2_sz , unsigned char * out ) {
0 commit comments