Tiny is divided into two parts, the Entropy Gateway (EG) and the Pseudo-Random Number Generator (PRNG). The PRNG is a slight modification of the PRNG used in Yarrow-160 (we use a MAC instead of a block cipher in counter mode, and make other minor changes). The entropy gateway is totally different than anything specified in the Yarrow paper, and is also completely different from the Yarrow-AES algorithm John and Pravir worked on while at Cigital (potential IP issues was one reason for this new algorithm; efficiency was the other).
The counter and entropy estimates initialize to zeros. The entropy buffer initializes to all bits set (each byte is 0xff). When the entropy pool is flushed (see below), all elements of the entropy pool get set to the original state, except for the counter.
The entropy buffer is really 8 parallel LSFRs. Entropy sources mix their data into this pool. Bytes get mixed in using a primitive polynomial of the appropriate size over GF(2). We use polynomials taken from /dev/random, though the mixing code is different.
Here are primitive polynomials taken from /dev/random. Hopefully they are not too sparse:
Special note: The buffer size must be at least eight times (default is 16) the size of the output size (UOL), to avoid entropy loss when sources only provide entropy in lower order bits. (Optionally, we can do some sort of shifting, but it seems like more effort than it is worth). This is sufficient for Tiny, because we never expect the entire buffer to contain more than UOL bits of entropy.
The 2nd-6th terms of the polynomial are "taps", numbered 1 through 5. To mix in a byte of entropy, we take the byte, xor it with the 5 taps, then we rotate the pool left one byte, and replace the first byte of the pool with the result.
When entropy comes in from a source, the entropy counter for that source is incremented by the "hint" provided by the source (note that there is no need to count past THRESH for any one source, and doing so might result in overflow errors).
After entropy is added, the EG checks to see if the LSFR has enough entropy to output. The output rule is as follows:
Total the entropy collected from all sources, after subtracting out the top R contributors. If the number of bits is > THRESH, then an output occurs.
Outputs can go to the output buffer or to the slow pool. The rules for where to output are as follows:
At startup, the slow pool counter is set to zero. The step is set to zero. The UMAC is initialized with a key of all zeros, and a nonce of the current time as reported by gettimeofday(), truncating off the most significant bits if necessary. The buffer is initialized to all zeros.
When the entropy pool has output to every byte of the pre-key once and only once, that is called a "pass" on the pre-key.
If the slow pool has never reseeded before, it reseeds after a single pass on the pre-key.
Otherwise, the slow pool takes twice as many passes on the pre-key to reseed as it did the last time it reseeded, with a maximum of 32.
When the slow pool reseeds, output KEYLEN blocks of output as follows:
Then, take the resulting bytes, and overwrite the UMAC key. Finally, zero out the pre-key.
Outputs are serviced from the output buffer. Outputs should be given in byte-quantities. Pending requests that cannot be fufilled should be queued until output is available. If multiple requests are pending, they should be served in round-robin style.
The Tiny EG should be able to save and restore its state. The UMAC context only should be stored. On restore, the requirement for entropy pool outputs to go to the slow pool is ignored. The slow pool reseeds after a single pass on the pre-key.
The EG tries to output pure entropy. We try to collect at least as many bits of entropy as we wish to output, and usually collect more, because of a conservative assumption that an attacker might be able to compromise one or more entropy sources. If sufficient entropy exists, the EG should produce "good" outputs. We mearly compress (lossily) and whiten the entropy pool using UMAC.
When sufficient entropy is not available due to compromise, UMAC provides cryptographic security as a fallback, assuming that the system has ever mixed sufficient entropy into the slow pool.
We clear the entropy pool every time to ensure that there are no correlations between successive outputs.
We use UMAC because it is fast and has good provable properties. The only assumption we need to make (assuming our design doesn't suck) is the cryptographic strength of AES.
Tiny uses the original Yarrow-160 PRNG, except that:
The generator gate frequency is a system parameter (for self-rekeying). The default frequency is every 10 outputs, as in Yarrow-160. The self-rekey operation is about the same as in Yarrow. The key is overwritten with blocks of generator output, along with the counter and the counter step. The step parameter is always modified to be odd after a rekey.
The seed should be raw entropy, and big enough to set the counter, the UMAC key and the step parameter. If the step parameter is not odd, it is modified to be so.
"Real" reseeds (ones where we add new entropy to the PRNG) can happen by periodic polling, or by push. In both cases, there should be a parameter, minimum time between reseeds. We recommend 60 seconds as the default parameter.