Closed travisgoodspeed closed 6 years ago
The plot above can be recreated like so.
x270% ./goodwatch.py --randdump samples2.txt
Fetching samples.
x270% gnuplot
Terminal type set to 'qt'
gnuplot> plot 'samples2.txt'
gnuplot>
I've run some tests as well. Could it be that "turbo" mode has a significant effect on this?
I've tested the output with rngtest
from rng-tools
which implements standard FIPS 140-2 tests and here are my results.
First, testing true_rand
as it is:
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 265280
rngtest: FIPS 140-2 successes: 0
rngtest: FIPS 140-2 failures: 13
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 13
rngtest: FIPS 140-2(2001-10-10) Runs: 13
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=9.313; avg=17.296; max=18.626)Gibits/s
rngtest: FIPS tests speed: (min=61.133; avg=62.473; max=63.367)Mibits/s
rngtest: Program run time: 4128 microseconds
That's not too bad. All blocks are failing "poker" and "runs" tests, while passing others. If I stop messing with ACLK divider, I get the following:
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 109440
rngtest: FIPS 140-2 successes: 3
rngtest: FIPS 140-2 failures: 2
rngtest: FIPS 140-2(2001-10-10) Monobit: 1
rngtest: FIPS 140-2(2001-10-10) Poker: 0
rngtest: FIPS 140-2(2001-10-10) Runs: 1
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=9.313; avg=15.522; max=18.626)Gibits/s
rngtest: FIPS tests speed: (min=57.974; avg=58.257; max=58.869)Mibits/s
rngtest: Program run time: 1874 microseconds
So, it might look a bit better. If I also don't mess with DCORSEL in each loop the results look even better :
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 654080
rngtest: FIPS 140-2 successes: 26
rngtest: FIPS 140-2 failures: 6
rngtest: FIPS 140-2(2001-10-10) Monobit: 6
rngtest: FIPS 140-2(2001-10-10) Poker: 1
rngtest: FIPS 140-2(2001-10-10) Runs: 1
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=6.209; avg=14.538; max=18.626)Gibits/s
rngtest: FIPS tests speed: (min=57.450; avg=58.318; max=60.551)Mibits/s
rngtest: Program run time: 10735 microseconds
Last run was longest and 26 out of 32 blocks passed. 6 failed monobit tests which would suggest some bias to either ones or zeroes.
In conclusion, it seems like messing with clocks on each loop makes things worse, but even so the RNG seems "good enough" for what it is. Any actual crypto use would definitely need whitening.
Here's a plot without last two lines in the loop:
Indeed looks much better.
Just to be clear, SLAA338 give 3 ways of adding randomness:
Second two of these correspond to UCSCTL1 += 5;
and UCSCTL5 ^= ((seed & 3) << 8)
respectively. It seems like skipping these two steps makes for better results in this particular case.
I found the bug.
UCSCTL1 += 5;
is incorrect, I misread the docs. The CC430 in question has DCORSEL bits at bit 4-6 of UCSCTL1 , not 0-3.
I'll run longer rngtest
tests and see what we get.
After running more tests, simply skipping omitting the two lines that mess with DCO speed and dividers seems to yield the best results.
Minor differences cannot be seen from this simple plot , but running rngtest
on about 16k samples gives the following:
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 262144
rngtest: FIPS 140-2 successes: 9
rngtest: FIPS 140-2 failures: 4
rngtest: FIPS 140-2(2001-10-10) Monobit: 4
rngtest: FIPS 140-2(2001-10-10) Poker: 2
rngtest: FIPS 140-2(2001-10-10) Runs: 1
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=6.209; avg=12.107; max=18.626)Gibits/s
rngtest: FIPS tests speed: (min=54.340; avg=58.315; max=61.133)Mibits/s
rngtest: Program run time: 5350 microseconds
This still isn't ideally uniform, but I'd judge it "good enough" for current purposes. Any actual cryptographic use would warrant whitening via hash function or available hardware accelerated AES.
A quick check of the
true_rand()
function as a scatterplot of the high and low bytes shows awkward grouping. I think that we might need to let the clocks drift further, or perhaps whiten the data through the hardware-accelerated AES module.Use this issue to track the RNG tests, and close it when we're convinced that the samples are good.