Remco Bloemen
/
EntropySource
Use your mbed and it\'s noisy analog inputs as a hardware random number generator!
EntropyPool.cpp@0:dda0a8c4ac0c, 2011-06-20 (annotated)
- Committer:
- Remco
- Date:
- Mon Jun 20 13:23:03 2011 +0000
- Revision:
- 0:dda0a8c4ac0c
Who changed what in which revision?
User | Revision | Line number | New 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 |