From 9dc8164dcc702a4e4fac8410302b69b4051410ce Mon Sep 17 00:00:00 2001 From: Johannes Bauer Date: Fri, 25 Oct 2019 18:17:43 +0200 Subject: [PATCH] Vaulted key database fully used Now all keys are encrypted when they're not in use to thwart cold-boot attacks. Furthermore, all unlocking messages are sent in bulk to avoid fragmentation and improve performance. --- client.c | 5 ++++- server.c | 26 +++++++++++++++++--------- vaulted_keydb.c | 15 +++++---------- vaulted_keydb.h | 2 +- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/client.c b/client.c index 91577f9..1c10d6c 100644 --- a/client.c +++ b/client.c @@ -84,11 +84,14 @@ static bool attempt_unlock_luks_volume(struct keyclient_t *keyclient, const stru return false; } - /* Volume! */ + /* This is a valid volume which we need to unlock */ int volume_index = keydb_get_volume_index(host, volume); if (volume_index != -1) { if (keyclient->opts->no_luks) { keyclient->volume_unlocked[volume_index] = true; +#ifdef DEBUG + dump_hexline(stderr, "Raw key: ", unlock_msg->luks_passphrase_raw, LUKS_PASSPHRASE_RAW_SIZE_BYTES, false); +#endif } else { if (!keyclient->volume_unlocked[volume_index]) { bool success = unlock_luks_volume(volume, unlock_msg); diff --git a/server.c b/server.c index 737a0ef..66ba886 100644 --- a/server.c +++ b/server.c @@ -142,6 +142,11 @@ static int psk_server_callback(SSL *ssl, const unsigned char *identity, size_t i return result; } +static void copy_luks_passphrase_callback(void *vctx, unsigned int volume_index, const void *source) { + struct msg_t *msgs = (struct msg_t*)vctx; + memcpy(msgs[volume_index].luks_passphrase_raw, source, LUKS_PASSPHRASE_RAW_SIZE_BYTES); +} + static void client_handler_thread(void *vctx) { struct client_thread_ctx_t *client = (struct client_thread_ctx_t*)vctx; @@ -156,19 +161,21 @@ static void client_handler_thread(void *vctx) { } else { if (client->host) { log_msg(LLVL_DEBUG, "Client \"%s\" connected, sending unlock data for %d volumes.", client->host->host_name, client->host->volume_count); + /* Initially prepare all messages we're about to send to the + * client by filling the UUID fields */ + struct msg_t msgs[client->host->volume_count]; for (unsigned int i = 0; i < client->host->volume_count; i++) { const struct volume_entry_t *volume = &client->host->volumes[i]; + memcpy(msgs[i].volume_uuid, volume->volume_uuid, 16); + } - struct msg_t msg = { 0 }; - memcpy(msg.volume_uuid, volume->volume_uuid, 16); - memcpy(msg.luks_passphrase_raw, volume->luks_passphrase_raw, LUKS_PASSPHRASE_RAW_SIZE_BYTES); + /* Then also fill the keys */ + vaulted_keydb_get_volume_luks_passphases_raw(client->vaulted_keydb, copy_luks_passphrase_callback, msgs, client->host); - int txlen = SSL_write(ssl, &msg, sizeof(msg)); - OPENSSL_cleanse(&msg, sizeof(msg)); - if (txlen != sizeof(msg)) { - log_msg(LLVL_WARNING, "Tried to send message of %d bytes, but sent %d. Severing connection to client.", sizeof(msg), txlen); - break; - } + int txlen = SSL_write(ssl, &msgs, sizeof(msgs)); + OPENSSL_cleanse(&msgs, sizeof(msgs)); + if (txlen != (long)sizeof(msgs)) { + log_msg(LLVL_WARNING, "Tried to send message of %d bytes, but sent %d. Severing connection to client.", sizeof(msgs), txlen); } } else { log_msg(LLVL_FATAL, "Client connected, but no host set."); @@ -316,6 +323,7 @@ bool keyserver_start(const struct pgmopts_server_t *opts) { close(keyserver.tcp_sd); } free_generic_tls_context(&keyserver.gctx); + vaulted_keydb_free(keyserver.vaulted_keydb); keydb_free(keyserver.keydb); return success; } diff --git a/vaulted_keydb.c b/vaulted_keydb.c index 6f0955c..4e157c2 100644 --- a/vaulted_keydb.c +++ b/vaulted_keydb.c @@ -83,19 +83,13 @@ bool vaulted_keydb_get_tls_psk(struct vaulted_keydb_t *vaulted_keydb, uint8_t de return true; } -bool vaulted_keydb_get_volume_luks_passphase_raw(struct vaulted_keydb_t *vaulted_keydb, uint8_t dest[LUKS_PASSPHRASE_RAW_SIZE_BYTES], const struct host_entry_t *host, const struct volume_entry_t *volume) { +bool vaulted_keydb_get_volume_luks_passphases_raw(struct vaulted_keydb_t *vaulted_keydb, void (*copy_callback)(void *vctx, unsigned int volume_index, const void *source), void *copy_ctx, const struct host_entry_t *host) { int host_index = keydb_get_host_index(vaulted_keydb->keydb, host); if (host_index < 0) { log_msg(LLVL_FATAL, "Unable to retrieve host index for vaulted key db entry."); return false; } - int volume_index = keydb_get_volume_index(host, volume); - if (volume_index < 0) { - log_msg(LLVL_FATAL, "Unable to retrieve volume index for vaulted key db entry."); - return false; - } - /* Get a pointer into the vaulted structure */ struct luks_passphrase_vault_entry_t *entry = vaulted_keydb_get_luks_passphrase_for_hostindex(vaulted_keydb, host_index); @@ -105,12 +99,13 @@ bool vaulted_keydb_get_volume_luks_passphase_raw(struct vaulted_keydb_t *vaulted return false; } - /* Copy out the data we need */ - memcpy(dest, &entry->volumes[volume_index].luks_passphrase_raw, LUKS_PASSPHRASE_RAW_SIZE_BYTES); + /* Copy out the data we need by calling back for all volumes */ + for (unsigned int i = 0; i < host->volume_count; i++) { + copy_callback(copy_ctx, i, &entry->volumes[i].luks_passphrase_raw); + } /* And close it back up */ if (!vault_close(vaulted_keydb->luks_passphrase_vault)) { - OPENSSL_cleanse(dest, PSK_SIZE_BYTES); log_msg(LLVL_FATAL, "Unable to close LUKS passphrase vault of vaulted key db entry."); return false; } diff --git a/vaulted_keydb.h b/vaulted_keydb.h index 99c7228..932146f 100644 --- a/vaulted_keydb.h +++ b/vaulted_keydb.h @@ -45,7 +45,7 @@ struct vaulted_keydb_t { /*************** AUTO GENERATED SECTION FOLLOWS ***************/ bool vaulted_keydb_get_tls_psk(struct vaulted_keydb_t *vaulted_keydb, uint8_t dest[PSK_SIZE_BYTES], const struct host_entry_t *host); -bool vaulted_keydb_get_volume_luks_passphase_raw(struct vaulted_keydb_t *vaulted_keydb, uint8_t dest[LUKS_PASSPHRASE_RAW_SIZE_BYTES], const struct host_entry_t *host, const struct volume_entry_t *volume); +bool vaulted_keydb_get_volume_luks_passphases_raw(struct vaulted_keydb_t *vaulted_keydb, void (*copy_callback)(void *ctx, unsigned int volume_index, const void *source), void *copy_ctx, const struct host_entry_t *host); struct vaulted_keydb_t *vaulted_keydb_new(struct keydb_t *keydb); void vaulted_keydb_free(struct vaulted_keydb_t *vaulted_keydb); /*************** AUTO GENERATED SECTION ENDS ***************/