From a45a181ceee684dcf4da3a81ee76a8df57254191 Mon Sep 17 00:00:00 2001 From: Stephen Lombardo Date: Wed, 30 Jul 2008 13:15:55 -0400 Subject: [PATCH] switch digest to sha256 (requires sha256 support in openssl); allow setting a passphrase instead of raw blob key; update readme --- Makefile.in | 16 +++++- README | 17 ++++++ sqlite3.def | 150 --------------------------------------------------- src/crypto.c | 54 +++++++++++++------ src/crypto.h | 15 +++++- src/pager.c | 16 ++++++ 6 files changed, 101 insertions(+), 167 deletions(-) delete mode 100644 sqlite3.def diff --git a/Makefile.in b/Makefile.in index 740377c..f1b19ec 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,6 +17,7 @@ # TOP = @srcdir@ + # C Compiler and options for use in building executables that # will run on the platform that is doing the build. # @@ -122,6 +123,13 @@ USE_GCOV = @USE_GCOV@ LTCOMPILE_EXTRAS += $(GCOV_CFLAGS$(USE_GCOV)) LTLINK_EXTRAS += $(GCOV_LDFLAGS$(USE_GCOV)) +# BEGIN CRYPTO +CRYPTOLIBOBJ = \ + crypto.lo + +CRYPTOSRC = \ + $(TOP)/src/crypto.c +# END CRYPTO # The directory into which to store package information for @@ -160,7 +168,7 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \ select.lo status.lo table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \ - where.lo utf.lo legacy.lo vtab.lo + where.lo utf.lo legacy.lo vtab.lo $(CRYPTOLIBOBJ) # Object files for the amalgamation. # @@ -175,6 +183,7 @@ LIBOBJ = $(OBJS$(USE_AMALGAMATION)) # All of the source code files. # SRC = \ + $(CRYPTOSRC) \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ @@ -464,6 +473,11 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c sqlite3.lo: sqlite3.c $(LTCOMPILE) -c sqlite3.c +# BEGIN CRYPTO +crypto.lo: $(TOP)/src/crypto.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/crypto.c +# END CRYPTO + # Rules to build individual files # alter.lo: $(TOP)/src/alter.c $(HDR) diff --git a/README b/README index 5942a8f..01f2629 100644 --- a/README +++ b/README @@ -1,3 +1,20 @@ +== SQLite Cipher Introduction == + +SQLite Cipher is an SQLite extension that provides transparent 256 bit AES encryption of database files. +Pages are encrypted before being written to disk and are decrypted when read back. + +Encryption is provided by the OpenSSL crypto library. + +Static linking (replace /opt/local/lib with the path to libcrypto.a) +./configure --disable-amalgamation CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="/opt/local/lib/libcrypto.a" +make + +Dynamic linking +./configure --disable-amalgamation CFLAGS="-DSQLITE_HAS_CODEC -lcrypto" +make + +== End Introduction == + This directory contains source code to SQLite: An Embeddable SQL Database Engine diff --git a/sqlite3.def b/sqlite3.def deleted file mode 100644 index 8a826ca..0000000 --- a/sqlite3.def +++ /dev/null @@ -1,150 +0,0 @@ -EXPORTS -sqlite3_aggregate_context -sqlite3_aggregate_count -sqlite3_auto_extension -sqlite3_bind_blob -sqlite3_bind_double -sqlite3_bind_int -sqlite3_bind_int64 -sqlite3_bind_null -sqlite3_bind_parameter_count -sqlite3_bind_parameter_index -sqlite3_bind_parameter_name -sqlite3_bind_text -sqlite3_bind_text16 -sqlite3_bind_value -sqlite3_bind_zeroblob -sqlite3_blob_bytes -sqlite3_blob_close -sqlite3_blob_open -sqlite3_blob_read -sqlite3_blob_write -sqlite3_busy_handler -sqlite3_busy_timeout -sqlite3_changes -sqlite3_clear_bindings -sqlite3_close -sqlite3_collation_needed -sqlite3_collation_needed16 -sqlite3_column_blob -sqlite3_column_bytes -sqlite3_column_bytes16 -sqlite3_column_count -sqlite3_column_decltype -sqlite3_column_decltype16 -sqlite3_column_double -sqlite3_column_int -sqlite3_column_int64 -sqlite3_column_name -sqlite3_column_name16 -sqlite3_column_text -sqlite3_column_text16 -sqlite3_column_type -sqlite3_column_value -sqlite3_commit_hook -sqlite3_complete -sqlite3_complete16 -sqlite3_create_collation -sqlite3_create_collation16 -sqlite3_create_collation_v2 -sqlite3_create_function -sqlite3_create_function16 -sqlite3_create_module -sqlite3_create_module_v2 -sqlite3_data_count -sqlite3_db_handle -sqlite3_declare_vtab -sqlite3_enable_load_extension -sqlite3_enable_shared_cache -sqlite3_errcode -sqlite3_errmsg -sqlite3_errmsg16 -sqlite3_exec -sqlite3_expired -sqlite3_extended_result_codes -sqlite3_file_control -sqlite3_finalize -sqlite3_free -sqlite3_free_table -sqlite3_get_autocommit -sqlite3_get_auxdata -sqlite3_get_table -sqlite3_global_recover -sqlite3_interrupt -sqlite3_last_insert_rowid -sqlite3_libversion -sqlite3_libversion_number -sqlite3_load_extension -sqlite3_malloc -sqlite3_memory_alarm -sqlite3_memory_highwater -sqlite3_memory_used -sqlite3_mprintf -sqlite3_mutex_alloc -sqlite3_mutex_enter -sqlite3_mutex_free -sqlite3_mutex_leave -sqlite3_mutex_try -sqlite3_open -sqlite3_open16 -sqlite3_open_v2 -sqlite3_overload_function -sqlite3_prepare -sqlite3_prepare16 -sqlite3_prepare16_v2 -sqlite3_prepare_v2 -sqlite3_profile -sqlite3_progress_handler -sqlite3_randomness -sqlite3_realloc -sqlite3_release_memory -sqlite3_reset -sqlite3_reset_auto_extension -sqlite3_result_blob -sqlite3_result_double -sqlite3_result_error -sqlite3_result_error16 -sqlite3_result_error_code -sqlite3_result_error_nomem -sqlite3_result_error_toobig -sqlite3_result_int -sqlite3_result_int64 -sqlite3_result_null -sqlite3_result_text -sqlite3_result_text16 -sqlite3_result_text16be -sqlite3_result_text16le -sqlite3_result_value -sqlite3_result_zeroblob -sqlite3_rollback_hook -sqlite3_set_authorizer -sqlite3_set_auxdata -sqlite3_sleep -sqlite3_snprintf -sqlite3_soft_heap_limit -sqlite3_sql -sqlite3_step -sqlite3_test_control -sqlite3_thread_cleanup -sqlite3_threadsafe -sqlite3_total_changes -sqlite3_trace -sqlite3_transfer_bindings -sqlite3_update_hook -sqlite3_user_data -sqlite3_value_blob -sqlite3_value_bytes -sqlite3_value_bytes16 -sqlite3_value_double -sqlite3_value_int -sqlite3_value_int64 -sqlite3_value_numeric_type -sqlite3_value_text -sqlite3_value_text16 -sqlite3_value_text16be -sqlite3_value_text16le -sqlite3_value_type -sqlite3_vfs_find -sqlite3_vfs_register -sqlite3_vfs_unregister -sqlite3_vmprintf diff --git a/src/crypto.c b/src/crypto.c index 1316d1f..448835d 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1,10 +1,11 @@ /* BEGIN CRYPTO */ #if defined(SQLITE_HAS_CODEC) -#include "sqliteInt.h" -#include "btreeInt.h" +#include #include #include +#include "sqliteInt.h" +#include "btreeInt.h" #include "crypto.h" typedef struct { @@ -16,7 +17,7 @@ typedef struct { void *buffer; } codec_ctx; -static int codec_hash(codec_ctx *ctx, void *out, int *outLen, void *in, int inLen) { +static int codec_page_hash(Pgno pgno, void *in, int inLen, void *out, int *outLen) { EVP_MD_CTX mdctx; unsigned int md_sz; unsigned char md_value[EVP_MAX_MD_SIZE]; @@ -24,10 +25,9 @@ static int codec_hash(codec_ctx *ctx, void *out, int *outLen, void *in, int inLe EVP_MD_CTX_init(&mdctx); EVP_DigestInit_ex(&mdctx, DIGEST, NULL); - if(ctx->rand) - EVP_DigestUpdate(&mdctx, ctx->rand, 16); + EVP_DigestUpdate(&mdctx, in, inLen); /* add random "salt" data to hash*/ + EVP_DigestUpdate(&mdctx, &pgno, sizeof(pgno)); - EVP_DigestUpdate(&mdctx, in, inLen); EVP_DigestFinal_ex(&mdctx, md_value, &md_sz); memcpy(out, md_value, md_sz); @@ -37,6 +37,21 @@ static int codec_hash(codec_ctx *ctx, void *out, int *outLen, void *in, int inLe *outLen = md_sz; } +static int codec_passphrase_hash(void *in, int inLen, void *out, int *outLen) { + EVP_MD_CTX mdctx; + unsigned int md_sz; + unsigned char md_value[EVP_MAX_MD_SIZE]; + + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, DIGEST, NULL); + EVP_DigestUpdate(&mdctx, in, inLen); + EVP_DigestFinal_ex(&mdctx, md_value, &md_sz); + memcpy(out, md_value, md_sz); + EVP_MD_CTX_cleanup(&mdctx); + memset(md_value, 0, md_sz); + *outLen = md_sz; +} + /* * ctx - codec context * pgno - page number in database @@ -45,12 +60,16 @@ static int codec_hash(codec_ctx *ctx, void *out, int *outLen, void *in, int inLe * in - pointer to input bytes * out - pouter to output bytes */ -static int codec_cipher(codec_ctx *ctx, int pgno, int mode, int size, void *in, void *out) { +static int codec_cipher(codec_ctx *ctx, Pgno pgno, int mode, int size, void *in, void *out) { EVP_CIPHER_CTX ectx; unsigned char iv[EVP_MAX_MD_SIZE]; int iv_sz, tmp_csz, csz; - codec_hash(ctx, iv, &iv_sz, &pgno, sizeof(pgno)); + /* the initilization vector is created from the hash of the + 16 byte database random salt and the page number. This will + ensure that each page in the database has a unique initialization + vector */ + codec_page_hash(pgno, ctx->rand, 16, iv, &iv_sz); EVP_CipherInit(&ectx, CIPHER, NULL, NULL, mode); EVP_CIPHER_CTX_set_padding(&ectx, 0); @@ -64,11 +83,6 @@ static int codec_cipher(codec_ctx *ctx, int pgno, int mode, int size, void *in, assert(size == csz); } - -void sqlite3_activate_see(const char* in) { - /* do nothing, security enhancements are always active */ -} - /* * sqlite3Codec can be called in multiple modes. * encrypt mode - expected to return a pointer to the @@ -152,12 +166,22 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { operations to avoid overhead of multiple memory allocations*/ ctx->buffer = sqlite3_malloc(sqlite3BtreeGetPageSize(ctx->pBt)); - /* if key string starts with x' then this is a blob literal key*/ + ctx->key_sz = EVP_CIPHER_key_length(CIPHER); + + /* if key string starts with x' then assume this is a blob literal key*/ if(sqlite3StrNICmp(zKey,"x'", 2) == 0) { int n = nKey - 3; /* adjust for leading x' and tailing ' */ const char *z = zKey + 2; /* adjust lead offset of x' */ - ctx->key_sz = EVP_CIPHER_key_length(CIPHER); + + assert((n/2) == ctx->key_sz); /* keylength after hex decode should equal cipher key length */ ctx->key = sqlite3HexToBlob(db, z, n); + + /* otherwise the key is provided as a string so hash it to get key data */ + } else { + int key_sz; + ctx->key = sqlite3_malloc(ctx->key_sz); + codec_passphrase_hash(zKey, nKey, ctx->key, &key_sz); + assert(key_sz == ctx->key_sz); } sqlite3pager_set_codec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, (void *) ctx); diff --git a/src/crypto.h b/src/crypto.h index 486afc7..f5159fc 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -1,15 +1,28 @@ /* +** SQLite Security Enh ** crypto.h developed by Stephen Lombardo (Zetetic LLC) ** sjlombardo at zetetic dot net ** http://zetetic.net +** +** July 30, 2008 ** + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +** */ /* BEGIN CRYPTO */ #ifndef CRYPTO_H #define CRYPTO_H #define CIPHER EVP_aes_256_cfb() -#define DIGEST EVP_sha1() +#define DIGEST EVP_sha256() /* HDR_SIZE allocates 16 bytes for random salt and 8 bytes for page size */ #define HDR_SZ 24 diff --git a/src/pager.c b/src/pager.c index 1722043..05350af 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5353,3 +5353,19 @@ i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ } #endif /* SQLITE_OMIT_DISKIO */ + +/* BEGIN CRYPTO */ +#if defined(SQLITE_HAS_CODEC) + +int sqlite3pager_get_codec(Pager *pPager, void **ctx) { + *ctx = pPager->pCodecArg; +} + +void sqlite3pager_set_codec(Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), void *pCodecArg){ + pPager->xCodec = xCodec; + pPager->pCodecArg = pCodecArg; +} + +#endif +/* END CRYPTO */ +