botan icon indicating copy to clipboard operation
botan copied to clipboard

Enable getrandom() by default?

Open securitykernel opened this issue 3 years ago • 6 comments

Support for getrandom() was introduced in 9a41b24157260eb9830e6a441c1131d6be09b3df, but disabled by default as it required a newer kernel and glibc. Two years down the road, would it make sense to enable it by default now?

Additionally, in recent Linux kernels starting with 5.6, there have been some major changes to the RNG (source):

  • Unrestricted generation of random numbers is available with /dev/urandom and the in-kernel function get_random_bytes. This implies that irrespective whether the entropy pool or the ChaCha20 DRNG received sufficient entropy, random data is generated.
  • When accessing /dev/random, random numbers are only generated when the entropy pool or the ChaCha20 DRNG received at least 128 bits of initial entropy. After reaching that threshold of 128 bits of entropy once, /dev/random will operate non-blocking for the lifetime of the system and thus operate identically to /dev/urandom.

In addition, the Linux kernel offers the getrandom system call documented by its respective man page which provides access to the Linux-RNG as follows:

  • When invoking getrandom where the flag field is zero, the system call accesses the ChaCha20 DRNG identically to /dev/random.
  • When invoking getrandom with a flag of GRND_INSECURE, the system call behaves like /dev/urandom.
  • The flag GRND_RANDOM is currently unused.

So it seems the blocking behaviour of /dev/random, one of its main criticism, was changed to just address the not enough entropy during early system startup problem and once seeded, never blocks anymore, so behaves like /dev/urandom from then on. getrandom() was changed to access /dev/random by default with flags set to 0, which Botan does. So to me it seems getrandom() is the best choice for a System_RNG on Linux these days.

securitykernel avatar Jan 26 '21 11:01 securitykernel

The syscall itself was introduced in Linux 3.7 [Dec 2012] and even 2 years ago that was old enough to rely on. However the libc wrappers were only added in glibc 2.25 [Feb 2017] and musl 1.1.20 [Sep 2018], which made switching in Sept 2018 a problem. However consulting https://repology.org/project/glibc/versions and https://repology.org/project/musl/versions it seems most active distros have a recent enough version, with the perhaps notable exception of RHEL7. However the fallback for old systems is easy.

So, seems good to me particularly for 3.0. I'm less certain about doing this on 2.x branch but suppose it's fine there if you see the need.

randombit avatar Jan 26 '21 12:01 randombit

Fine for me to enable this for 3.0 and leave 2.x as-is.

securitykernel avatar Jan 26 '21 12:01 securitykernel

Enabled now on master / for 3.0.0

randombit avatar Feb 21 '21 17:02 randombit

This broke the OSS-Fuzz build which is based on Ubuntu 18.04 interestingly 18.04 uses glibc 2.27 while getrandom support was added in glibc 2.25. I may revert this is it actually broke on 18.04 since that distro is still in wide use.

randombit avatar Feb 22 '21 16:02 randombit

ah too bad I was pretty glad with the changes...

devnexen avatar Feb 22 '21 17:02 devnexen

Reverted e340c08 at least temporarily to unblock OSS-Fuzz build. I need to confirm this is broken on all 18.04 or if there is something weird about OSS-Fuzz env.

randombit avatar Feb 23 '21 23:02 randombit