Using the TPM’s random number generator

Random number sources

[2020 Update] Josh now trains embedded engineers at Advanced Security Training. In a recent class, we built a TPM in Verilog on a Xilinx Zynq Device. Check out Advanced Security Training or subscribe and don’t miss Josh’s upcoming class announcements!


With the compliance vectors cleared from the TPM, the TPM can be integrated in other system services. This post will show you how to add the TPM as a hardware random number generator source with the rng-tools package.

Random number sources

Random number generators are an active topic of discussion among the cryptographic community. In Linux, the urandom vs random debate is equally opinionated. This post seeks only to show you how to use the TPM’s random number generator in Linux.

The decision on which random number generator source to use is left up to you. I’ll provide the following example on why using an external random source is advantageous. Without some sort of external entropy, you will quickly deplete the entropy on the BeagleBone. For example, if you try to generate a GPG key on the vanilla BeagleBone, be prepared to wait a very long time. This is the benefit of hardware random generator; it provides a much needed entropy source for otherwise entropy-starved embedded systems.

You don’t need to use the TPM however. You could use a dedicated open-source hardware random number generator like OneRNG or use a software entropy daemon like haveged. If you have a BeagleBone Black with a kernel greater than 3.13, you can use the built-in OMAP RNG. Presumably you have the CryptoCape, so let’s use the TPM.

Installing rng-tools

Install rng-tools with the familiar:

[code language=”bash” light=”true”]
sudo apt-get install rng-tools
[/code]

You’ll probably see the following error since we haven’t told it how to use the TPM:

[code language=”bash” light=”true”]
Starting Hardware RNG entropy gatherer daemon: (Hardware RNG device inode not found)
/etc/init.d/rng-tools: Cannot find a hardware RNG device to use.
invoke-rc.d: initscript rng-tools, action “start” failed.
[/code]

This can be solved by loading the tpm-rng module (as root):

[code language=”bash” light=”true”]
modprobe tpm-rng
echo tpm-rng >> /etc/modules
[/code]

Then edit /etc/default/rng-tools so that it looks like the following:

[code language=”bash”]
# 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

# 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=”–fill-watermark=90%”
[/code]

Finally restart rng-tools:

[code language=”bash” light=”true”]
service rng-tools restart
[/code]

The daemon will need to run for a while to provide an useful output, but the impenitent can send the SIGUSR1 signal to dump some output to the syslog:

[code language=”bash”]
root@hotblack:# pkill -USR1 rngd
root@hotblack:# tail -n 15 /var/log/syslog
Aug 20 02:35:32 hotblack rngd[457]: stats: bits received from HRNG source: 60064
Aug 20 02:35:32 hotblack rngd[457]: stats: bits sent to kernel pool: 16384
Aug 20 02:35:32 hotblack rngd[457]: stats: entropy added to kernel pool: 16384
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2 successes: 3
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2 failures: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2(2001-10-10) Monobit: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2(2001-10-10) Poker: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2(2001-10-10) Runs: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2(2001-10-10) Long run: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS 140-2(2001-10-10) Continuous run: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: HRNG source speed: (min=22.278; avg=24.461; max=25.808)Kibits/s
Aug 20 02:35:32 hotblack rngd[457]: stats: FIPS tests speed: (min=11.293; avg=11.317; max=11.340)Mibits/s
Aug 20 02:35:32 hotblack rngd[457]: stats: Lowest ready-buffers level: 2
Aug 20 02:35:32 hotblack rngd[457]: stats: Entropy starvations: 0
Aug 20 02:35:32 hotblack rngd[457]: stats: Time spent starving for entropy: (min=0; avg=0.000; max=0)us
[/code]

Thanks to this blog post for providing most of the details.