24 #include "NoiseSource.h" 
   28 #include "utility/ProgMemUtil.h" 
   29 #if defined (__arm__) && defined (__SAM3X8E__) 
   32 #define RNG_DUE_TRNG 1 
   33 #elif defined(__AVR__) 
   34 #include <avr/eeprom.h> 
   38 #if defined(MEGATINYCORE) || defined(LOGIC_H)  
   51 #elif defined(TCNT1L) || defined(TCNT0L) || defined(TCNT0) 
   52 #define RNG_WATCHDOG 1       
   55 #define RNG_EEPROM_ADDRESS (E2END + 1 - RNGClass::SEED_SIZE) 
   56 #elif defined(ESP8266) 
   60 #define RNG_WORD_TRNG 1 
   61 #define RNG_WORD_TRNG_GET() (ESP8266_DREG(0x20E44)) 
   64 #define RNG_WORD_TRNG 1 
   65 #define RNG_WORD_TRNG_GET() (esp_random()) 
   76 #if !defined(RNG_DUE_TRNG) && \ 
   77     !defined(RNG_WATCHDOG) && \ 
   78     !defined(RNG_WORD_TRNG) && \ 
   80 #warning "no hardware random number source detected for this platform" 
  187 #define RNG_ROUNDS          20 
  190 #define RNG_REKEY_BLOCKS    16 
  193 #define RNG_MAX_CREDITS     384u 
  198 extern uint8_t crypto_crc8(uint8_t tag, 
const void *data, 
unsigned size);
 
  202 static const char tagRNG[16] PROGMEM = {
 
  203     'e', 
'x', 
'p', 
'a', 
'n', 
'd', 
' ', 
'3',
 
  204     '2', 
'-', 
'b', 
'y', 
't', 
'e', 
' ', 
'k' 
  213 static const uint8_t initRNG[48] PROGMEM = {
 
  214     0xB0, 0x2A, 0xAE, 0x7D, 0xEE, 0xCB, 0xBB, 0xB1,
 
  215     0xFC, 0x03, 0x6F, 0xDD, 0xDC, 0x7D, 0x76, 0x67,
 
  216     0x0C, 0xE8, 0x1F, 0x0D, 0xA3, 0xA0, 0xAA, 0x1E,
 
  217     0xB0, 0xBD, 0x72, 0x6B, 0x2B, 0x4C, 0x8A, 0x7E,
 
  218     0x34, 0xFC, 0x37, 0x60, 0xF4, 0x1E, 0x22, 0xA0,
 
  219     0x0B, 0xFB, 0x18, 0x84, 0x60, 0xA5, 0x77, 0x72
 
  222 #if defined(RNG_WATCHDOG) 
  234 #define leftShift3(value)   ((value) << 3) 
  235 #define leftShift10(value)  ((value) << 10) 
  236 #define leftShift15(value)  ((value) << 15) 
  237 #define rightShift6(value)  ((value) >> 6) 
  238 #define rightShift11(value) ((value) >> 11) 
  240 static uint32_t 
volatile hash = 0;
 
  241 static uint8_t 
volatile outBits = 0;
 
  252     unsigned char value = TCNT1L;
 
  253 #elif defined(TCNT0L) 
  254     unsigned char value = TCNT0L;
 
  256     unsigned char value = TCNT0;
 
  261     hash += leftShift10(hash);
 
  262     hash ^= rightShift6(hash);
 
  266 #elif defined(RNG_CCL) 
  269 #define leftShift3(value)   ((value) << 3) 
  270 #define leftShift10(value)  ((value) << 10) 
  271 #define leftShift15(value)  ((value) << 15) 
  272 #define rightShift6(value)  ((value) >> 6) 
  273 #define rightShift11(value) ((value) >> 11) 
  275 static uint32_t 
volatile hash = 0;
 
  276 static uint8_t 
volatile outBits = 0;
 
  281     uint8_t temp = TCB0.INTFLAGS;
 
  291     RTC_INTFLAGS = RTC_OVF_bm; 
 
  292     unsigned char value = (TCB0.CNT); 
 
  294     hash += leftShift10(hash);
 
  295     hash ^= rightShift6(hash);
 
  328 #if defined(RNG_DUE_TRNG) 
  330     REG_TRNG_CR = TRNG_CR_KEY(0x524E47);
 
  332 #if defined(RNG_WATCHDOG) 
  338     MCUSR &= ~(1 << WDRF);
 
  341     _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
 
  346 #elif defined(RNG_CCL) 
  354 #if defined(RNG_DUE_TRNG) 
  358 #if defined(IFLASH1_ADDR) 
  359 #define RNG_FLASH_ADDR      IFLASH1_ADDR 
  360 #define RNG_FLASH_SIZE      IFLASH1_SIZE 
  361 #define RNG_FLASH_PAGE_SIZE IFLASH1_PAGE_SIZE 
  363 #elif defined(IFLASH0_ADDR) 
  364 #define RNG_FLASH_ADDR      IFLASH0_ADDR 
  365 #define RNG_FLASH_SIZE      IFLASH0_SIZE 
  366 #define RNG_FLASH_PAGE_SIZE IFLASH0_PAGE_SIZE 
  369 #define RNG_FLASH_ADDR      IFLASH_ADDR 
  370 #define RNG_FLASH_SIZE      IFLASH_SIZE 
  371 #define RNG_FLASH_PAGE_SIZE IFLASH_PAGE_SIZE 
  378 #define RNG_SEED_ADDR (RNG_FLASH_ADDR + RNG_FLASH_SIZE - RNG_FLASH_PAGE_SIZE) 
  379 #define RNG_SEED_PAGE ((RNG_FLASH_SIZE / RNG_FLASH_PAGE_SIZE) - 1) 
  385 __attribute__((section(
".ramfunc")))
 
  386 static 
void stirUniqueIdentifier(
void)
 
  391     RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
 
  392     while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) != 0)
 
  396     id[0] = *((
const uint32_t *)RNG_FLASH_ADDR);
 
  397     id[1] = *((
const uint32_t *)(RNG_FLASH_ADDR + 4));
 
  398     id[2] = *((
const uint32_t *)(RNG_FLASH_ADDR + 8));
 
  399     id[3] = *((
const uint32_t *)(RNG_FLASH_ADDR + 12));
 
  402     RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
 
  403     while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
 
  407     RNG.
stir((uint8_t *)id, 
sizeof(id));
 
  412 __attribute__((section(
".ramfunc")))
 
  413 static 
void eraseAndWriteSeed()
 
  416     RNG_EFC->EEFC_FCR = (0x5A << 24) | (RNG_SEED_PAGE << 8) | EFC_FCMD_EWP;
 
  419     while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
 
  445     memcpy_P(block, tagRNG, 
sizeof(tagRNG));
 
  446     memcpy_P(block + 4, initRNG, 
sizeof(initRNG));
 
  447 #if defined(RNG_EEPROM) 
  448     int address = RNG_EEPROM_ADDRESS;
 
  449     eeprom_read_block(stream, (
const void *)address, 
SEED_SIZE);
 
  450     if (crypto_crc8(
'S', stream, 
SEED_SIZE - 1) ==
 
  451             ((
const uint8_t *)stream)[
SEED_SIZE - 1]) {
 
  454         for (
int posn = 0; posn < 12; ++posn)
 
  455             block[posn + 4] ^= stream[posn];
 
  457 #elif defined(RNG_DUE_TRNG) 
  459     if (crypto_crc8(
'S', ((
const uint32_t *)RNG_SEED_ADDR) + 1, 
SEED_SIZE)
 
  460             == ((
const uint32_t *)RNG_SEED_ADDR)[0]) {
 
  462         for (
int posn = 0; posn < 12; ++posn)
 
  463             block[posn + 4] ^= ((
const uint32_t *)RNG_SEED_ADDR)[posn + 1];
 
  469     pmc_enable_periph_clk(ID_TRNG);
 
  470     REG_TRNG_CR = TRNG_CR_KEY(0x524E47) | TRNG_CR_ENABLE;
 
  471     REG_TRNG_IDR = TRNG_IDR_DATRDY; 
 
  474 #if defined(RNG_ESP_NVS) 
  476     nvs_handle handle = 0;
 
  477     if (nvs_open(
"rng", NVS_READONLY, &handle) == 0) {
 
  479         if (nvs_get_blob(handle, 
"seed", NULL, &len) == 0 && len == 
SEED_SIZE) {
 
  481             if (nvs_get_blob(handle, 
"seed", seed, &len) == 0) {
 
  482                 for (
int posn = 0; posn < 12; ++posn)
 
  483                     block[posn + 4] ^= seed[posn];
 
  490 #if defined(RNG_WORD_TRNG) 
  506         stir((
const uint8_t *)tag, strlen(tag));
 
  508 #if defined(RNG_DUE_TRNG) 
  511     stirUniqueIdentifier();
 
  512 #elif defined(ESP8266) 
  516     ids[0] = ESP.getChipId();
 
  517     ids[1] = ESP.getFlashChipId();
 
  518     stir((
const uint8_t *)ids, 
sizeof(ids));
 
  521     uint64_t mac = ESP.getEfuseMac();
 
  522     stir((
const uint8_t *)&mac, 
sizeof(mac));
 
  528     tag = __TIME__ __DATE__;
 
  529     stir((
const uint8_t *)tag, strlen(tag));
 
  532 #if defined(RNG_WATCHDOG) 
  538     MCUSR &= ~(1 << WDRF);
 
  542     _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
 
  543     _WD_CONTROL_REG = (1 << WDIE);
 
  547 #elif defined(RNG_CCL) 
  553     CCL.LUT1CTRLA = 0x01;  
 
  554     EVSYS.CHANNEL0 = EVSYS_CHANNEL0_CCL_LUT1_gc; 
 
  555     EVSYS.USERCCLLUT1A = EVSYS_USER_CHANNEL0_gc;
 
  556     EVSYS.USERTCB0COUNT = EVSYS_USER_CHANNEL0_gc;
 
  567     RTC.CLKSEL = RTC_CLKSEL_INT32K_gc;  
 
  568     while (RTC.STATUS > 0); 
 
  569     uint8_t CCL_SAMPLE_PERIOD;
 
  571     CCL_SAMPLE_PERIOD = 2;
 
  572 #elif(F_CPU == 4000000) 
  573     CCL_SAMPLE_PERIOD = 5;
 
  574 #elif(F_CPU == 2000000) 
  575     CCL_SAMPLE_PERIOD = 9;
 
  576 #elif(F_CPU == 1000000) 
  577     CCL_SAMPLE_PERIOD = 16;
 
  579     #error "Chip frequency not supported" 
  581     RTC.PER = CCL_SAMPLE_PERIOD;
 
  582     RTC.INTCTRL |= RTC_OVF_bm; 
 
  585     RTC.CTRLA = RTC_PRESCALER_DIV1_gc 
 
  613     #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0])) 
  614     if (count < MAX_NOISE_SOURCES) {
 
  615         noiseSources[count++] = &source;
 
  640     timeout = ((uint32_t)minutes) * 60000U;
 
  668     if ( (uint16_t)len > (credits / 8))
 
  689         if (count >= RNG_REKEY_BLOCKS) {
 
  702             memcpy(data, stream, len);
 
  705             memcpy(data, stream, 64);
 
  756     if (len >= (RNG_MAX_CREDITS / 8))
 
  757         return credits >= RNG_MAX_CREDITS;
 
  759         return (uint16_t)len <= (credits / 8);
 
  790     if ((credit / 8) >= len && len)
 
  792     if ((uint16_t)(RNG_MAX_CREDITS - credits) > credit)
 
  795         credits = RNG_MAX_CREDITS;
 
  804             size_t templen = len;
 
  807             uint8_t *output = ((uint8_t *)block) + 16;
 
  809             while (templen > 0) {
 
  810                 *output++ ^= *data++;
 
  824     if (firstSave && credits >= RNG_MAX_CREDITS) {
 
  862 #if defined(RNG_EEPROM) 
  866     int address = RNG_EEPROM_ADDRESS;
 
  867     eeprom_write_block(stream, (
void *)address, 
SEED_SIZE - 1);
 
  868     eeprom_write_byte((uint8_t *)(address + 
SEED_SIZE - 1),
 
  869                       crypto_crc8(
'S', stream, 
SEED_SIZE - 1));
 
  870 #elif defined(RNG_DUE_TRNG) 
  872     ((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8(
'S', stream, 
SEED_SIZE);
 
  873     for (posn = 0; posn < 12; ++posn)
 
  874         ((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
 
  875     for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
 
  876         ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF;
 
  878 #elif defined(RNG_ESP_NVS) 
  880     nvs_handle handle = 0;
 
  881     if (nvs_open(
"rng", NVS_READWRITE, &handle) == 0) {
 
  882         nvs_erase_all(handle);
 
  883         nvs_set_blob(handle, 
"seed", stream, 
SEED_SIZE);
 
  901     for (uint8_t posn = 0; posn < count; ++posn)
 
  902         noiseSources[posn]->
stir();
 
  904 #if defined(RNG_DUE_TRNG) 
  924     if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0) {
 
  925         block[4 + trngPosn] ^= REG_TRNG_ODATA;
 
  926         if (++trngPosn >= 12)
 
  928         if (credits < RNG_MAX_CREDITS) {
 
  936 #elif defined(RNG_WORD_TRNG) 
  938     block[4 + trngPosn] ^= RNG_WORD_TRNG_GET();
 
  939     if (++trngPosn >= 12)
 
  941     if (credits < RNG_MAX_CREDITS) {
 
  948 #elif defined(RNG_WATCHDOG) 
  952         uint32_t value = hash;
 
  959         value += leftShift3(value);
 
  960         value ^= rightShift11(value);
 
  961         value += leftShift15(value);
 
  966         if (credits > RNG_MAX_CREDITS)
 
  967             credits = RNG_MAX_CREDITS;
 
  971         block[4 + trngPosn] ^= value;
 
  972         if (++trngPosn >= 12) {
 
  982 #elif defined(RNG_CCL) 
  984         uint32_t value = hash;
 
  990         value += leftShift3(value);
 
  991         value ^= rightShift11(value);
 
  992         value += leftShift15(value);
 
  996         if (credits > RNG_MAX_CREDITS)
 
  997             credits = RNG_MAX_CREDITS;
 
 1000         block[4 + trngPosn] ^= value;
 
 1001         if (++trngPosn >= 12) {
 
 1012     if ((millis() - timer) >= timeout)
 
 1039 #if defined(RNG_EEPROM) 
 1040     int address = RNG_EEPROM_ADDRESS;
 
 1041     for (
int posn = 0; posn < 
SEED_SIZE; ++posn)
 
 1042         eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
 
 1043 #elif defined(RNG_DUE_TRNG) 
 1044     for (
unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
 
 1045         ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF;
 
 1046     eraseAndWriteSeed();
 
 1047 #elif defined(RNG_ESP_NVS) 
 1048     nvs_handle handle = 0;
 
 1049     if (nvs_open(
"rng", NVS_READWRITE, &handle) == 0) {
 
 1050         nvs_erase_all(handle);
 
 1061 void RNGClass::rekey()
 
 1069     memcpy(block + 4, stream, 48);
 
 1076     block[13] ^= micros();
 
 1082 void RNGClass::mixTRNG()
 
 1084 #if defined(RNG_DUE_TRNG) 
 1086     for (
int posn = 0; posn < 12; ++posn) {
 
 1092         for (counter = 0; counter < 200; ++counter) {
 
 1093             if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0)
 
 1098         block[posn + 4] ^= REG_TRNG_ODATA;
 
 1100 #elif defined(RNG_WORD_TRNG) 
 1102     for (uint8_t index = 4; index < 16; ++index)
 
 1103         block[index] ^= RNG_WORD_TRNG_GET();
 
 1104 #elif defined(RNG_WATCHDOG) 
 1107     if (outBits >= 32) {
 
 1108         uint32_t value = hash;
 
 1115         value += leftShift3(value);
 
 1116         value ^= rightShift11(value);
 
 1117         value += leftShift15(value);
 
 1124 #elif defined(RNG_CCL) 
 1125     if (outBits >= 32) {
 
 1126         uint32_t value = hash;
 
 1132         value += leftShift3(value);
 
 1133         value ^= rightShift11(value);
 
 1134         value += leftShift15(value);
 
static void hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
Executes the ChaCha hash core on an input memory block.
Abstract base class for random noise sources.
virtual void added()
Called when the noise source is added to RNG with RNG.addNoiseSource().
Pseudo random number generator suitable for cryptography.
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 setAutoSaveTime(uint16_t minutes)
Sets the amount of time between automatic seed saves.
void begin(const char *tag)
Initializes the random number generator.
void loop()
Run periodic housekeeping tasks on the random number generator.
void destroy()
Destroys the data in the random number pool and the saved seed in EEPROM.
void addNoiseSource(NoiseSource &source)
Adds a noise source to the random number generator.
bool available(size_t len) const
Determine if there is sufficient entropy available for a specific request size.
RNGClass()
Constructs a new random number generator instance.
void stir(const uint8_t *data, size_t len, unsigned int credit=0)
Stirs additional entropy data into the random pool.
static const int SEED_SIZE
Size of a saved random number seed in EEPROM space.
~RNGClass()
Destroys this random number generator instance.