Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/sqlcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -1484,7 +1484,7 @@ static void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
ctx->error = error;
}

static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx) {
static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx, int read_header) {
sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(ctx->pBt));

if(SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT)) {
Expand All @@ -1493,7 +1493,7 @@ static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx) {

/* read salt from header, if present, otherwise generate a new random salt */
sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_init_kdf_salt: obtaining salt");
if(fd == NULL || fd->pMethods == 0 || sqlite3OsRead(fd, ctx->kdf_salt, ctx->kdf_salt_sz, 0) != SQLITE_OK) {
if(!read_header || fd == NULL || fd->pMethods == 0 || sqlite3OsRead(fd, ctx->kdf_salt, ctx->kdf_salt_sz, 0) != SQLITE_OK) {
sqlcipher_log(SQLCIPHER_LOG_DEBUG, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_init_kdf_salt: unable to read salt from file header, generating random");
if(ctx->provider->random(ctx->provider_ctx, ctx->kdf_salt, ctx->kdf_salt_sz) != SQLITE_OK) {
sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_init_kdf_salt: error retrieving random bytes from provider");
Expand All @@ -1519,7 +1519,7 @@ static int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt,
static int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void** salt) {
int rc = SQLITE_OK;
if(!SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT)) {
if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) {
if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx, 1)) != SQLITE_OK) {
sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlcipher_codec_ctx_get_kdf_salt: error %d from sqlcipher_codec_ctx_init_kdf_salt", rc);
}
}
Expand Down Expand Up @@ -1867,7 +1867,7 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {

/* if necessary, initialize the salt from the header or random source */
if(!SQLCIPHER_FLAG_GET(ctx->flags, CIPHER_FLAG_HAS_KDF_SALT)) {
if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) {
if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx, 1)) != SQLITE_OK) {
sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "%s: error %d from sqlcipher_codec_ctx_init_kdf_salt", __func__, rc);
goto error;
}
Expand Down Expand Up @@ -3523,6 +3523,12 @@ static void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
goto cleanup;
}

/* encrypting before the salt is known means no page was read, so the file has no header yet */
if((mode == CODEC_WRITE_OP || mode == CODEC_JOURNAL_OP) && (rc = sqlcipher_codec_ctx_init_kdf_salt(ctx, 0)) != SQLITE_OK) {
sqlcipher_codec_ctx_set_error(ctx, rc);
goto cleanup;
}

/* call to derive keys if not present yet */
if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
sqlcipher_log(SQLCIPHER_LOG_ERROR, SQLCIPHER_LOG_CORE, "sqlite3Codec: error occurred during key derivation: %d", rc);
Expand Down
14 changes: 14 additions & 0 deletions test/sqlcipher-core.test
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ do_test test-sqlcipher-header-overwrite {
} {0}
file delete -force test.db

# verify that a new database gets a random salt when the VFS preallocates on SQLITE_FCNTL_SIZE_HINT
do_test test-sqlcipher-salt-chunk-size {
sqlite_orig db test.db
execsql { PRAGMA key = 'test'; }
file_control_chunksize_test db main 65536
execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES (1, 2); }
db close
set rc [string equal [hexio_read test.db 0 16] [string repeat 0 32]]
sqlite_orig db test.db
lappend rc [execsql { PRAGMA key = 'test'; SELECT * FROM t1; }]
} {0 {ok 1 2}}
db close
file delete -force test.db

# open the database and try to read from it without
# providing a passphrase. verify that the
# an error is returned from the library
Expand Down