top | item 21386189

(no title)

marios | 6 years ago

I'm surprised WireGuard asks RDRAND directly. Isn't there a facility inside the Linux to get random numbers ?

OpenBSD conveniently provides arc4random() in its libc for applications to use, and the same function is available for kernel components (obviously one needs to include different headers).

discuss

order

zx2c4|6 years ago

WireGuard uses the correct kernel function, get_random_u32(). WireGuard does not use RdRand directly. WireGuard instead uses the proper kernel function for asking for a unsigned 32-bit number. The kernel implements get_random_u32() under the hood using a variety of backends for it. One of them is RdRand.

Other facilities in the kernel, such as ASLR, also use get_random_u32().

Many things in the kernel use get_random_u32(). That's the proper function to use.

When presented with this bug, the upstream kernel maintainers chose not to fix get_random_u32(), due to the availability (?) of microcode updates for AMD chips. That's not my decision. WireGuard is just a mere consumer of get_random_u32(), like all other modules. This is an upstream kernel bug.

zaroth|6 years ago

> That's not my decision.

So says a maintainer of WireGuard. HN is beautiful sometimes.

If RANDOM_TRUST_CPU is disabled, that will stop the kernel function from using RDRAND and avoid this issue for anyone using the ‘get_random_u32()’ function?

dfox|6 years ago

From cursory look at the code wireguard relies on Linux's get_random_whatever() internal APIs, which are kernel-space interface to same PRNG as userspace (u)random/get_random()/get_entropy(). It even seems that there is not a single line of x86_64 assembly in the whole WireGuard.

On the other hand it is somewhat worrisome that brokenness of RDRAND can affect output of Linux's RNG that much.

cyphar|6 years ago

The problem is that the "right kernel API" (get_random_u32) will return whatever the hardware-provided RNG returns if it's available[1].

There is assembly in WireGuard for the crypto primitive implementations, but those are generated by scripts and are based on either formally-proven implementations or highly-vetted ones.

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

marios|6 years ago

Alright, so that would mean that it's not WireGuard that's broken because it's trying to be more picky about the RNG, but rather the Linux CSPRNG that's broken when RDRAND is misbehaving. As you said, worrisome.

tedunangst|6 years ago

As noted by others, linux does provide a similar function, get_random_u32(). However, it may depend exclusively on rdrand, instead of simply using rdrand as an input to another generator. (arc4random() always stirs and mixes, regardless of what hardware sources are available.)

gargravarr|6 years ago

Linux provides /dev/random and /dev/urandom to all applications as well as relevant API calls, but the quality of those is always in doubt (especially with urandom, which recycles the entropy pool when it gets too low). CPU hardware PRNGs are supposed to be much higher quality, when they work. So it's all about depending on the CPU to actually do what it's advertising - the CPUID flag advertises a high-quality hardware RNG, but then the firmware bug completely nurfs it.

nocturnial|6 years ago

> So it's all about depending on the CPU to actually do what it's advertising

I know I'm nitpicking but I disagree with that statement.

There's a kernel option called CONFIG_RANDOM_TRUST_CPU which you can set to false. So if for some reason, even if it's a bad one, you don't want your random numbers generated by your cpu then that's that. End of discussion. (In theory, not sure if rdrand if trapable)

I get that you're skeptical about the quality of what's provided in /dev/(u)random because in most cases it's true. Should I ever feel the need to hookup a hw random generator then I hope programs would use that one instead of guessing they can do better by calling rdrand.