mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 17:06:39 +09:00
We currently have a convoluted and complex selection of which random numbers to use. We can simplify this down to two functions that cover all of our use cases: 1) Randomness for crypto: this one needs to wait until the RNG is initialized. So it uses getrandom(0). If that's not available, it polls on /dev/random, and then reads from /dev/urandom. This function returns whether or not it was successful, as before. 2) Randomness for other things: this one uses getrandom(GRND_INSECURE). If it's not available it uses getrandom(GRND_NONBLOCK). And if that would block, then it falls back to /dev/urandom. And if /dev/urandom isn't available, it uses the fallback code. It never fails and doesn't return a value. These two cases match all the uses of randomness inside of systemd. I would prefer to make both of these return void, and get rid of the fallback code, and simply assert in the incredibly unlikely case that /dev/urandom doesn't exist. But Luca disagrees, so this commit attempts to instead keep case (1) returning a return value, which all the callers already check, and fix the fallback code in (2) to be less bad than before. For the less bad fallback code for (2), we now use auxval and some timestamps, together with various counters representing the invocation, hash it all together and provide the output. Provided that AT_RANDOM is secure, this construction is probably okay too, though notably it doesn't have any forward secrecy. Fortunately, it's only used by random_bytes() and not by crypto_random_bytes().
32 lines
915 B
C
32 lines
915 B
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
void random_bytes(void *p, size_t n); /* Returns random bytes suitable for most uses, but may be insecure sometimes. */
|
|
int crypto_random_bytes(void *p, size_t n); /* Returns secure random bytes after waiting for the RNG to initialize. */
|
|
|
|
static inline uint64_t random_u64(void) {
|
|
uint64_t u;
|
|
random_bytes(&u, sizeof(u));
|
|
return u;
|
|
}
|
|
|
|
static inline uint32_t random_u32(void) {
|
|
uint32_t u;
|
|
random_bytes(&u, sizeof(u));
|
|
return u;
|
|
}
|
|
|
|
/* Some limits on the pool sizes when we deal with the kernel random pool */
|
|
#define RANDOM_POOL_SIZE_MIN 32U
|
|
#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);
|
|
|
|
uint64_t random_u64_range(uint64_t max);
|