5 ms·
The source code has a lengthy comment explaining why. https://github.com/systemd/systemd/blob/bcac754d66374782a85a8de39fd543c1eaf9fa82/src/basic/random-util.c#
by LukeShu 6y ago
The source code has a lengthy comment explaining why.
https://github.com/systemd/systemd/blob/bcac754d66374782a85a8de39fd543c1eaf9fa82/src/basic/random-util.c#L40-L98 https://github.com/systemd/systemd/blob/bcac754d66374782a85a...
- robocat 6y agoint 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. */
- rasz 6y agoYes, the famous 'I want my Random number be even more random by adding more random numbers to it, otherwise its no good.
- LukeShu 6y agoThat's not what's going on here. You're referring to the braindead behavior that `/dev/random` can block because it thinks its entropy pool has been depleted, which is of course dumb because once the pool is sufficiently full it can't be emptied. What's going on here is the scenario where the pool genuinely is empty because it hasn't been filled yet. This can only happen at early boot, but is a genuine thing that happens; unlike it becoming empty later.
- gruez 6y agoBut what happens on systems that don't have rdrand? Surely there is a fallback. Why isn't the fallback used in all cases, given how flakey rdrand is?
- rcxdude 6y agoIt falls back to /dev/urandom, which will cause the kernel bitterly complain by spamming log messages while the entropy pool hasn't been seeded.
- LukeShu 6y agoIf I'm reading the source right, it actually falls back to a blocking `getrandom` followed by /dev/urandom; so actually instead of spamming the logs about "entropy pool hasn't been seeded", it will block until it is seeded.
- segfaultbuserr 6y agoIt'll also block the system from booting for as long as a few minutes in the absence of user input.
- secondcoming 6y agoSince they only use it for UUID generation, couldn't they use rdrand() to seed a PGC pseudo-RNG?
- deleted 6y ago[deleted]