Image of the glider from the Game of Life by John Conway
Skip to content

CPU Jitter Entropy for the Linux Kernel

Normally, I keep a sharp eye on all things cryptographic-related with the Linux kernel. However, in 4.2, I missed something fantastic: jitterentropy_rng.ko. This is a Linux kernel module that measures the jitter of the high resolution timing available in modern CPUs, and uses this jitter as a source of true randomness. In fact, using the CPU timer as a source of true randomness isn't anything new. If you're read my blog for some time, you're already familiar with haveged(8). This daemon also collects CPU jitter and feeds the collected data into the kernel's random number generator.

The main site is at http://www.chronox.de/jent.html and the PDF paper describing the CPU jitter entropy can be found on the site.

So why the blog post about jitterentropy_rng.ko? Because now that we have something in the mainline kernel, we get a few benefits:

  1. More eyes are looking at the code, and can adjust, analize, and refine the entropy gathering process, making sure it's not to aggressive nor conservative in its approach.
  2. We now have something that can collect entropy much earlier in the boot sequence, even before the random number generator has been initialized. This means we can have a properly seeded CSPRNG when the CSPRNG is initialized.
  3. While not available now, we could have a kernelspace daemon collecting entropy and feeding it to the CSPRNG without the need for extra software.
  4. This isn't just for servers, desktops, and VMs, but anything that runs the Linux kernel on a modern CPU, including Android phones, embedded devices, and SoC.
  5. While haveged(8) has been a good solution for a long time, it has been heavily criticized, and it seems development on it has stalled. Here is another software solution for true randomness without the need of potentially dangerous 3rd party USB random number generators.
  6. You don't need Intel's RDRAND. Any modern CPU with a high resolution timer will work. AMD, SPARC, ARM, MIPS, PA-RISC, Power, etc.

As mentioned in the list, unfortunately, loading the kernel doesn't automatically top-off the entropy estimate of the internal state of the CSPRNG (/proc/sys/kernel/random/entropy_avail). As such, /dev/random will still block when the estimate is low or exhausted. So you'll still need to run a userspace daemon to prevent this behavior. The author has also shipped a clean, light userspace daemon that just reads the data provided by the jitterentropy_rng.ko kernel module, and uses ioctl(2) to increase the estimate. The jitterentropy_rng.ko module provides about 10 KBps of random data.

Again, this isn't anything that something like haveged(8) doesn't already have access to. However, by taking advantage of a loaded kernel module, we can ensure that randomness is being collected before the CSPRNG is initialized. So, when CSPRNG initialization happens, we can ensure that it is properly seeded on first boot, minimizing the likelihood that exact keys will be created on distinct systems. This is something haveged(8) can't provide, as it runs entirely in userspace.

Unfortunately, jitterentropy-rngd(8) isn't available in the Debian repositories yet, so you'll need to download the compressed tarball from the author's website, manually compile and install yourself. However, he does ship a systemd(8) service file, which makes it easy to get the daemon up and running on boot with minimal effort.

I've had the jitterentropy_rng.ko module installed with the jitterentropy-rngd(8) userspace daemon running all day today, without haveged(8), and needless to say, I'm pleased. It keeps the CSPRNG entropy estimate sufficiently topped off for software that still relies on /dev/random (please stop doing this developers- start using /dev/urandom please) and provides adequate performance. Near as I can tell, there is not a character device created when loading the kernel module, so you can't access the unbiased data before feeding it into the CSPRNG. As such, I don't have a way to test its randomness quality. Supposedly, there is a way to access this via debugfs, but I haven't found it.

Anyway, I would recommend using jitterentropy_rng.ko and jitterentropy-rngd(8) over haveged(8) as the source for your randomness.

{ 3 } Comments

  1. Dax Kelson | May 24, 2016 at 8:54 pm | Permalink

    With Linux kernel 3.16 and newer, the kernel itself mixes data from hardware random number generators into /dev/random on a sliding scale based on the definable entropy estimation quality of the HWRNG. This means that no userspace daemon, such as rngd from rng-tools is needed to do that job. With Linux kernel 3.17+, the VirtIO RNG was modified to have a default quality defined above 0, and as such, is currently the only HWRNG mixed into /dev/random by default. (a paragraph I added to the wikipedia article on /dev/random last year)

    Basically modern Linux VM should just be using virtio-rng and thus piggy back back off the hypervisor.

  2. Aaron Toponce | May 25, 2016 at 9:42 am | Permalink

    The userspace daemons are only needed if you want to issue ioctl(2) calls to increase the entropy estimate, to prevent /dev/random from blocking (you should be using /dev/urandom anyway). VirtIORNG is only useful for virtualized guests, if the hypervisor is running a userspace daemon to keep /dev/random from blocking (such as rngd(8) attached to a HWRNG or havaged(8), or jitterentropy-rngd(8) as blogged about here). As you know, it attaches /dev/random from the hypervisor as /dev/hwrng in the virtualized guest. If /dev/random is blocking, VirtIORNG is useless.

    Regarding your comment about 3.16+ mixing data from HWRNGs on board, as far as I know, this only applies with RDRAND, and it's only reseeding the internal state. /dev/random will still block without a userspace daemon issuing the necessary ioctl(2) system call to increase the entropy estimate. So, this is limited to a select few Intel chips, whereas jitterentropy_rng.ko in 4.2+ is CPU agnostic, as it doesn't rely on a dedicated HWRNG in the chip, but uses timing in the chip itself as the HWRNG. Again though, this is only reseeding the internal state, without calling ioctl(2) to increase the entropy estimate. IE: /dev/random will still block, unless running jitterentropy_rngd(8).

  3. Frew Schmidt | June 5, 2016 at 8:58 pm | Permalink

    On my systems I set up /dev/random as a symlink to urandom. I don't expect to be able to convince people to stop using random till the Linux kernel just provides urandom (probably never.)

Post a Comment

Your email is never published nor shared.