diff --git a/src/crypto.c b/src/crypto.c index 9d18311b..7df296d4 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -91,6 +91,11 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c 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( sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){ + if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider", + sqlcipher_codec_get_cipher_provider(ctx)); + } + } else if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){ codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version()); }else diff --git a/src/crypto.h b/src/crypto.h index 0be700ad..70c09b0b 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -195,6 +195,7 @@ int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag); int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag); 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); #endif #endif /* END CRYPTO */ diff --git a/src/crypto_impl.c b/src/crypto_impl.c index bf5ba55e..56b256d3 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -795,5 +795,8 @@ int sqlcipher_codec_key_copy(codec_ctx *ctx, int source) { } } +const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) { + return ctx->read_ctx->provider->get_provider_name(ctx->read_ctx); +} #endif diff --git a/src/crypto_libtomcrypt.c b/src/crypto_libtomcrypt.c index 605cdfd8..7d34a4fe 100644 --- a/src/crypto_libtomcrypt.c +++ b/src/crypto_libtomcrypt.c @@ -3,36 +3,46 @@ #include "sqlcipher.h" #include +typedef struct { + prng_state prng; +} ltc_ctx; + static unsigned int ltc_init = 0; static int sqlcipher_ltc_activate(void *ctx) { + ltc_ctx *ltc = (ltc_ctx*)ctx; sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); if(ltc_init == 0) { - register_prng(&fortuna_desc); - register_cipher(&rijndael_desc); - register_hash(&sha256_desc); - register_hash(&sha1_desc); + 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(&(ltc->prng)) != CRYPT_OK) return SQLITE_ERROR; ltc_init = 1; } sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + return SQLITE_OK; } static int sqlcipher_ltc_deactivate(void *ctx) { + ltc_ctx *ltc = (ltc_ctx*)ctx; + fortuna_done(&(ltc->prng)); +} + +static const char* sqlcipher_ltc_get_provider_name(void *ctx) { + return "libtomcrypt"; } static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) { - prng_state prng; int random_value; int random_buffer_sz = 256; char random_buffer[random_buffer_sz]; - if(fortuna_start(&prng) != CRYPT_OK) return SQLITE_ERROR; + ltc_ctx *ltc = (ltc_ctx*)ctx; sqlite3_randomness(sizeof(random_value), &random_value); sqlite3_snprintf(random_buffer_sz, random_buffer, "%d", random_value); - if(fortuna_add_entropy(random_buffer, random_buffer_sz, &prng) != CRYPT_OK) return SQLITE_ERROR; - if(fortuna_ready(&prng) != CRYPT_OK) return SQLITE_ERROR; - fortuna_read(buffer, length, &prng); - fortuna_done(&prng); + if(fortuna_add_entropy(random_buffer, random_buffer_sz, &(ltc->prng)) != CRYPT_OK) return SQLITE_ERROR; + if(fortuna_ready(&(ltc->prng)) != CRYPT_OK) return SQLITE_ERROR; + fortuna_read(buffer, length, &(ltc->prng)); return SQLITE_OK; } @@ -68,7 +78,6 @@ static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key symmetric_CBC cbc; if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR; - if((hash_idx = find_hash("sha256")) == -1) return SQLITE_ERROR; if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR; rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc); if(rc != CRYPT_OK) return SQLITE_ERROR; @@ -109,18 +118,22 @@ static int sqlcipher_ltc_ctx_cmp(void *c1, void *c2) { } static int sqlcipher_ltc_ctx_init(void **ctx) { - sqlcipher_ltc_activate(&ctx); + *ctx = sqlcipher_malloc(sizeof(ltc_ctx)); + if(*ctx == NULL) return SQLITE_NOMEM; + sqlcipher_ltc_activate(*ctx); return SQLITE_OK; } static int sqlcipher_ltc_ctx_free(void **ctx) { sqlcipher_ltc_deactivate(&ctx); + sqlcipher_free(*ctx, sizeof(ltc_ctx)); return SQLITE_OK; } int sqlcipher_ltc_setup(sqlcipher_provider *p) { p->activate = sqlcipher_ltc_activate; - p->deactivate = sqlcipher_ltc_deactivate; + p->deactivate = sqlcipher_ltc_deactivate; + p->get_provider_name = sqlcipher_ltc_get_provider_name; p->random = sqlcipher_ltc_random; p->hmac = sqlcipher_ltc_hmac; p->kdf = sqlcipher_ltc_kdf; diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 872705b1..7406c859 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -60,6 +60,10 @@ static int sqlcipher_openssl_deactivate(void *ctx) { sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } +static const char* sqlcipher_openssl_get_provider_name(void *ctx) { + return "openssl"; +} + /* generate a defined number of pseudorandom bytes */ static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) { return RAND_bytes((unsigned char *)buffer, length); @@ -148,7 +152,8 @@ static int sqlcipher_openssl_ctx_free(void **ctx) { int sqlcipher_openssl_setup(sqlcipher_provider *p) { p->activate = sqlcipher_openssl_activate; - p->deactivate = sqlcipher_openssl_deactivate; + p->deactivate = sqlcipher_openssl_deactivate; + p->get_provider_name = sqlcipher_openssl_get_provider_name; p->random = sqlcipher_openssl_random; p->hmac = sqlcipher_openssl_hmac; p->kdf = sqlcipher_openssl_kdf; diff --git a/src/sqlcipher.h b/src/sqlcipher.h index 773fae7c..0012885b 100644 --- a/src/sqlcipher.h +++ b/src/sqlcipher.h @@ -39,6 +39,7 @@ typedef struct { int (*activate)(void *ctx); int (*deactivate)(void *ctx); + const char* (*get_provider_name)(void *ctx); int (*random)(void *ctx, void *buffer, int length); int (*hmac)(void *ctx, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out); int (*kdf)(void *ctx, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key);