rework hmac key derivation based on low iteration PBKDF2 with static salt mask

This commit is contained in:
Stephen Lombardo 2012-01-12 23:42:55 -05:00
parent 9c0dd8d449
commit f7591e02fe
5 changed files with 28 additions and 33 deletions

View File

@ -50,14 +50,14 @@ int codec_set_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) {
return SQLITE_ERROR; return SQLITE_ERROR;
} }
int codec_set_hmac_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) { int codec_set_fast_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) {
struct Db *pDb = &db->aDb[nDb]; struct Db *pDb = &db->aDb[nDb];
CODEC_TRACE(("codec_set_kdf_iter: entered db=%d nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx)); CODEC_TRACE(("codec_set_kdf_iter: entered db=%d nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx));
if(pDb->pBt) { if(pDb->pBt) {
codec_ctx *ctx; codec_ctx *ctx;
sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
return sqlcipher_codec_ctx_set_hmac_kdf_iter(ctx, kdf_iter, for_ctx); return sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, kdf_iter, for_ctx);
} }
return SQLITE_ERROR; return SQLITE_ERROR;
} }

View File

@ -56,10 +56,11 @@
#define DEFAULT_USE_HMAC 1 #define DEFAULT_USE_HMAC 1
#endif #endif
/* by default, sqlcipher will use an equal number of rounds to generate /* by default, sqlcipher will use a reduced number of iterations to generate
the HMAC key as it will to generate the encryption key */ the HMAC key / or transform a raw cipher key
#ifndef HMAC_PBKDF2_ITER */
#define HMAC_PBKDF2_ITER PBKDF2_ITER #ifndef FAST_PBKDF2_ITER
#define FAST_PBKDF2_ITER 2
#endif #endif
/* this if a fixed random array that will be xor'd with the database salt to ensure that the /* this if a fixed random array that will be xor'd with the database salt to ensure that the
@ -67,12 +68,8 @@
the encryption key. This can be overridden at compile time but it will make the resulting the encryption key. This can be overridden at compile time but it will make the resulting
binary incompatible with the default builds when using HMAC. A future version of SQLcipher binary incompatible with the default builds when using HMAC. A future version of SQLcipher
will likely allow this to be defined at runtime via pragma */ will likely allow this to be defined at runtime via pragma */
#ifndef HMAC_FIXED_SALT #ifndef HMAC_SALT_MASK
#define HMAC_FIXED_SALT {42,172,104,131,19,119,84,255,184,238,54,135,186,222,53,250} #define HMAC_SALT_MASK 0x3a
#endif
#ifndef HMAC_FIXED_SALT_SZ
#define HMAC_FIXED_SALT_SZ 16
#endif #endif
#ifdef CODEC_DEBUG #ifdef CODEC_DEBUG
@ -144,7 +141,7 @@ int sqlcipher_codec_ctx_get_reservesize(codec_ctx *);
int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int, int); int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int, int);
void* sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx); void* sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx);
int sqlcipher_codec_ctx_set_hmac_kdf_iter(codec_ctx *, int, int); int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *, int, int);
int sqlcipher_codec_ctx_set_cipher(codec_ctx *, const char *, int); int sqlcipher_codec_ctx_set_cipher(codec_ctx *, const char *, int);

View File

@ -47,8 +47,6 @@
#endif #endif
#endif #endif
static unsigned char cipher_hmac_fixed_salt[HMAC_FIXED_SALT_SZ] = HMAC_FIXED_SALT;
/* the default implementation of SQLCipher uses a cipher_ctx /* the default implementation of SQLCipher uses a cipher_ctx
to keep track of read / write state separately. The following to keep track of read / write state separately. The following
struct and associated functions are defined here */ struct and associated functions are defined here */
@ -58,7 +56,7 @@ typedef struct {
EVP_CIPHER_CTX ectx; EVP_CIPHER_CTX ectx;
HMAC_CTX hctx; HMAC_CTX hctx;
int kdf_iter; int kdf_iter;
int hmac_kdf_iter; int fast_kdf_iter;
int key_sz; int key_sz;
int iv_sz; int iv_sz;
int block_sz; int block_sz;
@ -205,7 +203,7 @@ int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
c1->evp_cipher == c2->evp_cipher c1->evp_cipher == c2->evp_cipher
&& c1->iv_sz == c2->iv_sz && c1->iv_sz == c2->iv_sz
&& c1->kdf_iter == c2->kdf_iter && c1->kdf_iter == c2->kdf_iter
&& c1->hmac_kdf_iter == c2->hmac_kdf_iter && c1->fast_kdf_iter == c2->fast_kdf_iter
&& c1->key_sz == c2->key_sz && c1->key_sz == c2->key_sz
&& c1->pass_sz == c2->pass_sz && c1->pass_sz == c2->pass_sz
&& ( && (
@ -313,11 +311,11 @@ int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter, int for_ctx)
return SQLITE_OK; return SQLITE_OK;
} }
int sqlcipher_codec_ctx_set_hmac_kdf_iter(codec_ctx *ctx, int hmac_kdf_iter, int for_ctx) { int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter, int for_ctx) {
cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx; cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
int rc; int rc;
c_ctx->hmac_kdf_iter = hmac_kdf_iter; c_ctx->fast_kdf_iter = fast_kdf_iter;
c_ctx->derive_key = 1; c_ctx->derive_key = 1;
if(for_ctx == 2) if(for_ctx == 2)
@ -429,7 +427,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc; if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc;
if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, PBKDF2_ITER, 0)) != SQLITE_OK) return rc; if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
if((rc = sqlcipher_codec_ctx_set_hmac_kdf_iter(ctx, HMAC_PBKDF2_ITER, 0)) != SQLITE_OK) return rc; if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER, 0)) != SQLITE_OK) return rc;
if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc; if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc;
/* Use HMAC signatures by default. Note that codec_set_use_hmac will implicity call /* Use HMAC signatures by default. Note that codec_set_use_hmac will implicity call
@ -561,19 +559,19 @@ int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int
int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
CODEC_TRACE(("codec_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \ CODEC_TRACE(("codec_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
ctx->kdf_salt=%d ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \ ctx->kdf_salt=%d ctx->kdf_salt_sz=%d c_ctx->kdf_iter=%d \
ctx->hmac_kdf_salt=%d, c_ctx->hmac_kdf_iter=%d c_ctx->key_sz=%d\n", ctx->hmac_kdf_salt=%d, c_ctx->fast_kdf_iter=%d c_ctx->key_sz=%d\n",
c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter, c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
ctx->hmac_kdf_salt, c_ctx->hmac_kdf_iter, c_ctx->key_sz)); ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz));
if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null
if (c_ctx->pass_sz == ((c_ctx->key_sz*2)+3) && sqlite3StrNICmp(c_ctx->pass ,"x'", 2) == 0) { if (c_ctx->pass_sz == ((c_ctx->key_sz*2)+3) && sqlite3StrNICmp(c_ctx->pass ,"x'", 2) == 0) {
int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */ int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
const char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ const char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
CODEC_TRACE(("codec_key_derive: deriving key from hex\n")); CODEC_TRACE(("codec_key_derive: deriving key from hex\n"));
cipher_hex2bin(z, n, c_ctx->key); cipher_hex2bin(z, n, c_ctx->key);
} else { } else {
CODEC_TRACE(("codec_key_derive: deriving key using PBKDF2\n")); CODEC_TRACE(("codec_key_derive: deriving key using full PBKDF2 with %d iterations\n", c_ctx->kdf_iter));
PKCS5_PBKDF2_HMAC_SHA1( c_ctx->pass, c_ctx->pass_sz, PKCS5_PBKDF2_HMAC_SHA1( c_ctx->pass, c_ctx->pass_sz,
ctx->kdf_salt, ctx->kdf_salt_sz, ctx->kdf_salt, ctx->kdf_salt_sz,
c_ctx->kdf_iter, c_ctx->key_sz, c_ctx->key); c_ctx->kdf_iter, c_ctx->key_sz, c_ctx->key);
@ -592,15 +590,15 @@ int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
easy to derive and publically known, is not the same as the salt used easy to derive and publically known, is not the same as the salt used
to generate the encryption key */ to generate the encryption key */
memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz); memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz);
for(i = 0; i < HMAC_FIXED_SALT_SZ && i < ctx->kdf_salt_sz; i++) { for(i = 0; i < ctx->kdf_salt_sz; i++) {
ctx->hmac_kdf_salt[i] = ctx->hmac_kdf_salt[i] ^ cipher_hmac_fixed_salt[i]; ctx->hmac_kdf_salt[i] ^= HMAC_SALT_MASK;
} }
CODEC_TRACE(("codec_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n", CODEC_TRACE(("codec_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n",
HMAC_PBKDF2_ITER)); c_ctx->fast_kdf_iter));
PKCS5_PBKDF2_HMAC_SHA1( (const char*)c_ctx->key, c_ctx->key_sz, PKCS5_PBKDF2_HMAC_SHA1( (const char*)c_ctx->key, c_ctx->key_sz,
ctx->hmac_kdf_salt, ctx->kdf_salt_sz, ctx->hmac_kdf_salt, ctx->kdf_salt_sz,
c_ctx->hmac_kdf_iter, c_ctx->key_sz, c_ctx->hmac_key); c_ctx->fast_kdf_iter, c_ctx->key_sz, c_ctx->hmac_key);
} }
c_ctx->derive_key = 0; c_ctx->derive_key = 0;

View File

@ -1503,9 +1503,9 @@ void sqlite3Pragma(
extern int codec_set_kdf_iter(sqlite3*, int, int, int); extern int codec_set_kdf_iter(sqlite3*, int, int, int);
codec_set_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration codec_set_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration
}else }else
if( sqlite3StrICmp(zLeft, "hmac_kdf_iter")==0 && zRight ){ if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0 && zRight ){
extern int codec_set_hmac_kdf_iter(sqlite3*, int, int, int); extern int codec_set_fast_kdf_iter(sqlite3*, int, int, int);
codec_set_hmac_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration codec_set_fast_kdf_iter(db, iDb, atoi(zRight), 2); // change of RW PBKDF2 iteration
}else }else
if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){ if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
extern int codec_set_kdf_iter(sqlite3*, int, int, int); extern int codec_set_kdf_iter(sqlite3*, int, int, int);

View File

@ -936,7 +936,7 @@ do_test custom-hmac-kdf-iter {
execsql { execsql {
PRAGMA key = 'testkey'; PRAGMA key = 'testkey';
PRAGMA hmac_kdf_iter = 10; PRAGMA fast_kdf_iter = 10;
CREATE table t1(a,b); CREATE table t1(a,b);
BEGIN; BEGIN;
} }
@ -955,7 +955,7 @@ do_test custom-hmac-kdf-iter {
execsql { execsql {
PRAGMA key = 'testkey'; PRAGMA key = 'testkey';
PRAGMA hmac_kdf_iter = 10; PRAGMA fast_kdf_iter = 10;
SELECT count(*) FROM t1; SELECT count(*) FROM t1;
} }