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));
257 timeout = ((uint32_t)minutes) * 60000U;
280 if (len > (credits / 8))
289 if (count >= RNG_REKEY_BLOCKS) {
302 memcpy(data, stream, len);
305 memcpy(data, stream, 64);
356 if (len >= (RNG_MAX_CREDITS / 8))
357 return credits >= RNG_MAX_CREDITS;
359 return len <= (credits / 8);
390 if ((credit / 8) >= len)
392 if ((RNG_MAX_CREDITS - credits) > credit)
395 credits = RNG_MAX_CREDITS;
404 size_t templen = len;
407 uint8_t *output = ((uint8_t *)block) + 16;
409 while (templen > 0) {
410 *output++ ^= *data++;
424 if (firstSave && credits >= RNG_MAX_CREDITS) {
474 eeprom_write_block(stream, (
void *)(address + 1), 48);
475 eeprom_update_byte((uint8_t *)address,
'S');
489 if ((millis() - timer) >= timeout)
517 for (
int posn = 0; posn <
SEED_SIZE; ++posn)
518 eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
524 void RNGClass::rekey()
532 memcpy(block + 4, stream, 48);
539 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.
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.