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

Dependencies:   mbed SHA256

Committer:
Remco
Date:
Mon Jun 20 13:23:03 2011 +0000
Revision:
0:dda0a8c4ac0c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Remco 0:dda0a8c4ac0c 1 #include <EntropyPool.h>
Remco 0:dda0a8c4ac0c 2
Remco 0:dda0a8c4ac0c 3 extern "C" void mbed_mac_address(char *mac);
Remco 0:dda0a8c4ac0c 4
Remco 0:dda0a8c4ac0c 5 EntropyPool::EntropyPool()
Remco 0:dda0a8c4ac0c 6 : SHA256()
Remco 0:dda0a8c4ac0c 7 , e(0)
Remco 0:dda0a8c4ac0c 8 , timer()
Remco 0:dda0a8c4ac0c 9 {
Remco 0:dda0a8c4ac0c 10 // Seed with MAC, but do not add entropy
Remco 0:dda0a8c4ac0c 11 char mac[6];
Remco 0:dda0a8c4ac0c 12 mbed_mac_address(mac);
Remco 0:dda0a8c4ac0c 13 append(mac, 6);
Remco 0:dda0a8c4ac0c 14
Remco 0:dda0a8c4ac0c 15 // Start the timer
Remco 0:dda0a8c4ac0c 16 timer.start();
Remco 0:dda0a8c4ac0c 17 }
Remco 0:dda0a8c4ac0c 18
Remco 0:dda0a8c4ac0c 19 char* EntropyPool::produce(int bytes)
Remco 0:dda0a8c4ac0c 20 {
Remco 0:dda0a8c4ac0c 21 // Make sure the entropy pool is full
Remco 0:dda0a8c4ac0c 22 while(e < 256) gather();
Remco 0:dda0a8c4ac0c 23
Remco 0:dda0a8c4ac0c 24 // Mix the pool
Remco 0:dda0a8c4ac0c 25 process_chunk();
Remco 0:dda0a8c4ac0c 26
Remco 0:dda0a8c4ac0c 27 // Output a word at a time, maintaining at least
Remco 0:dda0a8c4ac0c 28 // 128 bits entropy
Remco 0:dda0a8c4ac0c 29 int num_words = (bytes + 3) / 4;
Remco 0:dda0a8c4ac0c 30 unsigned int* out = new unsigned int[num_words];
Remco 0:dda0a8c4ac0c 31 for(int i = 0; i < num_words; ++i) {
Remco 0:dda0a8c4ac0c 32 out[i] = hash[i % 8];
Remco 0:dda0a8c4ac0c 33 e -= 32;
Remco 0:dda0a8c4ac0c 34 if(e < 128) {
Remco 0:dda0a8c4ac0c 35 // Refill the entropy pool
Remco 0:dda0a8c4ac0c 36 while(e < 256)
Remco 0:dda0a8c4ac0c 37 gather();
Remco 0:dda0a8c4ac0c 38 process_chunk();
Remco 0:dda0a8c4ac0c 39 }
Remco 0:dda0a8c4ac0c 40 }
Remco 0:dda0a8c4ac0c 41 return reinterpret_cast<char*>(out);
Remco 0:dda0a8c4ac0c 42 }
Remco 0:dda0a8c4ac0c 43
Remco 0:dda0a8c4ac0c 44 void EntropyPool::gather()
Remco 0:dda0a8c4ac0c 45 {
Remco 0:dda0a8c4ac0c 46 // The following default sources are of poor quality
Remco 0:dda0a8c4ac0c 47 // In a thight loop they would be highly predictable
Remco 0:dda0a8c4ac0c 48 // Yet it is still far better than nothing, and to prevent
Remco 0:dda0a8c4ac0c 49 // complete stall, I'll assume these add two bits of entropy
Remco 0:dda0a8c4ac0c 50 e += 2;
Remco 0:dda0a8c4ac0c 51
Remco 0:dda0a8c4ac0c 52 // Real time clock
Remco 0:dda0a8c4ac0c 53 time_t tvalue = time(0);
Remco 0:dda0a8c4ac0c 54 append(reinterpret_cast<char*>(&tvalue), sizeof(time_t));
Remco 0:dda0a8c4ac0c 55
Remco 0:dda0a8c4ac0c 56 // Ticker
Remco 0:dda0a8c4ac0c 57 unsigned int value = timer.read_us();
Remco 0:dda0a8c4ac0c 58 append(reinterpret_cast<char*>(&value), 4);
Remco 0:dda0a8c4ac0c 59
Remco 0:dda0a8c4ac0c 60 // Number of bytes appended so far
Remco 0:dda0a8c4ac0c 61 append(reinterpret_cast<char*>(&length), 4);
Remco 0:dda0a8c4ac0c 62
Remco 0:dda0a8c4ac0c 63 // Call user function
Remco 0:dda0a8c4ac0c 64 gatherer.call();
Remco 0:dda0a8c4ac0c 65
Remco 0:dda0a8c4ac0c 66 if(e > 256) e = 256;
Remco 0:dda0a8c4ac0c 67 }
Remco 0:dda0a8c4ac0c 68
Remco 0:dda0a8c4ac0c 69 void EntropyPool::gatherAnalogNoise(AnalogIn& in, int entropy)
Remco 0:dda0a8c4ac0c 70 {
Remco 0:dda0a8c4ac0c 71 unsigned short value = in.read_u16();
Remco 0:dda0a8c4ac0c 72 // Only the least significant bits change due to noise
Remco 0:dda0a8c4ac0c 73 // But the last four bits are repetitions of the first four
Remco 0:dda0a8c4ac0c 74 append(reinterpret_cast<char*>(&value), 2);
Remco 0:dda0a8c4ac0c 75 e += entropy;
Remco 0:dda0a8c4ac0c 76 }
Remco 0:dda0a8c4ac0c 77
Remco 0:dda0a8c4ac0c 78
Remco 0:dda0a8c4ac0c 79
Remco 0:dda0a8c4ac0c 80