diff --git a/doc/crypto-rng.dox b/doc/crypto-rng.dox
new file mode 100644
index 00000000..0f846ad6
--- /dev/null
+++ b/doc/crypto-rng.dox
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+\file crypto-rng.dox
+\page crypto_rng Generating random numbers
+
+Random numbers are one of the most important aspects of secure cryptography.
+Without a good source of random numbers it may be possible for an attacker
+to predict the encryption and authentication keys that are used to protect a
+session, or to predict the private component of a public/private key pair.
+This is especially difficult in embedded environments that do not have
+input sources like keystrokes, mouse movements, disk drive write times, etc
+to collect entropy from the user.
+
+\section crypto_rng_features Features of the random number generator
+
+This library provides the \link RNGClass RNG\endlink class to manage the
+global random number pool. It has the following features:
+
+\li Provision for plug-in environmental noise sources and entropy estimation.
+\li Whitening of noise values to scatter the input noise across the entire
+ random number pool.
+\li Support for mixing in static values like serial numbers and MAC
+ addresses so that otherwise identical devices do not generate the
+ same sequence of random numbers upon first boot.
+\li Cryptographically secure pseudo random number generator (PRNG) for
+ expanding the noise-based seed into an arbitrary amount of random material
+ for the application.
+\li Periodic saving of the random seed into EEPROM so that the accumulated
+ entropy is not lost across a power restart.
+\li Built-in protection so that if an attacker captures the seed, it cannot
+ be used to predict past outputs. And after mixing in a modest amount
+ of new noise, cannot be used to predict future outputs.
+
+The whitening function and the PRNG are based on ChaCha::hashCore()
+with 20 rounds. The structure of the PRNG is very similar to OpenBSD's
+ChaCha20-based arc4random() implementation.
+
+\section crypto_rng_noise_sources Standard noise sources
+
+The library provides two standard noise sources:
+
+\li TransistorNoiseSource for collecting avalanche noise from a transistor.
+ This is based on the work of
+ Rob Seward.
+\li RingOscillatorNoiseSource for collecting entropy from the jitter of a
+ \ref crypto_rng_ring "ring oscillator". This is a design of my own.
+
+The transistor design needs an input voltage of 10 to 15 VDC to trigger
+the avalanche effect, which can sometimes be difficult in a 5V Arduino
+environment. The ring oscillator design can run at 5V but the quality
+of the noise is less than for the transistor design. The
+RingOscillatorNoiseSource class attempts to make up for this by collecting
+more input bits for the same amount of output entropy.
+See \ref crypto_rng_ring "this page" for more information on ring oscillators.
+
+For both of the standard noise sources, the system should have enough entropy
+to safely generate 256 bits of key material about 3 to 4 seconds after startup.
+This is sufficient to create a private key for Curve25519 for example.
+
+If you are unsure which noise source to use, then I suggest
+TransistorNoiseSource as Rob's design has had more review. Another
+approach is to mix multiple noise sources together to get the best
+of both worlds.
+
+\section crypto_rng_init Initializing the random number generator
+
+To use the random number generator, both \link RNGClass RNG\endlink and a
+noise source must first be initialized. We start by including the necessary
+libraries:
+
+\code
+#include
+#include
+#include
+\endcode
+
+Next we create a global variable for the noise source and specify the
+I/O pin that the noise circuit is connected to:
+
+\code
+TransistorNoiseSource noise(A1);
+\endcode
+
+Then in the setup() function we call \link RNGClass::begin() RNG.begin()\endlink
+to start the random number generator running:
+
+\code
+void setup() {
+ // Initialize the random number generator with the application tag
+ // "MyApp 1.0" and load the previous seed from EEPROM address 500.
+ RNG.begin("MyApp 1.0", 500);
+
+ // ...
+}
+\endcode
+
+The begin() function is passed two arguments: a tag string that should
+be different for every application and an EEPROM address to use to
+load and save the random number seed. The tag string ensures that
+different applications and versions will generate different random numbers
+upon first boot before the noise source has collected any entropy.
+If the device also has a unique serial number or a MAC address, then
+those can be mixed in during the setup() function after calling begin():
+
+\code
+void setup() {
+ RNG.begin("MyApp 1.0", 500);
+ RNG.stir(serial_number, sizeof(serial_number));
+ RNG.stir(mac_address, sizeof(mac_address));
+ ...
+}
+\endcode
+
+The random number generator needs 49 bytes of EEPROM space at the
+specified address to store the previous seed. When the system is started
+next time, the previous saved seed is loaded and then deliberately
+overwritten with a new seed. This ensures that the device will not
+accidentally generate the same sequence of random numbers if it is
+restarted before a new seed can be saved.
+
+By default the seed is saved once an hour, although this can be changed
+with \link RNGClass::setAutoSaveTime() RNG.setAutoSaveTime()\endlink.
+Because the device may be restarted before the first hour expires, there
+is a special case in the code: the first time that the entropy pool
+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:
+
+\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();
+
+ // ...
+}
+\endcode
+
+The random number generator is now ready to generate data.
+
+\section crypto_rng_using Generating data with the random number generator
+
+Whenever the application needs random data, it calls
+\link RNGClass::rand() RNG.rand()\endlink with a buffer to fill.
+The following example generates a 256-bit encryption key and a 128-bit
+initialization vector; e.g. for use with AES256 in CTR mode:
+
+\code
+byte key[32];
+byte iv[16];
+
+void generateKeys() {
+ RNG.rand(key, sizeof(key));
+ RNG.rand(iv, sizeof(iv));
+}
+\endcode
+
+The data will be generated immediately, using whatever entropy happens to
+be in the global random number pool at the time. In Linux terms, the
+rand() function acts like the /dev/urandom device.
+
+If the system has been running for a while then this should be safe as
+the noise source would have already permuted the pool with noise-based entropy.
+However, when the system first starts up there may not be much entropy
+available other than that from the saved seed (which could have been
+compromised).
+
+In Linux terms we want the effect of the /dev/random device which
+blocks until sufficient entropy is available to service the request.
+Blocking isn't compatible with the Arduino way of doing things,
+so the library instead provides the
+\link RNGClass::available() RNG.available()\endlink function to poll
+how much entropy is in the global random number pool:
+
+\code
+byte key[32];
+byte iv[16];
+bool haveKeys = false;
+
+void generateKeys() {
+ if (!haveKeys && RNG.available(sizeof(key) + sizeof(iv))) {
+ RNG.rand(key, sizeof(key));
+ RNG.rand(iv, sizeof(iv));
+ haveKeys = true;
+ }
+}
+\endcode
+
+This feature should allow applications to generate secret material safely
+at startup. The application may want to implement a timeout: if the
+application has to wait too long to generate a key then the noise source
+may be disconnected or faulty.
+
+The global random number pool can hold up to 48 bytes, or 384 bits, of entropy.
+Requests for more than 384 bits will be allowed if the entropy is at
+maximum. That is, a request for 64 bytes (512 bits) of data will be
+allowed when there is only 384 bits of entropy in the pool. This behaviour
+prevents the application from waiting indefinitely if the request is
+too large.
+
+If the application truly needs more than 384 bits of real entropy (e.g. to
+generate a public/private key pair for an algorithm like RSA), then it
+should break the request up into smaller chunks and poll available()
+for each chunk.
+
+\section crypto_rng_secret Destroying secret data
+
+When the application is finished with the secret key material and plaintext,
+it should destroy the data to remove it from RAM permanently. The memset()
+function can be used for this purpose:
+
+\code
+memset(key, 0, sizeof(key));
+memset(iv, 0, sizeof(iv));
+\endcode
+
+However, this may not be safe. Optimizing compilers have been known to
+optimize away memset() calls if the compiler thinks that the value won't be
+used again. A safer method is to use the clean() function in the library:
+
+\code
+clean(key);
+clean(iv);
+\endcode
+
+The clean() function attempts to implement the memory clear in a way
+that the compiler shouldn't optimize away. By default the clean()
+function figures out the size of the buffer itself at compile time.
+In some cases (e.g. buffers that are passed by pointer), it may
+be necessary to specify the size manually:
+
+\code
+clean(key, 32);
+clean(iv, 16);
+\endcode
+
+*/
diff --git a/doc/crypto.dox b/doc/crypto.dox
index 1cd2fa74..63158c47 100644
--- a/doc/crypto.dox
+++ b/doc/crypto.dox
@@ -50,6 +50,10 @@ hashing, with 256-bit and 512-bit hash outputs respectively. They are
intended as high performance replacements for SHA256 and SHA512 for when
speed is critical but exact bit-compatibility of hash values is not.
+\section crypto_other Examples and other topics
+
+\li \ref crypto_rng "Generating random numbers"
+
\section crypto_performance Performance
All figures are for the Arduino Uno running at 16 MHz. Figures for the