diff --git a/src/crypto.c b/src/crypto.c index 851b8d33..3e624910 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -55,21 +55,30 @@ static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ct page_sz = sqlcipher_codec_ctx_get_pagesize(ctx); reserve_sz = sqlcipher_codec_ctx_get_reservesize(ctx); + CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz); + + CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entering database mutex %p\n", db->mutex); sqlite3_mutex_enter(db->mutex); + CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entered database mutex %p\n", db->mutex); db->nextPagesize = page_sz; /* before forcing the page size we need to unset the BTS_PAGESIZE_FIXED flag, else sqliteBtreeSetPageSize will block the change */ pDb->pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; - CODEC_TRACE(("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz)); rc = sqlite3BtreeSetPageSize(pDb->pBt, page_sz, reserve_sz, 0); + + CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize returned %d\n", rc); + + CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: leaving database mutex %p\n", db->mutex); sqlite3_mutex_leave(db->mutex); + CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: left database mutex %p\n", db->mutex); + return rc; } static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) { struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx)); + CODEC_TRACE("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx); if(pDb->pBt) { codec_ctx *ctx; sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); @@ -88,7 +97,7 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); } - CODEC_TRACE(("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx)); + CODEC_TRACE("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx); if( sqlite3StrICmp(zLeft, "cipher_fips_status")== 0 && !zRight ){ if(ctx) { @@ -300,7 +309,7 @@ void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { unsigned char *pData = (unsigned char *) data; void *buffer = sqlcipher_codec_ctx_get_data(ctx); void *kdf_salt = sqlcipher_codec_ctx_get_kdf_salt(ctx); - CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz)); + CODEC_TRACE("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz); /* call to derive keys if not present yet */ if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) { @@ -310,7 +319,7 @@ void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/ - CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset)); + CODEC_TRACE("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset); switch(mode) { case 0: /* decrypt */ case 2: @@ -349,7 +358,7 @@ void sqlite3FreeCodecArg(void *pCodecArg) { int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey)); + CODEC_TRACE("sqlite3CodecAttach: entered db=%p, nDb=%d zKey=%s, nKey=%d\n", db, nDb, (char *)zKey, nKey); if(nKey && zKey && pDb->pBt) { @@ -358,35 +367,48 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { sqlite3_file *fd = sqlite3Pager_get_fd(pPager); codec_ctx *ctx; + CODEC_TRACE("sqlite3CodecAttach: calling sqlcipher_activate()\n"); sqlcipher_activate(); /* perform internal initialization for sqlcipher */ + CODEC_TRACE_MUTEX("sqlite3CodecAttach: entering database mutex %p\n", db->mutex); sqlite3_mutex_enter(db->mutex); + CODEC_TRACE_MUTEX("sqlite3CodecAttach: entered database mutex %p\n", db->mutex); /* point the internal codec argument against the contet to be prepared */ + CODEC_TRACE("sqlite3CodecAttach: calling sqlcipher_codec_ctx_init()\n"); rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey); if(rc != SQLITE_OK) { /* initialization failed, do not attach potentially corrupted context */ + CODEC_TRACE("sqlite3CodecAttach: context initialization failed with rc=%d\n", rc); + CODEC_TRACE_MUTEX("sqlite3CodecAttach: leaving database mutex %p (early return on rc=%d)\n", db->mutex, rc); sqlite3_mutex_leave(db->mutex); + CODEC_TRACE_MUTEX("sqlite3CodecAttach: left database mutex %p (early return on rc=%d)\n", db->mutex, rc); return rc; } + CODEC_TRACE("sqlite3CodecAttach: calling sqlite3pager_sqlite3PagerSetCodec()\n"); sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx); + CODEC_TRACE("sqlite3CodecAttach: calling codec_set_btree_to_codec_pagesize()\n"); codec_set_btree_to_codec_pagesize(db, pDb, ctx); /* force secure delete. This has the benefit of wiping internal data when deleted and also ensures that all pages are written to disk (i.e. not skipped by sqlite3PagerDontWrite optimizations) */ + CODEC_TRACE("sqlite3CodecAttach: calling sqlite3BtreeSecureDelete()\n"); sqlite3BtreeSecureDelete(pDb->pBt, 1); /* if fd is null, then this is an in-memory database and we dont' want to overwrite the AutoVacuum settings if not null, then set to the default */ if(fd != NULL) { + CODEC_TRACE("sqlite3CodecAttach: calling sqlite3BtreeSetAutoVacuum()\n"); sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM); } + CODEC_TRACE_MUTEX("sqlite3CodecAttach: leaving database mutex %p\n", db->mutex); sqlite3_mutex_leave(db->mutex); + CODEC_TRACE_MUTEX("sqlite3CodecAttach: left database mutex %p\n", db->mutex); } return SQLITE_OK; } @@ -410,12 +432,12 @@ static int sqlcipher_find_db_index(sqlite3 *db, const char *zDb) { } int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) { - CODEC_TRACE(("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey)); + CODEC_TRACE("sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey); return sqlite3_key_v2(db, "main", pKey, nKey); } int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { - CODEC_TRACE(("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey)); + CODEC_TRACE("sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey); /* attach key if db and pKey are not null and nKey is > 0 */ if(db && pKey && nKey) { int db_index = sqlcipher_find_db_index(db, zDb); @@ -425,7 +447,7 @@ int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { } int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { - CODEC_TRACE(("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey)); + CODEC_TRACE("sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey); return sqlite3_rekey_v2(db, "main", pKey, nKey); } @@ -440,11 +462,11 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { ** 3. If there is a key present, re-encrypt the database with the new key */ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { - CODEC_TRACE(("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey)); + CODEC_TRACE("sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey); if(db && pKey && nKey) { int db_index = sqlcipher_find_db_index(db, zDb); struct Db *pDb = &db->aDb[db_index]; - CODEC_TRACE(("sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index)); + CODEC_TRACE("sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index); if(pDb->pBt) { codec_ctx *ctx; int rc, page_count; @@ -456,11 +478,13 @@ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { if(ctx == NULL) { /* there was no codec attached to this database, so this should do nothing! */ - CODEC_TRACE(("sqlite3_rekey_v2: no codec attached to db, exiting\n")); + CODEC_TRACE("sqlite3_rekey_v2: no codec attached to db, exiting\n"); return SQLITE_OK; } + CODEC_TRACE_MUTEX("sqlite3_rekey_v2: entering database mutex %p\n", db->mutex); sqlite3_mutex_enter(db->mutex); + CODEC_TRACE_MUTEX("sqlite3_rekey_v2: entered database mutex %p\n", db->mutex); codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX); @@ -480,25 +504,27 @@ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { if(rc == SQLITE_OK) { sqlite3PagerUnref(page); } else { - CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno)); + CODEC_TRACE("sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno); } } else { - CODEC_TRACE(("sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno)); + CODEC_TRACE("sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno); } } } /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */ if(rc == SQLITE_OK) { - CODEC_TRACE(("sqlite3_rekey_v2: committing\n")); + CODEC_TRACE("sqlite3_rekey_v2: committing\n"); rc = sqlite3BtreeCommit(pDb->pBt); sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX); } else { - CODEC_TRACE(("sqlite3_rekey_v2: rollback\n")); + CODEC_TRACE("sqlite3_rekey_v2: rollback\n"); sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK, 0); } + CODEC_TRACE_MUTEX("sqlite3_rekey_v2: leaving database mutex %p\n", db->mutex); sqlite3_mutex_leave(db->mutex); + CODEC_TRACE_MUTEX("sqlite3_rekey_v2: left database mutex %p\n", db->mutex); } return SQLITE_OK; } @@ -507,7 +533,7 @@ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey) { void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) { struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb)); + CODEC_TRACE("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb); if( pDb->pBt ) { codec_ctx *ctx; sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); diff --git a/src/crypto.h b/src/crypto.h index 695ff3cc..c8f42471 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -100,11 +100,28 @@ #define CIPHER_MAX_KEY_SZ 64 #endif +#ifdef __ANDROID__ +#include +#endif + +#ifdef CODEC_DEBUG_MUTEX +#ifdef __ANDROID__ +#define CODEC_TRACE_MUTEX(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);} +#else +#define CODEC_TRACE_MUTEX(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);} +#endif +#else +#define CODEC_TRACE_MUTEX(...) +#endif #ifdef CODEC_DEBUG -#define CODEC_TRACE(X) {printf X;fflush(stdout);} +#ifdef __ANDROID__ +#define CODEC_TRACE(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);} #else -#define CODEC_TRACE(X) +#define CODEC_TRACE(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);} +#endif +#else +#define CODEC_TRACE(...) #endif #ifdef CODEC_DEBUG_PAGEDATA diff --git a/src/crypto_impl.c b/src/crypto_impl.c index e43704df..e0d2462a 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -89,7 +89,10 @@ struct codec_ctx { }; int sqlcipher_register_provider(sqlcipher_provider *p) { + CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_enter(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + if(default_provider != NULL && default_provider != p) { /* only free the current registerd provider if it has been initialized and it isn't a pointer to the same provider passed to the function @@ -97,7 +100,10 @@ int sqlcipher_register_provider(sqlcipher_provider *p) { sqlcipher_free(default_provider, sizeof(sqlcipher_provider)); } default_provider = p; + CODEC_TRACE_MUTEX("sqlcipher_register_provider: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_leave(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_register_provider: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + return SQLITE_OK; } @@ -109,11 +115,15 @@ sqlcipher_provider* sqlcipher_get_provider() { } void sqlcipher_activate() { + CODEC_TRACE_MUTEX("sqlcipher_activate: entering static master mutex\n"); sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_activate: entered static master mutex\n"); if(sqlcipher_provider_mutex == NULL) { /* allocate a new mutex to guard access to the provider */ + CODEC_TRACE_MUTEX("sqlcipher_activate: allocating sqlcipher provider mutex\n"); sqlcipher_provider_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + CODEC_TRACE_MUTEX("sqlcipher_activate: allocated sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); } /* check to see if there is a provider registered at this point @@ -133,33 +143,53 @@ void sqlcipher_activate() { #else #error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED" #endif + CODEC_TRACE("sqlcipher_activate: calling sqlcipher_register_provider(%p)\n", p); sqlcipher_register_provider(p); + CODEC_TRACE("sqlcipher_activate: called sqlcipher_register_provider(%p)\n",p); } sqlcipher_activate_count++; /* increment activation count */ + CODEC_TRACE_MUTEX("sqlcipher_activate: leaving static master mutex\n"); sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_activate: left static master mutex\n"); } void sqlcipher_deactivate() { + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering static master mutex\n"); sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered static master mutex\n"); + sqlcipher_activate_count--; /* if no connections are using sqlcipher, cleanup globals */ if(sqlcipher_activate_count < 1) { + int rc; + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_enter(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + if(default_provider != NULL) { sqlcipher_free(default_provider, sizeof(sqlcipher_provider)); default_provider = NULL; } + + CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_leave(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); /* last connection closed, free provider mutex*/ + CODEC_TRACE_MUTEX("sqlcipher_deactivate: freeing sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_free(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: freed sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + sqlcipher_provider_mutex = NULL; sqlcipher_activate_count = 0; /* reset activation count */ } + + CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving static master mutex\n"); sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_deactivate: left static master mutex\n"); } /* constant time memset using volitile to avoid having the memset @@ -172,6 +202,7 @@ void* sqlcipher_memset(void *v, unsigned char value, int len) { if (v == NULL) return v; + CODEC_TRACE("sqlcipher_memset: setting %p[0-%d]=%d)\n", a, len, value); for(i = 0; i < len; i++) { a[i] = value; } @@ -217,6 +248,7 @@ int sqlcipher_memcmp(const void *v0, const void *v1, int len) { void sqlcipher_free(void *ptr, int sz) { if(ptr) { if(sz > 0) { + CODEC_TRACE("sqlcipher_free: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); sqlcipher_memset(ptr, 0, sz); #ifndef OMIT_MEMLOCK #if defined(__unix__) || defined(__APPLE__) @@ -238,7 +270,10 @@ VirtualUnlock(ptr, sz); * attempts to lock the memory pages so sensitive information won't be swapped */ void* sqlcipher_malloc(int sz) { - void *ptr = sqlite3Malloc(sz); + void *ptr; + CODEC_TRACE("sqlcipher_malloc: calling sqlite3Malloc(%d)\n", sz); + ptr = sqlite3Malloc(sz); + CODEC_TRACE("sqlcipher_malloc: calling sqlcipher_memset(%p,0,%d)\n", ptr, sz); sqlcipher_memset(ptr, 0, sz); #ifndef OMIT_MEMLOCK if(ptr) { @@ -265,21 +300,35 @@ void* sqlcipher_malloc(int sz) { static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) { int rc; cipher_ctx *ctx; + CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating context\n"); *iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx)); ctx = *iCtx; if(ctx == NULL) return SQLITE_NOMEM; + CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating provider\n"); ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider)); if(ctx->provider == NULL) return SQLITE_NOMEM; /* make a copy of the provider to be used for the duration of the context */ + CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: entering sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); sqlite3_mutex_enter(sqlcipher_provider_mutex); - memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider)); - sqlite3_mutex_leave(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: entered sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider)); + + CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: leaving sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + sqlite3_mutex_leave(sqlcipher_provider_mutex); + CODEC_TRACE_MUTEX("sqlcipher_cipher_ctx_init: left sqlcipher provider mutex %p\n", sqlcipher_provider_mutex); + + CODEC_TRACE("sqlcipher_cipher_ctx_init: calling provider ctx_init\n"); if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc; + + CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating key\n"); ctx->key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ); + + CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating hmac_key\n"); ctx->hmac_key = (unsigned char *) sqlcipher_malloc(CIPHER_MAX_KEY_SZ); + if(ctx->key == NULL) return SQLITE_NOMEM; if(ctx->hmac_key == NULL) return SQLITE_NOMEM; @@ -294,7 +343,7 @@ static int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) { */ static void sqlcipher_cipher_ctx_free(cipher_ctx **iCtx) { cipher_ctx *ctx = *iCtx; - CODEC_TRACE(("cipher_ctx_free: entered iCtx=%p\n", iCtx)); + CODEC_TRACE("cipher_ctx_free: entered iCtx=%p\n", iCtx); ctx->provider->ctx_free(&ctx->provider_ctx); sqlcipher_free(ctx->provider, sizeof(sqlcipher_provider)); sqlcipher_free(ctx->key, ctx->key_sz); @@ -327,7 +376,7 @@ static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) { c1->pass_sz) )); - CODEC_TRACE(("sqlcipher_cipher_ctx_cmp: entered \ + CODEC_TRACE("sqlcipher_cipher_ctx_cmp: entered \ c1=%p c2=%p \ c1->iv_sz=%d c2->iv_sz=%d \ c1->kdf_iter=%d c2->kdf_iter=%d \ @@ -359,7 +408,7 @@ static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) { (const unsigned char*)c2->pass, c1->pass_sz), are_equal - )); + ); return !are_equal; /* return 0 if they are the same, 1 otherwise */ } @@ -378,7 +427,7 @@ static int sqlcipher_cipher_ctx_copy(cipher_ctx *target, cipher_ctx *source) { void *provider = target->provider; void *provider_ctx = target->provider_ctx; - CODEC_TRACE(("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source)); + CODEC_TRACE("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source); sqlcipher_free(target->pass, target->pass_sz); sqlcipher_free(target->keyspec, target->keyspec_sz); memcpy(target, source, sizeof(cipher_ctx)); @@ -587,8 +636,8 @@ int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) { reserve = ((reserve % ctx->read_ctx->block_sz) == 0) ? reserve : ((reserve / ctx->read_ctx->block_sz) + 1) * ctx->read_ctx->block_sz; - CODEC_TRACE(("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n", - use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve)); + CODEC_TRACE("sqlcipher_codec_ctx_set_use_hmac: use=%d block_sz=%d md_size=%d reserve=%d\n", + use, ctx->read_ctx->block_sz, ctx->read_ctx->hmac_sz, reserve); if(use) { @@ -625,7 +674,7 @@ int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx) } void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) { - CODEC_TRACE(("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error)); + CODEC_TRACE("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error); sqlite3pager_sqlite3PagerSetError(ctx->pBt->pBt->pPager, error); ctx->pBt->pBt->db->errCode = error; } @@ -676,6 +725,9 @@ int sqlcipher_get_default_pagesize() { int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_file *fd, const void *zKey, int nKey) { int rc; codec_ctx *ctx; + + CODEC_TRACE("sqlcipher_codec_ctx_init: allocating context\n"); + *iCtx = sqlcipher_malloc(sizeof(codec_ctx)); ctx = *iCtx; @@ -687,6 +739,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f directly off the database file. This is the salt for the key derivation function. If we get a short read allocate a new random salt value */ + CODEC_TRACE("sqlcipher_codec_ctx_init: allocating kdf_salt\n"); ctx->kdf_salt_sz = FILE_HEADER_SZ; ctx->kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz); if(ctx->kdf_salt == NULL) return SQLITE_NOMEM; @@ -694,6 +747,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f /* allocate space for separate hmac salt data. We want the HMAC derivation salt to be different than the encryption key derivation salt */ + CODEC_TRACE("sqlcipher_codec_ctx_init: allocating hmac_kdf_salt\n"); ctx->hmac_kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz); if(ctx->hmac_kdf_salt == NULL) return SQLITE_NOMEM; @@ -703,24 +757,38 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f in encrypted and thus sqlite can't effectively determine the pagesize. this causes an issue in cases where bytes 16 & 17 of the page header are a power of 2 as reported by John Lehman */ + CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_pagesize with %d\n", default_page_size); if((rc = sqlcipher_codec_ctx_set_pagesize(ctx, default_page_size)) != SQLITE_OK) return rc; + CODEC_TRACE("sqlcipher_codec_ctx_init: initializing read_ctx\n"); if((rc = sqlcipher_cipher_ctx_init(&ctx->read_ctx)) != SQLITE_OK) return rc; + + CODEC_TRACE("sqlcipher_codec_ctx_init: initializing write_ctx\n"); if((rc = sqlcipher_cipher_ctx_init(&ctx->write_ctx)) != SQLITE_OK) return rc; + CODEC_TRACE("sqlcipher_codec_ctx_init: reading file header\n"); if(fd == NULL || sqlite3OsRead(fd, ctx->kdf_salt, FILE_HEADER_SZ, 0) != SQLITE_OK) { ctx->need_kdf_salt = 1; } + CODEC_TRACE("sqlcipher_codec_ctx_init: setting cipher\n"); if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc; + + CODEC_TRACE("sqlcipher_codec_ctx_init: setting default_kdf_iter\n"); if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, default_kdf_iter, 0)) != SQLITE_OK) return rc; + + CODEC_TRACE("sqlcipher_codec_ctx_init: setting fast_kdf_iter\n"); if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER, 0)) != SQLITE_OK) return rc; + + CODEC_TRACE("sqlcipher_codec_ctx_init: setting pass key\n"); if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc; /* Note that use_hmac is a special case that requires recalculation of page size so we call set_use_hmac to perform setup */ + CODEC_TRACE("sqlcipher_codec_ctx_init: setting use_hmac\n"); if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_flags & CIPHER_FLAG_HMAC)) != SQLITE_OK) return rc; + CODEC_TRACE("sqlcipher_codec_ctx_init: copying write_ctx to read_ctx\n"); if((rc = sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) return rc; return SQLITE_OK; @@ -732,7 +800,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f */ void sqlcipher_codec_ctx_free(codec_ctx **iCtx) { codec_ctx *ctx = *iCtx; - CODEC_TRACE(("codec_ctx_free: entered iCtx=%p\n", iCtx)); + CODEC_TRACE("codec_ctx_free: entered iCtx=%p\n", iCtx); sqlcipher_free(ctx->kdf_salt, ctx->kdf_salt_sz); sqlcipher_free(ctx->hmac_kdf_salt, ctx->kdf_salt_sz); sqlcipher_free(ctx->buffer, 0); @@ -802,12 +870,12 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int hmac_out = out + size + c_ctx->iv_sz; out_start = out; /* note the original position of the output buffer pointer, as out will be rewritten during encryption */ - CODEC_TRACE(("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size)); + CODEC_TRACE("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size); CODEC_HEXDUMP("codec_cipher: input page data", in, page_sz); /* the key size should never be zero. If it is, error out. */ if(c_ctx->key_sz == 0) { - CODEC_TRACE(("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno)); + CODEC_TRACE("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno); sqlcipher_memset(out, 0, page_sz); return SQLITE_ERROR; } @@ -822,25 +890,25 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT) && !ctx->skip_read_hmac) { if(sqlcipher_page_hmac(c_ctx, pgno, in, size + c_ctx->iv_sz, hmac_out) != SQLITE_OK) { sqlcipher_memset(out, 0, page_sz); - CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno)); + CODEC_TRACE("codec_cipher: hmac operations failed for pgno=%d\n", pgno); return SQLITE_ERROR; } - CODEC_TRACE(("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, c_ctx->hmac_sz)); + CODEC_TRACE("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, c_ctx->hmac_sz); if(sqlcipher_memcmp(hmac_in, hmac_out, c_ctx->hmac_sz) != 0) { /* the hmac check failed */ if(sqlcipher_ismemset(in, 0, page_sz) == 0) { /* first check if the entire contents of the page is zeros. If so, this page resulted from a short read (i.e. sqlite attempted to pull a page after the end of the file. these short read failures must be ignored for autovaccum mode to work so wipe the output buffer and return SQLITE_OK to skip the decryption step. */ - CODEC_TRACE(("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno)); + CODEC_TRACE("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno); sqlcipher_memset(out, 0, page_sz); return SQLITE_OK; } else { /* if the page memory is not all zeros, it means the there was data and a hmac on the page. since the check failed, the page was either tampered with or corrupted. wipe the output buffer, and return SQLITE_ERROR to the caller */ - CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno)); + CODEC_TRACE("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno); sqlcipher_memset(out, 0, page_sz); return SQLITE_ERROR; } @@ -875,11 +943,11 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int */ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { int rc; - CODEC_TRACE(("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \ + CODEC_TRACE("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \ ctx->kdf_salt=%p ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \ ctx->hmac_kdf_salt=%p, c_ctx->fast_kdf_iter=%d c_ctx->key_sz=%d\n", c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter, - ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz)); + ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz); if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null @@ -891,15 +959,15 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, c_ctx->key_sz * 2)) { int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ - CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n")); + CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n"); cipher_hex2bin(z, n, c_ctx->key); } else if (c_ctx->pass_sz == (((c_ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, (c_ctx->key_sz + ctx->kdf_salt_sz) * 2)) { const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ - CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n")); + CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n"); cipher_hex2bin(z, (c_ctx->key_sz * 2), c_ctx->key); cipher_hex2bin(z + (c_ctx->key_sz * 2), (ctx->kdf_salt_sz * 2), ctx->kdf_salt); } else { - CODEC_TRACE(("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n", c_ctx->kdf_iter)); + CODEC_TRACE("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n", c_ctx->kdf_iter); c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter, c_ctx->key_sz, c_ctx->key); @@ -924,8 +992,8 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { ctx->hmac_kdf_salt[i] ^= hmac_salt_mask; } - CODEC_TRACE(("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n", - c_ctx->fast_kdf_iter)); + CODEC_TRACE("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n", + c_ctx->fast_kdf_iter); c_ctx->provider->kdf(c_ctx->provider_ctx, c_ctx->key, c_ctx->key_sz, @@ -1057,14 +1125,14 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { int rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, "", &user_version); if(rc == SQLITE_OK){ - CODEC_TRACE(("No upgrade required - exiting\n")); + CODEC_TRACE("No upgrade required - exiting\n"); goto exit; } // Version 2 - check for 4k with hmac format rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_4k_kdf_iter, &user_version); if(rc == SQLITE_OK) { - CODEC_TRACE(("Version 2 format found\n")); + CODEC_TRACE("Version 2 format found\n"); upgrade_4k_format = 1; } @@ -1074,13 +1142,13 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_1x_and_4k, &user_version); sqlite3_free(pragma_1x_and_4k); if(rc == SQLITE_OK) { - CODEC_TRACE(("Version 1 format found\n")); + CODEC_TRACE("Version 1 format found\n"); upgrade_1x_format = 1; upgrade_4k_format = 1; } if(upgrade_1x_format == 0 && upgrade_4k_format == 0) { - CODEC_TRACE(("Upgrade format not determined\n")); + CODEC_TRACE("Upgrade format not determined\n"); goto handle_error; } @@ -1111,11 +1179,11 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { int i = 0; if( !db->autoCommit ){ - CODEC_TRACE(("cannot migrate from within a transaction")); + CODEC_TRACE("cannot migrate from within a transaction"); goto handle_error; } if( db->nVdbeActive>1 ){ - CODEC_TRACE(("cannot migrate - SQL statements in progress")); + CODEC_TRACE("cannot migrate - SQL statements in progress"); goto handle_error; } @@ -1168,14 +1236,14 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { remove(migrated_db_filename); sqlite3_free(migrated_db_filename); } else { - CODEC_TRACE(("*** migration failure** \n\n")); + CODEC_TRACE("*** migration failure** \n\n"); } } goto exit; handle_error: - CODEC_TRACE(("An error occurred attempting to migrate the database\n")); + CODEC_TRACE("An error occurred attempting to migrate the database\n"); rc = SQLITE_ERROR; exit: @@ -1193,7 +1261,7 @@ int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz int buffer_sz = n / 2; unsigned char *random; const unsigned char *z = (const unsigned char *)zRight + 2; /* adjust lead offset of x' */ - CODEC_TRACE(("sqlcipher_codec_add_random: using raw random blob from hex\n")); + CODEC_TRACE("sqlcipher_codec_add_random: using raw random blob from hex\n"); random = sqlcipher_malloc(buffer_sz); memset(random, 0, buffer_sz); cipher_hex2bin(z, n, random); diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 14f28b73..361176b9 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -71,11 +71,15 @@ static void HMAC_CTX_free(HMAC_CTX *ctx) static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) { #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering openssl_rand_mutex %p\n", openssl_rand_mutex); sqlite3_mutex_enter(openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered openssl_rand_mutex %p\n", openssl_rand_mutex); #endif RAND_add(buffer, length, 0); #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving openssl_rand_mutex %p\n", openssl_rand_mutex); sqlite3_mutex_leave(openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left openssl_rand_mutex %p\n", openssl_rand_mutex); #endif return SQLITE_OK; } @@ -90,7 +94,9 @@ static int sqlcipher_openssl_activate(void *ctx) { /* initialize openssl and increment the internal init counter but only if it hasn't been initalized outside of SQLCipher by this program e.g. on startup */ + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering static master mutex"); sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered static master mutex"); if(openssl_init_count == 0 && EVP_get_cipherbyname(CIPHER) != NULL) { /* if openssl has not yet been initialized by this library, but @@ -116,12 +122,16 @@ static int sqlcipher_openssl_activate(void *ctx) { #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND if(openssl_rand_mutex == NULL) { /* allocate a mutex to guard against concurrent calls to RAND_bytes() */ + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocating openssl_rand_mutex"); openssl_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: allocated openssl_rand_mutex %p", openssl_rand_mutex); } #endif openssl_init_count++; + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving static master mutex"); sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left static master mutex"); return SQLITE_OK; } @@ -129,7 +139,9 @@ static int sqlcipher_openssl_activate(void *ctx) { freeing the EVP structures on the final deactivation to ensure that OpenSSL memory is cleaned up */ static int sqlcipher_openssl_deactivate(void *ctx) { + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering static master mutex"); sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered static master mutex"); openssl_init_count--; if(openssl_init_count == 0) { @@ -144,11 +156,15 @@ static int sqlcipher_openssl_deactivate(void *ctx) { openssl_external_init = 0; } #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_rand_mutex %p", openssl_rand_mutex); sqlite3_mutex_free(openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_rand_mutex %p", openssl_rand_mutex); openssl_rand_mutex = NULL; #endif } + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving static master mutex"); sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left static master mutex"); return SQLITE_OK; } @@ -170,11 +186,15 @@ static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) { but a more proper solution is that applications setup platform-appropriate thread saftey in openssl externally */ #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entering openssl_rand_mutex %p", openssl_rand_mutex); sqlite3_mutex_enter(openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entered openssl_rand_mutex %p", openssl_rand_mutex); #endif rc = RAND_bytes((unsigned char *)buffer, length); #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: leaving openssl_rand_mutex %p", openssl_rand_mutex); sqlite3_mutex_leave(openssl_rand_mutex); + CODEC_TRACE_MUTEX("sqlcipher_openssl_random: left openssl_rand_mutex %p", openssl_rand_mutex); #endif return (rc == 1) ? SQLITE_OK : SQLITE_ERROR; }