diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/id.c | 92 | ||||
-rw-r--r-- | src/id.h | 20 | ||||
-rw-r--r-- | src/random-seed.c | 171 | ||||
-rw-r--r-- | src/sha2.c | 2 | ||||
-rw-r--r-- | src/util.c | 43 | ||||
-rw-r--r-- | src/util.h | 2 |
6 files changed, 178 insertions, 152 deletions
diff --git a/src/id.c b/src/id.c new file mode 100644 index 0000000..6095ef6 --- /dev/null +++ b/src/id.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include <assert.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/statfs.h> +#include <sys/types.h> +#include <sys/vfs.h> + +#include "id.h" +#include "util.h" + +#ifdef HAVE_UDEV + +#endif + +#ifdef HAVE_UTIL_LINUX + +#endif + +static char *really_get_machine_id() { +#ifdef MACHINE_ID_PATH + FILE *machine_id_file = fopen(MACHINE_ID_PATH, "r"); +#else + const char *etc_machine_id = "/etc/machine-id"; + const char *var_lib_dbus_machine_id = "/var/lib/dbus/machine-id"; + FILE *machine_id_file = fopen(etc_machine_id, "r"); + if (!machine_id_file) { + if (errno != ENOENT) + fprintf(stderr, "error opening %s: %s, trying %s\n", + etc_machine_id, strerror(errno), var_lib_dbus_machine_id); + machine_id_file = fopen(var_lib_dbus_machine_id, "r"); + } +#endif + + if (!machine_id_file) { + perror("couldn't open any machine-id file, last error"); + return NULL; + } + + char *machine_id = NULL; + size_t machine_id_len = 0; + if (getdelim(&machine_id, &machine_id_len, '\0', machine_id_file) == -1) { + fputs("error reading machine id file\n", stderr); + free(machine_id); + return NULL; + } + + return machine_id; +} + +size_t get_machine_id(char **machine_id) { + static char *c_machine_id; + if (!c_machine_id) + c_machine_id = really_get_machine_id(); + *machine_id = c_machine_id; + return strlen(*machine_id); +} + +size_t get_fs_id(fsid_t *fs_id, int seed_fd) { + struct statfs statfs_buf; + if (fstatfs(seed_fd, &statfs_buf) == -1) { + perror("error: statfs seed file: %s"); + return false; + } + + switch (statfs_buf.f_type) { + case 0x9123683e: // BTRFS_SUPER_MAGIC + case 0xef53: // EXT2_SUPER_MAGIC == EXT3_SUPER_MAGIC == EXT4_SUPER_MAGIC + case 0x3153464a: // JFS_SUPER_MAGIC + case 0x5346544e: // NTFS_SB_MAGIC + case 0x52654973: // REISERFS_SUPER_MAGIC + case 0x24051905: // UBIFS_SUPER_MAGIC + memcpy(fs_id, &statfs_buf.f_fsid, sizeof(fsid_t)); + return sizeof(fsid_t); + default: + fprintf(stderr, "error: filesystem type 0x%08x does not have consistent f_fsid\n", (unsigned int)statfs_buf.f_type); + return 0; + } +} + +void hash(const unsigned char salt[static SALT_LEN], unsigned char out[static HASH_LEN], const void *in, size_t size) { + assert(size < INT_MAX - SALT_LEN - 100); + sha256_ctx ctx; + sha256_init(&ctx); + sha256_update(&ctx, salt, SALT_LEN); + sha256_update(&ctx, in, (unsigned int)size); + sha256_final(&ctx, out); +} diff --git a/src/id.h b/src/id.h new file mode 100644 index 0000000..7c45a64 --- /dev/null +++ b/src/id.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef FSID_H +#define FSID_H + +#include <sys/types.h> + +#include "util.h" + +#if defined(HAVE_UDEV) || defined(HAVE_UTIL_LINUX) +size_t get_fs_uuid(char **fs_uuid, int seed_fd); +#endif +#ifdef HAVE_UDEV +size_t get_drive_id(char **drive_id, int seed_fd); +#endif +size_t get_machine_id(char **machine_id); +size_t get_fs_id(fsid_t *fs_id, int seed_fd); +void hash(const unsigned char salt[static SALT_LEN], unsigned char *out, const void *in, size_t size); + +#endif diff --git a/src/random-seed.c b/src/random-seed.c index b8e8ad7..0ce1f8b 100644 --- a/src/random-seed.c +++ b/src/random-seed.c @@ -18,6 +18,8 @@ #include <unistd.h> #include "config.h" + +#include "id.h" #include "musl-libgen-c.h" #include "util.h" @@ -46,104 +48,55 @@ static inline void usage() { puts("see random-seed(8) for more information."); } -static char *get_machine_id() { -#ifdef MACHINE_ID_PATH - FILE *machine_id_file = fopen(MACHINE_ID_PATH, "r"); +static bool run_seed_file_cmd(const char *cmd, const unsigned char *salt, FILE *seed_file) { +#define HASH_ID_CMD(my_cmd, type, fn, hash_access, ...) \ + do { \ + if (!streq(cmd, my_cmd)) \ + break; \ + char *arg = strtok(NULL, " \t"); \ + if (!arg) { \ + fputs("error parsing seed file: expected argument " \ + "to '" my_cmd "'\n", stderr); \ + return false; \ + } \ + type fn ## _buf; \ + unsigned char fn ## _hash[HASH_LEN]; \ + size_t sz = fn(&fn ## _buf, ##__VA_ARGS__); \ + if (sz == 0) { \ + fputs("error getting " my_cmd " hash\n", stderr); \ + return false; \ + } \ + hash(salt, fn ## _hash, hash_access fn ## _buf, sz); \ + unsigned char theirdigest[HASH_LEN]; \ + if (hex2mem(theirdigest, HASH_LEN, arg) == 0) { \ + fputs("error decoding hex hash\n", stderr); \ + exit(1); \ + } \ + if (memcmp(fn ## _hash, theirdigest, HASH_LEN)) { \ + fputs(my_cmd " hash does not match\n", stderr); \ + return false; \ + } \ + return true; \ + } while (0) + + HASH_ID_CMD("machine-id", char *, get_machine_id, ); + HASH_ID_CMD("fs-id", fsid_t, get_fs_id, &, fileno(seed_file)); +#if defined(HAVE_UDEV) || defined(HAVE_UTIL_LINUX) + HASH_ID_CMD("fs-uuid", char *, get_fs_uuid, fileno(seed_file)); #else - const char *etc_machine_id = "/etc/machine-id"; - const char *var_lib_dbus_machine_id = "/var/lib/dbus/machine-id"; - FILE *machine_id_file = fopen(etc_machine_id, "r"); - if (!machine_id_file) { - if (errno != ENOENT) - fprintf(stderr, "error opening %s: %s, trying %s\n", - etc_machine_id, strerror(errno), var_lib_dbus_machine_id); - machine_id_file = fopen(var_lib_dbus_machine_id, "r"); + if (streq(cmd, "fs-uuid")) { + fputs("error: fs-uuid not supported by this random-seed\n", stderr); + return false; } #endif - - if (!machine_id_file) { - perror("couldn't open any machine-id file, last error"); - return NULL; - } - - char *machine_id = NULL; - size_t machine_id_len = 0; - if (getdelim(&machine_id, &machine_id_len, '\0', machine_id_file) == -1) { - fputs("error reading machine id file\n", stderr); - free(machine_id); - return NULL; - } - - return machine_id; -} - -static bool get_machine_id_hash(const unsigned char salt[static SALT_LEN], unsigned char machine_id_digest[static HASH_LEN]) { - static char *c_machine_id; - if (!c_machine_id) - c_machine_id = get_machine_id(); - if (!c_machine_id) - return false; - - unsigned char c_machine_id_digest[HASH_LEN]; - hash(salt, c_machine_id_digest, c_machine_id, strlen(c_machine_id)); - memcpy(machine_id_digest, c_machine_id_digest, HASH_LEN); - return true; -} - -static inline bool get_fs_id_hash(const unsigned char salt[static SALT_LEN], unsigned char fsid_digest[static HASH_LEN], int seed_fd) { - struct statfs statfs_buf; - if (fstatfs(seed_fd, &statfs_buf) == -1) { - fprintf(stderr, "error statfs seed file: %s, " - "disabling entropy credit\n", strerror(errno)); +#ifdef HAVE_UDEV + HASH_ID_CMD("drive-id", char *, get_drive_id, fileno(seed_file)); +#else + if (streq(cmd, "drive-id")) { + fputs("error: drive-id not supported by this random-seed\n", stderr); return false; } - hash(salt, fsid_digest, &statfs_buf.f_fsid, sizeof(statfs_buf.f_fsid)); - return true; -} - -static bool run_seed_file_cmd(const char *cmd, const unsigned char *salt, FILE *seed_file) { - char *arg; - if (streq(cmd, "machine-id")) { - arg = strtok(NULL, " \t"); - if (!arg) { - fputs("error parsing seed file: expected argument " - "to 'machine-id'\n", stderr); - return false; - } - unsigned char machine_id_hash[HASH_LEN]; - if (!get_machine_id_hash(salt, machine_id_hash)) { - fputs("error getting machine id hash, disabling entropy credit\n", - stderr); - return false; - } - - if (!hash_match(machine_id_hash, arg)) { - fputs("machine-id does not match, disabling entropy credit\n", - stderr); - return false; - } - return true; - } - - if (streq(cmd, "fs-id")) { - arg = strtok(NULL, " \t"); - if (!arg) { - fputs("error parsing seed file: expected argument to 'fs-id'\n", stderr); - return false; - } - unsigned char fs_id_hash[HASH_LEN]; - if (!get_fs_id_hash(salt, fs_id_hash, fileno(seed_file))) { - fputs("error getting fs id hash, disabling entropy credit\n", stderr); - return false; - } - - if (!hash_match(fs_id_hash, arg)) { - fputs("fs id does not match, disabling entropy credit\n", stderr); - return false; - } - return true; - } - +#endif fprintf(stderr, "error parsing seed file: unsupported command: %s\n", cmd); return false; } @@ -302,14 +255,21 @@ static bool save(const char *seed_path, unsigned char *random_buf) { return false; } - unsigned char machine_id_digest[HASH_LEN]; - if (!get_machine_id_hash(random_ptr, machine_id_digest)) { - fputs("cannot obtain machine id, aborting save\n", stderr); - return false; - } - char machine_id_hash[HASH_STR_LEN]; - mem2hex(machine_id_hash, machine_id_digest, HASH_STR_LEN); - machine_id_hash[HASH_STR_LEN-1] = '\0'; +#define GET_HASH_STR(type, hash_access, name, ...) \ + char name ## _hash[HASH_STR_LEN]; \ + do { \ + type name ## _buf; \ + size_t name ## _len = get_ ## name(&name ## _buf, ##__VA_ARGS__); \ + if (!name ## _len) { \ + fputs("error obtaining " #name " \n", stderr); \ + return false; \ + } \ + unsigned char name ## _digest[HASH_LEN]; \ + hash(random_ptr, name ## _digest, hash_access name ## _buf, name ## _len); \ + mem2hex(name ## _hash, name ## _digest, HASH_LEN); \ + } while (0) + + GET_HASH_STR(char *, , machine_id); int seed_dir_fd = -1; int seed_fd = -1; @@ -341,14 +301,7 @@ static bool save(const char *seed_path, unsigned char *random_buf) { goto out; } - unsigned char fs_id_digest[HASH_LEN]; - if (!get_fs_id_hash(random_ptr, fs_id_digest, seed_dir_fd)) { - fputs("cannot obtain machine id, aborting save\n", stderr); - goto out; - } - char fs_id_hash[HASH_LEN*2+1]; - mem2hex(fs_id_hash, fs_id_digest, HASH_LEN); - fs_id_hash[sizeof(fs_id_hash)-1] = '\0'; + GET_HASH_STR(fsid_t, &, fs_id, seed_dir_fd); seed_fd = openat(seed_dir_fd, seed_name_new, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (seed_fd == -1) { @@ -83,7 +83,7 @@ uint32_t sha256_k[64] = /* SHA-256 functions */ -void sha256_transf(sha256_ctx *ctx, const unsigned char *message, +static void sha256_transf(sha256_ctx *ctx, const unsigned char *message, unsigned int block_nb) { uint32_t w[64]; @@ -50,50 +50,13 @@ static const char *HEX_CHARS = "0123456789abcdef"; * \param size the number of bytes to encode */ void mem2hex(char *dest, const void *src, size_t size) { - for (size_t i = 0; i < size; i++) { + size_t i; + for (i = 0; i < size; i++) { unsigned char c = *((const unsigned char *)src + i); dest[2*i] = HEX_CHARS[c >> 4]; dest[2*i+1] = HEX_CHARS[c & 0xf]; } - dest[size*2] = '\0'; -} - -void hash(const unsigned char salt[static SALT_LEN], unsigned char *out, const void *in, size_t size) { - assert(size < INT_MAX - SALT_LEN - 100); -#ifdef DEBUG - fprintf(stderr, "hashing %zu bytes starting with 0x%x ending with 0x%x\n", size, (int)((unsigned char*)in)[0], (int)((unsigned char*)in)[size-1]); -#endif - sha256_ctx ctx; - sha256_init(&ctx); - sha256_update(&ctx, salt, SALT_LEN); - sha256_update(&ctx, in, (unsigned int)size); - sha256_final(&ctx, out); -} - -static void print_hash(const unsigned char digest[static HASH_LEN]) { -#ifdef DEBUG - char hash[HASH_LEN*2+1]; - mem2hex(hash, digest, HASH_LEN); - fprintf(stderr, "hash: %s\n", hash); -#else - (void)digest; -#endif -} - -bool hash_match(const unsigned char digest[static HASH_LEN], const char *arg) { - unsigned char theirdigest[HASH_LEN]; - if (hex2mem(theirdigest, sizeof(theirdigest), arg) == 0) { - fputs("error decoding hex hash\n", stderr); - exit(1); - } -#ifdef DEBUG - fprintf(stderr, "comparing hash, theirs: %s = 0x%02x..0x%02x, ours: 0x%02x..0x%02x\n", arg, (int)theirdigest[0], (int)theirdigest[HASH_LEN-1], (int)digest[0], (int)theirdigest[HASH_LEN-1]); - fputs(" our ", stderr); - print_hash(digest); - fputs("their ", stderr); - print_hash(theirdigest); -#endif - return !memcmp(digest, theirdigest, HASH_LEN); + dest[2*i] = '\0'; } ssize_t random_get(void *buf, size_t buflen, unsigned int flags) { @@ -30,7 +30,5 @@ static inline bool streq(const char *s1, const char *s2) { ssize_t random_get(void *buf, size_t buflen, unsigned int flags); size_t hex2mem(unsigned char *dest, size_t size, const char *src); void mem2hex(char *dest, const void *src, size_t size); -void hash(const unsigned char salt[static SALT_LEN], unsigned char *out, const void *in, size_t size); -bool hash_match(const unsigned char digest[static HASH_LEN], const char *arg); #endif |