Further work in keydb

Work in transcribing the binary LUKS PSK to ASCII. Still buggy, had an
error in thinking (it's not 4 bytes transcribed to 3, but 3 to 4 of
course). Needs fixing.
This commit is contained in:
Johannes Bauer 2019-10-20 21:09:41 +02:00
parent bcd794a6c1
commit 0cb0e5d470
5 changed files with 142 additions and 6 deletions

View File

@ -110,7 +110,7 @@ static const struct editor_command_t commands[] = {
.param_names = "[hostname] [volumename]", .param_names = "[hostname] [volumename]",
.min_params = 2, .min_params = 2,
.max_params = 2, .max_params = 2,
.description = "Re-keys a volume of a given hostname", .description = "Re-keys the LUKS passphrase of a volume of a given hostname",
}, },
{ {
.cmdnames = { "showkey_volume" }, .cmdnames = { "showkey_volume" },
@ -118,7 +118,7 @@ static const struct editor_command_t commands[] = {
.param_names = "[hostname] [volumename]", .param_names = "[hostname] [volumename]",
.min_params = 2, .min_params = 2,
.max_params = 2, .max_params = 2,
.description = "Shows the key of a volume of a hostname", .description = "Shows the LUKS passphrase of a volume of a hostname",
}, },
{ {
.cmdnames = { "open", "load" }, .cmdnames = { "open", "load" },
@ -200,7 +200,27 @@ static enum cmd_returncode_t cmd_add_host(struct editor_context_t *ctx, const ch
} }
static enum cmd_returncode_t cmd_add_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { static enum cmd_returncode_t cmd_add_volume(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;
}
const char *host_name = params[0];
struct host_entry_t *host = keydb_get_host_by_name(ctx->keydb, host_name);
if (!host) {
fprintf(stderr, "No such host: %s\n", host_name);
return COMMAND_FAILURE;
}
const char *volume_name = params[1];
const char *volume_uuid_str = params[2];
if (!is_valid_uuid(volume_uuid_str)) {
fprintf(stderr, "Not a valid UUID: %s\n", volume_uuid_str);
return COMMAND_FAILURE;
}
uint8_t volume_uuid[16];
parse_uuid(volume_uuid, volume_uuid_str);
return keydb_add_volume(host, volume_name, volume_uuid) ? COMMAND_SUCCESS : COMMAND_FAILURE;
} }
static enum cmd_returncode_t cmd_rekey_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { static enum cmd_returncode_t cmd_rekey_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) {
@ -208,6 +228,20 @@ static enum cmd_returncode_t cmd_rekey_volume(struct editor_context_t *ctx, cons
} }
static enum cmd_returncode_t cmd_showkey_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) { static enum cmd_returncode_t cmd_showkey_volume(struct editor_context_t *ctx, const char *cmdname, unsigned int param_cnt, char **params) {
const char *host_name = params[0];
struct host_entry_t *host = keydb_get_host_by_name(ctx->keydb, host_name);
if (!host) {
fprintf(stderr, "No such host: %s\n", host_name);
return COMMAND_FAILURE;
}
const char *volume_name = params[1];
struct volume_entry_t *volume = keydb_get_volume_by_name(host, volume_name);
if (!volume) {
fprintf(stderr, "No such volume: %s\n", volume_name);
return COMMAND_FAILURE;
}
return COMMAND_SUCCESS; return COMMAND_SUCCESS;
} }

65
keydb.c
View File

@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <stdbool.h> #include <stdbool.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
@ -52,8 +53,13 @@ void keydb_free(struct keydb_t *keydb) {
free(keydb); free(keydb);
} }
bool keydb_add_host(struct keydb_t **keydb, const char *hostname) { bool keydb_add_host(struct keydb_t **keydb, const char *host_name) {
struct keydb_t *old_keydb = *keydb; struct keydb_t *old_keydb = *keydb;
if (keydb_get_host_by_name(old_keydb, host_name)) {
log_msg(LLVL_ERROR, "Host name \"%s\" already present in key database.", host_name);
return false;
}
struct keydb_t *new_keydb = realloc(old_keydb, keydb_getsize_hostcount(old_keydb->host_count + 1)); struct keydb_t *new_keydb = realloc(old_keydb, keydb_getsize_hostcount(old_keydb->host_count + 1));
if (!new_keydb) { if (!new_keydb) {
return false; return false;
@ -66,7 +72,7 @@ bool keydb_add_host(struct keydb_t **keydb, const char *hostname) {
/* We keep the reallocation but do not increase the host count */ /* We keep the reallocation but do not increase the host count */
return false; return false;
} }
strncpy(host->host_name, hostname, sizeof(host->host_name) - 1); strncpy(host->host_name, host_name, sizeof(host->host_name) - 1);
if (!buffer_randomize(host->tls_psk, sizeof(host->tls_psk))) { if (!buffer_randomize(host->tls_psk, sizeof(host->tls_psk))) {
/* We keep the reallocation but do not increase the host count */ /* We keep the reallocation but do not increase the host count */
return false; return false;
@ -76,6 +82,61 @@ bool keydb_add_host(struct keydb_t **keydb, const char *hostname) {
return true; return true;
} }
bool keydb_add_volume(struct host_entry_t *host, const char *devmapper_name, const uint8_t volume_uuid[static 16]) {
if (host->volume_count == MAX_VOLUMES_PER_HOST) {
log_msg(LLVL_ERROR, "Host \"%s\" already has maximum number of volumes (%d).", host->host_name, MAX_VOLUMES_PER_HOST);
return false;
}
if (keydb_get_volume_by_name(host, devmapper_name)) {
log_msg(LLVL_ERROR, "Volume name \"%s\" already present for host \"%s\" entry.", devmapper_name, host->host_name);
return false;
}
struct volume_entry_t *volume = &host->volumes[host->volume_count];
memcpy(volume->volume_uuid, volume_uuid, 16);
strncpy(volume->devmapper_name, devmapper_name, sizeof(volume->devmapper_name) - 1);
if (!buffer_randomize(volume->luks_passphrase, sizeof(volume->luks_passphrase))) {
log_msg(LLVL_ERROR, "Failed to produce %d bytes of entropy for LUKS passphrase.", sizeof(volume->luks_passphrase));
return false;
}
host->volume_count++;
return true;
}
int keydb_get_volume_index_by_name(struct host_entry_t *host, const char *devmapper_name) {
for (unsigned int i = 0; i < host->volume_count; i++) {
struct volume_entry_t *volume = &host->volumes[i];
if (!strcasecmp(volume->devmapper_name, devmapper_name)) {
return i;
}
}
return -1;
}
struct volume_entry_t *keydb_get_volume_by_name(struct host_entry_t *host, const char *devmapper_name) {
const int index = keydb_get_volume_index_by_name(host, devmapper_name);
return (index >= 0) ? &host->volumes[index] : NULL;
}
int keydb_get_host_index_by_name(struct keydb_t *keydb, const char *host_name) {
for (unsigned int i = 0; i < keydb->host_count; i++) {
struct host_entry_t *host = &keydb->hosts[i];
if (!strcasecmp(host->host_name, host_name)) {
return i;
}
}
return -1;
}
bool keydb_get_volume_luks_passphrase(const struct volume_entry_t *volume, char *dest) {
return ascii_encode(dest, volume->luks_passphrase, sizeof(volume->luks_passphrase));
}
struct host_entry_t *keydb_get_host_by_name(struct keydb_t *keydb, const char *host_name) {
const int index = keydb_get_host_index_by_name(keydb, host_name);
return (index >= 0) ? &keydb->hosts[index] : NULL;
}
bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase) { bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase) {
enum kdf_t kdf; enum kdf_t kdf;
if ((!passphrase) || (strlen(passphrase) == 0)) { if ((!passphrase) || (strlen(passphrase) == 0)) {

View File

@ -56,7 +56,13 @@ struct keydb_t {
/*************** AUTO GENERATED SECTION FOLLOWS ***************/ /*************** AUTO GENERATED SECTION FOLLOWS ***************/
struct keydb_t* keydb_new(void); struct keydb_t* keydb_new(void);
void keydb_free(struct keydb_t *keydb); void keydb_free(struct keydb_t *keydb);
bool keydb_add_host(struct keydb_t **keydb, const char *hostname); bool keydb_add_host(struct keydb_t **keydb, const char *host_name);
bool keydb_add_volume(struct host_entry_t *host, const char *devmapper_name, const uint8_t volume_uuid[static 16]);
int keydb_get_volume_index_by_name(struct host_entry_t *host, const char *devmapper_name);
struct volume_entry_t *keydb_get_volume_by_name(struct host_entry_t *host, const char *devmapper_name);
int keydb_get_host_index_by_name(struct keydb_t *keydb, const char *host_name);
bool keydb_get_volume_luks_passphrase(const struct volume_entry_t *volume, char *dest);
struct host_entry_t *keydb_get_host_by_name(struct keydb_t *keydb, const char *host_name);
bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase); bool keydb_write(const struct keydb_t *keydb, const char *filename, const char *passphrase);
struct keydb_t* keydb_read(const char *filename); struct keydb_t* keydb_read(const char *filename);
/*************** AUTO GENERATED SECTION ENDS ***************/ /*************** AUTO GENERATED SECTION ENDS ***************/

33
util.c
View File

@ -141,3 +141,36 @@ bool buffer_randomize(uint8_t *buffer, unsigned int length) {
fclose(f); fclose(f);
return true; return true;
} }
bool array_remove(void *base, unsigned int element_length, unsigned int element_count, unsigned int remove_element_index) {
if (remove_element_index >= element_count) {
return false;
}
uint8_t *bytebase = (uint8_t*)base;
const unsigned int destination_offset = remove_element_index * element_length;
const unsigned int source_offset = (remove_element_index + 1) * element_length;
const unsigned int copy_length = ((element_count - 1) - remove_element_index) * element_length;
if (copy_length) {
memcpy(bytebase + destination_offset, bytebase + source_offset, copy_length);
}
return true;
}
bool ascii_encode(char *dest, unsigned int dest_buffer_size, const uint8_t *source_data, unsigned int source_data_length) {
const char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+";
if ((source_data_length % 4) != 0) {
log_libc(LLVL_FATAL, "Can only encode binary data of which length is divisible by four, %d is not.", source_data_length);
return false;
}
const unsigned int require_dest_size = source_data_length / 4
for (unsigned int i = 0; i < source_data_length; i += 3) {
uint32_t word = (source_data[i + 0] << 0) | (source_data[i + 1] << 8) | (source_data[i + 2] << 16);
for (unsigned int shift = 0; shift < 24; shift += 6) {
*dest++ = alphabet[(word >> shift) & 0x3f];
}
}
*dest = 0;
return true;
}

2
util.h
View File

@ -38,6 +38,8 @@ bool is_hex(const char *str, int length);
int parse_hexstr(const char *hexstr, uint8_t *data, int maxlen); int parse_hexstr(const char *hexstr, uint8_t *data, int maxlen);
bool truncate_crlf(char *string); bool truncate_crlf(char *string);
bool buffer_randomize(uint8_t *buffer, unsigned int length); bool buffer_randomize(uint8_t *buffer, unsigned int length);
bool array_remove(void *base, unsigned int element_length, unsigned int element_count, unsigned int remove_element_index);
bool ascii_encode(char *dest, const uint8_t *source_data, unsigned int source_data_length);
/*************** AUTO GENERATED SECTION ENDS ***************/ /*************** AUTO GENERATED SECTION ENDS ***************/
#endif #endif