Skip to content
This repository has been archived by the owner on Nov 16, 2021. It is now read-only.

Commit

Permalink
Update to SQLCipher 3.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
3noch committed Dec 6, 2013
1 parent e554324 commit 60257e9
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 55 deletions.
15 changes: 7 additions & 8 deletions README.md
Expand Up @@ -9,13 +9,12 @@ security enhancements provided by SQLCipher are copied directly from its
source code. This is trivial since SQLCipher's modifications to SQLite's source
are denoted by code enclosed in

/* BEGIN CRYPTO */
/* BEGIN SQLCIPHER */
...
/* END CRYPTO */
/* END SQLCIPHER */

sqlcipher-windows adds a few minor code modifications to allow SQLCipher's
code to build with the SQLite amalgamation source distribution and to quell
some warnings.
*sqlcipher-windows* adds a few minor code modifications to allow SQLCipher's
code to build with the SQLite amalgamation source distribution.

This project was mostly informed by the generous video by Mike Stephenson which
can be found
Expand Down Expand Up @@ -49,9 +48,9 @@ folder structured like this:
[openssl headers]

Place the path to your `openssl` folder in a Windows environment variable
called `OpenSslDir`. For example, if `C:\Libraries\openssl-1.0.1c` is the path
called `OpenSslDir`. For example, if `C:\Libraries\openssl-1.0.1e` is the path
to your OpenSSL library folder, then `OpenSslDir` must be
`C:\Libraries\openssl-1.0.1c`.
`C:\Libraries\openssl-1.0.1e`.

[OpenSSL]: http://www.openssl.org/
[Building OpenSSL for Visual Studio]: http://developer.covenanteyes.com/building-openssl-for-visual-studio/
Expand All @@ -63,7 +62,7 @@ Versions
`sqlcipher-windows` is a combination of

* [SQLite 3.8.0.2 (amalgamation)](http://sourceforge.net/projects/sqlite.mirror/files/SQLite%203.8.0.2/)
* [SQLCipher 3.0.0](https://github.com/sqlcipher/sqlcipher/zipball/v3.0.0)
* [SQLCipher 3.0.1](https://github.com/sqlcipher/sqlcipher/zipball/v3.0.0)

and has been successfully built with the following versions of OpenSSL:

Expand Down
1 change: 1 addition & 0 deletions Shell/Shell.vcxproj
Expand Up @@ -111,6 +111,7 @@
</AdditionalIncludeDirectories>
<ExceptionHandling>false</ExceptionHandling>
<MinimalRebuild>false</MinimalRebuild>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand Down
2 changes: 2 additions & 0 deletions StaticLib/StaticLib.vcxproj
Expand Up @@ -20,6 +20,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="inc\sqlite3.h" />
<ClInclude Include="inc_priv\crypto.h" />
<ClInclude Include="inc_priv\sqlcipher.h" />
<ClInclude Include="inc_priv\sqlite3ext.h" />
</ItemGroup>
Expand Down Expand Up @@ -109,6 +110,7 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
<MinimalRebuild>false</MinimalRebuild>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
3 changes: 3 additions & 0 deletions StaticLib/StaticLib.vcxproj.filters
Expand Up @@ -19,6 +19,9 @@
<ClInclude Include="inc_priv\sqlcipher.h">
<Filter>Internal</Filter>
</ClInclude>
<ClInclude Include="inc_priv\crypto.h">
<Filter>Internal</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\sqlite3.c">
Expand Down
3 changes: 2 additions & 1 deletion StaticLib/src/crypto.h → StaticLib/inc_priv/crypto.h
Expand Up @@ -44,7 +44,7 @@
#define FILE_HEADER_SZ 16

#ifndef CIPHER_VERSION
#define CIPHER_VERSION "3.0.0"
#define CIPHER_VERSION "3.0.1"
#endif

#ifndef CIPHER
Expand Down Expand Up @@ -213,6 +213,7 @@ int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx)

const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
int sqlcipher_codec_add_random(codec_ctx *ctx, const char *data, int random_sz);
#endif
#endif
/* END SQLCIPHER */
9 changes: 8 additions & 1 deletion StaticLib/src/crypto.c
Expand Up @@ -92,7 +92,14 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef
}

CODEC_TRACE(("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx));


if( sqlite3StrICmp(zLeft, "cipher_add_random")==0 && zRight ){
if(ctx) {
char *add_random_status = sqlite3_mprintf("%d", sqlcipher_codec_add_random(ctx, zRight, sqlite3Strlen30(zRight)));
codec_vdbe_return_static_string(pParse, "cipher_add_random", add_random_status);
sqlite3_free(add_random_status);
}
} else
if( sqlite3StrICmp(zLeft, "cipher_migrate")==0 && !zRight ){
if(ctx){
char *migrate_status = sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx));
Expand Down
5 changes: 5 additions & 0 deletions StaticLib/src/crypto_cc.c
Expand Up @@ -36,6 +36,10 @@
#include <CommonCrypto/CommonCrypto.h>
#include <Security/SecRandom.h>

static int sqlcipher_cc_add_random(void *ctx, void *buffer, int length) {
return SQLITE_OK;
}

/* generate a defined number of random bytes */
static int sqlcipher_cc_random (void *ctx, void *buffer, int length) {
return (SecRandomCopyBytes(kSecRandomDefault, length, (uint8_t *)buffer) == 0) ? SQLITE_OK : SQLITE_ERROR;
Expand Down Expand Up @@ -132,6 +136,7 @@ int sqlcipher_cc_setup(sqlcipher_provider *p) {
p->ctx_cmp = sqlcipher_cc_ctx_cmp;
p->ctx_init = sqlcipher_cc_ctx_init;
p->ctx_free = sqlcipher_cc_ctx_free;
p->add_random = sqlcipher_cc_add_random;
return SQLITE_OK;
}

Expand Down
39 changes: 33 additions & 6 deletions StaticLib/src/crypto_impl.c
Expand Up @@ -87,6 +87,7 @@ struct codec_ctx {
cipher_ctx *read_ctx;
cipher_ctx *write_ctx;
unsigned int skip_read_hmac;
unsigned int need_kdf_salt;
};

int sqlcipher_register_provider(sqlcipher_provider *p) {
Expand Down Expand Up @@ -654,8 +655,7 @@ int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, sqlite3_f
if((rc = sqlcipher_cipher_ctx_init(&ctx->write_ctx)) != SQLITE_OK) return rc;

if(fd == NULL || sqlite3OsRead(fd, ctx->kdf_salt, FILE_HEADER_SZ, 0) != SQLITE_OK) {
/* if unable to read the bytes, generate random salt */
if(ctx->read_ctx->provider->random(ctx->read_ctx->provider_ctx, ctx->kdf_salt, FILE_HEADER_SZ) != SQLITE_OK) return SQLITE_ERROR;
ctx->need_kdf_salt = 1;
}

if((rc = sqlcipher_codec_ctx_set_cipher(ctx, CIPHER, 0)) != SQLITE_OK) return rc;
Expand Down Expand Up @@ -827,8 +827,13 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->kdf_iter,
ctx->hmac_kdf_salt, c_ctx->fast_kdf_iter, c_ctx->key_sz));


if(c_ctx->pass && c_ctx->pass_sz) { // if pass is not null

if(ctx->need_kdf_salt) {
if(ctx->read_ctx->provider->random(ctx->read_ctx->provider_ctx, ctx->kdf_salt, FILE_HEADER_SZ) != SQLITE_OK) return SQLITE_ERROR;
ctx->need_kdf_salt = 0;
}
if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0) {
int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
Expand Down Expand Up @@ -994,14 +999,14 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
char *attach_command = sqlite3_mprintf("ATTACH DATABASE '%s-migrated' as migrate KEY '%q';",
db_filename, key);

int rc = sqlcipher_check_connection(db_filename, key, key_sz, "", &user_version);
int rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, "", &user_version);
if(rc == SQLITE_OK){
CODEC_TRACE(("No upgrade required - exiting\n"));
goto exit;
}

// Version 2 - check for 4k with hmac format
rc = sqlcipher_check_connection(db_filename, key, key_sz, pragma_4k_kdf_iter, &user_version);
rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_4k_kdf_iter, &user_version);
if(rc == SQLITE_OK) {
CODEC_TRACE(("Version 2 format found\n"));
upgrade_4k_format = 1;
Expand All @@ -1010,7 +1015,7 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
// Version 1 - check both no hmac and 4k together
pragma_1x_and_4k = sqlite3_mprintf("%s%s", pragma_hmac_off,
pragma_4k_kdf_iter);
rc = sqlcipher_check_connection(db_filename, key, key_sz, pragma_1x_and_4k, &user_version);
rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_1x_and_4k, &user_version);
sqlite3_free(pragma_1x_and_4k);
if(rc == SQLITE_OK) {
CODEC_TRACE(("Version 1 format found\n"));
Expand Down Expand Up @@ -1123,6 +1128,28 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
return rc;
}

int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz){
const char *suffix = &zRight[random_sz-1];
int n = random_sz - 3; /* adjust for leading x' and tailing ' */
if (n > 0 &&
sqlite3StrNICmp((const char *)zRight ,"x'", 2) == 0 &&
sqlite3StrNICmp(suffix, "'", 1) == 0 &&
n % 2 == 0) {
int rc = 0;
int buffer_sz = n / 2;
unsigned char *random;
const unsigned char *z = (const unsigned char *)zRight + 2; /* adjust lead offset of x' */
CODEC_TRACE(("sqlcipher_codec_add_random: using raw random blob from hex\n"));
random = sqlcipher_malloc(buffer_sz);
memset(random, 0, buffer_sz);
cipher_hex2bin(z, n, random);
rc = ctx->read_ctx->provider->add_random(ctx->read_ctx->provider_ctx, random, buffer_sz);
sqlcipher_free(random, buffer_sz);
return rc;
}
return SQLITE_ERROR;
}


#endif
/* END SQLCIPHER */
111 changes: 72 additions & 39 deletions StaticLib/src/crypto_libtomcrypt.c
Expand Up @@ -35,50 +35,88 @@
#include "sqlcipher.h"
#include <tomcrypt.h>

typedef struct {
prng_state prng;
} ltc_ctx;

#define FORTUNA_MAX_SZ 32
static prng_state prng;
static unsigned int ltc_init = 0;
static unsigned int ltc_ref_count = 0;
static sqlite3_mutex* ltc_rand_mutex = NULL;

static int sqlcipher_ltc_add_random(void *ctx, void *buffer, int length) {
ltc_ctx *ltc = (ltc_ctx*)ctx;
int rc = fortuna_add_entropy(buffer, length, &(ltc->prng));
return rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
int rc = 0;
int data_to_read = length;
int block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
const unsigned char * data = (const unsigned char *)buffer;
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_enter(ltc_rand_mutex);
#endif
while(data_to_read > 0){
rc = fortuna_add_entropy(data, block_sz, &prng);
rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
if(rc != SQLITE_OK){
break;
}
data_to_read -= block_sz;
data += block_sz;
block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
}
fortuna_ready(&prng);
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_leave(ltc_rand_mutex);
#endif
return rc;
}

static int sqlcipher_ltc_activate(void *ctx) {
ltc_ctx *ltc = (ltc_ctx*)ctx;
int random_buffer_sz = sizeof(char) * 32;
unsigned char *random_buffer = sqlcipher_malloc(random_buffer_sz);
sqlcipher_memset(random_buffer, 0, random_buffer_sz);

unsigned char random_buffer[FORTUNA_MAX_SZ];
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
if(ltc_rand_mutex == NULL){
ltc_rand_mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
}
sqlite3_mutex_enter(ltc_rand_mutex);
#endif
sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
if(ltc_init == 0) {
if(register_prng(&fortuna_desc) != CRYPT_OK) return SQLITE_ERROR;
if(register_cipher(&rijndael_desc) != CRYPT_OK) return SQLITE_ERROR;
if(register_hash(&sha1_desc) != CRYPT_OK) return SQLITE_ERROR;
if(fortuna_start(&prng) != CRYPT_OK) {
return SQLITE_ERROR;
}
ltc_init = 1;
}
if(fortuna_start(&(ltc->prng)) != CRYPT_OK) {
return SQLITE_ERROR;
}
sqlite3_randomness(random_buffer_sz, random_buffer);
if(sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz) != SQLITE_OK) {
return SQLITE_ERROR;
}
if(sqlcipher_ltc_add_random(ctx, &ltc, sizeof(ltc_ctx*)) != SQLITE_OK) {
return SQLITE_ERROR;
}
if(fortuna_ready(&(ltc->prng)) != CRYPT_OK) {
ltc_ref_count++;
#ifndef SQLCIPHER_TEST
sqlite3_randomness(FORTUNA_MAX_SZ, random_buffer);
#endif
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_leave(ltc_rand_mutex);
#endif
if(sqlcipher_ltc_add_random(ctx, random_buffer, FORTUNA_MAX_SZ) != SQLITE_OK) {
return SQLITE_ERROR;
}
sqlcipher_free(random_buffer, random_buffer_sz);
sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
return SQLITE_OK;
}

static int sqlcipher_ltc_deactivate(void *ctx) {
ltc_ctx *ltc = (ltc_ctx*)ctx;
fortuna_done(&(ltc->prng));
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_enter(ltc_rand_mutex);
#endif
ltc_ref_count--;
if(ltc_ref_count == 0){
fortuna_done(&prng);
sqlcipher_memset((void *)&prng, 0, sizeof(prng));
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_leave(ltc_rand_mutex);
sqlite3_mutex_free(ltc_rand_mutex);
ltc_rand_mutex = NULL;
#endif
}
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
else {
sqlite3_mutex_leave(ltc_rand_mutex);
}
#endif
return SQLITE_OK;
}

Expand All @@ -87,13 +125,13 @@ static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
}

static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) {
ltc_ctx *ltc = (ltc_ctx*)ctx;
int rc;
if((rc = fortuna_ready(&(ltc->prng))) != CRYPT_OK) {
return SQLITE_ERROR;
}
fortuna_read(buffer, length, &(ltc->prng));
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_enter(ltc_rand_mutex);
#endif
fortuna_read(buffer, length, &prng);
#ifndef SQLCIPHER_LTC_NO_MUTEX_RAND
sqlite3_mutex_leave(ltc_rand_mutex);
#endif
return SQLITE_OK;
}

Expand All @@ -112,7 +150,6 @@ static int sqlcipher_ltc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, un

static int sqlcipher_ltc_kdf(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
int rc, hash_idx;
ltc_ctx *ltc = (ltc_ctx*)ctx;
unsigned long outlen = key_sz;
unsigned long random_buffer_sz = sizeof(char) * 256;
unsigned char *random_buffer = sqlcipher_malloc(random_buffer_sz);
Expand Down Expand Up @@ -173,7 +210,6 @@ static int sqlcipher_ltc_get_hmac_sz(void *ctx) {
}

static int sqlcipher_ltc_ctx_copy(void *target_ctx, void *source_ctx) {
memcpy(target_ctx, source_ctx, sizeof(ltc_ctx));
return SQLITE_OK;
}

Expand All @@ -182,15 +218,12 @@ static int sqlcipher_ltc_ctx_cmp(void *c1, void *c2) {
}

static int sqlcipher_ltc_ctx_init(void **ctx) {
*ctx = sqlcipher_malloc(sizeof(ltc_ctx));
if(*ctx == NULL) return SQLITE_NOMEM;
sqlcipher_ltc_activate(*ctx);
sqlcipher_ltc_activate(NULL);
return SQLITE_OK;
}

static int sqlcipher_ltc_ctx_free(void **ctx) {
sqlcipher_ltc_deactivate(&ctx);
sqlcipher_free(*ctx, sizeof(ltc_ctx));
return SQLITE_OK;
}

Expand Down

0 comments on commit 60257e9

Please sign in to comment.