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
206 address = eepromAddress;
209 memcpy_P(block, tagRNG,
sizeof(tagRNG));
210 memcpy_P(block + 4, initRNG,
sizeof(initRNG));
211 if (eeprom_read_byte((
const uint8_t *)address) ==
'S') {
213 for (
int posn = 0; posn < 12; ++posn) {
215 eeprom_read_dword((
const uint32_t *)(address + posn * 4 + 1));
230 stir((
const uint8_t *)tag, strlen(tag));
252 #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0]))
253 if (count < MAX_NOISE_SOURCES)
254 noiseSources[count++] = &source;
277 timeout = ((uint32_t)minutes) * 60000U;
300 if (len > (credits / 8))
309 if (count >= RNG_REKEY_BLOCKS) {
322 memcpy(data, stream, len);
325 memcpy(data, stream, 64);
376 if (len >= (RNG_MAX_CREDITS / 8))
377 return credits >= RNG_MAX_CREDITS;
379 return len <= (credits / 8);
410 if ((credit / 8) >= len)
412 if ((RNG_MAX_CREDITS - credits) > credit)
415 credits = RNG_MAX_CREDITS;
424 size_t templen = len;
427 uint8_t *output = ((uint8_t *)block) + 16;
429 while (templen > 0) {
430 *output++ ^= *data++;
444 if (firstSave && credits >= RNG_MAX_CREDITS) {
494 eeprom_write_block(stream, (
void *)(address + 1), 48);
495 eeprom_update_byte((uint8_t *)address,
'S');
509 for (uint8_t posn = 0; posn < count; ++posn)
510 noiseSources[posn]->
stir();
513 if ((millis() - timer) >= timeout)
541 for (
int posn = 0; posn <
SEED_SIZE; ++posn)
542 eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
548 void RNGClass::rekey()
556 memcpy(block + 4, stream, 48);
563 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.
virtual void stir()=0
Stirs entropy from this noise source into the global random number pool.
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.