|  |  | @@ -0,0 +1,157 @@ | 
		
	
		
			
			|  |  |  | // onetimepad.cpp | 
		
	
		
			
			|  |  |  | // Copyright (C) 2006-2007 MicroNeil Research Corporation | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #include "onetimepad.hpp" | 
		
	
		
			
			|  |  |  | #include "timing.hpp" | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | /* | 
		
	
		
			
			|  |  |  | class OneTimePad {                                                              // One Time Pad generator. | 
		
	
		
			
			|  |  |  | private: | 
		
	
		
			
			|  |  |  | MANGLER PagGenerator;                                                       // MANGLER as a PRNG. | 
		
	
		
			
			|  |  |  | PadBuffer Entropy(int Length = 1024);                                       // System entropy source. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | public: | 
		
	
		
			
			|  |  |  | **    OneTimePad();                                                               // Constructor initializes w/ Entropy. | 
		
	
		
			
			|  |  |  | **    PadBuffer Pad(int Length);                                                  // Get a pad of Length. | 
		
	
		
			
			|  |  |  | **    void addEntropy();                                                          // Add entropy from the system source. | 
		
	
		
			
			|  |  |  | **    void addEntropy(PadBuffer Entropy);                                         // Add entropy from this source. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | }; | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | //////////////////////////////////////////////////////////////////////////////// | 
		
	
		
			
			|  |  |  | // Platform specific strong entropy sourcing. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #ifdef WIN32 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | //// WIN32 Strong Entropy Source == CryptGenRandom() /////////////////////////// | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #include <windows.h> | 
		
	
		
			
			|  |  |  | #include <wincrypt.h> | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | PadBuffer OneTimePad::Entropy(int Length) {                                     // Get a PadBuffer full of randomness. | 
		
	
		
			
			|  |  |  | PadBuffer Buffer(Length, 0);                                                // Start by initializing the buffer. | 
		
	
		
			
			|  |  |  | HCRYPTPROV provider = 0;                                                    // We will need a handle for the source. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if(                                                                         // Try a two different sources. | 
		
	
		
			
			|  |  |  | !CryptAcquireContext(                                                     // If we can get a hardware source | 
		
	
		
			
			|  |  |  | &provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT)) {          // from an intel CPU then use that first. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if(                                                                     // If we can't use get that | 
		
	
		
			
			|  |  |  | !CryptAcquireContext(                                                 // entropy source for some reason then | 
		
	
		
			
			|  |  |  | &provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {       // try to use the RSA source. That should | 
		
	
		
			
			|  |  |  | // always work, but if it doesn't we need | 
		
	
		
			
			|  |  |  | provider = 0;                                                     // to know about it so we'll have a zero | 
		
	
		
			
			|  |  |  | }                                                                       // handle. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if(0 != provider) {                                                         // If we did get a good source then | 
		
	
		
			
			|  |  |  | CryptGenRandom (provider, Length, (BYTE*)&Buffer[0]);                   // grab the random bit required and | 
		
	
		
			
			|  |  |  | CryptReleaseContext(provider,0);                                        // then let the provider go. | 
		
	
		
			
			|  |  |  | StrongEntropyFlag = true;                                               // We DID get strong entropy. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else {                                                                      // If we did not get a good source | 
		
	
		
			
			|  |  |  | StrongEntropyFlag = false;                                              // then we are not strong. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | return Buffer;                                                              // Return the data we got. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #else | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | //// *NIX Strong Entropy Source == /dev/urandom //////////////////////////////// | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #include <fstream> | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | PadBuffer OneTimePad::Entropy(int Length) {                                     // Get Length bytes of strong entropy. | 
		
	
		
			
			|  |  |  | PadBuffer Buffer(Length, 0);                                                // Initialize a buffer to hold them. | 
		
	
		
			
			|  |  |  | try {                                                                       // Handle this in a try block. | 
		
	
		
			
			|  |  |  | ifstream Source("/dev/urandom", ios::binary);                           // Open /dev/urandom if possible. | 
		
	
		
			
			|  |  |  | Source.read(reinterpret_cast<char*>(&Buffer[0]), Length);               // Read data into the buffer. | 
		
	
		
			
			|  |  |  | if(!Source.bad() && Source.gcount() == Length) {                        // If we got what we came for then | 
		
	
		
			
			|  |  |  | StrongEntropyFlag = true;                                           // we have strong cryptography. | 
		
	
		
			
			|  |  |  | } else {                                                                // If we didn't then we are not | 
		
	
		
			
			|  |  |  | StrongEntropyFlag = false;                                          // strong, and don't have things | 
		
	
		
			
			|  |  |  | }                                                                       // to make us go. | 
		
	
		
			
			|  |  |  | Source.close();                                                         // We're done, so close the stream. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | catch(...) {                                                                // If we had an exception then we | 
		
	
		
			
			|  |  |  | StrongEntropyFlag = false;                                              // did not get strong entropy. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return Buffer;                                                              // Return the buffer. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #endif | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | // End Platform Specific Bits | 
		
	
		
			
			|  |  |  | //////////////////////////////////////////////////////////////////////////////// | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | // Lightweight entropy is built from a combination of the time in ms UTC that | 
		
	
		
			
			|  |  |  | // the application was started, the number of milliseconds since that time in | 
		
	
		
			
			|  |  |  | // milliseconds, the number and times of calls to addLightweightEntropy(), and | 
		
	
		
			
			|  |  |  | // the state of the MANGLER engine at each call -- that state is effected by | 
		
	
		
			
			|  |  |  | // the combined previous use of the MANGLER and any other entropy that was | 
		
	
		
			
			|  |  |  | // added including the timing of those events (since they all trigger the | 
		
	
		
			
			|  |  |  | // addLightweightEntropy() function. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | Timer OneTimePadRunTimer;                                                       // Millisecond entropy source. | 
		
	
		
			
			|  |  |  | msclock LightweightEntropyBuffer;                                               // Lightweight entropy bucket. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | void OneTimePad::addLightweightEntropy() {                                      // Add entropy based on the | 
		
	
		
			
			|  |  |  | msclock StartFill = OneTimePadRunTimer.getStartClock();                     // initial start time of the app | 
		
	
		
			
			|  |  |  | msclock ElapsedFill = OneTimePadRunTimer.getElapsedTime();                  // and the number of millisecs since. | 
		
	
		
			
			|  |  |  | msclock CombinedFill = StartFill ^ ElapsedFill;                             // XOR the two together to combine. | 
		
	
		
			
			|  |  |  | CombinedFill = CombinedFill ^ LightweightEntropyBuffer;                     // Pick up some previous state entropy. | 
		
	
		
			
			|  |  |  | unsigned char* PrimerBuffer = (unsigned char*) &CombinedFill;               // Treat the value as a bunch of bytes. | 
		
	
		
			
			|  |  |  | unsigned char* EntropyBuffer = (unsigned char*) &LightweightEntropyBuffer;  // Likewise with the entropy buffer. | 
		
	
		
			
			|  |  |  | for(int i = 0; i < sizeof(msclock); i++) {                                  // Fold bytes into the mangler one | 
		
	
		
			
			|  |  |  | EntropyBuffer[i] +=                                                     // byte at a time, capturing the | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(                                                 // the results and using one extra | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(PrimerBuffer[i]));                             // round per byte to increase the | 
		
	
		
			
			|  |  |  | }                                                                           // amount of guessing an attacker | 
		
	
		
			
			|  |  |  | }                                                                               // needs to do. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | void OneTimePad::addEntropy() {                                                 // Add strong entropy if available. | 
		
	
		
			
			|  |  |  | PadBuffer Fill = Entropy();                                                 // Grab the entropy bits to add. | 
		
	
		
			
			|  |  |  | for(int i = 0; i < Fill.size(); i++) {                                      // Pump them in one byte at a | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(                                                   // time and then run an extra | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(Fill.at(i)));                                    // round per byte to increase the | 
		
	
		
			
			|  |  |  | }                                                                           // amount of guessing an attacker | 
		
	
		
			
			|  |  |  | }                                                                               // needs to do. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | void OneTimePad::addEntropy(PadBuffer Entropy) {                                // Add entropy from a given source. | 
		
	
		
			
			|  |  |  | addLightweightEntropy();                                                    // Start with some lightweight entropy. | 
		
	
		
			
			|  |  |  | for(int i = 0; i < Entropy.size(); i++) {                                   // Then loop through the provided | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(                                                   // entropy and mix it in with one | 
		
	
		
			
			|  |  |  | PadGenerator.Encrypt(Entropy.at(i)));                                 // extra round per byte to increase | 
		
	
		
			
			|  |  |  | }                                                                           // the amount of guessing an attacker | 
		
	
		
			
			|  |  |  | }                                                                               // needs to do. | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | PadBuffer OneTimePad::Pad(int Length) {                                         // Grab a pad of a specific length. | 
		
	
		
			
			|  |  |  | addLightweightEntropy();                                                    // Add some lightweight entropy. | 
		
	
		
			
			|  |  |  | PadBuffer Output; Output.reserve(Length);                                   // Create a buffer the right size. | 
		
	
		
			
			|  |  |  | unsigned char x;                                                            // Starting with an uninitialized | 
		
	
		
			
			|  |  |  | for(int i = 0; i < Length; i++)                                             // char, fill the buffer with | 
		
	
		
			
			|  |  |  | Output.push_back(x = PadGenerator.Encrypt(x));                            // random bytes from the mangler. | 
		
	
		
			
			|  |  |  | return Output;                                                              // Return the new pad. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | void* OneTimePad::fill(void* Object, int Size) {                                // Fill *Object with random bytes. | 
		
	
		
			
			|  |  |  | PadBuffer FillData = Pad(Size);                                             // Get a Pad of the correct size. | 
		
	
		
			
			|  |  |  | unsigned char* Ptr = reinterpret_cast<unsigned char*>(Object);              // Reinterpret the pointer type. | 
		
	
		
			
			|  |  |  | for(int i = 0; i < Size; i++) Ptr[i] = FillData.at(i);                      // Fill the object with the Pad. | 
		
	
		
			
			|  |  |  | return Object;                                                              // Return the object. | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | bool OneTimePad::isStrong() { return StrongEntropyFlag; }                       // Tell them if I'm strong! | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | OneTimePad::OneTimePad() {                                                      // Initialize the one time pad. | 
		
	
		
			
			|  |  |  | addLightweightEntropy();                                                    // Add lightweight entropy. | 
		
	
		
			
			|  |  |  | addEntropy();                                                               // Add cryptographic entropy. | 
		
	
		
			
			|  |  |  | unsigned char x;                                                            // Starting with an uninitialized | 
		
	
		
			
			|  |  |  | for(int i = 0; i < 1024; i++) {                                             // character, run 1024 rounds to | 
		
	
		
			
			|  |  |  | x = PadGenerator.Encrypt(x);                                            // reduce the predictability of the | 
		
	
		
			
			|  |  |  | }                                                                           // initial Mangler state. | 
		
	
		
			
			|  |  |  | }                                                                               // The OneTimePad object is ready. | 
		
	
		
			
			|  |  |  | 
 |