4 years ago I was writing about getting an eKey to generate more entropy. Well, I never bought the eKey, and it took me 4 years to look at entropy generation again, but I found some interesting results today.

I was trying to set up /dev/hw_random on an Intel Xeon E3-1270. While /proc/cpuinfo indicates support for rdrand instructions, intel-rng refuses to load and I am still figuring out why.

While reading the readme of rng-tools, I stumbled across "The VIA Hardware RNG". Remembering that my Dedibox from online.fr uses a VIA Nano processor U2250, I ssh-ed into it, and discovered the awesomeness of this tiny CPU.

# cat /proc/cpuinfo 
processor	: 0
vendor_id	: CentaurHauls
cpu family	: 6
model		: 15
model name	: VIA Nano processor U2250 (1.6GHz Capable)
< ... snip ...>
flags		: ...  rng rng_en ...
< ... snip ...>

Note the 'rng' cpu flag above. That all that's needed to use the hwrng. Well, that and a few kernel modules:

# modprobe rng-core

# modprobe via_rng

# file /dev/hwrng 
/dev/hwrng: character special

The harware RNG is loaded in /dev/hwrng. Using the tools from the 'rng-tools' package, we can test the quality of the randomness provided.

# rngtest -c 100 < /dev/hwrng 
rngtest 2-unofficial-mt.14
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests...
rngtest: bits received from input: 2000032
rngtest: FIPS 140-2 successes: 100
rngtest: FIPS 140-2 failures: 0
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 0
rngtest: FIPS 140-2(2001-10-10) Runs: 0
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=140.395; avg=339.623; max=369.441)Kibits/s
rngtest: FIPS tests speed: (min=3.289; avg=48.125; max=57.798)Mibits/s
rngtest: Program run time: 5790927 microseconds

All FIPS tests pass. Now a small bandwidth test:

# dd if=/dev/hwrng of=awesomerandom bs=128 count=10240
10240+0 enregistrements lus
10240+0 enregistrements écrits
1310720 octets (1,3 MB) copiés, 27,9087 s, 47,0 kB/s

47kB/s, or 385024 bits per second, is pretty damn good for a random number generator! Now let's feed that into the kernel's entropy pool using rngd.

The initial entropy pool, while using SSH on the server:

# cat /proc/sys/kernel/random/entropy_avail
153

RNGD being installed, I configured the default parameters in /etc/default/rng-tools as shown below. I tried using the more recent viapadlock driver, but it doesn't seem to be supported on my architecture. The viakernel worked fine.

# cat /etc/default/rng-tools 
# Configuration for the rng-tools initscript
# $Id: rng-tools.default,v 1.1.2.5 2008-06-10 19:51:37 hmh Exp $

# This is a POSIX shell fragment

# Set to the input source for random data, leave undefined
# for the initscript to attempt auto-detection.  Set to /dev/null
# for the viapadlock driver.
HRNGDEVICE=/dev/hwrng
#HRNGDEVICE=/dev/null

# Additional options to send to rngd. See the rngd(8) manpage for
# more information.  Do not specify -r/--rng-device here, use
# HRNGDEVICE for that instead.
#RNGDOPTIONS="--hrng=intelfwh --fill-watermark=90% --feed-interval=1"
RNGDOPTIONS="--hrng=viakernel --fill-watermark=90% --feed-interval=1"
#RNGDOPTIONS="--hrng=viapadlock --fill-watermark=90% --feed-interval=1"

Then restart rngd:

# /etc/init.d/rng-tools restart
Stopping Hardware RNG entropy gatherer daemon: rngd.
Starting Hardware RNG entropy gatherer daemon: rngd.

# ps aux|grep rngd
root      6539  3.2  0.0  30628   616 ?        SLsl 17:42   0:00 /usr/sbin/rngd -r /dev/hwrng --hrng=viakernel --fill-watermark=90% --feed-interval=1

And, as a result, the entropy pool filled up immediatly:

# cat /proc/sys/kernel/random/entropy_avail
3968

A simple test shows the immense difference in entropy available. The results below show that retrieving 120kB of randomness takes 3.4s with rngd enabled, and forever without it. I had to kill dd after several minutes because it was getting nowhere. As soon as I restarted rngd, the pool filled up again.

# dd if=/dev/random of=randomstuff bs=128 count=1024
768+256 enregistrements lus
768+256 enregistrements écrits
120181 octets (120 kB) copiés, 3,47491 s, 34,6 kB/s

# /etc/init.d/rng-tools stop
Stopping Hardware RNG entropy gatherer daemon: rngd.

# dd if=/dev/random of=randomstuff bs=128 count=1024
^C2+10 enregistrements lus
2+10 enregistrements écrits
450 octets (450 B) copiés, 114,238 s, 0,0 kB/s

# cat /proc/sys/kernel/random/entropy_avail
103

# /etc/init.d/rng-tools start
Starting Hardware RNG entropy gatherer daemon: rngd.

# cat /proc/sys/kernel/random/entropy_avail
3968

I've had this server for 3 years, and I never thought it supported a hardware RNG. Today is a good day :)