diff --git a/src/crypto.c b/src/crypto.c index bb6e72ec..7a25f631 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -94,14 +94,22 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){ codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version()); }else - if( sqlite3StrICmp(zLeft, "cipher")==0 && zRight ){ - if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both + if( sqlite3StrICmp(zLeft, "cipher")==0 ){ + if( zRight ) { + if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both + }else { + if(ctx) sqlcipher_codec_ctx_get_cipher(pParse, ctx, 2); + } }else if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){ if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only }else - if( sqlite3StrICmp(zLeft, "kdf_iter")==0 && zRight ){ - if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration + if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){ + if( zRight ) { + if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration + } else { + if(ctx) sqlcipher_codec_ctx_get_kdf_iter(pParse, ctx, 2); + } }else if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0 && zRight ){ if(ctx) sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration @@ -111,23 +119,36 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c }else if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){ if(ctx) { - int size = atoi(zRight); - rc = sqlcipher_codec_ctx_set_pagesize(ctx, size); - if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); - rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx); - if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + if( zRight ) { + int size = atoi(zRight); + rc = sqlcipher_codec_ctx_set_pagesize(ctx, size); + if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx); + if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + } else { + sqlcipher_codec_ctx_get_cipher_pagesize(pParse, ctx); + } } }else if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){ - sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1)); + if( zRight ) { + sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1)); + } else { + sqlcipher_get_default_use_hmac(pParse); + } }else if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){ - if(ctx) { - rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1)); - if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); - /* since the use of hmac has changed, the page size may also change */ - rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx); - if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + + if( zRight ) { + if(ctx) { + rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1)); + if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + /* since the use of hmac has changed, the page size may also change */ + rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx); + if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc); + } + } else { + if(ctx) sqlcipher_codec_ctx_get_use_hmac(pParse, ctx, 2); } }else if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 47ef0461..664cb629 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -345,6 +345,15 @@ int sqlcipher_codec_ctx_set_cipher(codec_ctx *ctx, const char *cipher_name, int return SQLITE_OK; } +int sqlcipher_codec_ctx_get_cipher(Parse *pParse, codec_ctx *ctx, int for_ctx) { + cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx; + EVP_CIPHER *evp_cipher = c_ctx->evp_cipher; + char* name = EVP_CIPHER_name(evp_cipher); + codec_vdbe_return_static_string(pParse, "cipher", name); + + return SQLITE_OK; +} + int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter, int for_ctx) { cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx; int rc; @@ -359,6 +368,15 @@ int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter, int for_ctx) return SQLITE_OK; } +int sqlcipher_codec_ctx_get_kdf_iter(Parse *pParse, codec_ctx *ctx, int for_ctx) { + cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx; + char *kdf_iter = sqlite3_mprintf("%d", c_ctx->kdf_iter); + codec_vdbe_return_static_string(pParse, "kdf_iter", kdf_iter); + sqlite3_free(kdf_iter); + + return SQLITE_OK; +} + 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; int rc; @@ -379,6 +397,15 @@ void sqlcipher_set_default_use_hmac(int use) { else default_flags &= ~CIPHER_FLAG_HMAC; } +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); + codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac); + sqlite3_free(default_use_hmac); + + return SQLITE_OK; +} + /* 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 */ @@ -405,6 +432,16 @@ int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) { return SQLITE_OK; } +int sqlcipher_codec_ctx_get_use_hmac(Parse *pParse, codec_ctx *ctx, int for_ctx) { + cipher_ctx * c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx; + int hmac_flag_set = c_ctx->flags & CIPHER_FLAG_HMAC > 0; + char *hmac_flag = sqlite3_mprintf("%d", hmac_flag_set); + codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag); + sqlite3_free(hmac_flag); + + return SQLITE_OK; +} + int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag) { ctx->write_ctx->flags |= flag; ctx->read_ctx->flags |= flag; @@ -459,6 +496,15 @@ int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) { return SQLITE_OK; } +int sqlcipher_codec_ctx_get_cipher_pagesize(Parse *pParse, codec_ctx *ctx) { + int page_size_value = ctx->page_sz; + char *page_size = sqlite3_mprintf("%d", page_size_value); + codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size); + sqlite3_free(page_size); + + return SQLITE_OK; +} + int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_file *fd, const void *zKey, int nKey) { int rc; codec_ctx *ctx; diff --git a/test/crypto.test b/test/crypto.test index 97b6be28..3ea63af0 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1606,4 +1606,127 @@ do_test be-to-le-migration { db close file delete -force test.db +# verify the pragma cipher_use_hmac +# is set to true be default +do_test verify-pragma-cipher-use-hmac-default { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher_use_hmac; + } +} {1} +db close +file delete -force test.db + +# verify the pragma cipher_use_hmac +# reports the flag turned off +do_test verify-pragma-cipher-use-hmac-off { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher_use_hmac = off; + PRAGMA cipher_use_hmac; + } +} {0} +db close +file delete -force test.db + +# verify the pragma default_cipher_use_hmac +# is set to true by default +do_test verify-pragma-cipher-default-use-hmac-default { + sqlite_orig db test.db + execsql { + PRAGMA cipher_default_use_hmac; + } +} {1} +db close +file delete -force test.db + +# verify the pragma default_cipher_use_hmac +# reports the flag turned off +do_test verify-pragma-cipher-default-use-hmac-off { + sqlite_orig db test.db + execsql { + PRAGMA cipher_default_use_hmac = off; + PRAGMA cipher_default_use_hmac; + } +} {0} +db close +file delete -force test.db + +# verify the pragma kdf_iter +# reports the default value +do_test verify-pragma-kdf-iter-reports-default { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA kdf_iter; + } +} {4000} +db close +file delete -force test.db + +# verify the pragma kdf_iter +# reports value changed +do_test verify-pragma-kdf-iter-reports-value-changed { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA kdf_iter = 8000; + PRAGMA kdf_iter; + } +} {8000} +db close +file delete -force test.db + +# verify the pragma cipher_page_size +# reports default value +do_test verify-pragma-cipher-page-size-default { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher_page_size; + } +} {1024} +db close +file delete -force test.db + +# verify the pragma cipher_page_size +# reports change in value +do_test verify-pragma-cipher-page-size-changed { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher_page_size = 4096; + PRAGMA cipher_page_size; + } +} {4096} +db close +file delete -force test.db + +# verify the pragma cipher +# reports the default value +do_test verify-pragma-cipher-default { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher; + } +} {AES-256-CBC} +db close +file delete -force test.db + +# verify the pragma cipher +# reports a change in value +do_test verify-pragma-cipher-changed { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher = 'AES-256-ECB'; + PRAGMA cipher; + } +} {AES-256-ECB} +db close +file delete -force test.db + finish_test