Installing and testing OneRNG
OneRNG is an Open Hardware random number generator that plugs into USB. You can learn more about it on its website, its original Kickstarter campaign or in an LWN.net article from 2015. There is also a somewhat more technical project documentation.
Back in January, the OneRNG went back on sale. Jenix organized a group order and about two weeks ago, our units arrived. Here is what I have learned since then.
Installation
The packaging of the OneRNG contains a URL which leads to the installation instructions, including instructions for a physical examination of the device to make sure it has not been tampered with. However, the instructions for installing the software are a little sparse. They are fine if you run Debian or Fedora, but if you're building your Linux system in a more manual way and if you're compiling your own kernels, you might need some additional information.
The installation package simply installs a couple of scripts. Here is a brief overview of what each of them does:
/lib/udev/rules.d/79-onerng.rules
is a udev rule which triggers actions when the OneRNG gets plugged in or out/sbin/onerng_verify.py
is a python script that verifies the firmware of the OneRNG against a PGP public key which is hard-coded into the script/sbin/onerng.sh
gets called by the udev script mentioned above every time the OneRNG gets plugged in or out. Simply put, it does the following:- Initiate the hardware
- Check the firmware
- Start harnessing the OneRNG randomness by reading from the random number generator, scrambling the output by encrypting it with OpenSSL and then passing it to the rngd. The rngd then feeds the randomness into the Linux Kernel's entropy pool.
- Stop OpenSSL and the rngd when the OneRNG gets removed.
Personally, I use Gentoo, but have also helped installing a OneRNG on an Arch system. Presumably, these steps are more or less the same on most distributions.
Kernel
The device needs the CDC ACM driver. The kernel option for the driver is called CONFIG_USB_ACM
. In menuconfig
, you can find it like so:
Device Drivers --->
[*] USB support --->
<M> USB Modem (CDC ACM) support
I suggest installing it as a module that you can load and unload. The module will be called cdc_acm
.
Dependencies
There are a couple of dependencies:
* rngd
- a daemon that feeds randomness to the kernel. Usually packaged as "rng-tools"
* at
* python-gnupg
- a Python interface to GnuPG
On Gentoo, you can install those dependencies via
emerge -av \
sys-process/at \
dev-python/python-gnupg \
sys-apps/rng-tools
The service atd
needs to be started when the OneRNG is plugged in. To avoid the hassle of having to start it manually every time you plug in your OneRNG, just add it to the default runlevel:
# OpenRC
rc-update add atd
/etc/init.d/atd start
/etc/init.d/atd start
# Systemd
systemctl enable atd
systemctl start atd
For me, the version of python-gnupg
packaged for Gentoo (0.3.8) did not work. Apparently the output is formatted in a way which the onerng_verify.py
script did not understand. As a result, the firmware verification failed every time. Eventually, I installed a newer version of python-gnupg
through pip
as user root:
pip install --user python-gnupg
The package is stored in /root/.local/lib64/python3.4/site-packages/
.
Software
# Download the tarball from github
cd /usr/src
wget https://github.com/OneRNG/onerng.github.io/raw/master/sw/onerng_3.5.orig.tar.gz
# Unpack it
tar xzvf onerng_3.5.orig.tar.gz
cd onerng_3.5
# Install the software
./configure
make install
# Make udev reload the rules so it learns about the new one
udevadmin control --reload-rules
Testing
You can test the OneRNG by having a look at the randomness pool of your kernel, depleting it and then seeing how fast it fills up again.
First, you'll want to make sure no other instances of rngd
are running that might be filling up your randomness pool:
# Systems using sysv-init or OpenRC
/etc/init.d/rngd stop
# Systems using systemd
systemctl stop rngd
# Also kill manually started instances
until ! killall rngd; do continue; done
Also make sure that the OneRNG is not plugged in at the start of this test, so you can get a good comparison of what happens.
Check how much randomness is available (it usually tops out at 3800 and a bit):
cat /proc/sys/kernel/random/entropy_avail
Deplete all randomness (hit ctrl
+c
after a few seconds):
cat /dev/random > /dev/null
Then check your randomness pool again. It should now have a much lower value. If you check yet again, you should see that it's raising steadily but rather slowly.
Now plug in the OneRNG, then deplete the randomness again. If you now check the available randomness again, you should see that it is raising up to 3800 within seconds.
Here is a simple copy&paste script for the tests performed above. Make sure you do this in a new terminal though:
cat << EOF | bash
echo -n "Randomness avialable at the start: "
cat /proc/sys/kernel/random/entropy_avail
echo "Emptying randomness pool"
cat /dev/random > /dev/null &
sleep 1
kill %1
echo -n "Randomness just after depletion: "
cat /proc/sys/kernel/random/entropy_avail
sleep 1
echo -n "Randomness one second after depletion: "
cat /proc/sys/kernel/random/entropy_avail
EOF
Here is my output before and after plugging in the OneRNG:
# Before
Randomness avialable at the start: 2554
Emptying randomness pool
Randomness just after depletion: 22
bash: line 10: 10318 Terminated cat /dev/random > /dev/null
Randomness one second after depletion: 143
# After
Randomness avialable at the start: 3116
Emptying randomness pool
Randomness just after depletion: 7
bash: line 10: 10381 Terminated cat /dev/random > /dev/null
Randomness one second after depletion: 3100
From the value one second after the depletion, you can clearly see how much faster the available randomness is rising when the OneRNG is plugged in and working.
Debugging
It's annoying to have things not working and not knowing why and what to do. So here are some things you can have a look at if the OneRNG is not working for you. Most of the commands below will have to be run as root.
- When the software is working, a bright yellow LED should turn on on the OneRNG after it's plugged in
- When randomness is drawn from the OneRNG, the LED becomes dimmer. You can watch this happened by typing
cat /dev/random > /dev/null
- When randomness is drawn from the OneRNG, the LED becomes dimmer. You can watch this happened by typing
- Make sure the kernel module is loaded. It's called
cdc_acm
. You can check which modules are loaded by runninglsmod
. The module gets loaded automatically when the device gets plugged in. If for some reason it does not, you can always load it manually by runningmodprobe cdc_acm
- After plugging the device into your computer, check the output of
dmesg
to verify the device was recognized correctly:
[105837.526045] usb 1-1.2: new full-speed USB device number 8 using ehci-pci
[105837.609531] usb 1-1.2: New USB device found, idVendor=1d50, idProduct=6086
[105837.609535] usb 1-1.2: New USB device strings: Mfr=1, Product=3, SerialNumber=3
[105837.609537] usb 1-1.2: Product: 00
[105837.609539] usb 1-1.2: Manufacturer: Moonbase Otago http://www.moonbaseotago.com/random
[105837.609541] usb 1-1.2: SerialNumber: 00
[105837.610312] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device
- In the last line, you can see the name of the new device. Using this, you can now find it in your filesystem:
ls /dev/ttyACM0 && file /dev/ttyACM0
/dev/ttyACM0
/dev/ttyACM0: character special (166/0)
- Use
lsusb
(usually available in a packaged calledusbutils
) to see if the device was recognized correctly (The Bus and Device numbers will be different on your computer, the ID should be the same):
[...]
Bus 001 Device 008: ID 1d50:6086 OpenMoko, Inc.
[...]
- The scripts spawn two processes:
rngd -f -n 1 -d 1 -r /dev/stdin
openssl enc -aes128 -nosalt -in /dev/ttyACM0 -pass file:/dev/ttyACM0 -out /dev/stdout
To check if they are running, use ps -faux | grep -e openssl -e rngd
. Here is the output on my system:
root 10947 0.0 0.0 11516 884 pts/1 S+ 01:09 0:00 \_ grep --colour=auto -e openssl -e rngd
root 10376 0.0 0.0 15896 3732 pts/1 S 00:58 0:00 openssl enc -aes128 -nosalt -in /dev/ttyACM0 -pass file:/dev/ttyACM0 -out /dev/stdout
root 10377 0.0 0.0 9488 836 pts/1 S 00:58 0:00 rngd -f -n 1 -d 1 -r /dev/stdin
- The results of the firmware verification get written to the system log. For me the messages end up in
/var/log/messages
. Here are sample messages for a successful and a failed firmware verification:
Successful firmware verification:
Mar 12 00:58:17 pcsm1501 OneRNG[10341]: firmware verification passed OK - version=3
Invalid firmware detected / unsuccessful firmware verification:
Mar 9 19:25:45 pcsm1501 OneRNG[14816]: firmware verification failed: Invalid firmware signature: 3
- If you start the script manually, you can see some more potentially informative / useful information. Make sure you pass the correct
ttyACMn
device (checkdmesg
to find out which one is the correct one):
/sbin/onerng.sh daemon ttyACM0
Here is the output from a successful run:
/sbin/onerng.sh: line 192: 11415 Terminated dd if=/dev/$2 iflag=fullblock of=$t bs=1
/sbin/onerng.sh: line 192: 11420 Terminated dd if=/dev/$2 iflag=fullblock of=$t bs=4
nohup: redirecting stderr to stdout