a start towards allocating random salt in unused 16 byte header space at the start of the SQLite file
This commit is contained in:
parent
9a13dce6d4
commit
74a60987ce
72
src/crypto.c
72
src/crypto.c
@ -49,6 +49,7 @@ typedef struct {
|
||||
void *key;
|
||||
void *buffer;
|
||||
void *rekey;
|
||||
void *salt;
|
||||
int rekey_plaintext;
|
||||
} codec_ctx;
|
||||
|
||||
@ -214,7 +215,24 @@ void* sqlite3Codec(void *iCtx, void *pData, Pgno pgno, int mode) {
|
||||
break;
|
||||
}
|
||||
|
||||
codec_cipher(ctx, pgno, emode, pg_sz, pData, ctx->buffer);
|
||||
if(pgno == 1 ) {
|
||||
memcpy(ctx->buffer, pData, FILE_HEADER_SZ);
|
||||
|
||||
/* if this is a read & decrypt operation on the first page then copy the
|
||||
first 16 bytes off the page into the context's random salt buffer
|
||||
*/
|
||||
if(emode == CIPHER_ENCRYPT) {
|
||||
memcpy(ctx->buffer, ctx->salt, FILE_HEADER_SZ);
|
||||
} else {
|
||||
memcpy(ctx->buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ);
|
||||
}
|
||||
|
||||
/* adjust starting pointers in data page for header offset */
|
||||
codec_cipher(ctx, pgno, emode, pg_sz - FILE_HEADER_SZ, pData + FILE_HEADER_SZ, ctx->buffer + FILE_HEADER_SZ);
|
||||
} else {
|
||||
codec_cipher(ctx, pgno, emode, pg_sz, pData, ctx->buffer);
|
||||
}
|
||||
|
||||
if(emode == CIPHER_ENCRYPT) {
|
||||
return ctx->buffer; /* return persistent buffer data, pData remains intact */
|
||||
} else {
|
||||
@ -228,6 +246,9 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
|
||||
|
||||
if(nKey && zKey && pDb->pBt) {
|
||||
codec_ctx *ctx;
|
||||
PgHdr *page;
|
||||
Pager *pPager = pDb->pBt->pBt->pPager;
|
||||
int prepared_key_sz;
|
||||
|
||||
ctx = sqlite3Malloc(sizeof(codec_ctx));
|
||||
if(ctx == NULL) return SQLITE_NOMEM;
|
||||
@ -235,6 +256,10 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
|
||||
|
||||
ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
|
||||
|
||||
/* pre-allocate space for salt data */
|
||||
ctx->salt = sqlite3Malloc(FILE_HEADER_SZ);
|
||||
if(ctx->salt == NULL) return SQLITE_NOMEM;
|
||||
|
||||
/* pre-allocate a page buffer of PageSize bytes. This will
|
||||
be used as a persistent buffer for encryption and decryption
|
||||
operations to avoid overhead of multiple memory allocations*/
|
||||
@ -243,14 +268,30 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
|
||||
|
||||
ctx->key_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 */
|
||||
assert(nKey == ctx->key_sz);
|
||||
|
||||
ctx->key = sqlite3Malloc(ctx->key_sz);
|
||||
if(ctx->key == NULL) return SQLITE_NOMEM;
|
||||
memcpy(ctx->key, zKey, nKey);
|
||||
|
||||
#if 0
|
||||
if(sqlite3PagerGet(pPager, 1, &page) == SQLITE_OK) {
|
||||
fprintf(stderr,"got page1");
|
||||
memcpy(ctx->salt, page->pData, FILE_HEADER_SZ);
|
||||
sqlite3PagerUnref(page);
|
||||
} else {
|
||||
/* assign random salt data. This will be written to the first page
|
||||
if this is a new database file. If an existing database file is
|
||||
attached this will just be overwritten when the first page is
|
||||
read from disk */
|
||||
fprintf(stderr, "assigned random salt");
|
||||
|
||||
}
|
||||
#endif
|
||||
RAND_pseudo_bytes(ctx->salt, FILE_HEADER_SZ);
|
||||
|
||||
codec_prepare_key(db, zKey, nKey, ctx->key, &prepared_key_sz);
|
||||
/* key size should be exactly the same size as prepared_key_sz since this is
|
||||
raw key data at this point */
|
||||
assert(prepared_key_sz == ctx->key_sz);
|
||||
|
||||
sqlite3BtreeSetPageSize(ctx->pBt, sqlite3BtreeGetPageSize(ctx->pBt), ctx->iv_sz, 0);
|
||||
sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, (void *) ctx);
|
||||
@ -278,6 +319,11 @@ int sqlite3FreeCodecArg(void *pCodecArg) {
|
||||
sqlite3_free(ctx->buffer);
|
||||
}
|
||||
|
||||
if(ctx->salt) {
|
||||
memset(ctx->salt, 0, FILE_HEADER_SZ);
|
||||
sqlite3_free(ctx->salt);
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(codec_ctx));
|
||||
sqlite3_free(ctx);
|
||||
return SQLITE_OK;
|
||||
@ -290,20 +336,10 @@ void sqlite3_activate_see(const char* in) {
|
||||
int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
|
||||
/* attach key if db and pKey are not null and nKey is > 0 */
|
||||
if(db && pKey && nKey) {
|
||||
int i, prepared_key_sz;
|
||||
int key_sz = EVP_CIPHER_key_length(CIPHER);
|
||||
void *key = sqlite3Malloc(key_sz);
|
||||
if(key == NULL) return SQLITE_NOMEM;
|
||||
|
||||
codec_prepare_key(db, pKey, nKey, key, &prepared_key_sz);
|
||||
assert(prepared_key_sz == key_sz);
|
||||
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
sqlite3CodecAttach(db, i, key, prepared_key_sz);
|
||||
sqlite3CodecAttach(db, i, pKey, nKey);
|
||||
}
|
||||
|
||||
memset(key, 0, key_sz); /* cleanup temporary key data */
|
||||
sqlite3_free(key);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return SQLITE_ERROR;
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
#define FILE_HEADER_SZ 16
|
||||
|
||||
#define CIPHER EVP_aes_256_cfb()
|
||||
#define CIPHER_DECRYPT 0
|
||||
#define CIPHER_ENCRYPT 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user