diff --git a/editor.c b/editor.c index b1fb022..f3b7048 100644 --- a/editor.c +++ b/editor.c @@ -28,6 +28,7 @@ #include #include "editor.h" #include "util.h" +#include "keydb.h" #define MAX_COMMAND_ALIAS_COUNT 2 @@ -40,6 +41,7 @@ enum cmd_returncode_t { struct editor_context_t { bool running; + struct keydb_t *keydb; }; struct editor_command_t { @@ -158,7 +160,11 @@ static enum cmd_returncode_t cmd_help(struct editor_context_t *ctx, const char * } static enum cmd_returncode_t cmd_new(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { - return COMMAND_SUCCESS; + if (ctx->keydb) { + keydb_free(ctx->keydb); + } + ctx->keydb = keydb_new(); + return (ctx->keydb != NULL) ? COMMAND_SUCCESS : COMMAND_FAILURE; } static enum cmd_returncode_t cmd_list(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { @@ -166,7 +172,17 @@ static enum cmd_returncode_t cmd_list(struct editor_context_t *ctx, const char * } static enum cmd_returncode_t cmd_add_host(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { - return COMMAND_SUCCESS; + if (!ctx->keydb) { + ctx->keydb = keydb_new(); + if (!ctx->keydb) { + return COMMAND_FAILURE; + } + } + struct keydb_t *new_keydb = keydb_add_host(ctx->keydb, params[0]); + if (new_keydb) { + ctx->keydb = new_keydb; + } + return new_keydb ? COMMAND_SUCCESS : COMMAND_FAILURE; } static enum cmd_returncode_t cmd_add_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { @@ -182,11 +198,20 @@ static enum cmd_returncode_t cmd_showkey_volume(struct editor_context_t *ctx, co } static enum cmd_returncode_t cmd_open(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { - return COMMAND_SUCCESS; + if (ctx->keydb) { + keydb_free(ctx->keydb); + } + ctx->keydb = keydb_read(params[0]); + return (ctx->keydb != NULL) ? COMMAND_SUCCESS : COMMAND_FAILURE; } static enum cmd_returncode_t cmd_save(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { - return COMMAND_SUCCESS; + if (!ctx->keydb) { + fprintf(stderr, "No key database loaded.\n"); + return COMMAND_FAILURE; + } + bool success = keydb_write(ctx->keydb, params[0], "foobar"); + return success ? COMMAND_SUCCESS : COMMAND_FAILURE; } static const struct editor_command_t *find_command(const char *command_name) { @@ -275,6 +300,10 @@ void editor_start(void) { } } } + + if (editor_context.keydb) { + keydb_free(editor_context.keydb); + } } #ifndef __TEST_EDITOR__ diff --git a/file_encryption.c b/file_encryption.c index 1dd677b..b0df6cd 100644 --- a/file_encryption.c +++ b/file_encryption.c @@ -423,6 +423,7 @@ bool write_encrypted_file(const char *filename, const void *plaintext, unsigned if (RAND_bytes(encrypted_file->iv, ENCRYPTED_FILE_IV_SIZE) != 1) { log_openssl(LLVL_FATAL, "Failed to get entropy from RAND_bytes for IV"); OPENSSL_cleanse(&key, sizeof(key)); + free(encrypted_file); return false; } @@ -430,6 +431,7 @@ bool write_encrypted_file(const char *filename, const void *plaintext, unsigned if (!encrypt_aes256_gcm(plaintext, plaintext_length, key.key, encrypted_file->iv, encrypted_file->ciphertext, encrypted_file->auth_tag)) { log_libc(LLVL_FATAL, "encryption failed"); OPENSSL_cleanse(&key, sizeof(key)); + free(encrypted_file); return false; } @@ -451,5 +453,6 @@ bool write_encrypted_file(const char *filename, const void *plaintext, unsigned return false; } + free(encrypted_file); return success; } diff --git a/keydb.c b/keydb.c index 2a7d6e8..7abd022 100644 --- a/keydb.c +++ b/keydb.c @@ -25,18 +25,25 @@ #include #include #include +#include #include "keydb.h" #include "util.h" +#include "log.h" -unsigned int keydb_getsize(const struct keydb_t *keydb) { - return sizeof(struct keydb_t) + (keydb->host_count * sizeof(struct host_entry_t)); +static unsigned int keydb_getsize_hostcount(unsigned int host_count) { + return sizeof(struct keydb_t) + (host_count * sizeof(struct host_entry_t)); } -void keydb_init(struct keydb_t *keydb) { - memset(keydb, 0, sizeof(struct keydb_t)); +static unsigned int keydb_getsize(const struct keydb_t *keydb) { + return keydb_getsize_hostcount(keydb->host_count); +} + +struct keydb_t* keydb_new(void) { + struct keydb_t *keydb = calloc(sizeof(struct keydb_t), 1); keydb->keydb_version = KEYDB_VERSION; keydb->server_database = true; + return keydb; } void keydb_free(struct keydb_t *keydb) { @@ -44,10 +51,48 @@ void keydb_free(struct keydb_t *keydb) { free(keydb); } -void keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase, enum kdf_t kdf) { +struct keydb_t* keydb_add_host(struct keydb_t *keydb, const char *hostname) { + struct keydb_t *new_keydb = realloc(keydb, keydb_getsize_hostcount(keydb->host_count + 1)); + if (!new_keydb) { + return NULL; + } + memset(&new_keydb->hosts[new_keydb->host_count], 0, sizeof(struct host_entry_t)); + new_keydb->host_count++; + return new_keydb; +} + +bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase) { + enum kdf_t kdf; + if ((!passphrase) || (strlen(passphrase) == 0)) { + /* For empty password, we can also use garbage KDF */ + kdf = KDF_PBKDF2_SHA256_1000; + } else { + kdf = KDF_SCRYPT_N17_r8_p1; + } + return write_encrypted_file(filename, keydb, keydb_getsize(keydb), passphrase, kdf); } struct keydb_t* keydb_read(const char *filename) { - return NULL; + struct decrypted_file_t decrypted_file = read_encrypted_file(filename); + if (!decrypted_file.success) { + return NULL; + } + + struct keydb_t *keydb = (struct keydb_t*)decrypted_file.data; + if (keydb->keydb_version != KEYDB_VERSION) { + log_msg(LLVL_ERROR, "keydb in %s could be read, but is of version %u (we expected %u).\n", keydb->keydb_version, KEYDB_VERSION); + OPENSSL_cleanse(decrypted_file.data, decrypted_file.data_length); + free(decrypted_file.data); + return NULL; + } + + if (decrypted_file.data_length != keydb_getsize(keydb)) { + log_msg(LLVL_ERROR, "keydb in %s could be read, but was %u bytes long (we expected %u).\n", decrypted_file.data_length, keydb_getsize(keydb)); + OPENSSL_cleanse(decrypted_file.data, decrypted_file.data_length); + free(decrypted_file.data); + return NULL; + } + + return keydb; } diff --git a/keydb.h b/keydb.h index 3a3a5e1..3d9ab0d 100644 --- a/keydb.h +++ b/keydb.h @@ -55,10 +55,10 @@ struct keydb_t { }; /*************** AUTO GENERATED SECTION FOLLOWS ***************/ -unsigned int keydb_getsize(const struct keydb_t *keydb); -void keydb_init(struct keydb_t *keydb); +struct keydb_t* keydb_new(void); void keydb_free(struct keydb_t *keydb); -void keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase, enum kdf_t kdf); +struct keydb_t* keydb_add_host(struct keydb_t *keydb, const char *hostname); +bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase); struct keydb_t* keydb_read(const char *filename); /*************** AUTO GENERATED SECTION ENDS ***************/