summaryrefslogtreecommitdiff
path: root/src/crypto_libtomcrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto_libtomcrypt.c')
-rw-r--r--src/crypto_libtomcrypt.c121
1 files changed, 80 insertions, 41 deletions
diff --git a/src/crypto_libtomcrypt.c b/src/crypto_libtomcrypt.c
index 0299771..22f4efc 100644
--- a/src/crypto_libtomcrypt.c
+++ b/src/crypto_libtomcrypt.c
@@ -35,48 +35,89 @@
#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 = 32;
- unsigned char random_buffer[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_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;
}
static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
@@ -84,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;
}
@@ -107,12 +148,12 @@ static int sqlcipher_ltc_hmac(void *ctx, unsigned char *hmac_key, int key_sz, un
return SQLITE_OK;
}
-static int sqlcipher_ltc_kdf(void *ctx, const char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
+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;
unsigned long outlen = key_sz;
- unsigned long random_buffer_sz = 256;
- char random_buffer[random_buffer_sz];
- ltc_ctx *ltc = (ltc_ctx*)ctx;
+ unsigned long random_buffer_sz = sizeof(char) * 256;
+ unsigned char *random_buffer = sqlcipher_malloc(random_buffer_sz);
+ sqlcipher_memset(random_buffer, 0, random_buffer_sz);
hash_idx = find_hash("sha1");
if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
@@ -124,6 +165,7 @@ static int sqlcipher_ltc_kdf(void *ctx, const char *pass, int pass_sz, unsigned
return SQLITE_ERROR;
}
sqlcipher_ltc_add_random(ctx, random_buffer, random_buffer_sz);
+ sqlcipher_free(random_buffer, random_buffer_sz);
return SQLITE_OK;
}
@@ -132,7 +174,7 @@ static const char* sqlcipher_ltc_get_cipher(void *ctx) {
}
static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
- int rc, cipher_idx, hash_idx;
+ int rc, cipher_idx;
symmetric_CBC cbc;
if((cipher_idx = find_cipher(sqlcipher_ltc_get_cipher(ctx))) == -1) return SQLITE_ERROR;
@@ -168,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;
}
@@ -177,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;
}
@@ -208,6 +246,7 @@ int sqlcipher_ltc_setup(sqlcipher_provider *p) {
p->ctx_init = sqlcipher_ltc_ctx_init;
p->ctx_free = sqlcipher_ltc_ctx_free;
p->add_random = sqlcipher_ltc_add_random;
+ return SQLITE_OK;
}
#endif