From caf3865b8baa82f8b41217f5b7050f610844292d Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Fri, 16 Nov 2012 11:13:14 -0500 Subject: [PATCH] pragmas to override hmac salt mask and allow migration of 2.0 beta databases --- sqlcipher-2.0-beta-testkey.db | Bin 0 -> 2048 bytes src/crypto.c | 10 +++++++ src/crypto.h | 1 + src/crypto_impl.c | 7 ++++- test/crypto.test | 50 ++++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100755 sqlcipher-2.0-beta-testkey.db diff --git a/sqlcipher-2.0-beta-testkey.db b/sqlcipher-2.0-beta-testkey.db new file mode 100755 index 0000000000000000000000000000000000000000..5db36bb17906071346c5f09a90cbebc023cb2ba9 GIT binary patch literal 2048 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 literal 0 HcmV?d00001 diff --git a/src/crypto.c b/src/crypto.c index 7a25f63..1e15968 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -163,6 +163,16 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO); sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO); } + }else + if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){ + if(zRight) { + if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) { + unsigned char mask = 0; + const char *hex = zRight+2; + cipher_hex2bin(hex,2,&mask); + sqlcipher_set_hmac_salt_mask(mask); + } + } }else { return 0; } diff --git a/src/crypto.h b/src/crypto.h index 3dd400b..e44f82a 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -177,6 +177,7 @@ void* sqlcipher_codec_ctx_get_data(codec_ctx *); void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **); void sqlcipher_set_default_use_hmac(int use); +void sqlcipher_set_hmac_salt_mask(unsigned char mask); int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use); diff --git a/src/crypto_impl.c b/src/crypto_impl.c index c8f5d51..e434c52 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -80,6 +80,7 @@ int sqlcipher_cipher_ctx_key_derive(codec_ctx *, cipher_ctx *); int sqlcipher_page_hmac(cipher_ctx *, Pgno, unsigned char *, int, unsigned char *); static unsigned int default_flags = DEFAULT_CIPHER_FLAGS; +static unsigned char hmac_salt_mask = HMAC_SALT_MASK; static unsigned int openssl_external_init = 0; static unsigned int openssl_init_count = 0; @@ -397,6 +398,10 @@ void sqlcipher_set_default_use_hmac(int use) { else default_flags &= ~CIPHER_FLAG_HMAC; } +void sqlcipher_set_hmac_salt_mask(unsigned char mask) { + hmac_salt_mask = mask; +} + int sqlcipher_get_default_use_hmac(Parse *pParse) { int default_use_hmac_set = default_flags & CIPHER_FLAG_HMAC > 0; char *default_use_hmac = sqlite3_mprintf("%d", default_use_hmac_set); @@ -749,7 +754,7 @@ int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { to generate the encryption key */ memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz); for(i = 0; i < ctx->kdf_salt_sz; i++) { - ctx->hmac_kdf_salt[i] ^= HMAC_SALT_MASK; + 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", diff --git a/test/crypto.test b/test/crypto.test index 3ea63af..e077e1c 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1649,6 +1649,10 @@ do_test verify-pragma-cipher-default-use-hmac-off { execsql { PRAGMA cipher_default_use_hmac = off; PRAGMA cipher_default_use_hmac; + -- Be sure to turn cipher_default_use_hmac + -- back on or it will break later tests + -- (it's a global flag) + PRAGMA cipher_default_use_hmac = ON; } } {0} db close @@ -1729,4 +1733,50 @@ do_test verify-pragma-cipher-changed { db close file delete -force test.db +# open a 2.0 beta database with 4000 round hmac kdf and 0x00 +# hmac salt mask +# verify it can be opened +do_test open-2.0-beta-database { + sqlite_orig db sqlcipher-2.0-beta-testkey.db + execsql { + PRAGMA key = 'testkey'; + PRAGMA fast_kdf_iter = 4000; + PRAGMA cipher_hmac_salt_mask = "x'00'"; + SELECT count(*) FROM t1; + SELECT * FROM t1; + } +} {2 test-0-0 test-0-1 test-1-0 test-1-1} +db close + +# open a 2.0 beta database +# attach a new standard database +# copy schema between the two, and verify the latter +# can be opened +do_test 2.0-beta-to-2.0-migration { + sqlite_orig db sqlcipher-2.0-beta-testkey.db + + execsql { + PRAGMA key = 'testkey'; + PRAGMA cipher_hmac_salt_mask = "x'00'"; + PRAGMA fast_kdf_iter = 4000; + SELECT count(*) FROM sqlite_master; + + PRAGMA cipher_hmac_salt_mask = "x'3a'"; + ATTACH DATABASE 'test.db' AS db2 KEY 'testkey'; + + CREATE TABLE db2.t1(a,b); + INSERT INTO db2.t1 SELECT * FROM main.t1; + DETACH DATABASE db2; + } + db close + + sqlite_orig db test.db + execsql { + PRAGMA key = 'testkey'; + SELECT * FROM t1; + } +} {test-0-0 test-0-1 test-1-0 test-1-1} +db close +file delete -force test.db + finish_test