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.
This commit is contained in:
Johannes Bauer 2019-10-25 18:17:43 +02:00
parent f01ec97d6b
commit 9dc8164dcc
4 changed files with 27 additions and 21 deletions

View File

@ -84,11 +84,14 @@ static bool attempt_unlock_luks_volume(struct keyclient_t *keyclient, const stru
return false; return false;
} }
/* Volume! */ /* This is a valid volume which we need to unlock */
int volume_index = keydb_get_volume_index(host, volume); int volume_index = keydb_get_volume_index(host, volume);
if (volume_index != -1) { if (volume_index != -1) {
if (keyclient->opts->no_luks) { if (keyclient->opts->no_luks) {
keyclient->volume_unlocked[volume_index] = true; 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 { } else {
if (!keyclient->volume_unlocked[volume_index]) { if (!keyclient->volume_unlocked[volume_index]) {
bool success = unlock_luks_volume(volume, unlock_msg); bool success = unlock_luks_volume(volume, unlock_msg);

View File

@ -142,6 +142,11 @@ static int psk_server_callback(SSL *ssl, const unsigned char *identity, size_t i
return result; 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) { static void client_handler_thread(void *vctx) {
struct client_thread_ctx_t *client = (struct client_thread_ctx_t*)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 { } else {
if (client->host) { if (client->host) {
log_msg(LLVL_DEBUG, "Client \"%s\" connected, sending unlock data for %d volumes.", client->host->host_name, client->host->volume_count); 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++) { for (unsigned int i = 0; i < client->host->volume_count; i++) {
const struct volume_entry_t *volume = &client->host->volumes[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 }; /* Then also fill the keys */
memcpy(msg.volume_uuid, volume->volume_uuid, 16); vaulted_keydb_get_volume_luks_passphases_raw(client->vaulted_keydb, copy_luks_passphrase_callback, msgs, client->host);
memcpy(msg.luks_passphrase_raw, volume->luks_passphrase_raw, LUKS_PASSPHRASE_RAW_SIZE_BYTES);
int txlen = SSL_write(ssl, &msg, sizeof(msg)); int txlen = SSL_write(ssl, &msgs, sizeof(msgs));
OPENSSL_cleanse(&msg, sizeof(msg)); OPENSSL_cleanse(&msgs, sizeof(msgs));
if (txlen != sizeof(msg)) { if (txlen != (long)sizeof(msgs)) {
log_msg(LLVL_WARNING, "Tried to send message of %d bytes, but sent %d. Severing connection to client.", sizeof(msg), txlen); log_msg(LLVL_WARNING, "Tried to send message of %d bytes, but sent %d. Severing connection to client.", sizeof(msgs), txlen);
break;
}
} }
} else { } else {
log_msg(LLVL_FATAL, "Client connected, but no host set."); 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); close(keyserver.tcp_sd);
} }
free_generic_tls_context(&keyserver.gctx); free_generic_tls_context(&keyserver.gctx);
vaulted_keydb_free(keyserver.vaulted_keydb);
keydb_free(keyserver.keydb); keydb_free(keyserver.keydb);
return success; return success;
} }

View File

@ -83,19 +83,13 @@ bool vaulted_keydb_get_tls_psk(struct vaulted_keydb_t *vaulted_keydb, uint8_t de
return true; 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); int host_index = keydb_get_host_index(vaulted_keydb->keydb, host);
if (host_index < 0) { if (host_index < 0) {
log_msg(LLVL_FATAL, "Unable to retrieve host index for vaulted key db entry."); log_msg(LLVL_FATAL, "Unable to retrieve host index for vaulted key db entry.");
return false; 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 */ /* 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); 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; return false;
} }
/* Copy out the data we need */ /* Copy out the data we need by calling back for all volumes */
memcpy(dest, &entry->volumes[volume_index].luks_passphrase_raw, LUKS_PASSPHRASE_RAW_SIZE_BYTES); 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 */ /* And close it back up */
if (!vault_close(vaulted_keydb->luks_passphrase_vault)) { 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."); log_msg(LLVL_FATAL, "Unable to close LUKS passphrase vault of vaulted key db entry.");
return false; return false;
} }

View File

@ -45,7 +45,7 @@ struct vaulted_keydb_t {
/*************** AUTO GENERATED SECTION FOLLOWS ***************/ /*************** 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_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); struct vaulted_keydb_t *vaulted_keydb_new(struct keydb_t *keydb);
void vaulted_keydb_free(struct vaulted_keydb_t *vaulted_keydb); void vaulted_keydb_free(struct vaulted_keydb_t *vaulted_keydb);
/*************** AUTO GENERATED SECTION ENDS ***************/ /*************** AUTO GENERATED SECTION ENDS ***************/