sqlcipher_memset avoid's memset optimization

This commit is contained in:
Stephen Lombardo 2012-11-16 15:05:33 -05:00
parent 72a9eb2161
commit e8c819bcf8
2 changed files with 29 additions and 13 deletions

View File

@ -139,8 +139,9 @@ static void cipher_hex2bin(const char *hex, int sz, unsigned char *out){
typedef struct codec_ctx codec_ctx;
/* utility functions */
int sqlcipher_ismemset(const unsigned char *a0, unsigned char value, int len);
int sqlcipher_memcmp(const unsigned char *a0, const unsigned char *a1, int len);
void* sqlcipher_memset(void *v, unsigned char value, int len);
int sqlcipher_ismemset(const void *v, unsigned char value, int len);
int sqlcipher_memcmp(const void *v0, const void *v1, int len);
int sqlcipher_pseudorandom(void *, int);
void sqlcipher_free(void *, int);

View File

@ -132,14 +132,28 @@ void sqlcipher_deactivate() {
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
void* sqlcipher_memset(void *v, unsigned char value, int len) {
int i = 0;
volatile unsigned char *a = v;
if (v == NULL) return v;
for(i = 0; i < len; i++) {
a[i] = value;
}
return v;
}
/* constant time memory check tests every position of a memory segement
matches a single value (i.e. the memory is all zeros)
returns 0 if match, 1 of no match */
int sqlcipher_ismemset(const unsigned char *a0, unsigned char value, int len) {
int sqlcipher_ismemset(const void *v, unsigned char value, int len) {
const unsigned char *a = v;
int i = 0, result = 0;
for(i = 0; i < len; i++) {
result |= a0[i] ^ value;
result |= a[i] ^ value;
}
return (result != 0);
@ -147,7 +161,8 @@ int sqlcipher_ismemset(const unsigned char *a0, unsigned char value, int len) {
/* constant time memory comparison routine.
returns 0 if match, 1 if no match */
int sqlcipher_memcmp(const unsigned char *a0, const unsigned char *a1, int len) {
int sqlcipher_memcmp(const void *v0, const void *v1, int len) {
const unsigned char *a0 = v0, *a1 = v1;
int i = 0, result = 0;
for(i = 0; i < len; i++) {
@ -173,7 +188,7 @@ int sqlcipher_random (void *buffer, int length) {
void sqlcipher_free(void *ptr, int sz) {
if(ptr) {
if(sz > 0) {
memset(ptr, 0, sz);
sqlcipher_memset(ptr, 0, sz);
#ifndef OMIT_MEMLOCK
#if defined(__unix__) || defined(__APPLE__)
munlock(ptr, sz);
@ -193,7 +208,7 @@ void sqlcipher_free(void *ptr, int sz) {
*/
void* sqlcipher_malloc(int sz) {
void *ptr = sqlite3Malloc(sz);
memset(ptr, 0, sz);
sqlcipher_memset(ptr, 0, sz);
#ifndef OMIT_MEMLOCK
if(ptr) {
#if defined(__unix__) || defined(__APPLE__)
@ -219,7 +234,7 @@ int sqlcipher_cipher_ctx_init(cipher_ctx **iCtx) {
*iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
ctx = *iCtx;
if(ctx == NULL) return SQLITE_NOMEM;
memset(ctx, 0, sizeof(cipher_ctx));
sqlcipher_memset(ctx, 0, sizeof(cipher_ctx));
ctx->key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
ctx->hmac_key = (unsigned char *) sqlcipher_malloc(EVP_MAX_KEY_LENGTH);
if(ctx->key == NULL) return SQLITE_NOMEM;
@ -506,7 +521,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
if(ctx == NULL) return SQLITE_NOMEM;
memset(ctx, 0, sizeof(codec_ctx)); /* initialize all pointers and values to 0 */
sqlcipher_memset(ctx, 0, sizeof(codec_ctx)); /* initialize all pointers and values to 0 */
ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
/* allocate space for salt data. Then read the first 16 bytes
@ -637,7 +652,7 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
/* the key size should never be zero. If it is, error out. */
if(c_ctx->key_sz == 0) {
CODEC_TRACE(("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno));
memset(out, 0, page_sz);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_ERROR;
}
@ -650,7 +665,7 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
if((c_ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT)) {
if(sqlcipher_page_hmac(c_ctx, pgno, in, size + c_ctx->iv_sz, hmac_out) != SQLITE_OK) {
memset(out, 0, page_sz);
sqlcipher_memset(out, 0, page_sz);
CODEC_TRACE(("codec_cipher: hmac operations failed for pgno=%d\n", pgno));
return SQLITE_ERROR;
}
@ -663,14 +678,14 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
short read failures must be ignored for autovaccum mode to work so wipe the output buffer
and return SQLITE_OK to skip the decryption step. */
CODEC_TRACE(("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno));
memset(out, 0, page_sz);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_OK;
} else {
/* if the page memory is not all zeros, it means the there was data and a hmac on the page.
since the check failed, the page was either tampered with or corrupted. wipe the output buffer,
and return SQLITE_ERROR to the caller */
CODEC_TRACE(("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno));
memset(out, 0, page_sz);
sqlcipher_memset(out, 0, page_sz);
return SQLITE_ERROR;
}
}