Arduino Cryptography Library
Public Member Functions | Static Public Attributes | List of all members
RNGClass Class Reference

Pseudo random number generator suitable for cryptography. More...

#include <RNG.h>

Public Member Functions

 RNGClass ()
 Constructs a new random number generator instance. More...
 
 ~RNGClass ()
 Destroys this random number generator instance.
 
void begin (const char *tag)
 Initializes the random number generator. More...
 
void addNoiseSource (NoiseSource &source)
 Adds a noise source to the random number generator. More...
 
void setAutoSaveTime (uint16_t minutes)
 Sets the amount of time between automatic seed saves. More...
 
void rand (uint8_t *data, size_t len)
 Generates random bytes into a caller-supplied buffer. More...
 
bool available (size_t len) const
 Determine if there is sufficient entropy available for a specific request size. More...
 
void stir (const uint8_t *data, size_t len, unsigned int credit=0)
 Stirs additional entropy data into the random pool. More...
 
void save ()
 Saves the random seed to EEPROM. More...
 
void loop ()
 Run periodic housekeeping tasks on the random number generator. More...
 
void destroy ()
 Destroys the data in the random number pool and the saved seed in EEPROM. More...
 

Static Public Attributes

static const int SEED_SIZE = 48
 Size of a saved random number seed in EEPROM space. More...
 

Detailed Description

Pseudo random number generator suitable for cryptography.

Random number generators must be seeded properly before they can be used or an adversary may be able to predict the random output. Seed data may be:

The following example demonstrates how to initialise the random number generator:

#include <SPI.h>
#include <Ethernet.h>
#include <Crypto.h>
#include <RNG.h>
#include <TransistorNoiseSource.h>
// Noise source to seed the random number generator.
// MAC address for Ethernet communication.
byte mac_address[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
void setup() {
// Initialize the Ethernet shield.
Ethernet.begin(mac_address);
// Initialize the random number generator with the application tag
// "MyApp 1.0" and load the previous seed from EEPROM.
RNG.begin("MyApp 1.0");
// 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);
// ...
}
void begin(const char *tag)
Initializes the random number generator.
Definition: RNG.cpp:438
void addNoiseSource(NoiseSource &source)
Adds a noise source to the random number generator.
Definition: RNG.cpp:611
void stir(const uint8_t *data, size_t len, unsigned int credit=0)
Stirs additional entropy data into the random pool.
Definition: RNG.cpp:787
Processes the signal from a transistor-based noise source.

The application should regularly call loop() to stir in new data from the registered noise sources and to periodically save the seed:

void loop() {
// ...
// Perform regular housekeeping on the random number generator.
RNG.loop();
// ...
}
void loop()
Run periodic housekeeping tasks on the random number generator.
Definition: RNG.cpp:898

The loop() function will automatically save the random number seed on a regular basis to the last SEED_SIZE bytes of EEPROM memory. By default 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. It is wise to limit saving to once an hour or once a day depending upon how long you intend to field the device before replacing it. For example, an EEPROM rated for 100k erase/write cycles will last about 69 days saving once a minute or 11 years saving once an hour.

The application can still elect to call save() at any time if wants. For example, if the application can detect power loss or shutdown conditions programmatically, then it may make sense to force a save() of the seed upon shutdown.

The Arduino Due does not have EEPROM so RNG saves the seed into the last page of system flash memory instead. The RNG class will also mix in data from the CPU's built-in True Random Number Generator (TRNG). Assuming that the CPU's TRNG is trustworthy, this should be sufficient to properly seed the random number generator. It is recommended to also mix in data from other noise sources just in case the CPU's TRNG is not trustworthy.

See also
NoiseSource

Definition at line 31 of file RNG.h.

Constructor & Destructor Documentation

◆ RNGClass()

RNGClass::RNGClass ( )

Constructs a new random number generator instance.

This constructor must be followed by a call to begin() to properly initialize the random number generator.

See also
begin()

Definition at line 311 of file RNG.cpp.

Member Function Documentation

◆ addNoiseSource()

void RNGClass::addNoiseSource ( NoiseSource source)

Adds a noise source to the random number generator.

Parameters
sourceThe 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.

See also
loop(), begin()

Definition at line 611 of file RNG.cpp.

◆ available()

bool RNGClass::available ( size_t  len) const

Determine if there is sufficient entropy available for a specific request size.

Parameters
lenThe number of bytes of random data that will be requested via a call to rand().
Returns
Returns true if there is at least len * 8 bits of entropy in the random number pool, or false if not.

This function can be used by the application to wait for sufficient entropy to become available from the system's noise sources before generating important values. For example:

bool haveKey = false;
byte key[32];
void loop() {
...
if (!haveKey && RNG.available(sizeof(key))) {
RNG.rand(key, sizeof(key));
haveKey = true;
}
...
}
void rand(uint8_t *data, size_t len)
Generates random bytes into a caller-supplied buffer.
Definition: RNG.cpp:660
bool available(size_t len) const
Determine if there is sufficient entropy available for a specific request size.
Definition: RNG.cpp:754

If len is larger than the maximum number of entropy credits supported by the random number pool (384 bits, 48 bytes), then the maximum will be used instead. For example, asking if 512 bits (64 bytes) are available will return true if in reality only 384 bits are available. If this is a problem for the application's security requirements, then large requests for random data should be broken up into smaller chunks with the application waiting for the entropy pool to refill between chunks.

See also
rand()

Definition at line 754 of file RNG.cpp.

◆ begin()

void RNGClass::begin ( const char *  tag)

Initializes the random number generator.

Parameters
tagA string that is stirred into the random pool at startup; 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 generate the same sequence of values upon first boot.

This function should be followed by calls to addNoiseSource() to register the application's noise sources.

See also
addNoiseSource(), stir(), save()

Definition at line 438 of file RNG.cpp.

◆ destroy()

void RNGClass::destroy ( )

Destroys the data in the random number pool and the saved seed in EEPROM.

This function attempts to throw away any data that could theoretically be used to predict previous and future outputs of the random number generator if the device is captured, sold, or otherwise compromised.

After this function is called, begin() must be called again to re-initialize the random number generator.

Note
The rand() and save() functions take some care to manage the random number pool in a way that makes prediction of past outputs from a captured state very difficult. Future outputs may be predictable if noise or other high-entropy data is not mixed in with stir() on a regular basis.
See also
begin()

Definition at line 1035 of file RNG.cpp.

◆ loop()

void RNGClass::loop ( )

Run periodic housekeeping tasks on the random number generator.

This function must be called on a regular basis from the application's main "loop()" function.

Definition at line 898 of file RNG.cpp.

◆ rand()

void RNGClass::rand ( uint8_t *  data,
size_t  len 
)

Generates random bytes into a caller-supplied buffer.

Parameters
dataPoints to the buffer to fill with random bytes.
lenNumber of bytes to generate.

Calling this function will decrease the amount of entropy in the random number pool by len * 8 bits. If there isn't enough entropy, then this function will still return len bytes of random data generated from what entropy it does have.

If the application requires a specific amount of entropy before generating important values, the available() function can be polled to determine when sufficient entropy is available.

See also
available(), stir()

Definition at line 660 of file RNG.cpp.

◆ save()

void RNGClass::save ( )

Saves the random seed to EEPROM.

During system startup, noise sources typically won't have accumulated much entropy. But startup is usually the time when the system most needs to generate random data for session keys, IV's, and the like.

The purpose of this function is to pass some of the accumulated entropy from one session to the next after a loss of power. Thus, once the system has been running for a while it will get progressively better at generating random values and the accumulated entropy will not be completely lost.

Normally it isn't necessary to call save() directly. The loop() function will automatically save the seed on a periodic basis (default of 1 hour).

The seed that is saved is generated in such a way that it cannot be used to predict random values that were generated previously or subsequently in the current session. So a compromise of the EEPROM contents of a captured device should not result in compromise of random values that have already been generated. However, if power is lost and the system restarted, then there will be a short period of time where the random state will be predictable from the seed. For this reason it is very important to stir() in new noise data at startup.

See also
loop(), stir()

Definition at line 856 of file RNG.cpp.

◆ setAutoSaveTime()

void RNGClass::setAutoSaveTime ( uint16_t  minutes)

Sets the amount of time between automatic seed saves.

Parameters
minutesThe number of minutes between automatic seed saves.

The default time between automatic seed saves is 1 hour.

This function is intended to help with EEPROM wear by slowing down how often seed data is saved as noise is stirred into the random pool. The exact period to use depends upon how long you intend to field the device before replacing it. For example, an EEPROM rated for 100k erase/write cycles will last about 69 days saving once a minute or 11 years saving once an hour.

See also
save(), stir()

Definition at line 636 of file RNG.cpp.

◆ stir()

void RNGClass::stir ( const uint8_t *  data,
size_t  len,
unsigned int  credit = 0 
)

Stirs additional entropy data into the random pool.

Parameters
dataPoints to the additional data to be stirred in.
lenNumber of bytes to be stirred in.
creditThe number of bits of entropy to credit for the data that is stirred in. Note that this is bits, not bytes.

The maximum credit allowed is len * 8 bits, indicating that every bit in the input data is good and random. Practical noise sources are rarely that good, so credit will usually be smaller. For example, to credit 2 bits of entropy per byte, the function would be called as follows:

RNG.stir(noise_data, noise_bytes, noise_bytes * 2);

If credit is zero, then the data will be stirred in but no entropy credit is given. This is useful for static values like serial numbers and MAC addresses that are different between devices but highly predictable.

See also
loop()

Definition at line 787 of file RNG.cpp.

Member Data Documentation

◆ SEED_SIZE

RNGClass::SEED_SIZE = 48
static

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.

Definition at line 53 of file RNG.h.


The documentation for this class was generated from the following files: