The current mess of code seems like a hodgepodge of complex ideas, partially copied from systemd, but then subtly different, and it's a mess. Let's simplify this drastically. First, assume that getrandom() is always available. If the kernel is too old, we have an unoptimized slowpath for still supporting ancient kernels, a path that should be removed at some point. If getrandom() isn't available and the fallback path doesn't work, the system has much larger problems, so just crash. This should basically never happen. getrandom() and having randomness available in general is a critical system API that should be expected to be available on any functioning system. Second, assume that the rng is initialized, so that asking for random numbers should never block. This is virtually always true on modern kernels. On ancient kernels, it usually becomes true. But, more importantly, this is not the responsibility of various daemons, even ones that run at boot. Instead, this is something for the kernel and/or init to ensure. Putting these together, we adopt new behavior: - First, try getrandom(..., ..., 0). The 0 flags field means that this call will only return good random bytes, not insecure ones. - If this fails for some reason that isn't ENOSYS, crash. - If this fails due to ENOSYS, poll on /dev/random until 1 byte is available, suggesting that subsequent reads from the rng will almost have good random bytes. If this fails, crash. Then, read from /dev/urandom. If this fails, crash. We don't bother caching when getrandom() returns ENOSYS. We don't apply any other fancy optimizations to the slow fallback path. We keep that as barebones and minimal as we can. It works. It's for ancient kernels. It should be removed soon. It's not worth spending cycles over. Instead, the goal is to eventually reduce all of this down to a simple boring call to getrandom(..., ..., 0). https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2127
41 lines
650 B
C
41 lines
650 B
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2017 Red Hat, Inc.
|
|
*/
|
|
|
|
#ifndef __NM_RANDOM_UTILS_H__
|
|
#define __NM_RANDOM_UTILS_H__
|
|
|
|
void nm_random_get_bytes(void *p, size_t n);
|
|
|
|
static inline guint32
|
|
nm_random_u32(void)
|
|
{
|
|
guint32 v;
|
|
|
|
nm_random_get_bytes(&v, sizeof(v));
|
|
return v;
|
|
}
|
|
|
|
static inline guint64
|
|
nm_random_u64(void)
|
|
{
|
|
guint64 v;
|
|
|
|
nm_random_get_bytes(&v, sizeof(v));
|
|
return v;
|
|
}
|
|
|
|
static inline bool
|
|
nm_random_bool(void)
|
|
{
|
|
guint8 ch;
|
|
|
|
nm_random_get_bytes(&ch, sizeof(ch));
|
|
return ch % 2u;
|
|
}
|
|
|
|
guint64 nm_random_u64_range(guint64 begin, guint64 end);
|
|
|
|
#endif /* __NM_RANDOM_UTILS_H__ */
|