mirror of
https://github.com/status-im/sqlcipher.git
synced 2025-02-23 17:28:17 +00:00
rework hmac key derivation based on low iteration PBKDF2 with static salt mask
This commit is contained in:
parent
9c0dd8d449
commit
f7591e02fe
@ -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;
|
||||||
}
|
}
|
||||||
|
19
src/crypto.h
19
src/crypto.h
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user