pwarren/rtl-entropy

Create a char device in /dev

Opened this issue · 6 comments

rtl-entropy should create a character device instead of a named pipe.

Okay, I've had a quick read, and I'd thought that this would only be possible by creating a kernel driver, which I have no idea about how to even start!

There's ways of getting around that such as LD_PRELOAD, UInput or CUSE, but that's looking like being a bit beyond what I'm capable or interested in doing.

Can you please expand on why you think it should be a characer device?

I left it as a named pipe so that I didn't have to worry about kernel drivers, and so that there's some usefulness to my software outside linux systems.

Fair enough. I suggested a character devices instead of a named pipe for the sake of rngd(8), as it appeared to not take kindly to named pipes. However, things seem to be working now, so meh.

With that said, a character device will be more secure than a named pipe. At that point, it's in kernel space instead of user space, which would require a bit more work to compromise the stream of random numbers.

You could look at audio-entropyd. It is a daemon that uses entropy from a sound card to feed directly into the kernel's entropy pool. I use it, and it works fine. I was thinking of purchasing an RTL2832U device to add a different cheap entropy source (~$8 on Ebay), and was looking at your entropy application. Was thinking of transferring the code that does the pool feed in audio-entropyd to your app, so I could just (re)start it like I do audio-entropyd, from a cron job. So I saw this ticket, and decided to give you the opportunity. :-)

I hacked audio-entropyd a little already to standardize the interface, so the version I am using is different than the original, I think. I offered the new code, but I don't think it was accepted. I was going to use the entropy algorithms I created to extract entropy from the RTL2832U if it was necessary, as well. It doesn't seem that that is necessary, as from what I understand you generate entropy directly. And the kernel always massages the entropy fed to it by putting it through a hash, no matter how good it is.

Hi zipnemud,

My plans for the next version do include an option to stuff bits directly into the kernel pool, using the RNDADDENTROPY() system call on systems where that's supported. But any code you wish to add would be much appreciated!

I've no idea exactly when I'll start getting this stuff done, but hopefully before OSDC in hobart I'll have something together!

Thanks for the response.

Well, I was going to use the idea triggered by Tony Wong's rtlsdr-airband, https://github.com/microtony/RTLSDR-Airband, to scan several channels. Like audio-entropyd on steroids.

Open two random frequencies in the range, at highest device sample rate available. Grab 4k or 8k bytes. Close the device. Then use comparisons between the two channels to generate entropy. e.g. different sign, 1, same sign 0, or both switch sign, 1, both stay same, 0, etc. Would need testing. If more needed, open two new random frequencies, and repeat. Because the sample rate on the rtlsdr device is so high, this will easily keep up with normal demands from the kernel entropy pool. Probably wouldn't work for running monte carlo simulations, or other high demand applications.

I think this whole idea of using randomness directly is wrong. What we want for security aren't random bits, but unpredictable, cryptographically strong bits. Like what the modified mersenne twister on /dev/urandom provides. They should be passed through tests like you do in your app before they are used, to weed out weak numbers. Random bits are more suitable for games.

I've thought about hacking the kernel /dev/urandom generator to have four copies of the prng, switching among them using the entropy source. There's research showing that this is cryptographically strong (or at least I interpreted it that way ;-) ). But, it's just a pie in the sky project for me, and beyond my expertise, so won't happen.

So, I'll probably leverage the audio-entropyd code, combine it with your code in some form, and create something that does the above. Then, I'll hook it up to the kernel pool, and run the diehard tests, etc. on the result from /dev/random and see if it passes. Because of the hash, there is always a percentage of failures. Maybe, it would be better to generate files and run the tests directly from the files instead for testing purposes.

As you can tell, I think it is better to use algorithms on the samples, rather than using them directly. I'm not a cryptographer, but I think it is better entropy to do it that way. Harder to spoof, too, because the attacker has to know the random frequencies I sampled as well as the algorithm I am using to extract the entropy.

Something like the kidekin, http://kidekin.nimp.co.uk/trng/kidekin_trng_user_manual.html with almost 8 bits of entropy / byte can be used directly, but I doubt that atmospheric noise is that random.

I received my 2832. It's this one, Rafael Micro R820T 24 - 1766 MHz. The maximum sample rate it will tolerate without loss is 2.4M samples/sec.

I used your software, and your command line to create some large files (e.g. 1249015000 high_entropy.bin) that I could run through dieharder. I used several frequencies. The general format of the commands was
src/rtl_entropy -s 2.4M -f 101.5M -e | rngtest -c 500000 -p > high_entropy.bin
and
dieharder -a -f high_entropy.bin -g 201

I noticed that there were still occasional weak and failed results in dieharder, even though rngtest throws away output. I'm thinking of replacing the 15 cm antenna that came with the 2832 with an old 1.5 m whip antenna from a car to boost signal strength. But, the filtered results are better than the raw values out of /dev/urandom in the linux kernel, because that has no filtering to throw away statistical outliers.

Here is the summary of one of the runs:
rngtest: bits received from input: 10000000064
rngtest: bits sent to output: 9992120000
rngtest: FIPS 140-2 successes: 499606
rngtest: FIPS 140-2 failures: 394
rngtest: FIPS 140-2(2001-10-10) Monobit: 49
rngtest: FIPS 140-2(2001-10-10) Poker: 49
rngtest: FIPS 140-2(2001-10-10) Runs: 154
rngtest: FIPS 140-2(2001-10-10) Long run: 144
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=22.103; avg=6041.258; max=19531250.000)Kibits/s
rngtest: FIPS tests speed: (min=1.454; avg=87.107; max=165.856)Mibits/s
rngtest: output channel speed: (min=844.923; avg=1766758.286; max=19531250.000)Kibits/s

The failure rate in rngtest is about .1%, about the same rate as a TRNG would have, and the linux kernel PRNG has.

That same file had these instances that didn't get PASSED.

The file file_input_raw was rewound 3 times

    diehard_sums|   0|       100|     100|0.00043729|   WEAK

The file file_input_raw was rewound 120 times

  rgb_lagged_sum|  24|   1000000|     100|0.00203309|   WEAK

The file file_input_raw was rewound 165 times

  rgb_lagged_sum|  29|   1000000|     100|0.99632638|   WEAK

I think that your software output should actually go to a new /dev file, /dev/crypto, maybe that would be the character output this issue record calls for. This could default to /dev/urandom when there was no filtered feed available, but provide a filtered bitstream when your daemon was there.

Mr Brown, the author of dieharder, has an excellent article on randomness, cryptography, and statistical tests to determine strength. It's been a while since I read it, but IIRC it boils down to saying that TRNGs and PRNGs will fail statistical tests like rngtest and dieharder. And that it isn't certain that passing such statistical tests improves cryptographic strength in every case. But cutting off the tails of a test dimension makes it harder to determine the number using that dimension, because the number is in the 'herd', and not an outlier. It might be that we are doing the equivalent of putting a lock on the front door, but leaving the back door open. Experts like Bruce Schneier don't think so, but he could be wrong.

I think it would be great if your software had the ability to feed the entropy pool and create crypto numbers directly, at the same time.