rtl2832_entropyd - A program to use an rtl2832 USB dongle to generate
random data to feed the linux kernel /dev/random entropy pool.
SYNOPSIS
rtl2832_entropyd [-a --amplify=gain]
[-c --config-file=rtl2832_entropyd config file]
[-d --device_idx=device index]
[-e --entropy_buffer=buffer size]
[-g --group=group id]
[-h --help]
[-o --output_file=filename]
[-p --pid_file=pid file]
[-q --quiet level]
[-r --raw_buffer=raw buffer size]
[-t --test_stdout]
[-u --user=user id]
[-w --minimum_frequency=minimum frequency]
[-x --maximum_frequency=maximum frequency]
[-y --minimum_sample_rate=minimum sample rate]
[-z --maximum_sample_rate=maximum sample rate]
OPTIONS
-a --amplify=gain
Set the gain for the device.
These usually have discrete gain values
that are allowed. They will be listed
if not quiet, or they can be found by
running rtl_test from the rtl-sdr
library. The default is to use the
maximum available. If a value is given,
the nearest available gain will be used.
-c --config-file=rtl2832_entropyd config file
If run from the command line,
allows a configuration file to
be specified. Useful for testing. Configuration isn't recursive. If
a configuration file isn't specified, the program looks first for
/etc/rtl2832_entropyd.conf
then
/etc/sysconfig/rtl2832_entropyd.conf
If no configuration is found, internal defaults are used.
-d --device_idx=device index
The index of the rtl2832 USB dongle to use.
If not specified, it uses the last available rtl2832 device.
-e --entropy_buffer=buffer size
How many bytes of entropy to extract
before making them available to the pool or writing them to
a file. The default size is 512 bytes, which is the size of
the /dev/random kernel entropy pool.
-g --group=group id
The group id to run the program as.
It defaults to rtl2832_entropyd.
-h --help
Gives a short usage synopsis.
-o --output_file=filename
Write the entropy to a binary file
that can be used to feed programs like rngtest or dieharder.
For testing. .e.g
rtl2832_entropyd -o high_entropy.bin
dieharder -a -f high_entropy.bin -g 201
Such files should be a gigabyte or larger to be at all meaningful. This is as much entropy as a home user might use in a year or two.
By default, rtl2832_entropyd forks as a daemon; this prevents that.
-p --pid_file=pid file
When run as a daemon, writes this as the pid file.
-q --quiet=level
The level of verbosity from the program.
0 writes nothing, 1 writes errors, 2 writes informational message,
and 3 writes debug information.
-r --raw_buffer=raw buffer size
How many bytes to read from the device
at each frequency and sample rate. The entropy is extracted from
these bytes in chunks of entropy buffer size. For speed when
testing, this should be large. When feeding the pool, it is
better to be smaller so that data is read from lots of random
frequencies at lots of random sample rates. That slows down
extraction, but the device generates entropy so much faster than
it is used, it doesn't really matter. The default size is 4096.
The rtl-sdr library specifies that the minimal length is 512 bytes, the
maximum length is 4 MBytes, and the default is 64 KBytes. The buffer
used with rtl-sdr must align with a 256 byte boundary.
-t --test_stdout
Tells the program that it should send the output to stdout for
testing. .e.g.
rtl2832_entropyd -t | rngtest -p -b 1000 | dieharder -d 0 -g 200
will send the output through rngtest, filtering failures, then send it on to dieharder to do a birthday test. Dieharder uses a lot of data. It isn't feasible to run the full test suite at the rates that rtl2832_entropyd generates entropy, ~ 6.9 MBits/second at fastest. It might be possible, depending on the test, to stream to an individual test and get a result in a reasonable amount of time.
By default, rtl2832_entropyd forks as a daemon; this prevents that.
-u --user=user id
This is the user id to run the program as.
It defaults to rtl2832_entropyd.
-w --minimum_frequency=minimum frequency
This is the low end of the range
from which a random frequency is selected to sample for data.
Default is 880, which is 88 MHz.
-x --maximum_frequency=maximum frequency
This is the high end of the range
from which a random frequency is selected to sample for data.
Default is 1080, which is 108 MHz.
-y --minimum_sample_rate=minimum sample rate
This is the low end of the range
from which a random sample rate is selected to use while sampling data.
Default is 100, which is 1 MHz.
-z --maximum_sample_rate=maximum sample rate
This is the high end of the range
from which a random sample rate is selected to use while sampling data.
Default is 240, which is 2.4 MHz.
DESCRIPTION
rtl2832_entropyd is a program that is designed to feed entropy into the linux /dev/random kernel entropy pool. It automatically forks and runs as a daemon, unless one of the testing options, -o or -t, are selected. Then it never forks.
The program flow is simple. Configure, initialize the rtl2832 device, do a priming run to set everything up, then loop continuously, reading data from the rtl2832, extracting entropy from it, and sending it to the pool.
While it is looping, each time it reads a buffer of raw data, it changes the frequency and sample rate to random values in the configured range. It uses the previosly extracted entropy, in combination with current frequency and sample rate, as the randomness with which to select the next values to use.
The frequency range is split in half. One sample is taken from the lower range, and one from the upper range. The sample rate is drawn from a single range.
The algorithm used is fairly complicated. Two 256 bit buffers are filled with bytes from the raw buffers of two samplings of the device. A series of 4 bits are then read from a sequence that is 512 bits long. The 512 bit sequence is roughly optimized to maximize the independence of the bits. These bits are summed. If the sum of the bits is even, the entropy bit is a zero. If odd, a 1. The entropy bit is then written to the entropy buffer. No further filtering or conditioning of the entropy is used. In testing, output failed the rngtest at < .1%, comparable to the /dev/urandom PRNG in the kernel. The output is too slow to test as a streaming feed to dieharder, as it uses terabytes of data, especially in the later tests. But using files, I ran data through dieharder, with mostly passes and a few weak results. Almost 12 GBytes, which is probably over a decade of entropy used by the kernel for the average home system. In entropy terms, rtl2832_entropyd extracts 2 bits of entropy for every 8 bits of raw data.
I found that the FM range, 88 MHz to 108 MHz, is the best range for extracting entropy with the dongle as provided. There is a much larger range, but outside this range, the error rate goes up from .1% on rngtest to ~ 3%. I suspect that the little 15 cm antenna that comes with it is optimized for FM, and if a better antenna was used, these error rates would drop. The devices have a far wider range, mine is from 28 to 1766 MHz.
Running with two 4 MB raw buffers, a 4096 byte entropy buffer, two frequency ranges from 88 to 98 MHz and 98 to 108 MHz, and sampling frequencies from 2.0 to 2.4 MHz, entropy output is ~6.9 MBits per second. That is, it could replace the entire /dev/random kernel entropy pool ~ 1700 times/second. This is fast enough to write a test file, but not fast enough to run the full dieharder test suite in real time.
In production, I shrink the buffers so that data is read more often, at varying frequencies and sample rates. This helps prevent spoofing. A pair of 4 MB raw buffers will yield 16 MBits of entropy. This is about two to three weeks of entropy requiremnt, which I think is too large. I estimate that the 4096 byte raw buffers are refreshed about every 5 minutes with the defaults. Of course, you can set them however you want. When I set raw buffer size to 4096, entropy buffer to 512, frequency range from 100 to 240, with the default FM range, the rate of entropy creation drops to ~ 90 kbits / second. Still more than fast enough to feed the kernel entropy pool.
The program limits randomness to tenths of a MHz for frequency, and hundredths of a MHz for sample rate. Let's use the previous example configuration: running with 4 MB raw buffers, a 4096 byte entropy buffer, two frequency ranges from 88 to 98 MHz and 98 to 108 MHz, and sampling frequencies from 2.0 to 2.4 MHz. There will be 100 random possibilities for frequency for each buffer, and 40 random possibilities for sample rate. This means that there are 16 million possible combinations. Someone with the resources could monitor all of them.
Except I think there are two reasons this is infeasible, and so this is secure.
First, even if someone is monitoring all the frequencies, they need to be using my antenna to get my data stream. An antenna right next to it might be close, but if its outside the room, it picks up a slightly different signal.
Second, they need to sample at the exact same time as I do. There is an analog signal that we are taking samples of. If we sample it at different times, even if we are sampling at the same rate and frequency, our samples will be different.
In production, while I leave the frequency range the same as the above example, I change the sample rate range to be from 1 Mz to 2.4 Mz, so the number of possible sample rates is 140. This increases the combinations to 196 million. This slows the rate of entropy generation down considerably, but it is still more than adequate.
Another advantage is that the hardware is commodity, so they are relatively cheap; I bought one on Ebay for under $10 US.
If you use this program, I recommend you set the /proc/sys/kernel/random/urandom_min_reseed_secs to a lower number, say 5. And that you change /proc/sys/kernel/random/write_wakeup_threshold to something higher, like 3840. This will allow the PRNG in the kernel to be more robust, as it will draw entropy from the /dev/random pool more often.
I think it is a good idea to put something like
P "rtl2832-entropyd" /usr/bin/echo 3840 > /proc/sys/kernel/random/write_wakeup_threshold && /usr/bin/echo 5 > /proc/sys/kernel/random/urandom_min_reseed_secs && /usr/sbin/rtl2832-entropyd
in the /etc/cron.d/dwatch file so the daemon will be restarted within 5 minutes if it is stopped for any reason.
Or put it in an /etc/rc.d/rc.local file, so the daemon is automatically started with every boot.
COMPILING
There is nothing sophisticated about the setup. There is no configuration program, just a Makefile. If you have the header files for libcap and librtlsdr installed, the procedure should be as simple as
tar -zxvf rtl2832_entropyd.{version}.tar.gz
cd into the resulting rtl2832_entropyd.{version} directory.
make
make install will put the files into the /usr/local heirarchy.
But rtl2832_entropyd won't find the configuration file unless it is in the /etc or /etc/config location. You can point to the user/local file with the -c option, so it picks it up, or move it into the production location.
There is an init.d.rtl2832_entropyd file for use with init.d systems, and an rtl2832_entropyd.service file for use with systemd, but neither is automatically installed.
QUICK START EXAMPLES
To run rtl2832_entropyd as a daemon with the default values simply run:
rtl2832_entropyd
To create a file for use in testing run:
rtl2832_entropyd -o file name
dieharder -a -f file name -g 201
To pipe via stdout to a test program like rngtest or dieharder run:
rtl2832_entropyd -t | rngtest -b 1000
rtl2832_entropyd -t | rngtest -p -b 1000 | dieharder -a -g 200
rtl2832_entropyd -t | dieharder -d0 -g 200
BEST PRACTICE
Before you use this program, test it with your situation. I am satisfied with the performance I get here, but you need to be sure it is working for you.
WARNING
There is no guarantee that this program is producing random numbers, entropy. I haven't run the full dieharder suite the thousands of times that would be necessary to say with confidence that it seems to be.
All the tests I have run suggest that it is, but that is all I can say. See the PUBLICATION RULES immediately below.
However, running the raw data from the rtl2832 through rngtest or dieharder fails 100% of the time. That is, the raw feed is not random. I am not sure if this is because of the device characteristics, the rtl-sdr library, or the underlying analog data. The rtl-sdr library uses a 32 value symmetric finite impulse response (fir) filter while sampling. I think this would have the effect of causing correlation in neighboring values, which is why I took the approach I did.
PUBLICATION RULES
rtl2832_entropyd
is partially original code and partially GPL derived code, and can
be modified and used at will by any user, provided that:
a) The original copyright notices are maintained and that the source, including all modifications, is made publically available at the time of any derived publication. This is open source software according to the precepts and spirit of the Gnu Public License. See the accompanying file COPYING, which also must accompany any redistribution.
b) Full responsibility for the accuracy, suitability, and effectiveness of the program rests with the users and/or modifiers.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ACKNOWLEDGEMENTS
This program uses, and couldn't exist without, the rtl-sdr library,
http://sdr.osmocom.org/trac/wiki/rtl-sdr
It is derived from rtl-entropy, an rtl2832 random number generator that feeds a fifo. Think /dev/urandom or /dev/random
http://github.com/pwarren/rtl-entropy
The other parent is audio_entropyd, which is no longer under active development,
though still working, since I use it. The last developer of audio-entropyd,
Folkert van Heusden
http://www.vanheusden.com/entropybroker
http://github.com/flok99/entropybroker
I think this approach makes more sense than rtl2832_entropyd for server rooms and virtual devices. But you have the choice.
I used information from the page at
http://www.ab9il.net/software-defined-radio/rtl2832-sdr.html#linux
to better understand the rtl2832 device.
I first became aware of the rtl2832 via the wikipedia page.
http://en.wikipedia.org/wiki/Comparison_of_hardware_random_number_generators
There are many other hardware TRNGs listed there. If you are looking at this project, you are in the market, and one of them might serve your needs better.
The author of rngtest, Henrique de Moraes Holschuh
The author of dieharder, Robert G Brown
Without the ability to test the output for randomness, it would have been impossible to develop rtl2832_entropyd.
COPYRIGHT
Copyright 2015 Stan Lysiak
GPL 3; see the file COPYING that accompanies the source of this program. This is the "standard Gnu General Public License version 3 or any later version"