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