random-util: add common helper random_write_entropy() for crediting entropy to the kernel's pool
This commit is contained in:
parent
45250e66cc
commit
4dd055f907
|
@ -7,11 +7,13 @@
|
|||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/random.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if HAVE_SYS_AUXV_H
|
||||
|
@ -438,3 +440,36 @@ size_t random_pool_size(void) {
|
|||
/* Use the minimum as default, if we can't retrieve the correct value */
|
||||
return RANDOM_POOL_SIZE_MIN;
|
||||
}
|
||||
|
||||
int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(seed && size > 0);
|
||||
|
||||
if (credit) {
|
||||
_cleanup_free_ struct rand_pool_info *info = NULL;
|
||||
|
||||
/* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any
|
||||
* chance for confusion here. */
|
||||
if (size > INT_MAX / 8)
|
||||
return -EOVERFLOW;
|
||||
|
||||
info = malloc(offsetof(struct rand_pool_info, buf) + size);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
info->entropy_count = size * 8;
|
||||
info->buf_size = size;
|
||||
memcpy(info->buf, seed, size);
|
||||
|
||||
if (ioctl(fd, RNDADDENTROPY, info) < 0)
|
||||
return -errno;
|
||||
} else {
|
||||
r = loop_write(fd, seed, size, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,3 +38,5 @@ int rdrand(unsigned long *ret);
|
|||
#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U)
|
||||
|
||||
size_t random_pool_size(void);
|
||||
|
||||
int random_write_entropy(int fd, const void *seed, size_t size, bool credit);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/random.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
|
@ -11,6 +9,7 @@
|
|||
#include "efivars.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "random-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
/* If a random seed was passed by the boot loader in the LoaderRandomSeed EFI variable, let's credit it to
|
||||
|
@ -43,7 +42,6 @@ static void lock_down_efi_variables(void) {
|
|||
}
|
||||
|
||||
int efi_take_random_seed(void) {
|
||||
_cleanup_free_ struct rand_pool_info *info = NULL;
|
||||
_cleanup_free_ void *value = NULL;
|
||||
_cleanup_close_ int random_fd = -1;
|
||||
size_t size;
|
||||
|
@ -79,11 +77,6 @@ int efi_take_random_seed(void) {
|
|||
if (size == 0)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring.");
|
||||
|
||||
/* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any chance for
|
||||
* confusion here. */
|
||||
if (size > INT_MAX / 8)
|
||||
size = INT_MAX / 8;
|
||||
|
||||
random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (random_fd < 0)
|
||||
return log_warning_errno(errno, "Failed to open /dev/urandom for writing, ignoring: %m");
|
||||
|
@ -94,15 +87,8 @@ int efi_take_random_seed(void) {
|
|||
if (r < 0)
|
||||
return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m");
|
||||
|
||||
info = malloc(offsetof(struct rand_pool_info, buf) + size);
|
||||
if (!info)
|
||||
return log_oom();
|
||||
|
||||
info->entropy_count = size * 8;
|
||||
info->buf_size = size;
|
||||
memcpy(info->buf, value, size);
|
||||
|
||||
if (ioctl(random_fd, RNDADDENTROPY, info) < 0)
|
||||
r = random_write_entropy(random_fd, value, size, true);
|
||||
if (r < 0)
|
||||
return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m");
|
||||
|
||||
log_info("Successfully credited entropy passed from boot loader.");
|
||||
|
|
|
@ -236,24 +236,10 @@ static int run(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED)) {
|
||||
_cleanup_free_ struct rand_pool_info *info = NULL;
|
||||
|
||||
info = malloc(offsetof(struct rand_pool_info, buf) + k);
|
||||
if (!info)
|
||||
return log_oom();
|
||||
|
||||
info->entropy_count = k * 8;
|
||||
info->buf_size = k;
|
||||
memcpy(info->buf, buf, k);
|
||||
|
||||
if (ioctl(random_fd, RNDADDENTROPY, info) < 0)
|
||||
return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m");
|
||||
} else {
|
||||
r = loop_write(random_fd, buf, (size_t) k, false);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
}
|
||||
r = random_write_entropy(random_fd, buf, k,
|
||||
IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED));
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue