Hacker News new | ask | show | jobs
by onlydnaq 2431 days ago
Why would anyone use rdrand directly? Seems like user space applications should use getrandom() or /dev/urandom and the kernel should use rdrand as a complementary random number source in its random number generator.

No user space program should need to use rdrand directly at all.

4 comments

> Why would anyone use rdrand directly?

Indeed, because RDSEED is actually what most people want anyway.

Its an assembly instruction that gets the job done. People should be expecting that the assembly instructions of their CPUs work as intended. No different than using AVX-intrinsics or hand-crafted assembly in x264 / x265 code.

In any case, RDSEED is the assembly instruction for gathering entropy (aka: setting a random number generator should use RDSEED), while RDRAND is an older assembly instruction for purely getting a cryptographic random number. Its slightly different amounts of entropy involved in RDSEED vs RDRAND. So this is a very subtle issue that requires a lot of understanding of the x86 assembly instruction set.

But if you understand these details, then by golly you should use the instructions!

I believe Wireguard is implemented in the kernel. I'd argue there should be a kernel-wide wrapper function for this sort of thing, or if that already exists, Wireguard should probably use it.

That doesn't explain why systemd uses it, of course.

WireGuard does use the right wrapper -- get_random_u32(). The issue is that the implementation will just use whatever the architecture-provided randomness source provides if it's available[1]. That's the real bug.

[1]: https://elixir.bootlin.com/linux/v5.3.6/source/drivers/char/...

The problem with creating such wrapper function is that someone like systemd/Wireguard developers will doubtlessly exploit it to drain entropy pool (whatever that means), at which point kernel drivers may start locking up, waiting for more entropy to appear.

In comparison get_random_u32() is safe to call at any point — including early boot — and does not affect global entropy pool. At worst it may return low-quality numbers, but that can be easily fixed by running your own peudo-random generator on top of it (which is a good idea anyway because you don't want your kernel module to contend with other parties for RNG ownership).

Speed - RDRAND takes 100 nS, but reading from a device takes much longer. If you're using it to generate session IDs for a firewall, speed matters.
systemd may be running in an environment where /dev/urandom isn't available, and getrandom() will either block or return nothing depending on whether the entropy pool has been initialised so you still need a fallback if you're working in the early boot process.