Arduino Cryptography Library
 All Classes Files Functions Variables Enumerations Enumerator Pages
RNG.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "RNG.h"
24 #include "NoiseSource.h"
25 #include "ChaCha.h"
26 #include "Crypto.h"
27 #include "utility/ProgMemUtil.h"
28 #include <Arduino.h>
29 #if defined (__arm__) && defined (__SAM3X8E__)
30 // The Arduino Due does not have any EEPROM natively on the main chip.
31 // However, it does have a TRNG and flash memory.
32 #define RNG_DUE_TRNG 1
33 #elif defined(__AVR__)
34 #define RNG_EEPROM 1 // Use EEPROM to save the seed.
35 #define RNG_WATCHDOG 1 // Harvest entropy from watchdog jitter.
36 #include <avr/eeprom.h>
37 #include <avr/wdt.h>
38 #include <avr/io.h>
39 #define RNG_EEPROM_ADDRESS (E2END + 1 - RNGClass::SEED_SIZE)
40 #elif defined(ESP8266)
41 // ESP8266 does not have EEPROM but it does have SPI flash memory.
42 // It also has a TRNG register for generating "true" random numbers.
43 // For now we use the TRNG but don't save the seed in flash memory.
44 #define RNG_WORD_TRNG 1
45 #define RNG_WORD_TRNG_GET() (ESP8266_DREG(0x20E44))
46 #elif defined(ESP32)
47 // ESP32 has a word-based TRNG and an API for Non-Volatile Storage (NVS).
48 #define RNG_WORD_TRNG 1
49 #define RNG_WORD_TRNG_GET() (esp_random())
50 #define RNG_ESP_NVS 1
51 #include <nvs.h>
52 #endif
53 #include <string.h>
54 
55 // Throw an error if there is no built-in hardware random number source.
56 // If this happens, then you need to do one of two things:
57 // 1. Edit RNG.cpp to add your platform's hardware TRNG.
58 // 2. Provide a proper noise source like TransistorNoiseSource
59 // in your sketch and then comment out the #error line below.
60 #if !defined(RNG_DUE_TRNG) && \
61  !defined(RNG_WATCHDOG) && \
62  !defined(RNG_WORD_TRNG)
63 #error "no hardware random number source detected for this platform"
64 #endif
65 
159 RNGClass RNG;
160 
169 // Number of ChaCha hash rounds to use for random number generation.
170 #define RNG_ROUNDS 20
171 
172 // Force a rekey after this many blocks of random data.
173 #define RNG_REKEY_BLOCKS 16
174 
175 // Maximum entropy credit that can be contained in the pool.
176 #define RNG_MAX_CREDITS 384u
177 
180 // Imported from Crypto.cpp.
181 extern uint8_t crypto_crc8(uint8_t tag, const void *data, unsigned size);
182 
183 // Tag for 256-bit ChaCha20 keys. This will always appear in the
184 // first 16 bytes of the block. The remaining 48 bytes are the seed.
185 static const char tagRNG[16] PROGMEM = {
186  'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
187  '2', '-', 'b', 'y', 't', 'e', ' ', 'k'
188 };
189 
190 // Initialization seed. This is the ChaCha20 output of hashing
191 // "expand 32-byte k" followed by 48 bytes set to the numbers 1 to 48.
192 // The ChaCha20 output block is then truncated to the first 48 bytes.
193 //
194 // This value is intended to start the RNG in a semi-chaotic state if
195 // we don't have a previously saved seed in EEPROM.
196 static const uint8_t initRNG[48] PROGMEM = {
197  0xB0, 0x2A, 0xAE, 0x7D, 0xEE, 0xCB, 0xBB, 0xB1,
198  0xFC, 0x03, 0x6F, 0xDD, 0xDC, 0x7D, 0x76, 0x67,
199  0x0C, 0xE8, 0x1F, 0x0D, 0xA3, 0xA0, 0xAA, 0x1E,
200  0xB0, 0xBD, 0x72, 0x6B, 0x2B, 0x4C, 0x8A, 0x7E,
201  0x34, 0xFC, 0x37, 0x60, 0xF4, 0x1E, 0x22, 0xA0,
202  0x0B, 0xFB, 0x18, 0x84, 0x60, 0xA5, 0x77, 0x72
203 };
204 
205 #if defined(RNG_WATCHDOG)
206 
207 // Use jitter between the watchdog timer and the main CPU clock to
208 // harvest some entropy on AVR-based systems. This technique comes from:
209 //
210 // https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library
211 //
212 // The watchdog generates entropy very slowly - it can take around 32 seconds
213 // to generate 256 bits of entropy credit. This is a "better than nothing"
214 // entropy source but a real noise source is definitely recommended.
215 
216 // Helper macros for specific 32-bit shift counts.
217 #define leftShift3(value) ((value) << 3)
218 #define leftShift10(value) ((value) << 10)
219 #define leftShift15(value) ((value) << 15)
220 #define rightShift6(value) ((value) >> 6)
221 #define rightShift11(value) ((value) >> 11)
222 
223 static uint32_t volatile hash = 0;
224 static uint8_t volatile outBits = 0;
225 
226 // Watchdog interrupt handler. This fires off every 16ms. We collect
227 // 32 bits and then pass them off onto RNGClass::loop().
228 ISR(WDT_vect)
229 {
230  // Read the low byte of Timer 1. We assume that the timer was
231  // initialized by the Arduino startup code for PWM use or that the
232  // application is free-running Timer 1 for its own purposes.
233  // Timer 0 is used on systems that don't have a Timer 1.
234 #if defined(TCNT1L)
235  unsigned char value = TCNT1L;
236 #elif defined(TCNT0L)
237  unsigned char value = TCNT0L;
238 #else
239  unsigned char value = TCNT0;
240 #endif
241  // Use Jenkin's one-at-a-time hash function to scatter the entropy a bit.
242  // https://en.wikipedia.org/wiki/Jenkins_hash_function
243  hash += value;
244  hash += leftShift10(hash);
245  hash ^= rightShift6(hash);
246  ++outBits;
247 }
248 
249 #endif // RNG_WATCHDOG
250 
262  : credits(0)
263  , firstSave(1)
264  , initialized(0)
265  , trngPending(0)
266  , timer(0)
267  , timeout(3600000UL) // 1 hour in milliseconds
268  , count(0)
269  , trngPosn(0)
270 {
271 }
272 
277 {
278 #if defined(RNG_DUE_TRNG)
279  // Disable the TRNG in the Arduino Due.
280  REG_TRNG_CR = TRNG_CR_KEY(0x524E47);
281 #endif
282 #if defined(RNG_WATCHDOG)
283  // Disable interrupts and reset the watchdog.
284  cli();
285  wdt_reset();
286 
287  // Clear the "reset due to watchdog" flag.
288  MCUSR &= ~(1 << WDRF);
289 
290  // Disable the watchdog.
291  _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
292  _WD_CONTROL_REG = 0;
293 
294  // Re-enable interrupts. The watchdog should be stopped.
295  sei();
296 #endif
297  clean(block);
298  clean(stream);
299 }
300 
301 #if defined(RNG_DUE_TRNG)
302 
303 // Find the flash memory of interest. Allow for the possibility
304 // of other SAM-based Arduino variants in the future.
305 #if defined(IFLASH1_ADDR)
306 #define RNG_FLASH_ADDR IFLASH1_ADDR
307 #define RNG_FLASH_SIZE IFLASH1_SIZE
308 #define RNG_FLASH_PAGE_SIZE IFLASH1_PAGE_SIZE
309 #define RNG_EFC EFC1
310 #elif defined(IFLASH0_ADDR)
311 #define RNG_FLASH_ADDR IFLASH0_ADDR
312 #define RNG_FLASH_SIZE IFLASH0_SIZE
313 #define RNG_FLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
314 #define RNG_EFC EFC0
315 #else
316 #define RNG_FLASH_ADDR IFLASH_ADDR
317 #define RNG_FLASH_SIZE IFLASH_SIZE
318 #define RNG_FLASH_PAGE_SIZE IFLASH_PAGE_SIZE
319 #define RNG_EFC EFC
320 #endif
321 
322 // Address of the flash page to use for saving the seed on the Due.
323 // All SAM variants have a page size of 256 bytes or greater so there is
324 // plenty of room for the 48 byte seed in the last page of flash memory.
325 #define RNG_SEED_ADDR (RNG_FLASH_ADDR + RNG_FLASH_SIZE - RNG_FLASH_PAGE_SIZE)
326 #define RNG_SEED_PAGE ((RNG_FLASH_SIZE / RNG_FLASH_PAGE_SIZE) - 1)
327 
328 // Stir in the unique identifier for the Arduino Due's CPU.
329 // This function must be in RAM because programs running out of
330 // flash memory are not allowed to access the unique identifier.
331 // Info from: http://forum.arduino.cc/index.php?topic=289190.0
332 __attribute__((section(".ramfunc")))
333 static void stirUniqueIdentifier(void)
334 {
335  uint32_t id[4];
336 
337  // Start Read Unique Identifier.
338  RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
339  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) != 0)
340  ; // do nothing until FRDY falls.
341 
342  // Read the identifier.
343  id[0] = *((const uint32_t *)RNG_FLASH_ADDR);
344  id[1] = *((const uint32_t *)(RNG_FLASH_ADDR + 4));
345  id[2] = *((const uint32_t *)(RNG_FLASH_ADDR + 8));
346  id[3] = *((const uint32_t *)(RNG_FLASH_ADDR + 12));
347 
348  // Stop Read Unique Identifier.
349  RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
350  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
351  ; // do nothing until FRDY rises.
352 
353  // Stir the unique identifier into the entropy pool.
354  RNG.stir((uint8_t *)id, sizeof(id));
355 }
356 
357 // Erases the flash page containing the seed and then writes the new seed.
358 // It is assumed the seed has already been loaded into the latch registers.
359 __attribute__((section(".ramfunc")))
360 static void eraseAndWriteSeed()
361 {
362  // Execute the "Erase and Write Page" command.
363  RNG_EFC->EEFC_FCR = (0x5A << 24) | (RNG_SEED_PAGE << 8) | EFC_FCMD_EWP;
364 
365  // Wait for the FRDY bit to be raised.
366  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
367  ; // do nothing until FRDY rises.
368 }
369 
370 #endif
371 
385 void RNGClass::begin(const char *tag)
386 {
387  // Bail out if we have already done this.
388  if (initialized)
389  return;
390 
391  // Initialize the ChaCha20 input block from the saved seed.
392  memcpy_P(block, tagRNG, sizeof(tagRNG));
393  memcpy_P(block + 4, initRNG, sizeof(initRNG));
394 #if defined(RNG_EEPROM)
395  int address = RNG_EEPROM_ADDRESS;
396  eeprom_read_block(stream, (const void *)address, SEED_SIZE);
397  if (crypto_crc8('S', stream, SEED_SIZE - 1) ==
398  ((const uint8_t *)stream)[SEED_SIZE - 1]) {
399  // We have a saved seed: XOR it with the initialization block.
400  // Note: the CRC-8 value is included. No point throwing it away.
401  for (int posn = 0; posn < 12; ++posn)
402  block[posn + 4] ^= stream[posn];
403  }
404 #elif defined(RNG_DUE_TRNG)
405  // Do we have a seed saved in the last page of flash memory on the Due?
406  if (crypto_crc8('S', ((const uint32_t *)RNG_SEED_ADDR) + 1, SEED_SIZE)
407  == ((const uint32_t *)RNG_SEED_ADDR)[0]) {
408  // XOR the saved seed with the initialization block.
409  for (int posn = 0; posn < 12; ++posn)
410  block[posn + 4] ^= ((const uint32_t *)RNG_SEED_ADDR)[posn + 1];
411  }
412 
413  // If the device has just been reprogrammed, there will be no saved seed.
414  // XOR the initialization block with some output from the CPU's TRNG
415  // to permute the state in a first boot situation after reprogramming.
416  pmc_enable_periph_clk(ID_TRNG);
417  REG_TRNG_CR = TRNG_CR_KEY(0x524E47) | TRNG_CR_ENABLE;
418  REG_TRNG_IDR = TRNG_IDR_DATRDY; // Disable interrupts - we will poll.
419  mixTRNG();
420 #endif
421 #if defined(RNG_ESP_NVS)
422  // Do we have a seed saved in ESP non-volatile storage (NVS)?
423  nvs_handle handle = 0;
424  if (nvs_open("rng", NVS_READONLY, &handle) == 0) {
425  size_t len = 0;
426  if (nvs_get_blob(handle, "seed", NULL, &len) == 0 && len == SEED_SIZE) {
427  uint32_t seed[12];
428  if (nvs_get_blob(handle, "seed", seed, &len) == 0) {
429  for (int posn = 0; posn < 12; ++posn)
430  block[posn + 4] ^= seed[posn];
431  }
432  clean(seed);
433  }
434  nvs_close(handle);
435  }
436 #endif
437 #if defined(RNG_WORD_TRNG)
438  // Mix in some output from a word-based TRNG to initialize the state.
439  mixTRNG();
440 #endif
441 
442  // No entropy credits for the saved seed.
443  credits = 0;
444 
445  // Trigger an automatic save once the entropy credits max out.
446  firstSave = 1;
447 
448  // Rekey the random number generator immediately.
449  rekey();
450 
451  // Stir in the supplied tag data but don't credit any entropy to it.
452  if (tag)
453  stir((const uint8_t *)tag, strlen(tag));
454 
455 #if defined(RNG_DUE_TRNG)
456  // Stir in the unique identifier for the CPU so that different
457  // devices will give different outputs even without seeding.
458  stirUniqueIdentifier();
459 #elif defined(ESP8266)
460  // ESP8266's have a 32-bit CPU chip ID and 32-bit flash chip ID
461  // that we can use as a device unique identifier.
462  uint32_t ids[2];
463  ids[0] = ESP.getChipId();
464  ids[1] = ESP.getFlashChipId();
465  stir((const uint8_t *)ids, sizeof(ids));
466 #elif defined(ESP32)
467  // ESP32's have a MAC address that can be used as a device identifier.
468  uint64_t mac = ESP.getEfuseMac();
469  stir((const uint8_t *)&mac, sizeof(mac));
470 #else
471  // AVR devices don't have anything like a serial number so it is
472  // difficult to make every device unique. Use the compilation
473  // time and date to provide a little randomness across applications
474  // if not across devices running the same pre-compiled application.
475  tag = __TIME__ __DATE__;
476  stir((const uint8_t *)tag, strlen(tag));
477 #endif
478 
479 #if defined(RNG_WATCHDOG)
480  // Disable interrupts and reset the watchdog.
481  cli();
482  wdt_reset();
483 
484  // Clear the "reset due to watchdog" flag.
485  MCUSR &= ~(1 << WDRF);
486 
487  // Enable the watchdog with the smallest duration (16ms)
488  // and interrupt-only mode.
489  _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
490  _WD_CONTROL_REG = (1 << WDIE);
491 
492  // Re-enable interrupts. The watchdog should be running.
493  sei();
494 #endif
495 
496  // Re-save the seed to obliterate the previous value and to ensure
497  // that if the system is reset without a call to save() that we won't
498  // accidentally generate the same sequence of random data again.
499  save();
500 
501  // The RNG has now been initialized.
502  initialized = 1;
503 }
504 
518 {
519  #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0]))
520  if (count < MAX_NOISE_SOURCES) {
521  noiseSources[count++] = &source;
522  source.added();
523  }
524 }
525 
542 void RNGClass::setAutoSaveTime(uint16_t minutes)
543 {
544  if (!minutes)
545  minutes = 1; // Just in case.
546  timeout = ((uint32_t)minutes) * 60000U;
547 }
548 
566 void RNGClass::rand(uint8_t *data, size_t len)
567 {
568  // Make sure that the RNG is initialized in case the application
569  // forgot to call RNG.begin() at startup time.
570  if (!initialized)
571  begin(0);
572 
573  // Decrease the amount of entropy in the pool.
574  if (len > (credits / 8u))
575  credits = 0;
576  else
577  credits -= len * 8;
578 
579  // If we have pending TRNG data from the loop() function,
580  // then force a stir on the state. Otherwise mix in some
581  // fresh data from the TRNG because it is possible that
582  // the application forgot to call RNG.loop().
583  if (trngPending) {
584  stir(0, 0, 0);
585  trngPending = 0;
586  trngPosn = 0;
587  } else {
588  mixTRNG();
589  }
590 
591  // Generate the random data.
592  uint8_t count = 0;
593  while (len > 0) {
594  // Force a rekey if we have generated too many blocks in this request.
595  if (count >= RNG_REKEY_BLOCKS) {
596  rekey();
597  count = 1;
598  } else {
599  ++count;
600  }
601 
602  // Increment the low counter word and generate a new keystream block.
603  ++(block[12]);
604  ChaCha::hashCore(stream, block, RNG_ROUNDS);
605 
606  // Copy the data to the return buffer.
607  if (len < 64) {
608  memcpy(data, stream, len);
609  break;
610  } else {
611  memcpy(data, stream, 64);
612  data += 64;
613  len -= 64;
614  }
615  }
616 
617  // Force a rekey after every request.
618  rekey();
619 }
620 
660 bool RNGClass::available(size_t len) const
661 {
662  if (len >= (RNG_MAX_CREDITS / 8))
663  return credits >= RNG_MAX_CREDITS;
664  else
665  return len <= (credits / 8u);
666 }
667 
693 void RNGClass::stir(const uint8_t *data, size_t len, unsigned int credit)
694 {
695  // Increase the entropy credit.
696  if ((credit / 8) >= len && len)
697  credit = len * 8;
698  if ((RNG_MAX_CREDITS - credits) > credit)
699  credits += credit;
700  else
701  credits = RNG_MAX_CREDITS;
702 
703  // Process the supplied input data.
704  if (len > 0) {
705  // XOR the data with the ChaCha input block in 48 byte
706  // chunks and rekey the ChaCha cipher for each chunk to mix
707  // the data in. This should scatter any "true entropy" in
708  // the input across the entire block.
709  while (len > 0) {
710  size_t templen = len;
711  if (templen > 48)
712  templen = 48;
713  uint8_t *output = ((uint8_t *)block) + 16;
714  len -= templen;
715  while (templen > 0) {
716  *output++ ^= *data++;
717  --templen;
718  }
719  rekey();
720  }
721  } else {
722  // There was no input data, so just force a rekey so we
723  // get some mixing of the state even without new data.
724  rekey();
725  }
726 
727  // Save if this is the first time we have reached max entropy.
728  // This provides some protection if the system is powered off before
729  // the first auto-save timeout occurs.
730  if (firstSave && credits >= RNG_MAX_CREDITS) {
731  firstSave = 0;
732  save();
733  }
734 }
735 
763 {
764  // Generate random data from the current state and save
765  // that as the seed. Then force a rekey.
766  ++(block[12]);
767  ChaCha::hashCore(stream, block, RNG_ROUNDS);
768 #if defined(RNG_EEPROM)
769  // We shorten the seed from 48 bytes to 47 to leave room for
770  // the CRC-8 value. We do this to align the data on an 8-byte
771  // boundary in EERPOM.
772  int address = RNG_EEPROM_ADDRESS;
773  eeprom_write_block(stream, (void *)address, SEED_SIZE - 1);
774  eeprom_write_byte((uint8_t *)(address + SEED_SIZE - 1),
775  crypto_crc8('S', stream, SEED_SIZE - 1));
776 #elif defined(RNG_DUE_TRNG)
777  unsigned posn;
778  ((uint32_t *)(RNG_SEED_ADDR))[0] = crypto_crc8('S', stream, SEED_SIZE);
779  for (posn = 0; posn < 12; ++posn)
780  ((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
781  for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
782  ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF;
783  eraseAndWriteSeed();
784 #elif defined(RNG_ESP_NVS)
785  // Save the seed into ESP non-volatile storage (NVS).
786  nvs_handle handle = 0;
787  if (nvs_open("rng", NVS_READWRITE, &handle) == 0) {
788  nvs_erase_all(handle);
789  nvs_set_blob(handle, "seed", stream, SEED_SIZE);
790  nvs_commit(handle);
791  nvs_close(handle);
792  }
793 #endif
794  rekey();
795  timer = millis();
796 }
797 
805 {
806  // Stir in the entropy from all registered noise sources.
807  for (uint8_t posn = 0; posn < count; ++posn)
808  noiseSources[posn]->stir();
809 
810 #if defined(RNG_DUE_TRNG)
811  // If there is data available from the Arudino Due's TRNG, then XOR
812  // it with the state block and increase the entropy credit. We don't
813  // call stir() yet because that will seriously slow down the system
814  // given how fast the TRNG is. Instead we save up the XOR'ed TRNG
815  // data until the next rand() call and then hash it to generate the
816  // desired output.
817  //
818  // The CPU documentation claims that the TRNG output is very good so
819  // this should only make the pool more and more random as time goes on.
820  // However there is a risk that the CPU manufacturer was pressured by
821  // government or intelligence agencies to insert a back door that
822  // generates predictable output. Or the manufacturer was overly
823  // optimistic about their TRNG design and it is actually flawed in a
824  // way they don't realise.
825  //
826  // If you are concerned about such threats, then make sure to mix in
827  // data from other noise sources. By hashing together the TRNG with
828  // the other noise data, rand() should produce unpredictable data even
829  // if one of the sources is actually predictable.
830  if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0) {
831  block[4 + trngPosn] ^= REG_TRNG_ODATA;
832  if (++trngPosn >= 12)
833  trngPosn = 0;
834  if (credits < RNG_MAX_CREDITS) {
835  // Credit 1 bit of entropy for the word. The TRNG should be
836  // better than this but it is so fast that we want to collect
837  // up more data before passing it to the application.
838  ++credits;
839  }
840  trngPending = 1;
841  }
842 #elif defined(RNG_WORD_TRNG)
843  // Read a word from the TRNG and XOR it into the state.
844  block[4 + trngPosn] ^= RNG_WORD_TRNG_GET();
845  if (++trngPosn >= 12)
846  trngPosn = 0;
847  if (credits < RNG_MAX_CREDITS) {
848  // Credit 1 bit of entropy for the word. The TRNG should be
849  // better than this but it is so fast that we want to collect
850  // up more data before passing it to the application.
851  ++credits;
852  }
853  trngPending = 1;
854 #elif defined(RNG_WATCHDOG)
855  // Read the 32 bit buffer from the WDT interrupt.
856  cli();
857  if (outBits >= 32) {
858  uint32_t value = hash;
859  hash = 0;
860  outBits = 0;
861  sei();
862 
863  // Final steps of the Jenkin's one-at-a-time hash function.
864  // https://en.wikipedia.org/wiki/Jenkins_hash_function
865  value += leftShift3(value);
866  value ^= rightShift11(value);
867  value += leftShift15(value);
868 
869  // Credit 1 bit of entropy for each byte of input. It can take
870  // between 30 and 40 seconds to accumulate 256 bits of credit.
871  credits += 4;
872  if (credits > RNG_MAX_CREDITS)
873  credits = RNG_MAX_CREDITS;
874 
875  // XOR the word with the state. Stir once we accumulate 48 bytes,
876  // which happens about once every 6.4 seconds.
877  block[4 + trngPosn] ^= value;
878  if (++trngPosn >= 12) {
879  trngPosn = 0;
880  trngPending = 0;
881  stir(0, 0, 0);
882  } else {
883  trngPending = 1;
884  }
885  } else {
886  sei();
887  }
888 #endif
889 
890  // Save the seed if the auto-save timer has expired.
891  if ((millis() - timer) >= timeout)
892  save();
893 }
894 
915 {
916  clean(block);
917  clean(stream);
918 #if defined(RNG_EEPROM)
919  int address = RNG_EEPROM_ADDRESS;
920  for (int posn = 0; posn < SEED_SIZE; ++posn)
921  eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
922 #elif defined(RNG_DUE_TRNG)
923  for (unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
924  ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF;
925  eraseAndWriteSeed();
926 #elif defined(RNG_ESP_NVS)
927  nvs_handle handle = 0;
928  if (nvs_open("rng", NVS_READWRITE, &handle) == 0) {
929  nvs_erase_all(handle);
930  nvs_commit(handle);
931  nvs_close(handle);
932  }
933 #endif
934  initialized = 0;
935 }
936 
940 void RNGClass::rekey()
941 {
942  // Rekey the cipher for the next request by generating a new block.
943  // This is intended to make it difficult to wind the random number
944  // backwards if the state is captured later. The first 16 bytes of
945  // "block" remain set to "tagRNG".
946  ++(block[12]);
947  ChaCha::hashCore(stream, block, RNG_ROUNDS);
948  memcpy(block + 4, stream, 48);
949 
950  // Permute the high word of the counter using the system microsecond
951  // counter to introduce a little bit of non-stir randomness for each
952  // request. Note: If random data is requested on a predictable schedule
953  // then this may not help very much. It is still necessary to stir in
954  // high quality entropy data on a regular basis using stir().
955  block[13] ^= micros();
956 }
957 
961 void RNGClass::mixTRNG()
962 {
963 #if defined(RNG_DUE_TRNG)
964  // Mix in 12 words from the Due's TRNG.
965  for (int posn = 0; posn < 12; ++posn) {
966  // According to the documentation the TRNG should produce a new
967  // 32-bit random value every 84 clock cycles. If it still hasn't
968  // produced a value after 200 iterations, then assume that the
969  // TRNG is not producing output and stop.
970  int counter;
971  for (counter = 0; counter < 200; ++counter) {
972  if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0)
973  break;
974  }
975  if (counter >= 200)
976  break;
977  block[posn + 4] ^= REG_TRNG_ODATA;
978  }
979 #elif defined(RNG_WORD_TRNG)
980  // Read 12 words from the TRNG and XOR them into the state.
981  for (uint8_t index = 4; index < 16; ++index)
982  block[index] ^= RNG_WORD_TRNG_GET();
983 #elif defined(RNG_WATCHDOG)
984  // Read the pending 32 bit buffer from the WDT interrupt and mix it in.
985  cli();
986  if (outBits >= 32) {
987  uint32_t value = hash;
988  hash = 0;
989  outBits = 0;
990  sei();
991 
992  // Final steps of the Jenkin's one-at-a-time hash function.
993  // https://en.wikipedia.org/wiki/Jenkins_hash_function
994  value += leftShift3(value);
995  value ^= rightShift11(value);
996  value += leftShift15(value);
997 
998  // XOR the word with the state.
999  block[4] ^= value;
1000  } else {
1001  sei();
1002  }
1003 #endif
1004 }
void save()
Saves the random seed to EEPROM.
Definition: RNG.cpp:762
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
Definition: RNG.cpp:566
void begin(const char *tag)
Initializes the random number generator.
Definition: RNG.cpp:385
Abstract base class for random noise sources.
Definition: NoiseSource.h:29
~RNGClass()
Destroys this random number generator instance.
Definition: RNG.cpp:276
virtual void added()
Called when the noise source is added to RNG with RNG.addNoiseSource().
Definition: NoiseSource.cpp:95
void addNoiseSource(NoiseSource &source)
Adds a noise source to the random number generator.
Definition: RNG.cpp:517
RNGClass()
Constructs a new random number generator instance.
Definition: RNG.cpp:261
void destroy()
Destroys the data in the random number pool and the saved seed in EEPROM.
Definition: RNG.cpp:914
bool available(size_t len) const
Determine if there is sufficient entropy available for a specific request size.
Definition: RNG.cpp:660
void loop()
Run periodic housekeeping tasks on the random number generator.
Definition: RNG.cpp:804
Pseudo random number generator suitable for cryptography.
Definition: RNG.h:31
static const int SEED_SIZE
Size of a saved random number seed in EEPROM space.
Definition: RNG.h:53
static void hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
Executes the ChaCha hash core on an input memory block.
Definition: ChaCha.cpp:253
void stir(const uint8_t *data, size_t len, unsigned int credit=0)
Stirs additional entropy data into the random pool.
Definition: RNG.cpp:693
void setAutoSaveTime(uint16_t minutes)
Sets the amount of time between automatic seed saves.
Definition: RNG.cpp:542