Cache provided raw key data to provide to other attached databases; Add test case for attached DBs

This commit is contained in:
Stephen Lombardo 2009-04-22 09:21:52 -04:00
parent cfd52b7436
commit 309deae4f6
2 changed files with 59 additions and 3 deletions

View File

@ -45,11 +45,13 @@
typedef struct {
int key_sz;
int iv_sz;
int pass_sz;
int rekey_plaintext;
void *key;
void *buffer;
void *rekey;
void *salt;
void *pass;
Btree *pBt;
} codec_ctx;
@ -268,7 +270,13 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
/* allocate space for salt data */
ctx->key = sqlite3Malloc(ctx->key_sz);
if(ctx->key == NULL) return SQLITE_NOMEM;
/* allocate space for raw key data */
ctx->pass = sqlite3Malloc(nKey);
if(ctx->pass == NULL) return SQLITE_NOMEM;
memcpy(ctx->pass, zKey, nKey);
ctx->pass_sz = nKey;
/* read the first 16 bytes directly off the database file. This is the salt. */
sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
if(fd == NULL || sqlite3OsRead(fd, ctx->salt, 16, 0) != SQLITE_OK) {
@ -309,6 +317,11 @@ int sqlite3FreeCodecArg(void *pCodecArg) {
memset(ctx->salt, 0, FILE_HEADER_SZ);
sqlite3_free(ctx->salt);
}
if(ctx->pass) {
memset(ctx->pass, 0, ctx->pass_sz);
sqlite3_free(ctx->pass);
}
memset(ctx, 0, sizeof(codec_ctx));
sqlite3_free(ctx);
@ -407,6 +420,15 @@ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
if(rc == SQLITE_OK) {
rc = sqlite3BtreeCommit(pDb->pBt);
memcpy(ctx->key, ctx->rekey, key_sz);
if(ctx->pass) {
memset(ctx->pass, 0, ctx->pass_sz);
sqlite3_free(ctx->pass);
}
ctx->pass = sqlite3Malloc(nKey);
if(ctx->pass == NULL) return SQLITE_NOMEM;
memcpy(ctx->pass, pKey, nKey);
ctx->pass_sz = nKey;
} else {
printf("error\n");
sqlite3BtreeRollback(pDb->pBt);
@ -435,8 +457,8 @@ void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
/* if the codec has an attached codec_context user the raw key data */
if(ctx) {
*zKey = ctx->key;
*nKey = ctx->key_sz;
*zKey = ctx->pass;
*nKey = ctx->pass_sz;
} else {
*zKey = 0;
*nKey = 0;

View File

@ -38,6 +38,7 @@
file delete -force test.db
file delete -force test2.db
file delete -force test3.db
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -203,6 +204,39 @@ do_test codec-1.11 {
} {25000}
db close
db2 close
# attach an encrypted database
do_test codec-1.12 {
sqlite_orig db3 test3.db
execsql {
BEGIN;
PRAGMA key = 'testkey';
CREATE TABLE t3(a,b);
} db3
for {set i 1} {$i<=15000} {incr i} {
set r [expr {int(rand()*500000)}]
execsql "INSERT INTO t3 VALUES($i,$r);" db3
}
execsql {
COMMIT;
} db3
db3 close
sqlite_orig db2 test2.db
execsql {
PRAGMA key = 'testkey';
SELECT count(*) FROM t2;
ATTACH 'test3.db' AS db3;
SELECT count(*) FROM db3.t3;
} db2
} {25000 15000}
finish_test