summaryrefslogtreecommitdiff
path: root/src/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto.c')
-rw-r--r--src/crypto.c109
1 files changed, 87 insertions, 22 deletions
diff --git a/src/crypto.c b/src/crypto.c
index 2551e6b..c9814e3 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -78,7 +78,7 @@ static int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey,
return SQLITE_ERROR;
}
-int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
+int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
struct Db *pDb = &db->aDb[iDb];
codec_ctx *ctx = NULL;
int rc;
@@ -87,8 +87,35 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
}
- CODEC_TRACE(("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_store_pass")==0 && zRight ) {
+ sqlcipher_codec_set_store_pass(ctx, sqlite3GetBoolean(zRight, 1));
+ } else
+ if( sqlite3StrICmp(zLeft, "cipher_store_pass")==0 && !zRight ) {
+ char *store_pass_value = sqlite3_mprintf("%d", sqlcipher_codec_get_store_pass(ctx));
+ codec_vdbe_return_static_string(pParse, "cipher_store_pass", store_pass_value);
+ sqlite3_free(store_pass_value);
+ }
+ if( sqlite3StrICmp(zLeft, "cipher_profile")== 0 && zRight ){
+ char *profile_status = sqlite3_mprintf("%d", sqlcipher_cipher_profile(db, zRight));
+ codec_vdbe_return_static_string(pParse, "cipher_profile", profile_status);
+ sqlite3_free(profile_status);
+ } else
+ if( sqlite3StrICmp(zLeft, "cipher_add_random")==0 && zRight ){
+ if(ctx) {
+ char *add_random_status = sqlite3_mprintf("%d", sqlcipher_codec_add_random(ctx, zRight, sqlite3Strlen30(zRight)));
+ codec_vdbe_return_static_string(pParse, "cipher_add_random", add_random_status);
+ sqlite3_free(add_random_status);
+ }
+ } else
+ if( sqlite3StrICmp(zLeft, "cipher_migrate")==0 && !zRight ){
+ if(ctx){
+ char *migrate_status = sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx));
+ codec_vdbe_return_static_string(pParse, "cipher_migrate", migrate_status);
+ sqlite3_free(migrate_status);
+ }
+ } else
if( sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){
if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider",
sqlcipher_codec_get_cipher_provider(ctx));
@@ -110,6 +137,15 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only
}else
+ if( sqlite3StrICmp(zLeft,"cipher_default_kdf_iter")==0 ){
+ if( zRight ) {
+ sqlcipher_set_default_kdf_iter(atoi(zRight)); // change default KDF iterations
+ } else {
+ char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_get_default_kdf_iter());
+ codec_vdbe_return_static_string(pParse, "cipher_default_kdf_iter", kdf_iter);
+ sqlite3_free(kdf_iter);
+ }
+ }else
if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
if(ctx) {
if( zRight ) {
@@ -204,7 +240,7 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
if(zRight) {
if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
unsigned char mask = 0;
- const char *hex = zRight+2;
+ const unsigned char *hex = (const unsigned char *)zRight+2;
cipher_hex2bin(hex,2,&mask);
sqlcipher_set_hmac_salt_mask(mask);
}
@@ -220,6 +256,7 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
return 1;
}
+
/*
* sqlite3Codec can be called in multiple modes.
* encrypt mode - expected to return a pointer to the
@@ -325,16 +362,41 @@ void sqlite3_activate_see(const char* in) {
/* do nothing, security enhancements are always active */
}
+static int sqlcipher_find_db_index(sqlite3 *db, const char *zDb) {
+ int db_index;
+ if(zDb == NULL){
+ return 0;
+ }
+ for(db_index = 0; db_index < db->nDb; db_index++) {
+ struct Db *pDb = &db->aDb[db_index];
+ if(strcmp(pDb->zName, zDb) == 0) {
+ return db_index;
+ }
+ }
+ return 0;
+}
+
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));
/* attach key if db and pKey are not null and nKey is > 0 */
if(db && pKey && nKey) {
- return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db
+ int db_index = sqlcipher_find_db_index(db, zDb);
+ return sqlite3CodecAttach(db, db_index, pKey, nKey);
}
return SQLITE_ERROR;
}
-/* sqlite3_rekey
+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));
+ return sqlite3_rekey_v2(db, "main", pKey, nKey);
+}
+
+/* sqlite3_rekey_v2
** Given a database, this will reencrypt the database using a new key.
** There is only one possible modes of operation - to encrypt a database
** that is already encrpyted. If the database is not already encrypted
@@ -344,11 +406,12 @@ int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
** 2. If there is NOT already a key present do nothing
** 3. If there is a key present, re-encrypt the database with the new key
*/
-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));
+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));
if(db && pKey && nKey) {
- struct Db *pDb = &db->aDb[0];
- CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
+ 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));
if(pDb->pBt) {
codec_ctx *ctx;
int rc, page_count;
@@ -360,13 +423,13 @@ int sqlite3_rekey(sqlite3 *db, 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: no codec attached to db, exiting\n"));
+ CODEC_TRACE(("sqlite3_rekey_v2: no codec attached to db, exiting\n"));
return SQLITE_OK;
}
sqlite3_mutex_enter(db->mutex);
- codec_set_pass_key(db, 0, pKey, nKey, CIPHER_WRITE_CTX);
+ codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX);
/* do stuff here to rewrite the database
** 1. Create a transaction on the database
@@ -376,7 +439,7 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
*/
rc = sqlite3BtreeBeginTrans(pDb->pBt, 1); /* begin write transaction */
sqlite3PagerPagecount(pPager, &page_count);
- for(pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
+ for(pgno = 1; rc == SQLITE_OK && pgno <= (unsigned int)page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
if(!sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
rc = sqlite3PagerGet(pPager, pgno, &page);
if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
@@ -384,21 +447,21 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
if(rc == SQLITE_OK) {
sqlite3PagerUnref(page);
} else {
- CODEC_TRACE(("sqlite3_rekey: 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: 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: 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: rollback\n"));
+ CODEC_TRACE(("sqlite3_rekey_v2: rollback\n"));
sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK);
}
@@ -412,13 +475,15 @@ int sqlite3_rekey(sqlite3 *db, 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));
-
if( pDb->pBt ) {
codec_ctx *ctx;
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
-
- if(ctx) { /* if the codec has an attached codec_context user the raw key data */
- sqlcipher_codec_get_pass(ctx, zKey, nKey);
+ if(ctx) {
+ if(sqlcipher_codec_get_store_pass(ctx) == 1) {
+ sqlcipher_codec_get_pass(ctx, zKey, nKey);
+ } else {
+ sqlcipher_codec_get_keyspec(ctx, zKey, nKey);
+ }
} else {
*zKey = NULL;
*nKey = 0;