improvements and extensions to trace logging
This commit is contained in:
parent
df092f0a7a
commit
42e067d17f
60
src/crypto.c
60
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);
|
||||
|
||||
21
src/crypto.h
21
src/crypto.h
@ -100,11 +100,28 @@
|
||||
#define CIPHER_MAX_KEY_SZ 64
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user