24 #include "NoiseSource.h"
27 #include "utility/ProgMemUtil.h"
29 #include <avr/eeprom.h>
125 #define RNG_ROUNDS 20
128 #define RNG_REKEY_BLOCKS 16
131 #define RNG_MAX_CREDITS 384
137 static const char tagRNG[16] PROGMEM = {
138 'e',
'x',
'p',
'a',
'n',
'd',
' ',
'3',
139 '2',
'-',
'b',
'y',
't',
'e',
' ',
'k'
148 static const uint8_t initRNG[48] PROGMEM = {
149 0xB0, 0x2A, 0xAE, 0x7D, 0xEE, 0xCB, 0xBB, 0xB1,
150 0xFC, 0x03, 0x6F, 0xDD, 0xDC, 0x7D, 0x76, 0x67,
151 0x0C, 0xE8, 0x1F, 0x0D, 0xA3, 0xA0, 0xAA, 0x1E,
152 0xB0, 0xBD, 0x72, 0x6B, 0x2B, 0x4C, 0x8A, 0x7E,
153 0x34, 0xFC, 0x37, 0x60, 0xF4, 0x1E, 0x22, 0xA0,
154 0x0B, 0xFB, 0x18, 0x84, 0x60, 0xA5, 0x77, 0x72
205 address = eepromAddress;
208 memcpy_P(block, tagRNG,
sizeof(tagRNG));
209 memcpy_P(block + 4, initRNG,
sizeof(initRNG));
210 if (eeprom_read_byte((
const uint8_t *)address) ==
'S') {
212 for (
int posn = 0; posn < 12; ++posn) {
214 eeprom_read_dword((
const uint32_t *)(address + posn * 4 + 1));
229 stir((
const uint8_t *)tag, strlen(tag));
251 #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0]))
252 if (count < MAX_NOISE_SOURCES)
253 noiseSources[count++] = &source;
276 timeout = ((uint32_t)minutes) * 60000U;
299 if (len > (credits / 8))
308 if (count >= RNG_REKEY_BLOCKS) {
321 memcpy(data, stream, len);
324 memcpy(data, stream, 64);
375 if (len >= (RNG_MAX_CREDITS / 8))
376 return credits >= RNG_MAX_CREDITS;
378 return len <= (credits / 8);
409 if ((credit / 8) >= len)
411 if ((RNG_MAX_CREDITS - credits) > credit)
414 credits = RNG_MAX_CREDITS;
423 size_t templen = len;
426 uint8_t *output = ((uint8_t *)block) + 16;
428 while (templen > 0) {
429 *output++ ^= *data++;
443 if (firstSave && credits >= RNG_MAX_CREDITS) {
481 eeprom_write_block(stream, (
void *)(address + 1), 48);
482 eeprom_update_byte((uint8_t *)address,
'S');
496 for (uint8_t posn = 0; posn < count; ++posn)
497 noiseSources[posn]->
stir();
500 if ((millis() - timer) >= timeout)
527 for (
int posn = 0; posn <
SEED_SIZE; ++posn)
528 eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
534 void RNGClass::rekey()
542 memcpy(block + 4, stream, 48);
549 block[13] ^= micros();
void save()
Saves the random seed to EEPROM.
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
void begin(const char *tag, int eepromAddress)
Initializes the random number generator.
Abstract base class for random noise sources.
~RNGClass()
Destroys this random number generator instance.
void addNoiseSource(NoiseSource &source)
Adds a noise source to the random number generator.
RNGClass()
Constructs a new random number generator instance.
void destroy()
Destroys the data in the random number pool and the saved seed in EEPROM.
bool available(size_t len) const
Determine if there is sufficient entropy available for a specific request size.
void loop()
Run periodic housekeeping tasks on the random number generator.
Pseudo random number generator suitable for cryptography.
static const int SEED_SIZE
Size of a saved random number seed in EEPROM space.
static void hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
Executes the ChaCha hash core on an input memory block.
void stir(const uint8_t *data, size_t len, unsigned int credit=0)
Stirs additional entropy data into the random pool.
void setAutoSaveTime(uint16_t minutes)
Sets the amount of time between automatic seed saves.