From 067e8ac1771459f7b0d1a19efb01747f76d412d7 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 25 Mar 2015 19:35:44 +1000 Subject: [PATCH] Register the noise sources with RNG at setup time --- doc/crypto-rng.dox | 18 +++++----- libraries/Crypto/RNG.cpp | 36 +++++++++++++++---- libraries/Crypto/RNG.h | 3 ++ .../Crypto/RingOscillatorNoiseSource.cpp | 6 ++-- libraries/Crypto/TransistorNoiseSource.cpp | 6 ++-- libraries/Crypto/examples/TestRNG/TestRNG.ino | 6 ++-- 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/doc/crypto-rng.dox b/doc/crypto-rng.dox index 0f846ad6..403cb24c 100644 --- a/doc/crypto-rng.dox +++ b/doc/crypto-rng.dox @@ -103,7 +103,9 @@ TransistorNoiseSource noise(A1); \endcode Then in the setup() function we call \link RNGClass::begin() RNG.begin()\endlink -to start the random number generator running: +to start the random number generator running and call +\link RNGClass::addNoiseSource() RNG.addNoiseSource()\endlink to register +all of the application's noise sources: \code void setup() { @@ -111,6 +113,9 @@ void setup() { // "MyApp 1.0" and load the previous seed from EEPROM address 500. RNG.begin("MyApp 1.0", 500); + // Add the noise source to the list of sources known to RNG. + RNG.addNoiseSource(noise); + // ... } \endcode @@ -128,6 +133,7 @@ void setup() { RNG.begin("MyApp 1.0", 500); RNG.stir(serial_number, sizeof(serial_number)); RNG.stir(mac_address, sizeof(mac_address)); + RNG.addNoiseSource(noise); ... } \endcode @@ -147,18 +153,14 @@ fills up, a save will be automatically forced. To use the random number generator properly, there are some regular tasks that must be performed every time around the application's main loop(). -Newly accumulated noise must be mixed in with -\link RNGClass::stir() RNG.stir()\endlink and the -\link RNGClass::loop() RNG.loop()\endlink function must be called to -perform auto-saves: +Newly accumulated noise must be mixed in and auto-saves must be performed +on a regular basis. The \link RNGClass::loop() RNG.loop()\endlink +function takes care of these tasks for us: \code void loop() { // ... - // If the noise source has accumulated new entropy, then stir it in. - RNG.stir(noise); - // Perform regular housekeeping on the random number generator. RNG.loop(); diff --git a/libraries/Crypto/RNG.cpp b/libraries/Crypto/RNG.cpp index fa23d9d9..02bc647f 100644 --- a/libraries/Crypto/RNG.cpp +++ b/libraries/Crypto/RNG.cpp @@ -70,20 +70,20 @@ * // Stir in the Ethernet MAC address. * RNG.stir(mac_address, sizeof(mac_address)); * + * // Add the noise source to the list of sources known to RNG. + * RNG.addNoiseSource(noise); + * * // ... * } * \endcode * - * The application should regularly call stir() to mix in new data from - * the noise source and also regularly call loop(): + * The application should regularly call loop() to stir in new data + * from the registered noise sources and to periodically save the seed: * * \code * void loop() { * // ... * - * // If the noise source has accumulated new entropy, then stir it in. - * RNG.stir(noise); - * * // Perform regular housekeeping on the random number generator. * RNG.loop(); * @@ -170,6 +170,7 @@ RNGClass::RNGClass() , firstSave(1) , timer(0) , timeout(3600000UL) // 1 hour in milliseconds + , count(0) { } @@ -197,7 +198,7 @@ RNGClass::~RNGClass() * additional entropy data from noise sources to initialize the random * number generator properly. * - * \sa stir(), save() + * \sa addNoiseSource(), stir(), save() */ void RNGClass::begin(const char *tag, int eepromAddress) { @@ -234,6 +235,25 @@ void RNGClass::begin(const char *tag, int eepromAddress) save(); } +/** + * \brief Adds a noise source to the random number generator. + * + * \param source The noise source to add, which will be polled regularly + * by loop() to accumulate noise-based entropy from the source. + * + * RNG supports a maximum of four noise sources. If the application needs + * more than that then the application must poll the noise sources itself by + * calling NoiseSource::stir() directly. + * + * \sa loop(), begin() + */ +void RNGClass::addNoiseSource(NoiseSource &source) +{ + #define MAX_NOISE_SOURCES (sizeof(noiseSources) / sizeof(noiseSources[0])) + if (count < MAX_NOISE_SOURCES) + noiseSources[count++] = &source; +} + /** * \brief Sets the amount of time between automatic seed saves. * @@ -485,6 +505,10 @@ void RNGClass::save() */ void RNGClass::loop() { + // Stir in the entropy from all registered noise sources. + for (uint8_t posn = 0; posn < count; ++posn) + noiseSources[posn]->stir(); + // Save the seed if the auto-save timer has expired. if ((millis() - timer) >= timeout) save(); diff --git a/libraries/Crypto/RNG.h b/libraries/Crypto/RNG.h index 2d77e656..2284d105 100644 --- a/libraries/Crypto/RNG.h +++ b/libraries/Crypto/RNG.h @@ -35,6 +35,7 @@ public: ~RNGClass(); void begin(const char *tag, int eepromAddress); + void addNoiseSource(NoiseSource &source); void setAutoSaveTime(uint16_t minutes); @@ -60,6 +61,8 @@ private: uint16_t firstSave : 1; unsigned long timer; unsigned long timeout; + NoiseSource *noiseSources[4]; + uint8_t count; void rekey(); }; diff --git a/libraries/Crypto/RingOscillatorNoiseSource.cpp b/libraries/Crypto/RingOscillatorNoiseSource.cpp index 2f986feb..29dcab45 100644 --- a/libraries/Crypto/RingOscillatorNoiseSource.cpp +++ b/libraries/Crypto/RingOscillatorNoiseSource.cpp @@ -76,15 +76,15 @@ * // "MyApp 1.0" and load the previous seed from EEPROM address 500. * RNG.begin("MyApp 1.0", 500); * + * // Add the noise source to the list of sources known to RNG. + * RNG.addNoiseSource(noise); + * * // ... * } * * void loop() { * // ... * - * // If the noise source has accumulated new entropy, then stir it in. - * RNG.stir(noise); - * * // Perform regular housekeeping on the random number generator. * RNG.loop(); * diff --git a/libraries/Crypto/TransistorNoiseSource.cpp b/libraries/Crypto/TransistorNoiseSource.cpp index c8048184..61931136 100644 --- a/libraries/Crypto/TransistorNoiseSource.cpp +++ b/libraries/Crypto/TransistorNoiseSource.cpp @@ -56,15 +56,15 @@ * // "MyApp 1.0" and load the previous seed from EEPROM address 500. * RNG.begin("MyApp 1.0", 500); * + * // Add the noise source to the list of sources known to RNG. + * RNG.addNoiseSource(noise); + * * // ... * } * * void loop() { * // ... * - * // If the noise source has accumulated new entropy, then stir it in. - * RNG.stir(noise); - * * // Perform regular housekeeping on the random number generator. * RNG.loop(); * diff --git a/libraries/Crypto/examples/TestRNG/TestRNG.ino b/libraries/Crypto/examples/TestRNG/TestRNG.ino index 32ab5c2a..7686cb7a 100644 --- a/libraries/Crypto/examples/TestRNG/TestRNG.ino +++ b/libraries/Crypto/examples/TestRNG/TestRNG.ino @@ -29,6 +29,9 @@ void setup() { // Initialize the random number generator. RNG.begin(RNG_APP_TAG, RNG_EEPROM_ADDRESS); + // Add the noise source to the list of sources known to RNG. + RNG.addNoiseSource(noise); + startTime = millis(); } @@ -58,9 +61,6 @@ void loop() { Serial.println("calibrating"); } - // If the noise source has accumulated new entropy, then stir it in. - RNG.stir(noise); - // Perform regular housekeeping on the random number generator. RNG.loop();