int rdrand(unsigned long *ret) {
/* So, you are a "security researcher", and you wonder why we bother with using raw RDRAND here,
* instead of sticking to /dev/urandom or getrandom()?
*
* Here's why: early boot. On Linux, during early boot the random pool that backs /dev/urandom and
* getrandom() is generally not initialized yet. It is very common that initialization of the random
* pool takes a longer time (up to many minutes), in particular on embedded devices that have no
* explicit hardware random generator, as well as in virtualized environments such as major cloud
* installations that do not provide virtio-rng or a similar mechanism.
*
* In such an environment using getrandom() synchronously means we'd block the entire system boot-up
* until the pool is initialized, i.e. *very* long. Using getrandom() asynchronously (GRND_NONBLOCK)
* would mean acquiring randomness during early boot would simply fail. Using /dev/urandom would mean
* generating many kmsg log messages about our use of it before the random pool is properly
* initialized. Neither of these outcomes is desirable.
*
* Thus, for very specific purposes we use RDRAND instead of either of these three options. RDRAND
* provides us quickly and relatively reliably with random values, without having to delay boot,
* without triggering warning messages in kmsg.
*
* Note that we use RDRAND only under very specific circumstances, when the requirements on the
* quality of the returned entropy permit it. Specifically, here are some cases where we *do* use
* RDRAND:
*
* • UUID generation: UUIDs are supposed to be universally unique but are not cryptographic
* key material. The quality and trust level of RDRAND should hence be OK: UUIDs should be
* generated in a way that is reliably unique, but they do not require ultimate trust into
* the entropy generator. systemd generates a number of UUIDs during early boot, including
* 'invocation IDs' for every unit spawned that identify the specific invocation of the
* service globally, and a number of others. Other alternatives for generating these UUIDs
* have been considered, but don't really work: for example, hashing uuids from a local
* system identifier combined with a counter falls flat because during early boot disk
* storage is not yet available (think: initrd) and thus a system-specific ID cannot be
* stored or retrieved yet.
*
* • Hash table seed generation: systemd uses many hash tables internally. Hash tables are
* generally assumed to have O(1) access complexity, but can deteriorate to prohibitive
* O(n) access complexity if an attacker manages to trigger a large number of hash
* collisions. Thus, systemd (as any software employing hash tables should) uses seeded
* hash functions for its hash tables, with a seed generated randomly. The hash tables
* systemd employs watch the fill level closely and reseed if necessary. This allows use of
* a low quality RNG initially, as long as it improves should a hash table be under attack:
* the attacker after all needs to trigger many collisions to exploit it for the purpose
* of DoS, but if doing so improves the seed the attack surface is reduced as the attack
* takes place.
*
* Some cases where we do NOT use RDRAND are:
*
* • Generation of cryptographic key material
*
* • Generation of cryptographic salt values
*
* This function returns:
*
* -EOPNOTSUPP → RDRAND is not available on this system
* -EAGAIN → The operation failed this time, but is likely to work if you try again a few
* times
* -EUCLEAN → We got some random value, but it looked strange, so we refused using it.
* This failure might or might not be temporary.
*/