This weekend I've been noodling around with my perennial project of building a ersatz HSM (what are you using to protect your home CA root?) A fresh install of Debian 10 on a PCEngines APU2 later, I started some basic setup. One of the first things I started playing with was a source of randomness for the system. In "production" there won't physically be any network connections, and as an isolated box where presumably you'd boot it up, do one or two operations, and shut it back down, there's not a lot of chance to collect some entropy. Those operations will also tend to be things like "generate cryptographic keys", which consume a lot of entropy. "Low entropy generation" and "high entropy consumption" isn't a happy recipe.
Ages ago, I picked up a ChaosKey, which is a USB-based hardware random number generator with support in the Linux kernel. I've only got one, currently, and it is another thing I have to plug in and have stick out of the APU2, but then I remembered something else.
When I put this system together, however, I also bought the PCEngines TPM module, based on the Infineon TPM SLB 9665 line, which plugs into the LPC port on the board and provides a TPM 2.0 module. At the time, the idea was to play with the APU2 vboot and measured boot process. In the meantime, however, the TPM module also provides a hardware random number generator, which also apparently is supported by the Linux kernel.
The first question that came to mind is "okay, how to I see that
this is working?" A little looking lead me to the rng-tools
,
which includes a daemon, rngd
which will read from the
hardware random number generator (HWRNG), do some entropy quality
checks on it, and then fold that entropy into the kernel pool. So I
started that up, but I still didn't know if it was working. Checking
the status of the rng-tools
service in systemctl
I saw this:
Mar 08 16:43:09 hsm-test0 rngd[666]: block failed FIPS test: 0x1f Mar 08 16:43:09 hsm-test0 rngd[666]: block failed FIPS test: 0x1f Mar 08 16:43:09 hsm-test0 rngd[666]: Too many consecutive bad blocks of data, check entropy source! Mar 08 16:43:09 hsm-test0 rngd[666]: Throttling down entropy source read speed...
Okay, I thought, did I miss something in setting up the TPM? Do you have to go through the process of claiming the TPM and setting up ownership keys before the HWRNG starts working properly? It certainly isn't returning anything useful:
$ sudo hexdump -n 512 -C /dev/hwrng 00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * 00000200
Digging, I discovered that the APU2 is based on the AMD GX-412TC SOC, which includes AMD's "Cryptographic Coprocessor" and "Platform Security Processor", which appears to be an embedded ARM processor designed to work as a secure enclave of sorts. Anyways, I can see that it's there, and currently what the system is using as it's HWRNG:
$ cat /sys/class/misc/hw_random/rng_available ccp-1-rng tpm-rng-0 $ cat /sys/class/misc/hw_random/rng_current ccp-1-rng
You can switch the current HWRNG by writing to /sys/class/misc/hw_random/rng_current
:
$ /bin/echo -n "tpm-rng-0" | sudo tee /sys/class/misc/hw_random/rng_current
Which certainly seems to work better now:
$ sudo hexdump -n 512 -C /dev/hwrng 00000000 14 e4 bd d5 aa 82 c1 93 bb 06 05 2c 7c fc bd 26 |...........,|..&| 00000010 c6 41 b9 45 d9 c9 49 ef bc 34 54 16 1a 3c 81 68 |.A.E..I..4T..<.h| 00000020 bf f3 b1 b3 a7 eb 0c 89 c9 4e f9 77 6b be e3 41 |.........N.wk..A| 00000030 bf e0 16 9b 4f 04 a1 0c e1 fc 78 7c f8 d4 b9 c6 |....O.....x|....| [...]
You can also use rngtest
to run the same tests rngd
uses to check the quality of the entropy from the HWRNG:
$ sudo dd if=/dev/hwrng status=none | rngtest -c 100 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=53.131; avg=55.470; max=68.755)Kibits/s rngtest: FIPS tests speed: (min=10.474; avg=11.068; max=11.401)Mibits/s rngtest: Program run time: 35478549 microseconds
I'm not sure why the AMD CCP HWRNG is returning bogus data, I suspect
that the BIOS in the APU2 isn't properly initializing it, but don't
know for sure. There are two options: manually select which HWRNG I want
to use as shown above, or simply not load the CCP kernel module. Given that
the HWRNG on the CCP is obviously not working, I have no idea if anything
else on it is also working, so it's probably best not to trust it. You
can disable it by creating /etc/modprobe.d/blacklist.conf
with the following contents:
blacklist kvm_amd blacklist ccp
(kvm_amd
causes ccp
to be loaded, even if
I blacklist it — I'm not using KVM on this box anyways, so I
blacklist it as well). Run sudo update-initramfs -u
and
reboot, and it no longer shows up and rngd
is happy.
For comparison, here's the output of rngtest
after switching
to use the ChaosKey:
$ sudo dd if=/dev/hwrng status=none | rngtest -c 100 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=2.778; avg=5.023; max=7.798)Mibits/s rngtest: FIPS tests speed: (min=10.162; avg=12.822; max=14.004)Mibits/s rngtest: Program run time: 664867 microseconds
It generates entropy much much faster than the TPM, but I think the TPM will be fine with keeping up. Plus, it's already in the box.