From d5c4edebd90f60212a21f62be3712cd2eb170a35 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Tue, 19 Aug 2008 00:45:46 -0400 Subject: [PATCH] now rekey can be used on unencrpyted databases to encrypt the data --- src/crypto.c | 31 ++++++++++++++++++------------- test/codec.test | 27 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 057d303..ca7bc3c 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -27,7 +27,6 @@ #include "btreeInt.h" #include "crypto.h" -#define RESERVE 128 extern int sqlite3pager_get_codec(Pager *pPager, void * ctx); typedef struct { @@ -86,19 +85,10 @@ static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in, void *iv; int tmp_csz, csz; - size = size - ctx->iv_sz; /* adjust size to useable size and memset reserve at end of page */ - iv = out + size; - if(mode == CIPHER_ENCRYPT) { - RAND_pseudo_bytes(iv, ctx->iv_sz); - } else { - memcpy(iv, in+size, ctx->iv_sz); - } - - /* when this is an encryption operation and rekey is not null, we will actually encrypt ** data with the new rekey data */ void *key = ((mode == CIPHER_ENCRYPT && ctx->rekey != NULL) ? ctx->rekey : ctx->key); - + /* just copy raw data from in to out whenever ** 1. key is NULL; or ** 2. this is a decrypt operation and rekey_plaintext is true @@ -108,6 +98,14 @@ static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in, return SQLITE_OK; } + size = size - ctx->iv_sz; /* adjust size to useable size and memset reserve at end of page */ + iv = out + size; + if(mode == CIPHER_ENCRYPT) { + RAND_pseudo_bytes(iv, ctx->iv_sz); + } else { + memcpy(iv, in+size, ctx->iv_sz); + } + EVP_CipherInit(&ectx, CIPHER, NULL, NULL, mode); EVP_CIPHER_CTX_set_padding(&ectx, 0); EVP_CipherInit(&ectx, NULL, key, iv, mode); @@ -180,7 +178,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { if(ctx->buffer == NULL) return SQLITE_NOMEM; ctx->key_sz = EVP_CIPHER_key_length(CIPHER); - ctx->iv_sz = EVP_CIPHER_key_length(CIPHER); + ctx->iv_sz = EVP_CIPHER_iv_length(CIPHER); /* key size should be exactly the same size as nKey since this is raw key data at this point */ @@ -190,7 +188,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { if(ctx->key == NULL) return SQLITE_NOMEM; memcpy(ctx->key, zKey, nKey); - sqlite3BtreeSetPageSize(ctx->pBt, sqlite3BtreeGetPageSize(ctx->pBt), RESERVE); + sqlite3BtreeSetPageSize(ctx->pBt, sqlite3BtreeGetPageSize(ctx->pBt), ctx->iv_sz); sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, (void *) ctx); } } @@ -278,6 +276,11 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); if(ctx == NULL) { /* there was no codec attached to this database,so attach one now with a null password */ + char *error; + db->nextPagesize = sqlite3BtreeGetPageSize(pDb->pBt); + pDb->pBt->pBt->pageSizeFixed = 0; /* required for sqlite3BtreeSetPageSize to modify pagesize setting */ + sqlite3BtreeSetPageSize(pDb->pBt, db->nextPagesize, EVP_CIPHER_iv_length(CIPHER)); + sqlite3RunVacuum(&error, db); sqlite3CodecAttach(db, i, key, prepared_key_sz); sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); ctx->rekey_plaintext = 1; @@ -297,6 +300,7 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { rc = sqlite3PagerGet(pPager, pgno, &page); if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */ rc = sqlite3PagerWrite(page); + //printf("sqlite3PagerWrite(%d)\n", pgno); if(rc == SQLITE_OK) { sqlite3PagerUnref(page); } @@ -309,6 +313,7 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { rc = sqlite3BtreeCommit(pDb->pBt); memcpy(ctx->key, ctx->rekey, key_sz); } else { + printf("error\n"); sqlite3BtreeRollback(pDb->pBt); } diff --git a/test/codec.test b/test/codec.test index e63a00b..9d60081 100644 --- a/test/codec.test +++ b/test/codec.test @@ -138,6 +138,33 @@ do_test codec-1.10 { } } {25000} +# test rekey on an unecrypted database +do_test codec-1.11 { + sqlite_orig db2 test2.db + execsql { + BEGIN; + CREATE TABLE t2(a,b); + } db2 + + for {set i 1} {$i<=25000} {incr i} { + set r [expr {int(rand()*500000)}] + execsql "INSERT INTO t2 VALUES($i,$r);" db2 + } + + execsql { + COMMIT; + PRAGMA rekey = 'testkey'; + } db2 + + db2 close + sqlite_orig db2 test2.db + + execsql { + PRAGMA key = 'testkey'; + SELECT count(*) FROM t2; + } db2 + +} {25000} db close finish_test