1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00
arduinolibs/crypto_rng.html
Rhys Weatherley 77f9295247 Update docs
2016-02-13 07:01:47 +10:00

199 lines
21 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.6"/>
<title>ArduinoLibs: Generating random numbers</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">ArduinoLibs
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.6 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main&#160;Page</span></a></li>
<li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
<li>
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</li>
</ul>
</div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Pages</a></div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Generating random numbers </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>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.</p>
<h1><a class="anchor" id="crypto_rng_features"></a>
Features of the random number generator</h1>
<p>This library provides the <a class="el" href="classRNGClass.html">RNG</a> class to manage the global random number pool. It has the following features:</p>
<ul>
<li>Provision for plug-in environmental noise sources and entropy estimation. </li>
<li>Whitening of noise values to scatter the input noise across the entire random number pool. </li>
<li>Built-in support for the True Random Number Generator (TRNG) in the Arduino Due's CPU. </li>
<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>
<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>
<li>Periodic saving of the random seed into EEPROM so that the accumulated entropy is not lost across a power restart. </li>
<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.</li>
</ul>
<p>The whitening function and the PRNG are based on <a class="el" href="classChaCha.html#a41ac3262e52ff49dcd916d0b3b2e2038" title="Executes the ChaCha hash core on an input memory block. ">ChaCha::hashCore()</a> with 20 rounds. The structure of the PRNG is very similar to OpenBSD's ChaCha20-based arc4random() implementation.</p>
<h1><a class="anchor" id="crypto_rng_noise_sources"></a>
Standard noise sources</h1>
<p>The library provides two standard noise sources:</p>
<ul>
<li><a class="el" href="classTransistorNoiseSource.html" title="Processes the signal from a transistor-based noise source. ">TransistorNoiseSource</a> for collecting avalanche noise from a transistor. This is based on the work of <a href="http://robseward.com/misc/RNG2/">Rob Seward</a>. </li>
<li><a class="el" href="classRingOscillatorNoiseSource.html" title="Processes the signal from a ring oscillator based noise source. ">RingOscillatorNoiseSource</a> for collecting entropy from the jitter of a <a class="el" href="crypto_rng_ring.html">ring oscillator</a>. This is a design of my own.</li>
</ul>
<p>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 <a class="el" href="classRingOscillatorNoiseSource.html" title="Processes the signal from a ring oscillator based noise source. ">RingOscillatorNoiseSource</a> class attempts to make up for this by collecting more input bits for the same amount of output entropy. See <a class="el" href="crypto_rng_ring.html">this page</a> for more information on ring oscillators.</p>
<p>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 <a class="el" href="classCurve25519.html" title="Diffie-Hellman key agreement based on the elliptic curve modulo 2^255 - 19. ">Curve25519</a> for example.</p>
<p>If you are unsure which noise source to use, then I suggest <a class="el" href="classTransistorNoiseSource.html" title="Processes the signal from a transistor-based noise source. ">TransistorNoiseSource</a> as Rob's design has had more review. Another approach is to mix multiple noise sources together to get the best of both worlds.</p>
<h1><a class="anchor" id="crypto_rng_builtin"></a>
Built-in entropy sources</h1>
<p>Some entropy sources are built in and do not need to be provided via a <a class="el" href="classNoiseSource.html" title="Abstract base class for random noise sources. ">NoiseSource</a> object.</p>
<p>On the Arduino Due, the built-in True Random Number Generator (TRNG) is used to seed the random number generator in addition to any configured noise sources.</p>
<p>On AVR-based Arduino platforms (Uno, Nano, Mega, etc), jitter between the watchdog timer and the main CPU clock is used to harvest some entropy using a technique similar to that described <a href="https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library">here</a>. This is not a high quality source of entropy but it is "better than nothing" if an external noise source is not available or practical. Entropy accumulates very slowly and it could take several minutes before the state is sufficiently random for safe use.</p>
<p>For security-critical applications it is very important to combine the built-in entropy sources with an external noise source.</p>
<h1><a class="anchor" id="crypto_rng_init"></a>
Initializing the random number generator</h1>
<p>To use the random number generator, both <a class="el" href="classRNGClass.html">RNG</a> and a noise source must first be initialized. We start by including the necessary libraries:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;Crypto.h&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;RNG.h&gt;</span></div>
<div class="line"><span class="preprocessor">#include &lt;TransistorNoiseSource.h&gt;</span></div>
</div><!-- fragment --><p>Next we create a global variable for the noise source and specify the I/O pin that the noise circuit is connected to:</p>
<div class="fragment"><div class="line"><a class="code" href="classTransistorNoiseSource.html">TransistorNoiseSource</a> noise(A1);</div>
</div><!-- fragment --><p>Then in the setup() function we call <a class="el" href="classRNGClass.html#a7f1aab3c324f8e8a424d683425e0fcf8">RNG.begin()</a> to start the random number generator running and call <a class="el" href="classRNGClass.html#aacf23b192b0e4cc8726d9abe05f5a9db">RNG.addNoiseSource()</a> to register all of the application's noise sources:</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> setup() {</div>
<div class="line"> <span class="comment">// Initialize the random number generator with the application tag</span></div>
<div class="line"> <span class="comment">// &quot;MyApp 1.0&quot; and load the previous seed from EEPROM address 950.</span></div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a7f1aab3c324f8e8a424d683425e0fcf8">begin</a>(<span class="stringliteral">&quot;MyApp 1.0&quot;</span>, 950);</div>
<div class="line"></div>
<div class="line"> <span class="comment">// Add the noise source to the list of sources known to RNG.</span></div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#aacf23b192b0e4cc8726d9abe05f5a9db">addNoiseSource</a>(noise);</div>
<div class="line"></div>
<div class="line"> <span class="comment">// ...</span></div>
<div class="line">}</div>
</div><!-- fragment --><p>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():</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> setup() {</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a7f1aab3c324f8e8a424d683425e0fcf8">begin</a>(<span class="stringliteral">&quot;MyApp 1.0&quot;</span>, 950);</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#ad99535ea23ae2fec55bdebb8c24def02">stir</a>(serial_number, <span class="keyword">sizeof</span>(serial_number));</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#ad99535ea23ae2fec55bdebb8c24def02">stir</a>(mac_address, <span class="keyword">sizeof</span>(mac_address));</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#aacf23b192b0e4cc8726d9abe05f5a9db">addNoiseSource</a>(noise);</div>
<div class="line"> ...</div>
<div class="line">}</div>
</div><!-- fragment --><p>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 the first automatic save of the seed.</p>
<p>By default the seed is saved once an hour, although this can be changed with <a class="el" href="classRNGClass.html#a5848e87a5f2f0302c88b0377f0e3366d">RNG.setAutoSaveTime()</a>. 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.</p>
<p>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.</p>
<p>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 and auto-saves must be performed on a regular basis. The <a class="el" href="classRNGClass.html#a8cb91e39f0c4591de5bf98b1e2880b13">RNG.loop()</a> function takes care of these tasks for us:</p>
<div class="fragment"><div class="line"><span class="keywordtype">void</span> loop() {</div>
<div class="line"> <span class="comment">// ...</span></div>
<div class="line"></div>
<div class="line"> <span class="comment">// Perform regular housekeeping on the random number generator.</span></div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a8cb91e39f0c4591de5bf98b1e2880b13">loop</a>();</div>
<div class="line"></div>
<div class="line"> <span class="comment">// ...</span></div>
<div class="line">}</div>
</div><!-- fragment --><p>The random number generator is now ready to generate data.</p>
<h1><a class="anchor" id="crypto_rng_using"></a>
Generating data with the random number generator</h1>
<p>Whenever the application needs random data, it calls <a class="el" href="classRNGClass.html#a418a833cf18198fd7e5d6dbd78c99c29">RNG.rand()</a> 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 <a class="el" href="classAES256.html" title="AES block cipher with 256-bit keys. ">AES256</a> in <a class="el" href="classCTR.html" title="Implementation of the Counter (CTR) mode for 128-bit block ciphers. ">CTR</a> mode:</p>
<div class="fragment"><div class="line">byte key[32];</div>
<div class="line">byte iv[16];</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> generateKeys() {</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a418a833cf18198fd7e5d6dbd78c99c29">rand</a>(key, <span class="keyword">sizeof</span>(key));</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a418a833cf18198fd7e5d6dbd78c99c29">rand</a>(iv, <span class="keyword">sizeof</span>(iv));</div>
<div class="line">}</div>
</div><!-- fragment --><p>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 <code>/dev/urandom</code> device.</p>
<p>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).</p>
<p>In Linux terms we want the effect of the <code>/dev/random</code> device which blocks until sufficient entropy is available to service the request. Blocking isn't very friendly to other application tasks, so the library instead provides the <a class="el" href="classRNGClass.html#a49e3231ba65a5e4b045bc90976e0a659">RNG.available()</a> function to poll how much entropy is in the global random number pool:</p>
<div class="fragment"><div class="line">byte key[32];</div>
<div class="line">byte iv[16];</div>
<div class="line"><span class="keywordtype">bool</span> haveKeys = <span class="keyword">false</span>;</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> generateKeys() {</div>
<div class="line"> <span class="keywordflow">if</span> (!haveKeys &amp;&amp; RNG.<a class="code" href="classRNGClass.html#a49e3231ba65a5e4b045bc90976e0a659">available</a>(<span class="keyword">sizeof</span>(key) + <span class="keyword">sizeof</span>(iv))) {</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a418a833cf18198fd7e5d6dbd78c99c29">rand</a>(key, <span class="keyword">sizeof</span>(key));</div>
<div class="line"> RNG.<a class="code" href="classRNGClass.html#a418a833cf18198fd7e5d6dbd78c99c29">rand</a>(iv, <span class="keyword">sizeof</span>(iv));</div>
<div class="line"> haveKeys = <span class="keyword">true</span>;</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p>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.</p>
<p>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.</p>
<p>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.</p>
<h1><a class="anchor" id="crypto_rng_secret"></a>
Destroying secret data</h1>
<p>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:</p>
<div class="fragment"><div class="line">memset(key, 0, <span class="keyword">sizeof</span>(key));</div>
<div class="line">memset(iv, 0, <span class="keyword">sizeof</span>(iv));</div>
</div><!-- fragment --><p>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:</p>
<div class="fragment"><div class="line">clean(key);</div>
<div class="line">clean(iv);</div>
</div><!-- fragment --><p>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:</p>
<div class="fragment"><div class="line">clean(key, 32);</div>
<div class="line">clean(iv, 16);</div>
</div><!-- fragment --> </div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Sat Feb 13 2016 07:01:07 for ArduinoLibs by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.6
</small></address>
</body>
</html>