ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups 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 #endif
39 #include <string.h>
40 
134 RNGClass RNG;
135 
141 // Number of ChaCha hash rounds to use for random number generation.
142 #define RNG_ROUNDS 20
143 
144 // Force a rekey after this many blocks of random data.
145 #define RNG_REKEY_BLOCKS 16
146 
147 // Maximum entropy credit that can be contained in the pool.
148 #define RNG_MAX_CREDITS 384
149 
152 // Tag for 256-bit ChaCha20 keys. This will always appear in the
153 // first 16 bytes of the block. The remaining 48 bytes are the seed.
154 static const char tagRNG[16] PROGMEM = {
155  'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
156  '2', '-', 'b', 'y', 't', 'e', ' ', 'k'
157 };
158 
159 // Initialization seed. This is the ChaCha20 output of hashing
160 // "expand 32-byte k" followed by 48 bytes set to the numbers 1 to 48.
161 // The ChaCha20 output block is then truncated to the first 48 bytes.
162 //
163 // This value is intended to start the RNG in a semi-chaotic state if
164 // we don't have a previously saved seed in EEPROM.
165 static const uint8_t initRNG[48] PROGMEM = {
166  0xB0, 0x2A, 0xAE, 0x7D, 0xEE, 0xCB, 0xBB, 0xB1,
167  0xFC, 0x03, 0x6F, 0xDD, 0xDC, 0x7D, 0x76, 0x67,
168  0x0C, 0xE8, 0x1F, 0x0D, 0xA3, 0xA0, 0xAA, 0x1E,
169  0xB0, 0xBD, 0x72, 0x6B, 0x2B, 0x4C, 0x8A, 0x7E,
170  0x34, 0xFC, 0x37, 0x60, 0xF4, 0x1E, 0x22, 0xA0,
171  0x0B, 0xFB, 0x18, 0x84, 0x60, 0xA5, 0x77, 0x72
172 };
173 
174 #if defined(RNG_WATCHDOG)
175 
176 // Use jitter between the watchdog timer and the main CPU clock to
177 // harvest some entropy on AVR-based systems. This technique comes from:
178 //
179 // https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library
180 //
181 // The watchdog generates entropy very slowly - it can take around 32 seconds
182 // to generate 256 bits of entropy credit. This is a "better than nothing"
183 // entropy source but a real noise source is definitely recommended.
184 
185 // Helper macros for specific 32-bit shift counts.
186 #define leftShift3(value) ((value) << 3)
187 #define leftShift10(value) ((value) << 10)
188 #define leftShift15(value) ((value) << 15)
189 #define rightShift6(value) ((value) >> 6)
190 #define rightShift11(value) ((value) >> 11)
191 
192 static uint32_t volatile hash = 0;
193 static uint8_t volatile outBits = 0;
194 
195 // Watchdog interrupt handler. This fires off every 16ms. We collect
196 // 32 bits and then pass them off onto RNGClass::loop().
197 ISR(WDT_vect)
198 {
199  // Read the low byte of Timer 1. We assume that the timer was
200  // initialized by the Arduino startup code for PWM use or that the
201  // application is free-running Timer 1 for its own purposes.
202  // Timer 0 is used on systems that don't have a Timer 1.
203 #if defined(TCNT1L)
204  unsigned char value = TCNT1L;
205 #elif defined(TCNT0L)
206  unsigned char value = TCNT0L;
207 #else
208  unsigned char value = TCNT0;
209 #endif
210  // Use Jenkin's one-at-a-time hash function to scatter the entropy a bit.
211  // https://en.wikipedia.org/wiki/Jenkins_hash_function
212  hash += value;
213  hash += leftShift10(hash);
214  hash ^= rightShift6(hash);
215  ++outBits;
216 }
217 
218 #endif // RNG_WATCHDOG
219 
231  : address(0)
232  , credits(0)
233  , firstSave(1)
234  , timer(0)
235  , timeout(3600000UL) // 1 hour in milliseconds
236  , count(0)
237  , trngPosn(0)
238 {
239 }
240 
245 {
246 #if defined(RNG_DUE_TRNG)
247  // Disable the TRNG in the Arduino Due.
248  REG_TRNG_CR = TRNG_CR_KEY(0x524E47);
249 #endif
250 #if defined(RNG_WATCHDOG)
251  // Disable interrupts and reset the watchdog.
252  cli();
253  wdt_reset();
254 
255  // Clear the "reset due to watchdog" flag.
256  MCUSR &= ~(1 << WDRF);
257 
258  // Disable the watchdog.
259  _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
260  _WD_CONTROL_REG = 0;
261 
262  // Re-enable interrupts. The watchdog should be stopped.
263  sei();
264 #endif
265  clean(block);
266  clean(stream);
267 }
268 
269 #if defined(RNG_DUE_TRNG)
270 
271 // Find the flash memory of interest. Allow for the possibility
272 // of other SAM-based Arduino variants in the future.
273 #if defined(IFLASH1_ADDR)
274 #define RNG_FLASH_ADDR IFLASH1_ADDR
275 #define RNG_FLASH_SIZE IFLASH1_SIZE
276 #define RNG_FLASH_PAGE_SIZE IFLASH1_PAGE_SIZE
277 #define RNG_EFC EFC1
278 #elif defined(IFLASH0_ADDR)
279 #define RNG_FLASH_ADDR IFLASH0_ADDR
280 #define RNG_FLASH_SIZE IFLASH0_SIZE
281 #define RNG_FLASH_PAGE_SIZE IFLASH0_PAGE_SIZE
282 #define RNG_EFC EFC0
283 #else
284 #define RNG_FLASH_ADDR IFLASH_ADDR
285 #define RNG_FLASH_SIZE IFLASH_SIZE
286 #define RNG_FLASH_PAGE_SIZE IFLASH_PAGE_SIZE
287 #define RNG_EFC EFC
288 #endif
289 
290 // Address of the flash page to use for saving the seed on the Due.
291 // All SAM variants have a page size of 256 bytes or greater so there is
292 // plenty of room for the 48 byte seed in the last page of flash memory.
293 #define RNG_SEED_ADDR (RNG_FLASH_ADDR + RNG_FLASH_SIZE - RNG_FLASH_PAGE_SIZE)
294 #define RNG_SEED_PAGE ((RNG_FLASH_SIZE / RNG_FLASH_PAGE_SIZE) - 1)
295 
296 // Stir in the unique identifier for the Arduino Due's CPU.
297 // This function must be in RAM because programs running out of
298 // flash memory are not allowed to access the unique identifier.
299 // Info from: http://forum.arduino.cc/index.php?topic=289190.0
300 __attribute__((section(".ramfunc")))
301 static void stirUniqueIdentifier(void)
302 {
303  uint32_t id[4];
304 
305  // Start Read Unique Identifier.
306  RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
307  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) != 0)
308  ; // do nothing until FRDY falls.
309 
310  // Read the identifier.
311  id[0] = *((const uint32_t *)RNG_FLASH_ADDR);
312  id[1] = *((const uint32_t *)(RNG_FLASH_ADDR + 4));
313  id[2] = *((const uint32_t *)(RNG_FLASH_ADDR + 8));
314  id[3] = *((const uint32_t *)(RNG_FLASH_ADDR + 12));
315 
316  // Stop Read Unique Identifier.
317  RNG_EFC->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
318  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
319  ; // do nothing until FRDY rises.
320 
321  // Stir the unique identifier into the entropy pool.
322  RNG.stir((uint8_t *)id, sizeof(id));
323 }
324 
325 // Erases the flash page containing the seed and then writes the new seed.
326 // It is assumed the seed has already been loaded into the latch registers.
327 __attribute__((section(".ramfunc")))
328 static void eraseAndWriteSeed()
329 {
330  // Execute the "Erase and Write Page" command.
331  RNG_EFC->EEFC_FCR = (0x5A << 24) | (RNG_SEED_PAGE << 8) | EFC_FCMD_EWP;
332 
333  // Wait for the FRDY bit to be raised.
334  while ((RNG_EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
335  ; // do nothing until FRDY rises.
336 }
337 
338 #endif
339 
359 void RNGClass::begin(const char *tag, int eepromAddress)
360 {
361  // Save the EEPROM address for use by save().
362  address = eepromAddress;
363 
364  // Initialize the ChaCha20 input block from the saved seed.
365  memcpy_P(block, tagRNG, sizeof(tagRNG));
366  memcpy_P(block + 4, initRNG, sizeof(initRNG));
367 #if defined(RNG_EEPROM)
368  if (eeprom_read_byte((const uint8_t *)address) == 'S') {
369  // We have a saved seed: XOR it with the initialization block.
370  for (int posn = 0; posn < 12; ++posn) {
371  block[posn + 4] ^=
372  eeprom_read_dword((const uint32_t *)(address + posn * 4 + 1));
373  }
374  }
375 #elif defined(RNG_DUE_TRNG)
376  // Do we have a seed saved in the last page of flash memory on the Due?
377  int posn, counter;
378  if (((const uint32_t *)RNG_SEED_ADDR)[0] == 'S') {
379  // XOR the saved seed with the initialization block.
380  for (posn = 0; posn < 12; ++posn)
381  block[posn + 4] ^= ((const uint32_t *)RNG_SEED_ADDR)[posn + 1];
382  }
383 
384  // If the device has just been reprogrammed, there will be no saved seed.
385  // XOR the initialization block with some output from the CPU's TRNG
386  // to permute the state in a first boot situation after reprogramming.
387  pmc_enable_periph_clk(ID_TRNG);
388  REG_TRNG_CR = TRNG_CR_KEY(0x524E47) | TRNG_CR_ENABLE;
389  REG_TRNG_IDR = TRNG_IDR_DATRDY; // Disable interrupts - we will poll.
390  for (posn = 0; posn < 12; ++posn) {
391  // According to the documentation the TRNG should produce a new
392  // 32-bit random value every 84 clock cycles. If it still hasn't
393  // produced a value after 200 iterations, then assume that the
394  // TRNG is not producing output and stop.
395  for (counter = 0; counter < 200; ++counter) {
396  if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0)
397  break;
398  }
399  if (counter >= 200)
400  break;
401  block[posn + 4] ^= REG_TRNG_ODATA;
402  }
403 #endif
404 
405  // No entropy credits for the saved seed.
406  credits = 0;
407 
408  // Trigger an automatic save once the entropy credits max out.
409  firstSave = 1;
410 
411  // Rekey the random number generator immediately.
412  rekey();
413 
414  // Stir in the supplied tag data but don't credit any entropy to it.
415  if (tag)
416  stir((const uint8_t *)tag, strlen(tag));
417 
418 #if defined(RNG_DUE_TRNG)
419  // Stir in the unique identifier for the CPU so that different
420  // devices will give different outputs even without seeding.
421  stirUniqueIdentifier();
422 #endif
423 
424 #if defined(RNG_WATCHDOG)
425  // Disable interrupts and reset the watchdog.
426  cli();
427  wdt_reset();
428 
429  // Clear the "reset due to watchdog" flag.
430  MCUSR &= ~(1 << WDRF);
431 
432  // Enable the watchdog with the smallest duration (16ms)
433  // and interrupt-only mode.
434  _WD_CONTROL_REG |= (1 << _WD_CHANGE_BIT) | (1 << WDE);
435  _WD_CONTROL_REG = (1 << WDIE);
436 
437  // Re-enable interrupts. The watchdog should be running.
438  sei();
439 #endif
440 
441  // Re-save the seed to obliterate the previous value and to ensure
442  // that if the system is reset without a call to save() that we won't
443  // accidentally generate the same sequence of random data again.
444  save();
445 }
446 
460 {
461  #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0]))
462  if (count < MAX_NOISE_SOURCES) {
463  noiseSources[count++] = &source;
464  source.added();
465  }
466 }
467 
484 void RNGClass::setAutoSaveTime(uint16_t minutes)
485 {
486  if (!minutes)
487  minutes = 1; // Just in case.
488  timeout = ((uint32_t)minutes) * 60000U;
489 }
490 
508 void RNGClass::rand(uint8_t *data, size_t len)
509 {
510  // Decrease the amount of entropy in the pool.
511  if (len > (credits / 8))
512  credits = 0;
513  else
514  credits -= len * 8;
515 
516  // Generate the random data.
517  uint8_t count = 0;
518  while (len > 0) {
519  // Force a rekey if we have generated too many blocks in this request.
520  if (count >= RNG_REKEY_BLOCKS) {
521  rekey();
522  count = 1;
523  } else {
524  ++count;
525  }
526 
527  // Increment the low counter word and generate a new keystream block.
528  ++(block[12]);
529  ChaCha::hashCore(stream, block, RNG_ROUNDS);
530 
531  // Copy the data to the return buffer.
532  if (len < 64) {
533  memcpy(data, stream, len);
534  break;
535  } else {
536  memcpy(data, stream, 64);
537  data += 64;
538  len -= 64;
539  }
540  }
541 
542  // Force a rekey after every request.
543  rekey();
544 }
545 
585 bool RNGClass::available(size_t len) const
586 {
587  if (len >= (RNG_MAX_CREDITS / 8))
588  return credits >= RNG_MAX_CREDITS;
589  else
590  return len <= (credits / 8);
591 }
592 
618 void RNGClass::stir(const uint8_t *data, size_t len, unsigned int credit)
619 {
620  // Increase the entropy credit.
621  if ((credit / 8) >= len && len)
622  credit = len * 8;
623  if ((RNG_MAX_CREDITS - credits) > credit)
624  credits += credit;
625  else
626  credits = RNG_MAX_CREDITS;
627 
628  // Process the supplied input data.
629  if (len > 0) {
630  // XOR the data with the ChaCha input block in 48 byte
631  // chunks and rekey the ChaCha cipher for each chunk to mix
632  // the data in. This should scatter any "true entropy" in
633  // the input across the entire block.
634  while (len > 0) {
635  size_t templen = len;
636  if (templen > 48)
637  templen = 48;
638  uint8_t *output = ((uint8_t *)block) + 16;
639  len -= templen;
640  while (templen > 0) {
641  *output++ ^= *data++;
642  --templen;
643  }
644  rekey();
645  }
646  } else {
647  // There was no input data, so just force a rekey so we
648  // get some mixing of the state even without new data.
649  rekey();
650  }
651 
652  // Save if this is the first time we have reached max entropy.
653  // This provides some protection if the system is powered off before
654  // the first auto-save timeout occurs.
655  if (firstSave && credits >= RNG_MAX_CREDITS) {
656  firstSave = 0;
657  save();
658  }
659 }
660 
688 {
689  // Generate random data from the current state and save
690  // that as the seed. Then force a rekey.
691  ++(block[12]);
692  ChaCha::hashCore(stream, block, RNG_ROUNDS);
693 #if defined(RNG_EEPROM)
694  eeprom_write_block(stream, (void *)(address + 1), 48);
695  eeprom_update_byte((uint8_t *)address, 'S');
696 #elif defined(RNG_DUE_TRNG)
697  unsigned posn;
698  ((uint32_t *)(RNG_SEED_ADDR))[0] = 'S';
699  for (posn = 0; posn < 12; ++posn)
700  ((uint32_t *)(RNG_SEED_ADDR))[posn + 1] = stream[posn];
701  for (posn = 13; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
702  ((uint32_t *)(RNG_SEED_ADDR))[posn + 13] = 0xFFFFFFFF;
703  eraseAndWriteSeed();
704 #endif
705  rekey();
706  timer = millis();
707 }
708 
716 {
717  // Stir in the entropy from all registered noise sources.
718  for (uint8_t posn = 0; posn < count; ++posn)
719  noiseSources[posn]->stir();
720 
721 #if defined(RNG_DUE_TRNG)
722  // If there is data available from the Arudino Due's TRNG, then XOR
723  // it with the state block and increase the entropy credit. We don't
724  // call stir() yet because that will seriously slow down the system
725  // given how fast the TRNG is. Instead we save up the XOR'ed TRNG
726  // data until the next rand() call and then hash it to generate the
727  // desired output.
728  //
729  // The CPU documentation claims that the TRNG output is very good so
730  // this should only make the pool more and more random as time goes on.
731  // However there is a risk that the CPU manufacturer was pressured by
732  // government or intelligence agencies to insert a back door that
733  // generates predictable output. Or the manufacturer was overly
734  // optimistic about their TRNG design and it is actually flawed in a
735  // way they don't realise.
736  //
737  // If you are concerned about such threats, then make sure to mix in
738  // data from other noise sources. By hashing together the TRNG with
739  // the other noise data, rand() should produce unpredictable data even
740  // if one of the sources is actually predictable.
741  if ((REG_TRNG_ISR & TRNG_ISR_DATRDY) != 0) {
742  block[4 + trngPosn] ^= REG_TRNG_ODATA;
743  if (++trngPosn >= 12)
744  trngPosn = 0;
745  if (credits < RNG_MAX_CREDITS) {
746  // Credit 1 bit of entropy for the word. The TRNG should be
747  // better than this but it is so fast that we want to collect
748  // up more data before passing it to the application.
749  ++credits;
750  }
751  }
752 #elif defined(RNG_WATCHDOG)
753  // Read the 32 bit buffer from the WDT interrupt.
754  cli();
755  if (outBits >= 32) {
756  uint32_t value = hash;
757  hash = 0;
758  outBits = 0;
759  sei();
760 
761  // Final steps of the Jenkin's one-at-a-time hash function.
762  // https://en.wikipedia.org/wiki/Jenkins_hash_function
763  value += leftShift3(value);
764  value ^= rightShift11(value);
765  value += leftShift15(value);
766 
767  // XOR the word with the state. Stir once we accumulate 48 bytes,
768  // which happens about once every 6.4 seconds.
769  block[4 + trngPosn] ^= value;
770  if (++trngPosn >= 12) {
771  trngPosn = 0;
772 
773  // Credit 1 bit of entropy for each byte of input. It can take
774  // between 30 and 40 seconds to accumulate 256 bits of credit.
775  stir(0, 0, 48);
776  }
777  } else {
778  sei();
779  }
780 #endif
781 
782  // Save the seed if the auto-save timer has expired.
783  if ((millis() - timer) >= timeout)
784  save();
785 }
786 
807 {
808  clean(block);
809  clean(stream);
810 #if defined(RNG_EEPROM)
811  for (int posn = 0; posn < SEED_SIZE; ++posn)
812  eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
813 #elif defined(RNG_DUE_TRNG)
814  for (unsigned posn = 0; posn < (RNG_FLASH_PAGE_SIZE / 4); ++posn)
815  ((uint32_t *)(RNG_SEED_ADDR))[posn] = 0xFFFFFFFF;
816  eraseAndWriteSeed();
817 #endif
818 }
819 
823 void RNGClass::rekey()
824 {
825  // Rekey the cipher for the next request by generating a new block.
826  // This is intended to make it difficult to wind the random number
827  // backwards if the state is captured later. The first 16 bytes of
828  // "block" remain set to "tagRNG".
829  ++(block[12]);
830  ChaCha::hashCore(stream, block, RNG_ROUNDS);
831  memcpy(block + 4, stream, 48);
832 
833  // Permute the high word of the counter using the system microsecond
834  // counter to introduce a little bit of non-stir randomness for each
835  // request. Note: If random data is requested on a predictable schedule
836  // then this may not help very much. It is still necessary to stir in
837  // high quality entropy data on a regular basis using stir().
838  block[13] ^= micros();
839 }
void save()
Saves the random seed to EEPROM.
Definition: RNG.cpp:687
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
Definition: RNG.cpp:508
void begin(const char *tag, int eepromAddress)
Initializes the random number generator.
Definition: RNG.cpp:359
Abstract base class for random noise sources.
Definition: NoiseSource.h:29
~RNGClass()
Destroys this random number generator instance.
Definition: RNG.cpp:244
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:459
RNGClass()
Constructs a new random number generator instance.
Definition: RNG.cpp:230
void destroy()
Destroys the data in the random number pool and the saved seed in EEPROM.
Definition: RNG.cpp:806
bool available(size_t len) const
Determine if there is sufficient entropy available for a specific request size.
Definition: RNG.cpp:585
void loop()
Run periodic housekeeping tasks on the random number generator.
Definition: RNG.cpp:715
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:618
void setAutoSaveTime(uint16_t minutes)
Sets the amount of time between automatic seed saves.
Definition: RNG.cpp:484