Skip to content

Commit 573d7b2

Browse files
committed
improve initialization and thread safety for default crypto provider
1 parent 5818768 commit 573d7b2

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

src/crypto_impl.c

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ typedef struct {
6666

6767
static unsigned int default_flags = DEFAULT_CIPHER_FLAGS;
6868
static unsigned char hmac_salt_mask = HMAC_SALT_MASK;
69-
69+
static unsigned int sqlcipher_activate_count = 0;
70+
static sqlite3_mutex* sqlcipher_provider_mutex = NULL;
7071
static sqlcipher_provider *default_provider = NULL;
7172

7273
struct codec_ctx {
@@ -81,13 +82,15 @@ struct codec_ctx {
8182
};
8283

8384
int sqlcipher_register_provider(sqlcipher_provider *p) {
85+
sqlite3_mutex_enter(sqlcipher_provider_mutex);
8486
if(default_provider != NULL && default_provider != p) {
8587
/* only free the current registerd provider if it has been initialized
8688
and it isn't a pointer to the same provider passed to the function
8789
(i.e. protect against a caller calling register twice for the same provider) */
8890
sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
8991
}
9092
default_provider = p;
93+
sqlite3_mutex_leave(sqlcipher_provider_mutex);
9194
return SQLITE_OK;
9295
}
9396

@@ -99,35 +102,57 @@ sqlcipher_provider* sqlcipher_get_provider() {
99102
}
100103

101104
void sqlcipher_activate() {
102-
sqlcipher_provider *p;
103-
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
104-
p = sqlcipher_malloc(sizeof(sqlcipher_provider));
105-
{
105+
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
106+
107+
if(sqlcipher_provider_mutex == NULL) {
108+
/* allocate a new mutex to guard access to the provider */
109+
sqlcipher_provider_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
110+
}
111+
112+
/* check to see if there is a provider registered at this point
113+
if there no provider registered at this point, register the
114+
default provider */
115+
if(sqlcipher_get_provider() == NULL) {
116+
sqlcipher_provider *p = sqlcipher_malloc(sizeof(sqlcipher_provider));
106117
#if defined (SQLCIPHER_CRYPTO_CC)
107-
extern int sqlcipher_cc_setup(sqlcipher_provider *p);
108-
sqlcipher_cc_setup(p);
118+
extern int sqlcipher_cc_setup(sqlcipher_provider *p);
119+
sqlcipher_cc_setup(p);
109120
#elif defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT)
110-
extern int sqlcipher_ltc_setup(sqlcipher_provider *p);
111-
sqlcipher_ltc_setup(p);
121+
extern int sqlcipher_ltc_setup(sqlcipher_provider *p);
122+
sqlcipher_ltc_setup(p);
112123
#elif defined (SQLCIPHER_CRYPTO_OPENSSL)
113-
extern int sqlcipher_openssl_setup(sqlcipher_provider *p);
114-
sqlcipher_openssl_setup(p);
124+
extern int sqlcipher_openssl_setup(sqlcipher_provider *p);
125+
sqlcipher_openssl_setup(p);
115126
#else
116127
#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
117128
#endif
129+
sqlcipher_register_provider(p);
118130
}
119-
sqlcipher_register_provider(p);
120131

121-
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
132+
sqlcipher_activate_count++; /* increment activation count */
133+
134+
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
122135
}
123136

124137
void sqlcipher_deactivate() {
125-
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
126-
if(default_provider != NULL) {
127-
sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
128-
default_provider = NULL;
138+
sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
139+
sqlcipher_activate_count--;
140+
/* if no connections are using sqlcipher, cleanup globals */
141+
if(sqlcipher_activate_count < 1) {
142+
sqlite3_mutex_enter(sqlcipher_provider_mutex);
143+
if(default_provider != NULL) {
144+
sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
145+
default_provider = NULL;
146+
}
147+
sqlite3_mutex_leave(sqlcipher_provider_mutex);
148+
149+
/* last connection closed, free provider mutex*/
150+
sqlite3_mutex_free(sqlcipher_provider_mutex);
151+
sqlcipher_provider_mutex = NULL;
152+
153+
sqlcipher_activate_count = 0; /* reset activation count */
129154
}
130-
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
155+
sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
131156
}
132157

133158
/* constant time memset using volitile to avoid having the memset
@@ -235,7 +260,11 @@ static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
235260

236261
ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider));
237262
if(ctx->provider == NULL) return SQLITE_NOMEM;
263+
264+
/* make a copy of the provider to be used for the duration of the context */
265+
sqlite3_mutex_enter(sqlcipher_provider_mutex);
238266
memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
267+
sqlite3_mutex_leave(sqlcipher_provider_mutex);
239268

240269
if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc;
241270
ctx->key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ);

0 commit comments

Comments
 (0)