GRAND - 6Mbps USB True Random Number Generator

Submitted by GG on Sun, 02/28/2021 - 14:48
Project Status

GRANDA good random numbers generator is fundamental to ensure the security of many modern data encryption algorithms. Depending on the workload, the entropy collected automatically by the kernel might not be sufficient to generate the random numbers at the requested rate. In these cases an external entropy source can greatly improve performance. GRAND is a USB TRNG (True Random Number Generator) based on the ST Microelectronics STM32.


While researching entropy sources we evaluated several strategies: radioactive decay, Zener avalanche noise and thermal noise. Most of these solutions however require board space for the circuit and produce a non white noise. Whitening the noise either reduces the amount of random data or requires computing power only available on the larger and more expensive MCUs.
During our research we noticed that several modern MCUs have an internal hardware random number generator which meets all the requirements and can fit in a tiny USB stick.
The two final candidates were the STM32L052/062 and the Microchip ATSAML21. Both have a ARM Cortex-M0 CPU core, an HW full speed USB implementation and a suitable TRNG.
We opted for the STM32 because we are more familiar with the programming environment.
The schematics implements a minimal STM32 USB system. A small 3.3V regulator provides power to the MCU, an combination ESD diode protects the MCU USB pins and a bi-color LED to show the device status.


To maximize software compatibility the firmware implements a VCP (virtual Com Port). Data is output constantly in binary form. GRAND performs Chi Squared test on the output data on 256KBytes blocks. If the statistics falls outside an acceptable range the device stops generating numbers. This check can be disabled to slightly increase the performance.
Control of the device is accomplished by writing to the VCP port (echo 'cmd' >/dev/hwrandom). Three commands are currently supported:
'0' No data test
'X' Perform Chi Squared test on the output data
'RST' reset the device

Configuration and use

On plug events GRAND will show up as a ttyACMx device. To make life easier a simple udev rule can be placed in /dev/udev/rules.d
ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="3e11", \
MODE="600", GROUP="root", TAG+="uaccess", ENV{ID_MM_DEVICE_IGNORE}="1", \
SYMLINK+="hwrandom", RUN+="/usr/bin/stty -F /dev/%k -echo raw"

The rule also puts the kernel driver in raw mode and disabled echo (this is required to obtain the maximum speed). Commands can be sent using echo to the appropriate device node.

Random data can be read from the device using any method. The following dd command can be used to save 64MBytes to a file in raw binary format:
dd if=/dev/hwrandom of=random.bin bs=64k count=1k iflag=fullblock status=progress

GRAND is also compatible with rng-tools to enhance the kernel entropy pool.

The green LED will light up when the device is generating/sending random numbers to the host computer.
The red LED will blink briefly during transfer when the chi-squared test is enabled. A solid red LED means the device has been stopped because the data failed the chi-squared test.


GRAND can output random numbers at about 800KBytes/s. The maximum speed is limited by the CPU and the USB full speed HW block inside the MCU. The standard STM32 CDC implementation that is supplied by the STM CUBE IDE is much slower (about 100-150KB/s). To achieve the higher speed we investigated the use of double buffer endpoints but the copy to USB RAM took too long to take full advantage of the feature. We ended up allocating multiple buffers in the USB RAM and stream the random numbers directly to these buffers. The USB ISR has been rewritten to prioritize servicing the CDC BULK endpoint and quickly update the TX pointer to the next available buffer.

The random number generated consistently pass FIPS-140 (rngtest), ent and dieharder. The numbers can be used directly or they can be used as an etropy source for the kernel RNG. Using GRAND in conjunction with rngtools will make /dev/random generate bits significantly faster. On our test workstation we went from 30Bytes/s to more than 200KBytes/s.

Filed under