From 1b5ba8e022836fa8ab93bc90df1b34a29ea6e134 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 17 Jan 2013 14:18:26 -0500 Subject: Imported Upstream version 2.1.1 --- src/crypto.c | 227 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 144 insertions(+), 83 deletions(-) (limited to 'src/crypto.c') diff --git a/src/crypto.c b/src/crypto.c index 3423b0a..50213b5 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -38,6 +38,10 @@ #include "btreeInt.h" #include "crypto.h" +const char* codec_get_cipher_version() { + return CIPHER_VERSION; +} + /* Generate code to return a string value */ void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const char *value){ Vdbe *v = sqlite3GetVdbe(pParse); @@ -47,30 +51,6 @@ void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const ch sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } -int codec_set_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) { - struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_kdf_iter: entered db=%p nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx)); - - if(pDb->pBt) { - codec_ctx *ctx; - sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - if(ctx) return sqlcipher_codec_ctx_set_kdf_iter(ctx, kdf_iter, for_ctx); - } - return SQLITE_ERROR; -} - -int codec_set_fast_kdf_iter(sqlite3* db, int nDb, int kdf_iter, int for_ctx) { - struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_kdf_iter: entered db=%p nDb=%d kdf_iter=%d for_ctx=%d\n", db, nDb, kdf_iter, for_ctx)); - - if(pDb->pBt) { - codec_ctx *ctx; - sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - if(ctx) return sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, kdf_iter, for_ctx); - } - return SQLITE_ERROR; -} - static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ctx) { int rc, page_sz, reserve_sz; @@ -89,76 +69,154 @@ static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ct return rc; } -void codec_set_default_use_hmac(int use) { - sqlcipher_set_default_use_hmac(use); -} - -int codec_set_use_hmac(sqlite3* db, int nDb, int use) { +int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) { struct Db *pDb = &db->aDb[nDb]; - - CODEC_TRACE(("codec_set_use_hmac: entered db=%p nDb=%d use=%d\n", db, nDb, use)); - + CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx)); if(pDb->pBt) { - int rc; codec_ctx *ctx; sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - if(ctx) { - rc = sqlcipher_codec_ctx_set_use_hmac(ctx, use); - if(rc != SQLITE_OK) return rc; - /* since the use of hmac has changed, the page size may also change */ - return codec_set_btree_to_codec_pagesize(db, pDb, ctx); - } + if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx); } return SQLITE_ERROR; -} +} -int codec_set_page_size(sqlite3* db, int nDb, int size) { - struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_page_size: entered db=%p nDb=%d size=%d\n", db, nDb, size)); +int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) { + struct Db *pDb = &db->aDb[iDb]; + codec_ctx *ctx = NULL; + int rc; if(pDb->pBt) { - int rc; - codec_ctx *ctx; sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - - if(ctx) { - rc = sqlcipher_codec_ctx_set_pagesize(ctx, size); - if(rc != SQLITE_OK) return rc; - return codec_set_btree_to_codec_pagesize(db, pDb, ctx); - } } - return SQLITE_ERROR; -} -/** - * - * when for_ctx == 0 then it will change for read - * when for_ctx == 1 then it will change for write - * when for_ctx == 2 then it will change for both - */ -int codec_set_cipher_name(sqlite3* db, int nDb, const char *cipher_name, int for_ctx) { - struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_cipher_name: entered db=%p nDb=%d cipher_name=%s for_ctx=%d\n", db, nDb, cipher_name, for_ctx)); + CODEC_TRACE(("codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx)); - if(pDb->pBt) { - codec_ctx *ctx; - sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - if(ctx) return sqlcipher_codec_ctx_set_cipher(ctx, cipher_name, for_ctx); + 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 ){ + if(ctx) { + if( zRight ) { + sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both + }else { + codec_vdbe_return_static_string(pParse, "cipher", + sqlcipher_codec_ctx_get_cipher(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 ){ + if(ctx) { + if( zRight ) { + sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration + } else { + char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx, 2)); + codec_vdbe_return_static_string(pParse, "kdf_iter", kdf_iter); + sqlite3_free(kdf_iter); + } + } + }else + if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0){ + if(ctx) { + if( zRight ) { + sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration + } else { + char *fast_kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx, 2)); + codec_vdbe_return_static_string(pParse, "fast_kdf_iter", fast_kdf_iter); + sqlite3_free(fast_kdf_iter); + } + } + }else + if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){ + if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 1); // write iterations only + }else + if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){ + if(ctx) { + 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 { + char * page_size = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx)); + codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size); + sqlite3_free(page_size); + } + } + }else + if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){ + if( zRight ) { + sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1)); + } else { + char *default_use_hmac = sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac()); + codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac); + sqlite3_free(default_use_hmac); + } + }else + if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){ + if(ctx) { + if( zRight ) { + 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 { + char *hmac_flag = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx, 2)); + codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag); + sqlite3_free(hmac_flag); + } + } + }else + if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){ + if(ctx) { + if(zRight) { + // clear both pgno endian flags + if(sqlite3StrICmp(zRight, "le") == 0) { + sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO); + sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO); + } else if(sqlite3StrICmp(zRight, "be") == 0) { + sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO); + sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO); + } else if(sqlite3StrICmp(zRight, "native") == 0) { + sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO); + sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO); + } + } else { + if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_LE_PGNO, 2)) { + codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "le"); + } else if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_BE_PGNO, 2)) { + codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "be"); + } else { + codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "native"); + } + } + } + }else + if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){ + if(ctx) { + if(zRight) { + if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) { + unsigned char mask = 0; + const char *hex = zRight+2; + cipher_hex2bin(hex,2,&mask); + sqlcipher_set_hmac_salt_mask(mask); + } + } else { + char *hmac_salt_mask = sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask()); + codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask); + sqlite3_free(hmac_salt_mask); + } + } + }else { + return 0; } - return SQLITE_ERROR; + return 1; } -int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) { - struct Db *pDb = &db->aDb[nDb]; - CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx)); - if(pDb->pBt) { - codec_ctx *ctx; - sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx); - if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx); - } - return SQLITE_ERROR; -} - /* * sqlite3Codec can be called in multiple modes. * encrypt mode - expected to return a pointer to the @@ -216,6 +274,7 @@ void sqlite3FreeCodecArg(void *pCodecArg) { codec_ctx *ctx = (codec_ctx *) pCodecArg; if(pCodecArg == NULL) return; sqlcipher_codec_ctx_free(&ctx); // wipe and free allocated memory for the context + sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */ } int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { @@ -223,7 +282,6 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey)); - sqlcipher_activate(); if(nKey && zKey && pDb->pBt) { int rc; @@ -231,9 +289,15 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { sqlite3_file *fd = sqlite3Pager_get_fd(pPager); codec_ctx *ctx; + sqlcipher_activate(); /* perform internal initialization for sqlcipher */ + /* point the internal codec argument against the contet to be prepared */ rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey); + if(rc != SQLITE_OK) return rc; /* initialization failed, do not attach potentially corrupted context */ + + sqlite3_mutex_enter(db->mutex); + sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx); codec_set_btree_to_codec_pagesize(db, pDb, ctx); @@ -246,7 +310,6 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) { /* if fd is null, then this is an in-memory database and we dont' want to overwrite the AutoVacuum settings if not null, then set to the default */ - sqlite3_mutex_enter(db->mutex); if(fd != NULL) { sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM); } @@ -263,8 +326,7 @@ int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) { CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey)); /* attach key if db and pKey are not null and nKey is > 0 */ if(db && pKey && nKey) { - sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db - return SQLITE_OK; + return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db } return SQLITE_ERROR; } @@ -281,7 +343,6 @@ int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) { */ int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) { CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey)); - sqlcipher_activate(); if(db && pKey && nKey) { struct Db *pDb = &db->aDb[0]; CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb)); -- cgit v1.2.3