From 4bc6ba08f84179ececdd04d8a7193ea5571403d2 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Wed, 24 Jul 2013 17:07:42 -0500 Subject: [PATCH] Initial work on a PRAGMA cipher_migrate Swapping of the Btree meta data is not working properly now. --- src/crypto.c | 7 +++++ src/crypto.h | 1 + src/crypto_impl.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/src/crypto.c b/src/crypto.c index ca24521..32b2184 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -89,6 +89,13 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c CODEC_TRACE(("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_migrate")==0 && !zRight ){ + if(ctx){ + char *migrate_status = sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx)); + codec_vdbe_return_static_string(pParse, "sqlcipher_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)); diff --git a/src/crypto.h b/src/crypto.h index aa77670..c4849bc 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -209,6 +209,7 @@ int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag); int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx); const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx); +int sqlcipher_codec_ctx_migrate(codec_ctx *ctx); #endif #endif /* END SQLCIPHER */ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 5510073..c4c9f1d 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -867,5 +867,79 @@ const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) { return ctx->read_ctx->provider->get_provider_name(ctx->read_ctx); } +int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { + u32 meta; + int rc = 0; + int command_idx = 0; + sqlite3 *db = ctx->pBt->db; + const char *db_filename = sqlite3_db_filename(db, "main"); + const char *migrated_db_filename = sqlite3_mprintf("%s-migrated", db_filename); + const char *key = ctx->read_ctx->pass; + int db_idx = db->nDb; + CODEC_TRACE(("current database count:%d\n", db_idx)); + if(db_filename){ + char *attach_command = sqlite3_mprintf("ATTACH DATABASE '%s-migrated' as migrate KEY '%s';", + db_filename, key); + const char *commands[] = { + "PRAGMA kdf_iter = '4000';", + attach_command, + "SELECT sqlcipher_export('migrate');", + }; + for(command_idx = 0; command_idx < ArraySize(commands); command_idx++){ + const char *command = commands[command_idx]; + rc = sqlite3_exec(db, command, NULL, NULL, NULL); + if(rc != SQLITE_OK){ + break; + } + } + sqlite3_free(attach_command); + if(rc == SQLITE_OK){ + + static const unsigned char aCopy[] = { + BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ + BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ + BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ + BTREE_USER_VERSION, 0, /* Preserve the user version */ + BTREE_APPLICATION_ID, 0, /* Preserve the application id */ + }; + + CODEC_TRACE(("current database count:%d\n", db->nDb)); + Btree *pDest = db->aDb[0].pBt; + Btree *pSrc = db->aDb[db->nDb-1].pBt; + + CODEC_TRACE(("pSrc is '%p'\n", (void*)pSrc)); + CODEC_TRACE(("pDest is '%p'\n", (void*)pDest)); + + //rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL); + rc = sqlite3BtreeBeginTrans(pSrc, 2); + rc = sqlite3BtreeBeginTrans(pDest, 2); + + assert( 1==sqlite3BtreeIsInTrans(pDest) ); + assert( 1==sqlite3BtreeIsInTrans(pSrc) ); + + CODEC_TRACE(("before metadata copy\n")); + int i = 0; + for(i=0; i