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

Dependencies:   mbed SHA256

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EntropyPool.cpp Source File

EntropyPool.cpp

00001 #include <EntropyPool.h>
00002 
00003 extern "C" void mbed_mac_address(char *mac);
00004 
00005 EntropyPool::EntropyPool()
00006 : SHA256()
00007 , e(0)
00008 , timer()
00009 {
00010     // Seed with MAC, but do not add entropy
00011     char mac[6];
00012     mbed_mac_address(mac);
00013     append(mac, 6);
00014     
00015     // Start the timer
00016     timer.start();
00017 }
00018 
00019 char* EntropyPool::produce(int bytes)
00020 {
00021     // Make sure the entropy pool is full
00022     while(e < 256) gather();
00023     
00024     // Mix the pool
00025     process_chunk();
00026 
00027     // Output a word at a time, maintaining at least
00028     // 128 bits entropy
00029     int num_words = (bytes + 3) / 4;
00030     unsigned int* out = new unsigned int[num_words];
00031     for(int i = 0; i < num_words; ++i) {
00032         out[i] = hash[i % 8];
00033         e -= 32;
00034         if(e < 128) {
00035             // Refill the entropy pool
00036             while(e < 256)
00037                 gather();
00038             process_chunk();
00039         }
00040     }
00041     return reinterpret_cast<char*>(out);
00042 }
00043 
00044 void EntropyPool::gather()
00045 {
00046     // The following default sources are of poor quality
00047     // In a thight loop they would be highly predictable
00048     // Yet it is still far better than nothing, and to prevent
00049     // complete stall, I'll assume these add two bits of entropy
00050     e += 2;
00051 
00052     // Real time clock
00053     time_t tvalue = time(0);
00054     append(reinterpret_cast<char*>(&tvalue), sizeof(time_t));
00055     
00056     // Ticker
00057     unsigned int value = timer.read_us();
00058     append(reinterpret_cast<char*>(&value), 4);
00059     
00060     // Number of bytes appended so far
00061     append(reinterpret_cast<char*>(&length), 4);
00062     
00063     // Call user function
00064     gatherer.call();
00065     
00066     if(e > 256) e = 256;
00067 }
00068 
00069 void EntropyPool::gatherAnalogNoise(AnalogIn& in, int entropy)
00070 {
00071     unsigned short value = in.read_u16();
00072     // Only the least significant bits change due to noise
00073     // But the last four bits are repetitions of the first four
00074     append(reinterpret_cast<char*>(&value), 2);
00075     e += entropy;
00076 }
00077 
00078 
00079 
00080