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;
278 timeout = ((uint32_t)minutes) * 60000U;
301 if (len > (credits / 8))
310 if (count >= RNG_REKEY_BLOCKS) {
323 memcpy(data, stream, len);
326 memcpy(data, stream, 64);
377 if (len >= (RNG_MAX_CREDITS / 8))
378 return credits >= RNG_MAX_CREDITS;
380 return len <= (credits / 8);
411 if ((credit / 8) >= len)
413 if ((RNG_MAX_CREDITS - credits) > credit)
416 credits = RNG_MAX_CREDITS;
425 size_t templen = len;
428 uint8_t *output = ((uint8_t *)block) + 16;
430 while (templen > 0) {
431 *output++ ^= *data++;
445 if (firstSave && credits >= RNG_MAX_CREDITS) {
483 eeprom_write_block(stream, (
void *)(address + 1), 48);
484 eeprom_update_byte((uint8_t *)address,
'S');
498 for (uint8_t posn = 0; posn < count; ++posn)
499 noiseSources[posn]->
stir();
502 if ((millis() - timer) >= timeout)
529 for (
int posn = 0; posn <
SEED_SIZE; ++posn)
530 eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
536 void RNGClass::rekey()
544 memcpy(block + 4, stream, 48);
551 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.
virtual void added()
Called when the noise source is added to RNG with RNG.addNoiseSource().
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.