Cache provided raw key data to provide to other attached databases; Add test case for attached DBs
This commit is contained in:
parent
cfd52b7436
commit
309deae4f6
28
src/crypto.c
28
src/crypto.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue