From 569c6676a6ddb0ff73821d7693b5e18ddef809b9 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 16 Oct 2014 22:51:35 -0400 Subject: Imported Upstream version 3.2.0 --- src/crypto.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 22 deletions(-) (limited to 'src/crypto.c') 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; -- cgit v1.2.3