Make vault threadsafe
We might have multiple processes accessing the vault and need to always keep a proper reference count.
This commit is contained in:
parent
54063ec025
commit
0bf0759c9c
49
vault.c
49
vault.c
@ -28,8 +28,10 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <pthread.h>
|
||||
#include "vault.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
static bool vault_derive_key(const struct vault_t *vault, uint8_t key[static 32]) {
|
||||
/* Derive the AES key from it */
|
||||
@ -73,6 +75,11 @@ struct vault_t* vault_init(unsigned int data_length, double target_derivation_ti
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&vault->mutex, NULL)) {
|
||||
log_libc(LLVL_FATAL, "Unable to initialize vault mutex.");
|
||||
free(vault);
|
||||
return NULL;
|
||||
}
|
||||
vault->key = malloc(DEFAULT_KEY_LENGTH_BYTES);
|
||||
vault->key_length = DEFAULT_KEY_LENGTH_BYTES;
|
||||
if (!vault->key) {
|
||||
@ -85,7 +92,7 @@ struct vault_t* vault_init(unsigned int data_length, double target_derivation_ti
|
||||
vault_free(vault);
|
||||
return NULL;
|
||||
}
|
||||
vault->is_open = true;
|
||||
vault->reference_count = 1;
|
||||
vault->data_length = data_length;
|
||||
vault_calibrate_derivation_time(vault, target_derivation_time);
|
||||
|
||||
@ -101,11 +108,7 @@ static void vault_destroy_content(struct vault_t *vault) {
|
||||
}
|
||||
}
|
||||
|
||||
bool vault_open(struct vault_t *vault) {
|
||||
if (vault->is_open) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vault_decrypt(struct vault_t *vault) {
|
||||
uint8_t dkey[32];
|
||||
if (!vault_derive_key(vault, dkey)) {
|
||||
return false;
|
||||
@ -152,7 +155,6 @@ bool vault_open(struct vault_t *vault) {
|
||||
} while (false);
|
||||
|
||||
if (success) {
|
||||
vault->is_open = true;
|
||||
OPENSSL_cleanse(vault->key, vault->key_length);
|
||||
OPENSSL_cleanse(vault->auth_tag, 16);
|
||||
} else {
|
||||
@ -165,11 +167,19 @@ bool vault_open(struct vault_t *vault) {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool vault_close(struct vault_t *vault) {
|
||||
if (!vault->is_open) {
|
||||
return true;
|
||||
bool vault_open(struct vault_t *vault) {
|
||||
bool success = true;
|
||||
pthread_mutex_lock(&vault->mutex);
|
||||
vault->reference_count++;
|
||||
if (vault->reference_count == 1) {
|
||||
/* Vault was closed, we need to decrypt it. */
|
||||
success = vault_decrypt(vault);
|
||||
}
|
||||
pthread_mutex_unlock(&vault->mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool vault_encrypt(struct vault_t *vault) {
|
||||
/* Generate a new key source */
|
||||
if (RAND_bytes(vault->key, vault->key_length) != 1) {
|
||||
return false;
|
||||
@ -223,9 +233,7 @@ bool vault_close(struct vault_t *vault) {
|
||||
}
|
||||
} while (false);
|
||||
|
||||
if (success) {
|
||||
vault->is_open = false;
|
||||
} else {
|
||||
if (!success) {
|
||||
/* Vault may be in an inconsistent state. Destroy contents. */
|
||||
vault_destroy_content(vault);
|
||||
}
|
||||
@ -235,6 +243,19 @@ bool vault_close(struct vault_t *vault) {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool vault_close(struct vault_t *vault) {
|
||||
bool success = true;
|
||||
pthread_mutex_lock(&vault->mutex);
|
||||
vault->reference_count--;
|
||||
if (vault->reference_count == 0) {
|
||||
/* Vault is now closed, we need to encrypt it. */
|
||||
success = vault_encrypt(vault);
|
||||
}
|
||||
pthread_mutex_unlock(&vault->mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void vault_free(struct vault_t *vault) {
|
||||
vault_destroy_content(vault);
|
||||
free(vault->data);
|
||||
@ -252,7 +273,7 @@ static void dump(const uint8_t *data, unsigned int length) {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
/* gcc -Wall -std=c11 -Wmissing-prototypes -Wstrict-prototypes -Werror=implicit-function-declaration -Wimplicit-fallthrough -Wshadow -pie -fPIE -fsanitize=address -fsanitize=undefined -fsanitize=leak -o vault vault.c -lasan -lubsan -lcrypto
|
||||
/* gcc -D__TEST_VAULT__ -Wall -std=c11 -Wmissing-prototypes -Wstrict-prototypes -Werror=implicit-function-declaration -Wimplicit-fallthrough -Wshadow -pie -fPIE -fsanitize=address -fsanitize=undefined -fsanitize=leak -pthread -o vault vault.c util.c log.c -lcrypto
|
||||
*/
|
||||
struct vault_t *vault = vault_init(64, 0.1);
|
||||
dump(vault->data, vault->data_length);
|
||||
|
Loading…
Reference in New Issue
Block a user