major simplification - allocate space at end of each page for random initialization vector

This commit is contained in:
Stephen Lombardo 2008-08-09 08:13:30 -04:00
parent 2fe24cf434
commit 301a6beeef
2 changed files with 18 additions and 60 deletions

View File

@ -27,39 +27,19 @@
#include "btreeInt.h"
#include "crypto.h"
#define RESERVE 128
extern int sqlite3pager_get_codec(Pager *pPager, void * ctx);
extern int sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno);
typedef struct {
int key_sz;
int iv_sz;
Btree *pBt;
void *key;
void *rand;
void *buffer;
void *rekey;
int rekey_plaintext;
} codec_ctx;
static int codec_page_hash(Pgno pgno, const void *in, int inLen, void *out, int *outLen) {
EVP_MD_CTX mdctx;
unsigned int md_sz;
unsigned char md_value[EVP_MAX_MD_SIZE];
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, DIGEST, NULL);
EVP_DigestUpdate(&mdctx, in, inLen); /* add random "salt" data to hash*/
EVP_DigestUpdate(&mdctx, &pgno, sizeof(pgno));
EVP_DigestFinal_ex(&mdctx, md_value, &md_sz);
memcpy(out, md_value, md_sz);
EVP_MD_CTX_cleanup(&mdctx);
memset(md_value, 0, md_sz);
*outLen = md_sz;
}
static int codec_passphrase_hash(const void *in, int inLen, void *out, int *outLen) {
EVP_MD_CTX mdctx;
unsigned int md_sz;
@ -103,8 +83,15 @@ static int codec_prepare_key(sqlite3 *db, const void *zKey, int nKey, void *out,
*/
static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in, void *out) {
EVP_CIPHER_CTX ectx;
unsigned char iv[EVP_MAX_MD_SIZE];
int iv_sz, tmp_csz, csz;
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(ctx->iv, ctx->iv_sz);
memset(iv, 0, ctx->iv_sz);
}
/* when this is an encryption operation and rekey is not null, we will actually encrypt
** data with the new rekey data */
@ -119,12 +106,6 @@ static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in,
return SQLITE_OK;
}
/* the initilization vector is created from the hash of the
16 byte database random salt and the page number. This will
ensure that each page in the database has a unique initialization
vector */
codec_page_hash(pgno, ctx->rand, 16, iv, &iv_sz);
EVP_CipherInit(&ectx, CIPHER, NULL, NULL, mode);
EVP_CIPHER_CTX_set_padding(&ectx, 0);
EVP_CipherInit(&ectx, NULL, key, iv, mode);
@ -135,6 +116,7 @@ static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in,
csz += tmp_csz;
EVP_CIPHER_CTX_cleanup(&ectx);
assert(size == csz);
}
/*
@ -164,26 +146,16 @@ void* sqlite3Codec(void *iCtx, void *pData, Pgno pgno, int mode) {
break;
}
#if 0
if(pgno == 1 ) {
/* duplicate first 24 bytes of page 1 exactly to include random header data and page size */
memcpy(ctx->buffer, pData, HDR_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->rand, 16);
} else { /* CIPHER_DECRYPT */
memcpy(ctx->rand, pData, 16);
memcpy(ctx->buffer, SQLITE_FILE_HEADER, 16);
}
/* adjust starting pointers in data page for header offset */
codec_cipher(ctx, pgno, emode, pg_sz - HDR_SZ, &pData[HDR_SZ], &ctx->buffer[HDR_SZ]);
} else {
codec_cipher(ctx, pgno, emode, pg_sz, pData, ctx->buffer);
}
#endif
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 {
@ -201,7 +173,6 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
if(nKey && zKey && pDb->pBt) {
codec_ctx *ctx;
int rc;
MemPage *pPage1;
ctx = sqlite3DbMallocRaw(db, sizeof(codec_ctx));
if(ctx == NULL) return SQLITE_NOMEM;
@ -209,15 +180,6 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
/* 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 */
ctx->rand = sqlite3DbMallocRaw(db, 16);
if(ctx->rand == NULL) return SQLITE_NOMEM;
RAND_pseudo_bytes(ctx->rand, 16);
/* 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*/
@ -225,6 +187,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);
/* key size should be exactly the same size as nKey since this is
raw key data at this point */
@ -234,6 +197,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);
sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, (void *) ctx);
}
}
@ -252,11 +216,6 @@ int sqlite3FreeCodecArg(void *pCodecArg) {
sqlite3_free(ctx->rekey);
}
if(ctx->rand) {
memset(ctx->rand, 0, 16);
sqlite3_free(ctx->rand);
}
if(ctx->buffer) {
memset(ctx->buffer, 0, sqlite3BtreeGetPageSize(ctx->pBt));
sqlite3_free(ctx->buffer);

View File

@ -26,8 +26,7 @@
#define CIPHER_DECRYPT 0
#define CIPHER_ENCRYPT 1
/* HDR_SIZE allocates 16 bytes for random salt and 8 bytes for page size */
#define HDR_SZ 24
#define HDR_SZ 100
#endif
/* END CRYPTO */