adds PRAGMA cipher_compatibility and cipher_default_compatibility

This commit is contained in:
Stephen Lombardo 2018-12-12 17:24:24 -05:00
parent 60b49b6826
commit e4b66d6cc8
4 changed files with 224 additions and 44 deletions

BIN
sqlcipher-4.0-testkey.db Normal file

Binary file not shown.

View File

@ -369,7 +369,6 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef
} else if(sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) {
rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
}
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
} else {
int algorithm = sqlcipher_get_default_hmac_algorithm();
if(algorithm == SQLCIPHER_HMAC_SHA1) {
@ -415,7 +414,6 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef
} else if(sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) {
rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
}
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
} else {
int algorithm = sqlcipher_get_default_kdf_algorithm();
if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
@ -427,6 +425,108 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef
}
}
}else
if( sqlite3StrICmp(zLeft,"cipher_compatibility")==0 ){
if(ctx) {
if(zRight) {
int version = atoi(zRight);
switch(version) {
case 1:
rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 0);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
break;
case 2:
rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
break;
case 3:
rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 64000);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
break;
default:
rc = sqlcipher_codec_ctx_set_pagesize(ctx, 4096);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA512);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA512);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 256000);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
break;
}
rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
}
}
}else
if( sqlite3StrICmp(zLeft,"cipher_default_compatibility")==0 ){
if(zRight) {
int version = atoi(zRight);
switch(version) {
case 1:
sqlcipher_set_default_pagesize(1024);
sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
sqlcipher_set_default_kdf_iter(4000);
sqlcipher_set_default_use_hmac(0);
break;
case 2:
sqlcipher_set_default_pagesize(1024);
sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
sqlcipher_set_default_kdf_iter(4000);
sqlcipher_set_default_use_hmac(1);
break;
case 3:
sqlcipher_set_default_pagesize(1024);
sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
sqlcipher_set_default_kdf_iter(64000);
sqlcipher_set_default_use_hmac(1);
break;
default:
sqlcipher_set_default_pagesize(4096);
sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
sqlcipher_set_default_kdf_iter(256000);
sqlcipher_set_default_use_hmac(1);
break;
}
}
}else
if( sqlite3StrICmp(zLeft,"cipher_memory_security")==0 ){
if( zRight ) {
sqlcipher_set_mem_security(sqlite3GetBoolean(zRight,1));

View File

@ -1235,14 +1235,11 @@ cleanup:
}
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
int i, pass_sz, keyspec_sz, nRes, user_version, upgrade_from, rc, oflags;
int i, pass_sz, keyspec_sz, nRes, user_version, rc, oflags;
Db *pDb = 0;
sqlite3 *db = ctx->pBt->db;
const char *db_filename = sqlite3_db_filename(db, "main");
char *v1_pragmas = "PRAGMA cipher_use_hmac = OFF; PRAGMA kdf_iter = 4000; PRAGMA cipher_page_size = 1024; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;";
char *v2_pragmas = "PRAGMA kdf_iter = 4000; PRAGMA cipher_page_size = 1024; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;";
char *v3_pragmas = "PRAGMA kdf_iter = 64000; PRAGMA cipher_page_size = 1024; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;";
char *set_user_version = NULL, *pass = NULL, *attach_command = NULL, *migrated_db_filename = NULL, *keyspec = NULL, *temp = NULL, *journal_mode = NULL, *set_journal_mode = NULL;
char *set_user_version = NULL, *pass = NULL, *attach_command = NULL, *migrated_db_filename = NULL, *keyspec = NULL, *temp = NULL, *journal_mode = NULL, *set_journal_mode = NULL, *pragma_compat = NULL;
Btree *pDest = NULL, *pSrc = NULL;
const char* commands[5];
sqlite3_file *srcfile, *destfile;
@ -1250,7 +1247,7 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
LPWSTR w_db_filename = NULL, w_migrated_db_filename = NULL;
int w_db_filename_sz = 0, w_migrated_db_filename_sz = 0;
#endif
pass_sz = keyspec_sz = rc = user_version = upgrade_from = 0;
pass_sz = keyspec_sz = rc = user_version = 0;
if(!db_filename || sqlite3Strlen30(db_filename) < 1)
goto cleanup; /* exit immediately if this is an in memory database */
@ -1268,29 +1265,19 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
goto cleanup;
}
/* Version 3 - check for 64k with hmac format and 1024 page size */
rc = sqlcipher_check_connection(db_filename, pass, pass_sz, v3_pragmas, &user_version, &journal_mode);
for(int i = 3; i > 0; i--) {
pragma_compat = sqlite3_mprintf("PRAGMA cipher_compatibility = %d;", i);
rc = sqlcipher_check_connection(db_filename, pass, pass_sz, pragma_compat, &user_version, &journal_mode);
if(rc == SQLITE_OK) {
CODEC_TRACE("Version 3 format found\n");
upgrade_from = 3;
CODEC_TRACE("Version %d format found\n", i);
goto migrate;
}
/* Version 2 - check for 4k with hmac format and 1024 page size */
rc = sqlcipher_check_connection(db_filename, pass, pass_sz, v2_pragmas, &user_version, &journal_mode);
if(rc == SQLITE_OK) {
CODEC_TRACE("Version 2 format found\n");
upgrade_from = 2;
goto migrate;
}
/* Version 1 - check no HMAC, 4k KDF, and 1024 page size */
rc = sqlcipher_check_connection(db_filename, pass, pass_sz, v1_pragmas, &user_version, &journal_mode);
if(rc == SQLITE_OK) {
CODEC_TRACE("Version 1 format found\n");
upgrade_from = 1;
goto migrate;
if(pragma_compat) sqlcipher_free(pragma_compat, sqlite3Strlen30(pragma_compat));
pragma_compat = NULL;
}
/* if we exit the loop normally we failed to determine the version, this is an error */
CODEC_TRACE("Upgrade format not determined\n");
goto handle_error;
migrate:
@ -1303,20 +1290,8 @@ migrate:
attach_command = sqlite3_mprintf("ATTACH DATABASE '%s' as migrate KEY '%q';", migrated_db_filename, pass);
set_user_version = sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version);
switch(upgrade_from) {
case 1:
commands[0] = v1_pragmas;
break;
case 2:
commands[0] = v2_pragmas;
break;
case 3:
commands[0] = v3_pragmas;
break;
default:
CODEC_TRACE("Upgrade format not determined\n");
goto handle_error;
}
commands[0] = pragma_compat;
commands[1] = "PRAGMA journal_mode = delete;"; /* force journal mode to DELETE, we will set it back later if different */
commands[2] = attach_command;
commands[3] = "SELECT sqlcipher_export('migrate');";
@ -1423,6 +1398,7 @@ cleanup:
if(set_user_version) sqlcipher_free(set_user_version, sqlite3Strlen30(set_user_version));
if(set_journal_mode) sqlcipher_free(set_journal_mode, sqlite3Strlen30(set_journal_mode));
if(journal_mode) sqlcipher_free(journal_mode, sqlite3Strlen30(journal_mode));
if(pragma_compat) sqlcipher_free(pragma_compat, sqlite3Strlen30(pragma_compat));
#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
if(w_db_filename) sqlcipher_free(w_db_filename, w_db_filename_sz);
if(w_migrated_db_filename) sqlcipher_free(w_migrated_db_filename, w_migrated_db_filename_sz);

View File

@ -107,6 +107,17 @@ db2 close
file delete -force test.db
file delete -force test2.db
# open a 4.0 database
do_test compat-open-4.0-database {
sqlite_orig db $sampleDir/sqlcipher-4.0-testkey.db
execsql {
PRAGMA key = 'testkey';
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
db close
# create an encrypted database, attach an default-key encrypted volume
# copy data between, verify the second database
do_test encrypted-attach-default-key {
@ -1228,6 +1239,99 @@ db close
file delete -force plain.db
file delete -force encrypted.db
# open a 1.1.8 database using cipher_compatibility
do_test compat-open-1.1.8-database {
sqlite_orig db $sampleDir/sqlcipher-1.1.8-testkey.db
execsql {
PRAGMA key = 'testkey';
PRAGMA cipher_compatibility = 1;
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 75709}
db close
# open a 2.0 database using cipher_compatibility
do_test compat-open-2.0-database {
sqlite_orig db $sampleDir/sqlcipher-2.0-le-testkey.db
execsql {
PRAGMA key = 'testkey';
PRAGMA cipher_compatibility = 2;
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
db close
# open a 3.0 database using cipher_compatibility
do_test compat-open-3.0-database {
sqlite_orig db $sampleDir/sqlcipher-3.0-testkey.db
execsql {
PRAGMA key = 'testkey';
PRAGMA cipher_compatibility = 3;
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
db close
# open a 4.0 database using cipher_compatibility
do_test compat-open-4.0-database {
sqlite_orig db $sampleDir/sqlcipher-4.0-testkey.db
execsql {
PRAGMA key = 'testkey';
PRAGMA cipher_compatibility = 4;
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
db close
# open a 1.1.8 database using cipher_default_compatibility
do_test default-compat-open-1.1.8-database {
sqlite_orig db $sampleDir/sqlcipher-1.1.8-testkey.db
execsql {
PRAGMA cipher_default_compatibility = 1;
PRAGMA key = 'testkey';
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 75709}
db close
# open a 2.0 database using cipher_default_compatibility
do_test default-compat-open-2.0-database {
sqlite_orig db $sampleDir/sqlcipher-2.0-le-testkey.db
execsql {
PRAGMA cipher_default_compatibility = 2;
PRAGMA key = 'testkey';
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
# open a 3.0 database using cipher_default_compatibility
do_test default-compat-open-3.0-database {
sqlite_orig db $sampleDir/sqlcipher-3.0-testkey.db
execsql {
PRAGMA cipher_default_compatibility = 3;
PRAGMA key = 'testkey';
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
# re-open a 4.0 database using cipher_default_compatibility
do_test default-compat-open-4.0-database {
sqlite_orig db $sampleDir/sqlcipher-4.0-testkey.db
execsql {
PRAGMA cipher_default_compatibility = 4;
PRAGMA key = 'testkey';
PRAGMA integrity_check;
SELECT count(*) FROM t1;
}
} {ok 78536}
sqlite3_test_control_pending_byte $old_pending_byte
finish_test