1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Remove EEPROM address argument from RNG.begin()

Always store the seed at the very end of EEPROM memory.
This commit is contained in:
Rhys Weatherley 2017-11-04 10:18:05 +10:00
parent 506af269b7
commit d452bea037
9 changed files with 32 additions and 39 deletions

View File

@ -133,8 +133,8 @@ all of the application's noise sources:
\code \code
void setup() { void setup() {
// Initialize the random number generator with the application tag // Initialize the random number generator with the application tag
// "MyApp 1.0" and load the previous seed from EEPROM address 950. // "MyApp 1.0" and load the previous seed from EEPROM.
RNG.begin("MyApp 1.0", 950); RNG.begin("MyApp 1.0");
// Add the noise source to the list of sources known to RNG. // Add the noise source to the list of sources known to RNG.
RNG.addNoiseSource(noise); RNG.addNoiseSource(noise);
@ -143,17 +143,16 @@ void setup() {
} }
\endcode \endcode
The begin() function is passed two arguments: a tag string that should The begin() function is passed a tag string that should be different for
be different for every application and an EEPROM address to use to every application. The tag string ensures that different applications and
load and save the random number seed. The tag string ensures that versions will generate different random numbers upon first boot before
different applications and versions will generate different random numbers the noise source has collected any entropy. If the device also has a unique
upon first boot before the noise source has collected any entropy. serial number or a MAC address, then those can be mixed in during the
If the device also has a unique serial number or a MAC address, then setup() function after calling begin():
those can be mixed in during the setup() function after calling begin():
\code \code
void setup() { void setup() {
RNG.begin("MyApp 1.0", 950); RNG.begin("MyApp 1.0");
RNG.stir(serial_number, sizeof(serial_number)); RNG.stir(serial_number, sizeof(serial_number));
RNG.stir(mac_address, sizeof(mac_address)); RNG.stir(mac_address, sizeof(mac_address));
RNG.addNoiseSource(noise); RNG.addNoiseSource(noise);
@ -161,8 +160,8 @@ void setup() {
} }
\endcode \endcode
The random number generator needs 49 bytes of EEPROM space at the The random number generator uses 49 bytes of space at the end of
specified address to store the previous seed. When the system is started EEPROM memory to store the previous seed. When the system is started
next time, the previous saved seed is loaded and then deliberately next time, the previous saved seed is loaded and then deliberately
overwritten with a new seed. This ensures that the device will not overwritten with a new seed. This ensures that the device will not
accidentally generate the same sequence of random numbers if it is accidentally generate the same sequence of random numbers if it is

View File

@ -57,7 +57,7 @@ RNGClass::~RNGClass()
clean(stream); clean(stream);
} }
void RNGClass::begin(const char *tag, int eepromAddress) void RNGClass::begin(const char *tag)
{ {
} }

View File

@ -35,6 +35,8 @@
#define RNG_WATCHDOG 1 // Harvest entropy from watchdog jitter. #define RNG_WATCHDOG 1 // Harvest entropy from watchdog jitter.
#include <avr/eeprom.h> #include <avr/eeprom.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/io.h>
#define RNG_EEPROM_ADDRESS (E2END + 1 - RNGClass::SEED_SIZE)
#endif #endif
#include <string.h> #include <string.h>
@ -73,8 +75,8 @@
* Ethernet.begin(mac_address); * Ethernet.begin(mac_address);
* *
* // Initialize the random number generator with the application tag * // Initialize the random number generator with the application tag
* // "MyApp 1.0" and load the previous seed from EEPROM address 950. * // "MyApp 1.0" and load the previous seed from EEPROM.
* RNG.begin("MyApp 1.0", 950); * RNG.begin("MyApp 1.0");
* *
* // Stir in the Ethernet MAC address. * // Stir in the Ethernet MAC address.
* RNG.stir(mac_address, sizeof(mac_address)); * RNG.stir(mac_address, sizeof(mac_address));
@ -101,8 +103,8 @@
* \endcode * \endcode
* *
* The loop() function will automatically save the random number seed on a * The loop() function will automatically save the random number seed on a
* regular basis. By default the seed is saved every hour but this can be * regular basis to the last SEED_SIZE bytes of EEPROM memory. By default
* changed using setAutoSaveTime(). * the seed is saved every hour but this can be changed using setAutoSaveTime().
* *
* Keep in mind that saving too often may cause the EEPROM to wear out quicker. * Keep in mind that saving too often may cause the EEPROM to wear out quicker.
* It is wise to limit saving to once an hour or once a day depending * It is wise to limit saving to once an hour or once a day depending
@ -136,6 +138,9 @@ RNGClass RNG;
/** /**
* \var RNGClass::SEED_SIZE * \var RNGClass::SEED_SIZE
* \brief Size of a saved random number seed in EEPROM space. * \brief Size of a saved random number seed in EEPROM space.
*
* The seed is saved into the last SEED_SIZE bytes of EEPROM memory.
* The address is dependent upon the size of EEPROM fitted in the device.
*/ */
// Number of ChaCha hash rounds to use for random number generation. // Number of ChaCha hash rounds to use for random number generation.
@ -228,8 +233,7 @@ ISR(WDT_vect)
* \sa begin() * \sa begin()
*/ */
RNGClass::RNGClass() RNGClass::RNGClass()
: address(0) : credits(0)
, credits(0)
, firstSave(1) , firstSave(1)
, timer(0) , timer(0)
, timeout(3600000UL) // 1 hour in milliseconds , timeout(3600000UL) // 1 hour in milliseconds
@ -344,27 +348,19 @@ static void eraseAndWriteSeed()
* usually this should be a value that is unique to the application and * usually this should be a value that is unique to the application and
* version such as "MyApp 1.0" so that different applications do not * version such as "MyApp 1.0" so that different applications do not
* generate the same sequence of values upon first boot. * generate the same sequence of values upon first boot.
* \param eepromAddress The EEPROM address to load the previously saved
* seed from and to save new seeds when save() is called. There must be
* at least SEED_SIZE (49) bytes of EEPROM space available at the address.
* *
* This function should be followed by calls to addNoiseSource() to * This function should be followed by calls to addNoiseSource() to
* register the application's noise sources. * register the application's noise sources.
* *
* The \a eepromAddress is ignored on the Arduino Due. The seed is instead
* stored in the last page of system flash memory.
*
* \sa addNoiseSource(), stir(), save() * \sa addNoiseSource(), stir(), save()
*/ */
void RNGClass::begin(const char *tag, int eepromAddress) void RNGClass::begin(const char *tag)
{ {
// Save the EEPROM address for use by save().
address = eepromAddress;
// Initialize the ChaCha20 input block from the saved seed. // Initialize the ChaCha20 input block from the saved seed.
memcpy_P(block, tagRNG, sizeof(tagRNG)); memcpy_P(block, tagRNG, sizeof(tagRNG));
memcpy_P(block + 4, initRNG, sizeof(initRNG)); memcpy_P(block + 4, initRNG, sizeof(initRNG));
#if defined(RNG_EEPROM) #if defined(RNG_EEPROM)
int address = RNG_EEPROM_ADDRESS;
if (eeprom_read_byte((const uint8_t *)address) == 'S') { if (eeprom_read_byte((const uint8_t *)address) == 'S') {
// We have a saved seed: XOR it with the initialization block. // We have a saved seed: XOR it with the initialization block.
for (int posn = 0; posn < 12; ++posn) { for (int posn = 0; posn < 12; ++posn) {
@ -691,6 +687,7 @@ void RNGClass::save()
++(block[12]); ++(block[12]);
ChaCha::hashCore(stream, block, RNG_ROUNDS); ChaCha::hashCore(stream, block, RNG_ROUNDS);
#if defined(RNG_EEPROM) #if defined(RNG_EEPROM)
int address = RNG_EEPROM_ADDRESS;
eeprom_write_block(stream, (void *)(address + 1), 48); eeprom_write_block(stream, (void *)(address + 1), 48);
eeprom_update_byte((uint8_t *)address, 'S'); eeprom_update_byte((uint8_t *)address, 'S');
#elif defined(RNG_DUE_TRNG) #elif defined(RNG_DUE_TRNG)
@ -808,6 +805,7 @@ void RNGClass::destroy()
clean(block); clean(block);
clean(stream); clean(stream);
#if defined(RNG_EEPROM) #if defined(RNG_EEPROM)
int address = RNG_EEPROM_ADDRESS;
for (int posn = 0; posn < SEED_SIZE; ++posn) for (int posn = 0; posn < SEED_SIZE; ++posn)
eeprom_write_byte((uint8_t *)(address + posn), 0xFF); eeprom_write_byte((uint8_t *)(address + posn), 0xFF);
#elif defined(RNG_DUE_TRNG) #elif defined(RNG_DUE_TRNG)

View File

@ -34,7 +34,7 @@ public:
RNGClass(); RNGClass();
~RNGClass(); ~RNGClass();
void begin(const char *tag, int eepromAddress); void begin(const char *tag);
void addNoiseSource(NoiseSource &source); void addNoiseSource(NoiseSource &source);
void setAutoSaveTime(uint16_t minutes); void setAutoSaveTime(uint16_t minutes);
@ -55,7 +55,6 @@ public:
private: private:
uint32_t block[16]; uint32_t block[16];
uint32_t stream[16]; uint32_t stream[16];
int address;
uint16_t credits : 15; uint16_t credits : 15;
uint16_t firstSave : 1; uint16_t firstSave : 1;
unsigned long timer; unsigned long timer;

View File

@ -207,7 +207,7 @@ void setup()
// Start the random number generator. We don't initialise a noise // Start the random number generator. We don't initialise a noise
// source here because we don't need one for testing purposes. // source here because we don't need one for testing purposes.
// Real DH applications should of course use a proper noise source. // Real DH applications should of course use a proper noise source.
RNG.begin("TestCurve25519 1.0", 950); RNG.begin("TestCurve25519 1.0");
// Perform the tests. // Perform the tests.
testEval(); testEval();

View File

@ -173,7 +173,7 @@ void setup()
// Start the random number generator. We don't initialise a noise // Start the random number generator. We don't initialise a noise
// source here because we don't need one for testing purposes. // source here because we don't need one for testing purposes.
// Real applications should of course use a proper noise source. // Real applications should of course use a proper noise source.
RNG.begin("TestEd25519 1.0", 950); RNG.begin("TestEd25519 1.0");
// Perform the tests. // Perform the tests.
testFixedVectors(); testFixedVectors();

View File

@ -503,7 +503,7 @@ void setup()
// Start the random number generator. We don't initialise a noise // Start the random number generator. We don't initialise a noise
// source here because we don't need one for testing purposes. // source here because we don't need one for testing purposes.
// Real DH applications should of course use a proper noise source. // Real DH applications should of course use a proper noise source.
RNG.begin("TestP521 1.0", 950); RNG.begin("TestP521 1.0");
// Perform the tests. // Perform the tests.
testEval(); testEval();

View File

@ -11,9 +11,6 @@
// even if the input noise or seed data is otherwise identical. // even if the input noise or seed data is otherwise identical.
#define RNG_APP_TAG "MyApp 1.0" #define RNG_APP_TAG "MyApp 1.0"
// EEPROM address to save the random number seed at.
#define RNG_EEPROM_ADDRESS 950
// Noise source to seed the random number generator. // Noise source to seed the random number generator.
TransistorNoiseSource noise(A1); TransistorNoiseSource noise(A1);
//RingOscillatorNoiseSource noise; //RingOscillatorNoiseSource noise;
@ -28,7 +25,7 @@ void setup() {
Serial.println("start"); Serial.println("start");
// Initialize the random number generator. // Initialize the random number generator.
RNG.begin(RNG_APP_TAG, RNG_EEPROM_ADDRESS); RNG.begin(RNG_APP_TAG);
// Add the noise source to the list of sources known to RNG. // Add the noise source to the list of sources known to RNG.
RNG.addNoiseSource(noise); RNG.addNoiseSource(noise);

View File

@ -908,7 +908,7 @@ void setup()
// Start the random number generator. We don't initialise a noise // Start the random number generator. We don't initialise a noise
// source here because we don't need one for testing purposes. // source here because we don't need one for testing purposes.
// Real applications should of course use a proper noise source. // Real applications should of course use a proper noise source.
RNG.begin("TestNewHope 1.0", 950); RNG.begin("TestNewHope 1.0");
// Perform the tests. // Perform the tests.
Serial.println(); Serial.println();