From 8f061f1a50b643aae195a85765deb77ff855416b Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 29 Feb 2012 11:14:42 -0500 Subject: [PATCH] add pragma cipher_default_use_hmac to toggle global HMAC setting --- src/crypto.c | 4 ++++ src/crypto.h | 2 ++ src/crypto_impl.c | 9 ++++++- src/pragma.c | 10 ++++---- test/crypto.test | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 5c8b2d6..431613e 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -77,6 +77,10 @@ static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ct return rc; } +void codec_set_default_use_hmac(int use) { + sqlcipher_set_default_use_hmac(use); +} + int codec_set_use_hmac(sqlite3* db, int nDb, int use) { struct Db *pDb = &db->aDb[nDb]; diff --git a/src/crypto.h b/src/crypto.h index a5a62ec..7a7165b 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -149,6 +149,8 @@ void* sqlcipher_codec_ctx_get_data(codec_ctx *); void sqlcipher_exportFunc(sqlite3_context *, int, sqlite3_value **); +void sqlcipher_set_default_use_hmac(int use); + int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use); /* end extensions defined in crypto_impl.c */ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 336afbd..f0e9dfb 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -79,6 +79,8 @@ int sqlcipher_cipher_ctx_key_derive(codec_ctx *, cipher_ctx *); /* prototype for pager HMAC function */ int sqlcipher_page_hmac(cipher_ctx *, Pgno, unsigned char *, int, unsigned char *); +static int default_use_hmac = DEFAULT_USE_HMAC; + struct codec_ctx { int kdf_salt_sz; int page_sz; @@ -325,7 +327,12 @@ int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter, int return SQLITE_OK; } +/* set the global default flag for HMAC */ +void sqlcipher_set_default_use_hmac(int use) { + default_use_hmac = use; +} +/* set the codec flag for whether this individual database should be using hmac */ int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) { int reserve = EVP_MAX_IV_LENGTH; /* base reserve size will be IV only */ @@ -432,7 +439,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f /* Use HMAC signatures by default. Note that codec_set_use_hmac will implicity call codec_set_page_size to set the default */ - if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, DEFAULT_USE_HMAC)) != SQLITE_OK) return rc; + if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_use_hmac)) != SQLITE_OK) return rc; if((rc = sqlcipher_cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) return rc; diff --git a/src/pragma.c b/src/pragma.c index d9047e1..264c133 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1515,13 +1515,13 @@ void sqlite3Pragma( extern int codec_set_page_size(sqlite3*, int, int); codec_set_page_size(db, iDb, atoi(zRight)); // change page size }else + if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){ + extern void codec_set_default_use_hmac(int); + codec_set_default_use_hmac(sqlite3GetBoolean(zRight)); + }else if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){ extern int codec_set_use_hmac(sqlite3*, int, int); - if(sqlite3GetBoolean(zRight)) { - codec_set_use_hmac(db, iDb, 1); - } else { - codec_set_use_hmac(db, iDb, 0); - } + codec_set_use_hmac(db, iDb, sqlite3GetBoolean(zRight)); }else /** END CRYPTO **/ #endif diff --git a/test/crypto.test b/test/crypto.test index aabb481..7824056 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1145,4 +1145,64 @@ do_test cipher-options-before-keys { db close file delete -force test.db +# open a 1.1.8 database (no HMAC), then +# try to open another 1.1.8 database. The +# attached database should have the same hmac +# setting as the original +do_test default-use-hmac-attach { + file copy -force sqlcipher-1.1.8-testkey.db test.db + sqlite_orig db test.db + execsql { + PRAGMA cipher_default_use_hmac = OFF; + PRAGMA key = 'testkey'; + SELECT count(*) FROM t1; + ATTACH 'sqlcipher-1.1.8-testkey.db' AS db2; + SELECT count(*) from db2.t1; + PRAGMA cipher_default_use_hmac = ON; + } +} {4 4} +db close +file delete -force test.db + +# open a 2.0 database (with HMAC), then +# try to a 1.1.8 database. this should +# fail because the hmac setting for the +# attached database is not compatible +do_test attach-1.1.8-database-from-2.0-fails { + sqlite_orig db test.db + catchsql { + PRAGMA key = 'testkey'; + CREATE table t1(a,b); + ATTACH 'sqlcipher-1.1.8-testkey.db' AS db2; + } +} {1 {file is encrypted or is not a database}} +db close +file delete -force test.db + +# open a 2.0 database (with HMAC), then +# set the default hmac setting to OFF. +# try to a 1.1.8 database. this should +# succeed now that hmac is off by default +# before the attach +do_test change-default-use-hmac-attach { + sqlite_orig db test.db + execsql { + PRAGMA key = 'testkey'; + CREATE table t1(a,b); + INSERT INTO t1(a,b) VALUES (1,2); + } + db close + sqlite_orig db test.db + execsql { + PRAGMA key = 'testkey'; + SELECT count(*) FROM t1; + PRAGMA cipher_default_use_hmac = OFF; + ATTACH 'sqlcipher-1.1.8-testkey.db' AS db2; + SELECT count(*) from db2.t1; + PRAGMA cipher_default_use_hmac = ON; + } +} {1 4} +db close +file delete -force test.db + finish_test