Use your mbed and it\'s noisy analog inputs as a hardware random number generator!

Dependencies:   mbed SHA256

EntropyPool.cpp

Committer:
Remco
Date:
2011-06-20
Revision:
0:dda0a8c4ac0c

File content as of revision 0:dda0a8c4ac0c:

#include <EntropyPool.h>

extern "C" void mbed_mac_address(char *mac);

EntropyPool::EntropyPool()
: SHA256()
, e(0)
, timer()
{
    // Seed with MAC, but do not add entropy
    char mac[6];
    mbed_mac_address(mac);
    append(mac, 6);
    
    // Start the timer
    timer.start();
}

char* EntropyPool::produce(int bytes)
{
    // Make sure the entropy pool is full
    while(e < 256) gather();
    
    // Mix the pool
    process_chunk();

    // Output a word at a time, maintaining at least
    // 128 bits entropy
    int num_words = (bytes + 3) / 4;
    unsigned int* out = new unsigned int[num_words];
    for(int i = 0; i < num_words; ++i) {
        out[i] = hash[i % 8];
        e -= 32;
        if(e < 128) {
            // Refill the entropy pool
            while(e < 256)
                gather();
            process_chunk();
        }
    }
    return reinterpret_cast<char*>(out);
}

void EntropyPool::gather()
{
    // The following default sources are of poor quality
    // In a thight loop they would be highly predictable
    // Yet it is still far better than nothing, and to prevent
    // complete stall, I'll assume these add two bits of entropy
    e += 2;

    // Real time clock
    time_t tvalue = time(0);
    append(reinterpret_cast<char*>(&tvalue), sizeof(time_t));
    
    // Ticker
    unsigned int value = timer.read_us();
    append(reinterpret_cast<char*>(&value), 4);
    
    // Number of bytes appended so far
    append(reinterpret_cast<char*>(&length), 4);
    
    // Call user function
    gatherer.call();
    
    if(e > 256) e = 256;
}

void EntropyPool::gatherAnalogNoise(AnalogIn& in, int entropy)
{
    unsigned short value = in.read_u16();
    // Only the least significant bits change due to noise
    // But the last four bits are repetitions of the first four
    append(reinterpret_cast<char*>(&value), 2);
    e += entropy;
}