TRNG characterization - betrusted-io/betrusted-wiki GitHub Wiki

TL;DR

We built some TRNGs. They seem to work. You're welcome to check our work.

We have a CI bench that collects data from:

  • raw ring oscillator ro
  • raw avalanche generator av
  • XOR of both AV+RO outputs seeded into a ChaCha CSPRNG (trng)

The results of the CI bench are available for you to download and run an independent analysis to confirm that our TRNGs are working correctly. If you find any problems, please open a detailed issue on GitHub, or contact us via IRC (#betrusted:matrix.org).

We would like to get this right.

This link will stay live, subject to bandwidth limitations; each CI run generates ~10GiB of random data, and eventually we're going to fill up some terabyte of data with random data available at this URL.

Background

Betrusted contains two TRNGs: a ring oscillator, and an avalanche noise source. The ring oscillator is fully internal to the FPGA, whereas the avalanche noise source is fully external to the FPGA. The ring oscillator is more difficult to disturb by an attacker with physical access to the device, but it is impossible to inspect its construction; the avalanche generator can be visually inspected and verified for correct construction, but likewise can be tampered with by an a attacker with physical access to the hardware.

The final TRNG source as revealed by the cryptographic API servers in Betrusted will combine entropy from both sources by XOR'ing the bitstreams together, hopefully getting the best of both worlds. However, for characterization, we separately and individually characterize raw bitstreams, without whitening, to confirm correct operation of each source individually.

Data composition

Avalanche

The avalanche generator consist of two avalanche diodes connected to two channels of a 12-bit ADC. The avalanche generator inherently does not swing rail-to-rail; some headroom is necessary to optimize operation and ensure low power. Thus the ADC values are not directly used as a source of entropy. The 16-bit data result is composed with the following algorithm:

            let mut r: u16 = 0;
            for _ in 0..4 {
                r <<= 4;
                wait_adc_sampling_time()
                r ^= noise0() ^ noise1();
            }

where noise0() and noise1() return a 12-bit value that is the ADC code, and wait_adc_sampling_time() is just a delay equal to the length of the ADC sampling period.

In other words, we require that the minimum amplitude of true entropy out of the TRNG be 4 bits, and any entropy present beyond that is just gravy; and a 16-bit result is composed by shifting and overlaying 8 total sets of samples (2 channels by 4 iterations).

This is necessary in part also because the nature of the avalanche noise generator is to have a set of ramps that go up and down in a somewhat predictable fashion. Some TRNGs resolve this by simply slicing the avalanche noise along a mid-point, and calling all samples above a certain value as 1, and those below as 0. This is effectively decimating the the TRNG down to 1 bit but it has the problem of oversampling: the average "frequency" of the TRNG is quite sensitive to a number of environmental factors, and thus it's hard to pick an appropriate sampling rate. However, the "frequency", as it may be, is "around" 1 MHz when defined as the approximate distance between avalanche peaks.

XOR'ing the LSB's of two sets of noise diodes should, in theory, create quite a bit of entropy, and at a much higher rate than the zero-crossing methodology. The max bitrate of this RNG is consistent and equal to roughly 1/8th the sample rate of the ADC. In Betrusted, the sample rate of the XADC is 1Msps and thus the peak bitrate of the RNG is about 128kwords per second, and each word is 16 bits in length, so the entropy bitrate is ~2Mbps.

Ring Oscillator

The ring oscillator architecture consists of multiple small-order ring oscillators that can be merged into a larger ring through a multiplexer. It is modeled after this paper from Samsung Electronics.

The basic idea is to use a two-phase system. In phase 1, you gather entropy. In phase 2, you measure it. During the entropy-gathering phase, instead of using a single large ring oscillator to sum together jitter from N stages, have N small ring oscillators which independently accumulate phase from local noise-induced jitter. When you're ready to measure entropy, use a multiplexer to merge those ring oscillators into a single large one and have them "vote" on the net phase of the large oscillator, and then sample that against a deterministic reference clock to get your random bit out. Thus the random variable is phase of the large ring oscillator versus the deterministic phase of the sampling clock.

A failing of ring oscillators (as was demonstrated in the V1 implementation) is that inside a densely routed FPGA, the noise generated by the primary clock net is quite large, and this can couple into the ring oscillators. Most FPGA-based ring oscillator papers demonstrate the devices as lone circuits in a mostly empty FPGA, so the noise of the primary clock tree is minimal. In the case of Betrusted, the ring oscillator is embedded in a densely routed fabric with a lot of clock loads at a single frequency. The switching of this clock load tends to "train" ring oscillators to phase-lock to the sysclk domain, thus reducing the amount of randomness available. This tends to manifest itself as a failure of the sts_serial suite in dieharder. In fact, for the V1 oscillator, we could pass many of the tests, but not this one. The putative reason is that most of the time the V1 oscillator is decoupled from the clock network and generating entropy, but "occasionally" it will phase-lock, and the net result is a "long" run of either 10101.., 11111.., or 00000... In definite terms, the run is maybe length 4-12, every couple thousand bits or so. This is rare enough that you can pass many statistical tests, but the distribution of overlapping n-bit polynomials will be thrown off enough that it sticks out in the sts_serial test.

Thus we hypothesize that the problem with the V1 oscillator is that a long, large ring-oscillator actually re-inforces the coupling of global clock noise. Because global clock is, by definition, arriving at all end points within fractions of a nanosecond of each other, even if the large ring oscillator is striped across the entire FPGA, this consistent noise on the power supply is reinforced by coupling each stage of the ring oscillator to the next one.

V2 architecture consists of 32-bit TRNG result, and 33 1-stage LUT ring oscillators. The 1-stage ring oscillators contain, in addition to the inverter, two logic elements: one is a power-gate enable, and the other is a multiplexer to pick the stage input as either being from the current stage (thus making it a 1-stage oscillator), or from the n-1 stage (thus creating a 33-stage chain). Because 6-input LUTs are used for the logic mapping, the delay cost of the power gate and mux is the same as either one on its own.

During dwell, the 1-stage LUTs oscillate independently among themselves, at an estimated frequency of around 200-300MHz. At the end of dwell, the muxes are switched, and the LUTs are merged into a 33-stage oscillator. The exact state of the oscillator has to "figure itself out" -- initially, you expect some "contradictory" states where e.g. you have an inverter where 0 is fed in while the output is also 0. This convergence process should take about the length of the period of the oscillator, but potentially longer. Of course, during the convergence process, you have the system clock deterministic noise training against the randomness; so if you let it converge for too long, you lose most of the benefit of having independent stages.

The final implementation for V2 deviates from the Samsung paper in that during the dwell phase, 32 of the 33 ring oscillators are constantly XOR'ing their current bit state into the rand output. In other words, the ring oscillator might free-run at around 200-300MHz; this is being undersampled by the 100MHZ syclk into a flip flop, and the result of this is bit-wise XOR'd into the rand output at sysclk rate (so oscillator 0 XOR's into rand[0], oscillator 1 into rand[1], and so forth). When the dwell mux is flipped, the XORing stops. After a convergence delay, the result of the entire ring's aggregate phase is sampled into rand[0], while the rest of the rand register is shifted left. The process then repeats 32 times, until each bit in the register has nominally received an aggregate phase plus numerous samples of its independent phase.

With a sysclk of 100MHz, the parameters tested for dwell are 100 sysclocks (so a 1MHz shift-register rate, resulting in about a 30kbps final entropy rate), and a convergence delay of 8 sysclocks (or 80ns). Assuming a 1-stage oscillator rings at around 300MHz, this means we collect 100 samples of jitter over 3000 cycles of the small oscillators into individual bits, and we provide just about enough time for the signal to make one full propagation around the ring for convergence before sampling into the cross-entropy pool. These parameters are passing the Dieharder test suite; presumably we could tune this and speed up to a higher entropy generation rate, but this is not necessary for Betrusted, and thus we leave the parameters here for production.

As a footnote, the system is implemented with the ability to turn gang entropy collection off. In this mode, only entropy collected from the sampling of the large ring is accumulated; the bit-wise XOR of the individual oscillators is disabled. When run in this mode, the TRNG does not pass the Dieharder test suite. Thus the sampling of individual small oscillators is also important. It's hypothesized that the "down-and-cross" mixing is key: each small ring oscillator is like an individual, but slightly biased, coin flip. The "sample" is catching all the coins at once in mid-flip and coming up with a consensus of odd-or-even number of heads/tails. The fact that each coin's result is being put into a bin, but then shifted to the next coin and mixed in, is more effective at removing bias than trying to measure all the coins at once, because the measurement process itself has a bias to it (due to the coupling of the sysclk noise).

In other words an important part of what's happening here is that we're allowing each small ring oscillator to imprint its own tiny bias onto each bit serially, and then using a shift-and-XOR operation to mix that. Whereas if we connected the small oscillators together into one big one, the individual biases of each small oscillator can actually cancel out, and also, you get reinforcement of clock noise across the entire length of the oscillator.

That's a guess, at least.

[below are deprecated, historical notes]

The ring oscillator architecture consists of several rings of dissimilar speed. There is one slow "sampling" ring, and several faster "noise" rings. The "sampling" ring runs at about 30x-300x the speed of the others.

The idea is to use the slower ring oscillator to clock flip flops that sample the edges of the faster oscillators. Shortly after every low-to-high transition of the slow ring oscillator clock, the noise results are sampled into a fast, stable clock domain, XOR'd together, and shifted into a 32-bit register. Once 32 bits of data are obtained, a flag is set to indicate collection is complete, and the host can read out the data. Thus the bitrate of this RNG is approximately equal to the slow ring oscillator's clock rate (which is entirely variable with temperature and voltage, but targeted to around 1MHz by design). The anecdotal measured entropy bitrate is around 700kbps (64Mbits collected in about 94 seconds).

The slower ring oscillator's routing is forced to run through the length of the FPGA's core fabric, so that it picks up as much jitter noise as possible. The rings are also routed using different strategies, so that local variations are not accidentally cancelled out. Ideally, the magnitude of the jitter picked up by the slower ring is much greater than the period of the fast oscillator.

As of July 1, 2020, the specific Betrusted RO TRNG consists of a large ring, and four fast rings. The fast rings have lengths of 1, 3, 5, and 7 LUT-inverter stages. Each of the rings "tap" the slow oscillator at different points for sampling: length-1 ring taps at the midpoint, length-3 at 1/4th, length-5 at 1/3, and length-7 at 3/5ths of the way around the slow ring. The sampled fast rings are then synchronized through independent registers (to capture the random variable of each ring vs the stable system clock), and XOR'd together in the system clock domain before being shifted into a 32-bit register for readout.

Methodology

Two methodologies are used to characterize the TRNGs on Betrusted.

  1. Fast sequential readout.
  2. On-demand network readout.

Fast sequential readout

In this case, data is read out at the maximum rate possible. The idea behind this style of test is to confirm the maximum entropy generation rate.

The problem is, we do not have a way to store or transfer the gigabytes of entropy necessary to run the Dieharder test suite. Thus, data from the TRNG are read out and stored in an 8MiB chunk of RAM, and downloaded as a serialized file to a host machine. This process is repeated until enough chunks (about 512MiB worth) of data is accumulated to run the Dieharder test suite.

On-demand network readout

In this case, data is read out over the network to a host machine, at network speeds. This is fed via a Unix file pipe to Dieharder, allowing the suite to collect the tens of gigabytes of entropy necessary to run its tests without rewinding files. However, the read out is not done at the max possible rate of the TRNG.

Results

Characterization is an on-going process. More results will be updated here as we continue to test.

AV ^ RO TRNG output, as fed into the Kernel (no whitening)

This is a full, dynamically generated stream of random data with no rewinding, on the composite output of the TRNG as fed into the kernel for use; it is the Avalanche Generator + Ring Oscillator, XOR'd together. Takes about a month to run.

Note that the command line below started the run, but a few individual tests had to be run separately because of a server reboot.

% target/release/bt-rngd | pv -b -a -t | dieharder -g 200 -a | tee -a dieharder_result_av_ro_dec2020_extended.txt

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.46e+04  |2996226851|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.37987916|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.67388538|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.59155142|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.12244899|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.66926173|  PASSED  
        diehard_opso|   0|   2097152|     100|0.78474341|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.98402422|  PASSED  
         diehard_dna|   0|   2097152|     100|0.97964439|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.86179753|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.77941943|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.10060329|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.59795945|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.40349345|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.04858313|  PASSED  
        diehard_sums|   0|       100|     100|0.02448124|  PASSED  
        diehard_runs|   0|    100000|     100|0.03495598|  PASSED  
        diehard_runs|   0|    100000|     100|0.09601851|  PASSED  
       diehard_craps|   0|    200000|     100|0.95708996|  PASSED  
       diehard_craps|   0|    200000|     100|0.04937685|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.38331962|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.98927581|  PASSED  
         sts_monobit|   1|    100000|     100|0.46468541|  PASSED  
            sts_runs|   2|    100000|     100|0.40153149|  PASSED  
          sts_serial|   1|    100000|     100|0.43813666|  PASSED  
          sts_serial|   2|    100000|     100|0.34640877|  PASSED  
          sts_serial|   3|    100000|     100|0.26804167|  PASSED  
          sts_serial|   3|    100000|     100|0.81345781|  PASSED  
          sts_serial|   4|    100000|     100|0.43118802|  PASSED  
          sts_serial|   4|    100000|     100|0.72648695|  PASSED  
          sts_serial|   5|    100000|     100|0.87318949|  PASSED  
          sts_serial|   5|    100000|     100|0.85072539|  PASSED  
          sts_serial|   6|    100000|     100|0.51700780|  PASSED  
          sts_serial|   6|    100000|     100|0.29482681|  PASSED  
          sts_serial|   7|    100000|     100|0.46972982|  PASSED  
          sts_serial|   7|    100000|     100|0.54171643|  PASSED  
          sts_serial|   8|    100000|     100|0.06752607|  PASSED  
          sts_serial|   8|    100000|     100|0.04063133|  PASSED  
          sts_serial|   9|    100000|     100|0.74324003|  PASSED  
          sts_serial|   9|    100000|     100|0.99574641|   WEAK   
          sts_serial|  10|    100000|     100|0.66560085|  PASSED  
          sts_serial|  10|    100000|     100|0.50104591|  PASSED  
          sts_serial|  11|    100000|     100|0.43326071|  PASSED  
          sts_serial|  11|    100000|     100|0.68189195|  PASSED  
          sts_serial|  12|    100000|     100|0.63887739|  PASSED  
          sts_serial|  12|    100000|     100|0.86634061|  PASSED  
          sts_serial|  13|    100000|     100|0.42419817|  PASSED  
          sts_serial|  13|    100000|     100|0.53720064|  PASSED  
          sts_serial|  14|    100000|     100|0.38884361|  PASSED  
          sts_serial|  14|    100000|     100|0.83216108|  PASSED  
          sts_serial|  15|    100000|     100|0.21879550|  PASSED  
          sts_serial|  15|    100000|     100|0.28136265|  PASSED  
          sts_serial|  16|    100000|     100|0.76816750|  PASSED  
          sts_serial|  16|    100000|     100|0.63408579|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.09372221|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.16720758|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.99012934|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.41650016|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.53943954|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.42906448|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.27279873|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.90715211|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.73125809|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.08736455|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.03432687|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.98629114|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.48175415|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.41830512|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.98537637|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.00294391|   WEAK   
    rgb_permutations|   2|    100000|     100|0.23772247|  PASSED  
    rgb_permutations|   3|    100000|     100|0.29237809|  PASSED  
    rgb_permutations|   4|    100000|     100|0.92097132|  PASSED  
    rgb_permutations|   5|    100000|     100|0.11444710|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.28529517|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.78441105|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.26009914|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.23686041|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.59528516|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.82832550|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.91611591|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.67828551|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.88778470|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.70851794|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.95028486|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.45088174|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.73507084|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.94446388|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.82428134|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.30303886|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.85166899|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.40614514|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.29892091|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.50012739|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.48895935|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.07089092|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.09368194|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.98770129|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.95798773|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.65060331|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.73201502|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.76714949|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.83879046|  PASSED 

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.54e+03  | 110225389|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
     rgb_kstest_test|   0|     10000|    1000|0.29109986|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.51e+04  |3314706186|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
     dab_bytedistrib|   0|  51200000|       1|0.64189951|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.46e+03  |2038655357|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
             dab_dct| 256|     50000|       1|0.55309354|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.45e+03  |2835360790|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
        dab_filltree|  32|  15000000|       1|0.64571840|  PASSED  
        dab_filltree|  32|  15000000|       1|0.84552875|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.46e+03  | 608735165|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
        dab_filltree|  32|  15000000|       1|0.91386084|  PASSED  
        dab_filltree|  32|  15000000|       1|0.97853447|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.45e+03  |2872426696|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
       dab_filltree2|   0|   5000000|       1|0.92531084|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.02678683|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.46e+03  |3051868364|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
        dab_monobit2|  12|  65000000|       1|0.27824779|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.18e+04  | 319510590|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
      rgb_lagged_sum|  29|   1000000|     100|0.55015980|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  7.55e+03  |3834131415|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
      rgb_lagged_sum|  30|   1000000|     100|0.06809145|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  8.34e+03  |3720085181|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
      rgb_lagged_sum|  31|   1000000|     100|0.30139946|  PASSED  
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.11e+04  |1613170077|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
      rgb_lagged_sum|  32|   1000000|     100|0.97900466|  PASSED  

Avalanche-Only

The below is a full run of the Avalanche generator only (without XOR'ing with the Ring Oscillator), took ~1 month to complete.

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.50e+04  | 862058002|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.81231816|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.07240508|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.33361595|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.64124985|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.98142811|  PASSED  
        diehard_opso|   0|   2097152|     100|0.68599856|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.31135650|  PASSED  
         diehard_dna|   0|   2097152|     100|0.98308305|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.99496495|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.06834453|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.55881466|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.11882046|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.83646926|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.22664699|  PASSED  
        diehard_sums|   0|       100|     100|0.36246073|  PASSED  
        diehard_runs|   0|    100000|     100|0.76000199|  PASSED  
        diehard_runs|   0|    100000|     100|0.17946925|  PASSED  
       diehard_craps|   0|    200000|     100|0.21847038|  PASSED  
       diehard_craps|   0|    200000|     100|0.62202412|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.69567934|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.88924371|  PASSED  
         sts_monobit|   1|    100000|     100|0.78949906|  PASSED  
            sts_runs|   2|    100000|     100|0.99571279|   WEAK   
          sts_serial|   1|    100000|     100|0.70925896|  PASSED  
          sts_serial|   2|    100000|     100|0.43143437|  PASSED  
          sts_serial|   3|    100000|     100|0.31601383|  PASSED  
          sts_serial|   3|    100000|     100|0.09567658|  PASSED  
          sts_serial|   4|    100000|     100|0.90043773|  PASSED  
          sts_serial|   4|    100000|     100|0.88277678|  PASSED  
          sts_serial|   5|    100000|     100|0.41298818|  PASSED  
          sts_serial|   5|    100000|     100|0.47178604|  PASSED  
          sts_serial|   6|    100000|     100|0.68869735|  PASSED  
          sts_serial|   6|    100000|     100|0.93671460|  PASSED  
          sts_serial|   7|    100000|     100|0.28992675|  PASSED  
          sts_serial|   7|    100000|     100|0.57811905|  PASSED  
          sts_serial|   8|    100000|     100|0.49599604|  PASSED  
          sts_serial|   8|    100000|     100|0.70701561|  PASSED  
          sts_serial|   9|    100000|     100|0.12399001|  PASSED  
          sts_serial|   9|    100000|     100|0.13935049|  PASSED  
          sts_serial|  10|    100000|     100|0.78679856|  PASSED  
          sts_serial|  10|    100000|     100|0.70353176|  PASSED  
          sts_serial|  11|    100000|     100|0.37837587|  PASSED  
          sts_serial|  11|    100000|     100|0.52658265|  PASSED  
          sts_serial|  12|    100000|     100|0.06453688|  PASSED  
          sts_serial|  12|    100000|     100|0.33651750|  PASSED  
          sts_serial|  13|    100000|     100|0.17734686|  PASSED  
          sts_serial|  13|    100000|     100|0.63050324|  PASSED  
          sts_serial|  14|    100000|     100|0.52865469|  PASSED  
          sts_serial|  14|    100000|     100|0.84311179|  PASSED  
          sts_serial|  15|    100000|     100|0.58584683|  PASSED  
          sts_serial|  15|    100000|     100|0.98980744|  PASSED  
          sts_serial|  16|    100000|     100|0.49183640|  PASSED  
          sts_serial|  16|    100000|     100|0.02482445|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.88988571|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.85263105|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.69081569|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.58840973|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.70223209|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.14834440|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.30843935|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.72079843|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.02181853|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.80266941|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.76148207|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.34892622|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.91445955|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.04871139|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.78792690|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.21010465|  PASSED  
    rgb_permutations|   2|    100000|     100|0.85884629|  PASSED  
    rgb_permutations|   3|    100000|     100|0.76202998|  PASSED  
    rgb_permutations|   4|    100000|     100|0.78633080|  PASSED  
    rgb_permutations|   5|    100000|     100|0.93190005|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.55287659|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.89073618|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.51435431|  PASSED  

Avalanche, fast sequential readout

This is a "fast run" just for smoke testing of the generator.

536MiB of data is collected, sha512 sum of 908aeb1cf060179917913ece75d6fc8bfb4a940d54eb3f25b94a4b27864b5b7f03f3f5139da12cc5c9dffd68d89644869ae703ffa2fe8681bfaf310acde1253e

Run result:

$ dieharder -a -g 201 -f av
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |           filename             |rands/second|
 file_input_raw|                              av|  5.29e+07  |
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.19117306|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.69956049|  PASSED  
# The file file_input_raw was rewound 1 times
  diehard_rank_32x32|   0|     40000|     100|0.27307619|  PASSED  
# The file file_input_raw was rewound 2 times
    diehard_rank_6x8|   0|    100000|     100|0.21450260|  PASSED  
# The file file_input_raw was rewound 2 times
   diehard_bitstream|   0|   2097152|     100|0.32916713|  PASSED  
# The file file_input_raw was rewound 3 times
        diehard_opso|   0|   2097152|     100|0.73424940|  PASSED  
# The file file_input_raw was rewound 4 times
        diehard_oqso|   0|   2097152|     100|0.81829061|  PASSED  
# The file file_input_raw was rewound 5 times
         diehard_dna|   0|   2097152|     100|0.78622456|  PASSED  
# The file file_input_raw was rewound 5 times
diehard_count_1s_str|   0|    256000|     100|0.93520475|  PASSED  
# The file file_input_raw was rewound 6 times
diehard_count_1s_byt|   0|    256000|     100|0.67804056|  PASSED  
# The file file_input_raw was rewound 6 times
 diehard_parking_lot|   0|     12000|     100|0.99466010|  PASSED  
# The file file_input_raw was rewound 6 times
    diehard_2dsphere|   2|      8000|     100|0.80631826|  PASSED  
# The file file_input_raw was rewound 6 times
    diehard_3dsphere|   3|      4000|     100|0.09414183|  PASSED  
# The file file_input_raw was rewound 7 times
     diehard_squeeze|   0|    100000|     100|0.14023162|  PASSED  
# The file file_input_raw was rewound 7 times
        diehard_sums|   0|       100|     100|0.44092712|  PASSED  
# The file file_input_raw was rewound 7 times
        diehard_runs|   0|    100000|     100|0.19569925|  PASSED  
        diehard_runs|   0|    100000|     100|0.53268667|  PASSED  
# The file file_input_raw was rewound 8 times
       diehard_craps|   0|    200000|     100|0.48571906|  PASSED  
       diehard_craps|   0|    200000|     100|0.09241079|  PASSED  
# The file file_input_raw was rewound 23 times
 marsaglia_tsang_gcd|   0|  10000000|     100|0.00000000|  FAILED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.53832243|  PASSED  
# The file file_input_raw was rewound 23 times
         sts_monobit|   1|    100000|     100|0.88268876|  PASSED  
# The file file_input_raw was rewound 23 times
            sts_runs|   2|    100000|     100|0.34576702|  PASSED  
# The file file_input_raw was rewound 23 times
          sts_serial|   1|    100000|     100|0.42825544|  PASSED  
          sts_serial|   2|    100000|     100|0.77184155|  PASSED  
          sts_serial|   3|    100000|     100|0.58740561|  PASSED  
          sts_serial|   3|    100000|     100|0.52323279|  PASSED  
          sts_serial|   4|    100000|     100|0.72478868|  PASSED  
          sts_serial|   4|    100000|     100|0.27631546|  PASSED  
          sts_serial|   5|    100000|     100|0.89253074|  PASSED  
          sts_serial|   5|    100000|     100|0.86886473|  PASSED  
          sts_serial|   6|    100000|     100|0.56720125|  PASSED  
          sts_serial|   6|    100000|     100|0.90438202|  PASSED  
          sts_serial|   7|    100000|     100|0.95688259|  PASSED  
          sts_serial|   7|    100000|     100|0.69049177|  PASSED  
          sts_serial|   8|    100000|     100|0.86978377|  PASSED  
          sts_serial|   8|    100000|     100|0.14078118|  PASSED  
          sts_serial|   9|    100000|     100|0.47499599|  PASSED  
          sts_serial|   9|    100000|     100|0.37985735|  PASSED  
          sts_serial|  10|    100000|     100|0.80097054|  PASSED  
          sts_serial|  10|    100000|     100|0.93202904|  PASSED  
          sts_serial|  11|    100000|     100|0.63533866|  PASSED  
          sts_serial|  11|    100000|     100|0.72659443|  PASSED  
          sts_serial|  12|    100000|     100|0.97705430|  PASSED  
          sts_serial|  12|    100000|     100|0.68587652|  PASSED  
          sts_serial|  13|    100000|     100|0.67529970|  PASSED  
          sts_serial|  13|    100000|     100|0.67419362|  PASSED  
          sts_serial|  14|    100000|     100|0.79636938|  PASSED  
          sts_serial|  14|    100000|     100|0.43053706|  PASSED  
          sts_serial|  15|    100000|     100|0.47951104|  PASSED  
          sts_serial|  15|    100000|     100|0.76244768|  PASSED  
          sts_serial|  16|    100000|     100|0.68758955|  PASSED  
          sts_serial|  16|    100000|     100|0.73312096|  PASSED  
# The file file_input_raw was rewound 23 times
         rgb_bitdist|   1|    100000|     100|0.69495547|  PASSED  
# The file file_input_raw was rewound 23 times
         rgb_bitdist|   2|    100000|     100|0.88475605|  PASSED  
# The file file_input_raw was rewound 24 times
         rgb_bitdist|   3|    100000|     100|0.33465628|  PASSED  
# The file file_input_raw was rewound 24 times
         rgb_bitdist|   4|    100000|     100|0.19630558|  PASSED  
# The file file_input_raw was rewound 25 times
         rgb_bitdist|   5|    100000|     100|0.76707206|  PASSED  
# The file file_input_raw was rewound 26 times
         rgb_bitdist|   6|    100000|     100|0.39077590|  PASSED  
# The file file_input_raw was rewound 27 times
         rgb_bitdist|   7|    100000|     100|0.45212688|  PASSED  
# The file file_input_raw was rewound 28 times
         rgb_bitdist|   8|    100000|     100|0.25343935|  PASSED  
# The file file_input_raw was rewound 29 times
         rgb_bitdist|   9|    100000|     100|0.98595371|  PASSED  
# The file file_input_raw was rewound 31 times
         rgb_bitdist|  10|    100000|     100|0.71066887|  PASSED  
# The file file_input_raw was rewound 32 times
         rgb_bitdist|  11|    100000|     100|0.71593718|  PASSED  
# The file file_input_raw was rewound 34 times
         rgb_bitdist|  12|    100000|     100|0.87456330|  PASSED  
# The file file_input_raw was rewound 34 times
rgb_minimum_distance|   2|     10000|    1000|0.67883197|  PASSED  
# The file file_input_raw was rewound 34 times
rgb_minimum_distance|   3|     10000|    1000|0.83820278|  PASSED  
# The file file_input_raw was rewound 35 times
rgb_minimum_distance|   4|     10000|    1000|0.37211677|  PASSED  
# The file file_input_raw was rewound 35 times
rgb_minimum_distance|   5|     10000|    1000|0.17950497|  PASSED  
# The file file_input_raw was rewound 35 times
    rgb_permutations|   2|    100000|     100|0.77863942|  PASSED  
# The file file_input_raw was rewound 35 times
    rgb_permutations|   3|    100000|     100|0.93853168|  PASSED  
# The file file_input_raw was rewound 36 times
    rgb_permutations|   4|    100000|     100|0.02931757|  PASSED  
# The file file_input_raw was rewound 36 times
    rgb_permutations|   5|    100000|     100|0.41512889|  PASSED  
# The file file_input_raw was rewound 37 times
      rgb_lagged_sum|   0|   1000000|     100|0.71392037|  PASSED  
# The file file_input_raw was rewound 38 times
      rgb_lagged_sum|   1|   1000000|     100|0.53595464|  PASSED  
# The file file_input_raw was rewound 40 times
      rgb_lagged_sum|   2|   1000000|     100|0.43651016|  PASSED  
# The file file_input_raw was rewound 43 times
      rgb_lagged_sum|   3|   1000000|     100|0.58673998|  PASSED  
# The file file_input_raw was rewound 47 times
      rgb_lagged_sum|   4|   1000000|     100|0.68351386|  PASSED  
# The file file_input_raw was rewound 51 times
      rgb_lagged_sum|   5|   1000000|     100|0.35046231|  PASSED  
# The file file_input_raw was rewound 56 times
      rgb_lagged_sum|   6|   1000000|     100|0.33356155|  PASSED  
# The file file_input_raw was rewound 62 times
      rgb_lagged_sum|   7|   1000000|     100|0.47537982|  PASSED  
# The file file_input_raw was rewound 68 times
      rgb_lagged_sum|   8|   1000000|     100|0.17976396|  PASSED  
# The file file_input_raw was rewound 75 times
      rgb_lagged_sum|   9|   1000000|     100|0.25710617|  PASSED  
# The file file_input_raw was rewound 83 times
      rgb_lagged_sum|  10|   1000000|     100|0.32334979|  PASSED  
# The file file_input_raw was rewound 92 times
      rgb_lagged_sum|  11|   1000000|     100|0.86609124|  PASSED  
# The file file_input_raw was rewound 101 times
      rgb_lagged_sum|  12|   1000000|     100|0.12230157|  PASSED  
# The file file_input_raw was rewound 111 times
      rgb_lagged_sum|  13|   1000000|     100|0.25379869|  PASSED  
# The file file_input_raw was rewound 121 times
      rgb_lagged_sum|  14|   1000000|     100|0.24604802|  PASSED  
# The file file_input_raw was rewound 133 times
      rgb_lagged_sum|  15|   1000000|     100|0.05549815|  PASSED  
# The file file_input_raw was rewound 145 times
      rgb_lagged_sum|  16|   1000000|     100|0.99483303|  PASSED  
# The file file_input_raw was rewound 158 times
      rgb_lagged_sum|  17|   1000000|     100|0.90674354|  PASSED  
# The file file_input_raw was rewound 171 times
      rgb_lagged_sum|  18|   1000000|     100|0.77928826|  PASSED  
# The file file_input_raw was rewound 185 times
      rgb_lagged_sum|  19|   1000000|     100|0.76670368|  PASSED  
# The file file_input_raw was rewound 200 times
      rgb_lagged_sum|  20|   1000000|     100|0.13847406|  PASSED  
# The file file_input_raw was rewound 216 times
      rgb_lagged_sum|  21|   1000000|     100|0.80486018|  PASSED  
# The file file_input_raw was rewound 232 times
      rgb_lagged_sum|  22|   1000000|     100|0.69022280|  PASSED  
# The file file_input_raw was rewound 250 times
      rgb_lagged_sum|  23|   1000000|     100|0.10946179|  PASSED  
# The file file_input_raw was rewound 267 times
      rgb_lagged_sum|  24|   1000000|     100|0.47255874|  PASSED  
# The file file_input_raw was rewound 286 times
      rgb_lagged_sum|  25|   1000000|     100|0.16189798|  PASSED  
# The file file_input_raw was rewound 305 times
      rgb_lagged_sum|  26|   1000000|     100|0.66220913|  PASSED  
# The file file_input_raw was rewound 325 times
      rgb_lagged_sum|  27|   1000000|     100|0.99652553|   WEAK   
# The file file_input_raw was rewound 346 times
      rgb_lagged_sum|  28|   1000000|     100|0.78998409|  PASSED  
# The file file_input_raw was rewound 367 times
      rgb_lagged_sum|  29|   1000000|     100|0.12229688|  PASSED  
# The file file_input_raw was rewound 389 times
      rgb_lagged_sum|  30|   1000000|     100|0.21416911|  PASSED  
# The file file_input_raw was rewound 412 times
      rgb_lagged_sum|  31|   1000000|     100|0.00006609|   WEAK   
# The file file_input_raw was rewound 435 times
      rgb_lagged_sum|  32|   1000000|     100|0.19601983|  PASSED  
# The file file_input_raw was rewound 435 times
     rgb_kstest_test|   0|     10000|    1000|0.99276658|  PASSED  
# The file file_input_raw was rewound 436 times
     dab_bytedistrib|   0|  51200000|       1|0.46249697|  PASSED  
# The file file_input_raw was rewound 437 times
             dab_dct| 256|     50000|       1|0.34034616|  PASSED  
Preparing to run test 207.  ntuple = 0
# The file file_input_raw was rewound 437 times
        dab_filltree|  32|  15000000|       1|0.02751019|  PASSED  
        dab_filltree|  32|  15000000|       1|0.58225411|  PASSED  
Preparing to run test 208.  ntuple = 0
# The file file_input_raw was rewound 438 times
       dab_filltree2|   0|   5000000|       1|0.33964020|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.48677072|  PASSED  
Preparing to run test 209.  ntuple = 0
# The file file_input_raw was rewound 438 times
        dab_monobit2|  12|  65000000|       1|0.84221453|  PASSED  

Note that some failures/weak results are expected due to the fact that the file was "rewound" several times during certain tests.

Ring oscillator, fast sequential readout

536MiB of data was collected, sha512 sum of 908aeb1cf060179917913ece75d6fc8bfb4a940d54eb3f25b94a4b27864b5b7f03f3f5139da12cc5c9dffd68d89644869ae703ffa2fe8681bfaf310acde1253e

Run result:

656MiB of data was, sha512 sum of
8c6a42e263aaa51c8cc684e1fd8fa0934e900653fce7ce297642347cdfb27db96713f6a47a0295e63e76a097b7980d57217d7958838fe5e83f64a1b268a6f71a

$ dieharder -a -g 201 -f r2gd
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |           filename             |rands/second|
 file_input_raw|                            r2gd|  5.03e+07  |
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.95664134|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.90939246|  PASSED  
# The file file_input_raw was rewound 1 times
  diehard_rank_32x32|   0|     40000|     100|0.99330474|  PASSED  
# The file file_input_raw was rewound 1 times
    diehard_rank_6x8|   0|    100000|     100|0.05725161|  PASSED  
# The file file_input_raw was rewound 1 times
   diehard_bitstream|   0|   2097152|     100|0.36178035|  PASSED  
# The file file_input_raw was rewound 3 times
        diehard_opso|   0|   2097152|     100|0.59751738|  PASSED  
# The file file_input_raw was rewound 3 times
        diehard_oqso|   0|   2097152|     100|0.55937135|  PASSED  
# The file file_input_raw was rewound 4 times
         diehard_dna|   0|   2097152|     100|0.05937999|  PASSED  
# The file file_input_raw was rewound 4 times
diehard_count_1s_str|   0|    256000|     100|0.93496163|  PASSED  
# The file file_input_raw was rewound 5 times
diehard_count_1s_byt|   0|    256000|     100|0.39337780|  PASSED  
# The file file_input_raw was rewound 5 times
 diehard_parking_lot|   0|     12000|     100|0.53133973|  PASSED  
# The file file_input_raw was rewound 5 times
    diehard_2dsphere|   2|      8000|     100|0.59796284|  PASSED  
# The file file_input_raw was rewound 5 times
    diehard_3dsphere|   3|      4000|     100|0.21458121|  PASSED  
# The file file_input_raw was rewound 6 times
     diehard_squeeze|   0|    100000|     100|0.26639741|  PASSED  
# The file file_input_raw was rewound 6 times
        diehard_sums|   0|       100|     100|0.00707877|  PASSED  
# The file file_input_raw was rewound 6 times
        diehard_runs|   0|    100000|     100|0.40151864|  PASSED  
        diehard_runs|   0|    100000|     100|0.48308205|  PASSED  
# The file file_input_raw was rewound 7 times
       diehard_craps|   0|    200000|     100|0.68991052|  PASSED  
       diehard_craps|   0|    200000|     100|0.24877233|  PASSED  
# The file file_input_raw was rewound 18 times
 marsaglia_tsang_gcd|   0|  10000000|     100|0.00000007|  FAILED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.00226548|   WEAK   
# The file file_input_raw was rewound 19 times
         sts_monobit|   1|    100000|     100|0.14555135|  PASSED  
# The file file_input_raw was rewound 19 times
            sts_runs|   2|    100000|     100|0.63947441|  PASSED  
# The file file_input_raw was rewound 19 times
          sts_serial|   1|    100000|     100|0.09206134|  PASSED  
          sts_serial|   2|    100000|     100|0.70549596|  PASSED  
          sts_serial|   3|    100000|     100|0.96863451|  PASSED  
          sts_serial|   3|    100000|     100|0.86559854|  PASSED  
          sts_serial|   4|    100000|     100|0.03760763|  PASSED  
          sts_serial|   4|    100000|     100|0.02016119|  PASSED  
          sts_serial|   5|    100000|     100|0.04508607|  PASSED  
          sts_serial|   5|    100000|     100|0.48941054|  PASSED  
          sts_serial|   6|    100000|     100|0.91908954|  PASSED  
          sts_serial|   6|    100000|     100|0.07316265|  PASSED  
          sts_serial|   7|    100000|     100|0.96315720|  PASSED  
          sts_serial|   7|    100000|     100|0.44822603|  PASSED  
          sts_serial|   8|    100000|     100|0.75271332|  PASSED  
          sts_serial|   8|    100000|     100|0.34659251|  PASSED  
          sts_serial|   9|    100000|     100|0.55660526|  PASSED  
          sts_serial|   9|    100000|     100|0.84478023|  PASSED  
          sts_serial|  10|    100000|     100|0.38920128|  PASSED  
          sts_serial|  10|    100000|     100|0.92364945|  PASSED  
          sts_serial|  11|    100000|     100|0.98769467|  PASSED  
          sts_serial|  11|    100000|     100|0.20343479|  PASSED  
          sts_serial|  12|    100000|     100|0.25680242|  PASSED  
          sts_serial|  12|    100000|     100|0.91957866|  PASSED  
          sts_serial|  13|    100000|     100|0.69838626|  PASSED  
          sts_serial|  13|    100000|     100|0.72365229|  PASSED  
          sts_serial|  14|    100000|     100|0.55262502|  PASSED  
          sts_serial|  14|    100000|     100|0.98131027|  PASSED  
          sts_serial|  15|    100000|     100|0.29956758|  PASSED  
          sts_serial|  15|    100000|     100|0.52169988|  PASSED  
          sts_serial|  16|    100000|     100|0.93647870|  PASSED  
          sts_serial|  16|    100000|     100|0.35062053|  PASSED  
# The file file_input_raw was rewound 19 times
         rgb_bitdist|   1|    100000|     100|0.76875753|  PASSED  
# The file file_input_raw was rewound 19 times
         rgb_bitdist|   2|    100000|     100|0.28666159|  PASSED  
# The file file_input_raw was rewound 19 times
         rgb_bitdist|   3|    100000|     100|0.91360976|  PASSED  
# The file file_input_raw was rewound 20 times
         rgb_bitdist|   4|    100000|     100|0.17419808|  PASSED  
# The file file_input_raw was rewound 20 times
         rgb_bitdist|   5|    100000|     100|0.11127395|  PASSED  
# The file file_input_raw was rewound 21 times
         rgb_bitdist|   6|    100000|     100|0.23855846|  PASSED  
# The file file_input_raw was rewound 22 times
         rgb_bitdist|   7|    100000|     100|0.45183857|  PASSED  
# The file file_input_raw was rewound 23 times
         rgb_bitdist|   8|    100000|     100|0.74014851|  PASSED  
# The file file_input_raw was rewound 24 times
         rgb_bitdist|   9|    100000|     100|0.67164657|  PASSED  
# The file file_input_raw was rewound 25 times
         rgb_bitdist|  10|    100000|     100|0.90933693|  PASSED  
# The file file_input_raw was rewound 26 times
         rgb_bitdist|  11|    100000|     100|0.92498126|  PASSED  
# The file file_input_raw was rewound 28 times
         rgb_bitdist|  12|    100000|     100|0.38504935|  PASSED  
# The file file_input_raw was rewound 28 times
rgb_minimum_distance|   2|     10000|    1000|0.97332656|  PASSED  
# The file file_input_raw was rewound 28 times
rgb_minimum_distance|   3|     10000|    1000|0.53946962|  PASSED  
# The file file_input_raw was rewound 28 times
rgb_minimum_distance|   4|     10000|    1000|0.22227924|  PASSED  
# The file file_input_raw was rewound 29 times
rgb_minimum_distance|   5|     10000|    1000|0.43766198|  PASSED  
# The file file_input_raw was rewound 29 times
    rgb_permutations|   2|    100000|     100|0.39024741|  PASSED  
# The file file_input_raw was rewound 29 times
    rgb_permutations|   3|    100000|     100|0.50008079|  PASSED  
# The file file_input_raw was rewound 29 times
    rgb_permutations|   4|    100000|     100|0.23573629|  PASSED  
# The file file_input_raw was rewound 29 times
    rgb_permutations|   5|    100000|     100|0.95765710|  PASSED  
# The file file_input_raw was rewound 30 times
      rgb_lagged_sum|   0|   1000000|     100|0.03834857|  PASSED  
# The file file_input_raw was rewound 31 times
      rgb_lagged_sum|   1|   1000000|     100|0.93547822|  PASSED  
# The file file_input_raw was rewound 33 times
      rgb_lagged_sum|   2|   1000000|     100|0.97661888|  PASSED  
# The file file_input_raw was rewound 35 times
      rgb_lagged_sum|   3|   1000000|     100|0.69620755|  PASSED  
# The file file_input_raw was rewound 38 times
      rgb_lagged_sum|   4|   1000000|     100|0.99733188|   WEAK   
# The file file_input_raw was rewound 42 times
      rgb_lagged_sum|   5|   1000000|     100|0.72210898|  PASSED  
# The file file_input_raw was rewound 46 times
      rgb_lagged_sum|   6|   1000000|     100|0.88035129|  PASSED  
# The file file_input_raw was rewound 50 times
      rgb_lagged_sum|   7|   1000000|     100|0.00686507|  PASSED  
# The file file_input_raw was rewound 55 times
      rgb_lagged_sum|   8|   1000000|     100|0.80902072|  PASSED  
# The file file_input_raw was rewound 61 times
      rgb_lagged_sum|   9|   1000000|     100|0.25540007|  PASSED  
# The file file_input_raw was rewound 68 times
      rgb_lagged_sum|  10|   1000000|     100|0.83896554|  PASSED  
# The file file_input_raw was rewound 75 times
      rgb_lagged_sum|  11|   1000000|     100|0.82527346|  PASSED  
# The file file_input_raw was rewound 82 times
      rgb_lagged_sum|  12|   1000000|     100|0.59429364|  PASSED  
# The file file_input_raw was rewound 90 times
      rgb_lagged_sum|  13|   1000000|     100|0.91887010|  PASSED  
# The file file_input_raw was rewound 99 times
      rgb_lagged_sum|  14|   1000000|     100|0.13279602|  PASSED  
# The file file_input_raw was rewound 108 times
      rgb_lagged_sum|  15|   1000000|     100|0.00064208|   WEAK   
# The file file_input_raw was rewound 118 times
      rgb_lagged_sum|  16|   1000000|     100|0.12504309|  PASSED  
# The file file_input_raw was rewound 129 times
      rgb_lagged_sum|  17|   1000000|     100|0.28835351|  PASSED  
# The file file_input_raw was rewound 140 times
      rgb_lagged_sum|  18|   1000000|     100|0.33883707|  PASSED  
# The file file_input_raw was rewound 151 times
      rgb_lagged_sum|  19|   1000000|     100|0.14820792|  PASSED  
# The file file_input_raw was rewound 164 times
      rgb_lagged_sum|  20|   1000000|     100|0.91827815|  PASSED  
# The file file_input_raw was rewound 176 times
      rgb_lagged_sum|  21|   1000000|     100|0.42673045|  PASSED  
# The file file_input_raw was rewound 190 times
      rgb_lagged_sum|  22|   1000000|     100|0.68775757|  PASSED  
# The file file_input_raw was rewound 204 times
      rgb_lagged_sum|  23|   1000000|     100|0.07479913|  PASSED  
# The file file_input_raw was rewound 218 times
      rgb_lagged_sum|  24|   1000000|     100|0.65072008|  PASSED  
# The file file_input_raw was rewound 233 times
      rgb_lagged_sum|  25|   1000000|     100|0.60954177|  PASSED  
# The file file_input_raw was rewound 249 times
      rgb_lagged_sum|  26|   1000000|     100|0.95495153|  PASSED  
# The file file_input_raw was rewound 265 times
      rgb_lagged_sum|  27|   1000000|     100|0.34813186|  PASSED  
# The file file_input_raw was rewound 282 times
      rgb_lagged_sum|  28|   1000000|     100|0.43004064|  PASSED  
# The file file_input_raw was rewound 300 times
      rgb_lagged_sum|  29|   1000000|     100|0.16469168|  PASSED  
# The file file_input_raw was rewound 318 times
      rgb_lagged_sum|  30|   1000000|     100|0.34427995|  PASSED  
# The file file_input_raw was rewound 336 times
      rgb_lagged_sum|  31|   1000000|     100|0.19256759|  PASSED  
# The file file_input_raw was rewound 356 times
      rgb_lagged_sum|  32|   1000000|     100|0.63575322|  PASSED  
# The file file_input_raw was rewound 356 times
     rgb_kstest_test|   0|     10000|    1000|0.10212163|  PASSED  
# The file file_input_raw was rewound 356 times
     dab_bytedistrib|   0|  51200000|       1|0.14305453|  PASSED  
# The file file_input_raw was rewound 357 times
             dab_dct| 256|     50000|       1|0.32921614|  PASSED  
Preparing to run test 207.  ntuple = 0
# The file file_input_raw was rewound 357 times
        dab_filltree|  32|  15000000|       1|0.08710904|  PASSED  
        dab_filltree|  32|  15000000|       1|0.82153918|  PASSED  
Preparing to run test 208.  ntuple = 0
# The file file_input_raw was rewound 357 times
       dab_filltree2|   0|   5000000|       1|0.08344795|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.06535524|  PASSED  
Preparing to run test 209.  ntuple = 0
# The file file_input_raw was rewound 358 times
        dab_monobit2|  12|  65000000|       1|0.77076163|  PASSED 

Continuous (Eternal?) Integration Testing

We now have a CI setup generating data continuously and recording many gigabytes of data to a spinning disk -- about 2GiB/day, and we've got 2TiB of space to fill still. Each of the two types of generators' raw output (ring oscillator and avalanche), plus the conditioned output (after going through a ChaCha CSPRNG) are recorded. We then run the Dieharder, NIST STS tests and rngtest from rng-tools against the traces.

Significantly, this table is from the cryptech.is site for the rngtest tool:

Test Expected failure rate
Total 800ppm
Monobit 100ppm
Poker 100ppm
Runs 300ppm
Long run 300ppm
Continuous run Extremely rare

So far, no significant problems have been found. In practice, the ring oscillator's entropy quality seems less than the others, but it's hard to say by how much. It doesn't fail any tests, but it does show more weak results than the other sources. Inspection of on-line health tests during the long runs shows occasional (once every few minutes generating at a 50kiB/s rate) marginal readings on one of the four cores (the exact core is not deterministic), so I'm guessing every now and then there are resonance effects between the ring oscillators or the rest of the system that can reduce their effectiveness. But, hey, that's why we're using four cores instead of just one.