From e705e0a24ea26c6e8f92583d1d885c186f1cfded Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Mon, 15 Nov 2021 17:12:44 -0500 Subject: [PATCH] add facility for testing random codec failures --- src/crypto.c | 19 +++++++++++++++++-- src/crypto.h | 3 +++ src/crypto_impl.c | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index a0bc3d2a..fef032b4 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -145,6 +145,15 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef char *flags = sqlite3_mprintf("%i", sqlcipher_get_test_flags()); codec_vdbe_return_string(pParse, "cipher_test", flags, P4_DYNAMIC); }else + if( sqlite3StrICmp(zLeft,"cipher_test_rand")==0 ){ + if( zRight ) { + int rand = atoi(zRight); + sqlcipher_set_test_rand(rand); + } else { + char *rand = sqlite3_mprintf("%d", sqlcipher_get_test_rand()); + codec_vdbe_return_string(pParse, "cipher_test_rand", rand, P4_DYNAMIC); + } + } else #endif if( sqlite3StrICmp(zLeft, "cipher_fips_status")== 0 && !zRight ){ if(ctx) { @@ -734,7 +743,10 @@ static void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset); #ifdef SQLCIPHER_TEST - if((sqlcipher_get_test_flags() & TEST_FAIL_ENCRYPT) > 0) rc = SQLITE_ERROR; + if((sqlcipher_get_test_flags() & TEST_FAIL_ENCRYPT) > 0 && sqlcipher_get_test_fail()) { + rc = SQLITE_ERROR; + fprintf(stderr, "simulating encryption failure\n"); + } #endif if(rc != SQLITE_OK) { /* clear results of failed cipher operation */ /* this will be considered a temporary error condition. the pager is still usable */ @@ -759,7 +771,10 @@ static void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { } rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset); #ifdef SQLCIPHER_TEST - if((sqlcipher_get_test_flags() & TEST_FAIL_DECRYPT) > 0) rc = SQLITE_ERROR; + if((sqlcipher_get_test_flags() & TEST_FAIL_DECRYPT) > 0 && sqlcipher_get_test_fail()) { + fprintf(stderr, "simulating decryption failure\n"); + rc = SQLITE_ERROR; + } #endif if(rc != SQLITE_OK) { /* clear results of failed cipher operation and set error */ /* failure to encrypt a page is considered a permanent error and will render the pager unusable diff --git a/src/crypto.h b/src/crypto.h index 3aaf2387..e4626a41 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -198,6 +198,9 @@ static int cipher_isHex(const unsigned char *hex, int sz){ #define TEST_FAIL_MIGRATE 0x04 unsigned int sqlcipher_get_test_flags(void); void sqlcipher_set_test_flags(unsigned int); +int sqlcipher_get_test_rand(void); +void sqlcipher_set_test_rand(int); +int sqlcipher_get_test_fail(void); #endif /* extensions defined in crypto_impl.c */ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index ee7e0f5d..57b2b846 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -52,6 +52,23 @@ unsigned int sqlcipher_get_test_flags() { void sqlcipher_set_test_flags(unsigned int flags) { cipher_test_flags = flags; } + +static volatile int cipher_test_rand = 0; +int sqlcipher_get_test_rand() { + return cipher_test_rand; +} +void sqlcipher_set_test_rand(int rand) { + cipher_test_rand = rand; +} +int sqlcipher_get_test_fail() { + int x; + + /* if cipher_test_rand is not set to a non-zero value always fail (return true) */ + if (cipher_test_rand == 0) return 1; + + sqlite3_randomness(sizeof(x), &x); + return ((x % cipher_test_rand) == 0); +} #endif /* Generate code to return a string value */ -- 2.11.4.GIT