diff --git a/blumshub.cpp b/blumshub.cpp index 6e1854d8..be9b7582 100644 --- a/blumshub.cpp +++ b/blumshub.cpp @@ -32,6 +32,18 @@ byte PublicBlumBlumShub::GenerateByte() return b; } +void PublicBlumBlumShub::GenerateBlock(byte *output, size_t size) +{ + while (size--) + *output++ = PublicBlumBlumShub::GenerateByte(); +} + +void PublicBlumBlumShub::ProcessData(byte *outString, const byte *inString, size_t length) +{ + while (length--) + *outString++ = *inString++ ^ PublicBlumBlumShub::GenerateByte(); +} + BlumBlumShub::BlumBlumShub(const Integer &p, const Integer &q, const Integer &seed) : PublicBlumBlumShub(p*q, seed), p(p), q(q), diff --git a/blumshub.h b/blumshub.h index 6aab3261..5e507478 100644 --- a/blumshub.h +++ b/blumshub.h @@ -17,12 +17,8 @@ public: unsigned int GenerateBit(); byte GenerateByte(); - - void ProcessData(byte *outString, const byte *inString, size_t length) - { - while (length--) - *outString++ = *inString ^ GenerateByte(); - } + void GenerateBlock(byte *output, size_t size); + void ProcessData(byte *outString, const byte *inString, size_t length); bool IsSelfInverting() const {return true;} bool IsForwardTransformation() const {return true;} diff --git a/cryptlib.cpp b/cryptlib.cpp index b6f25a1a..bbab37c9 100644 --- a/cryptlib.cpp +++ b/cryptlib.cpp @@ -11,6 +11,8 @@ #include "fips140.h" #include "argnames.h" #include "fltrimpl.h" +#include "trdlocal.h" +#include "osrng.h" #include @@ -91,6 +93,11 @@ const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs return iv; } +void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV) +{ + rng.GenerateBlock(IV, IVSize()); +} + void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t numberOfBlocks) const { unsigned int blockSize = BlockSize(); @@ -104,6 +111,11 @@ void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, cons } } +unsigned int BlockTransformation::BlockAlignment() const +{ + return GetAlignmentOf(); +} + void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length) { assert(MinLastBlockSize() == 0); // this function should be overriden otherwise @@ -116,39 +128,53 @@ void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inStrin unsigned int RandomNumberGenerator::GenerateBit() { - return Parity(GenerateByte()); + return GenerateByte() & 1; } -void RandomNumberGenerator::GenerateBlock(byte *output, size_t size) +byte RandomNumberGenerator::GenerateByte() { - while (size--) - *output++ = GenerateByte(); + byte b; + GenerateBlock(&b, 1); + return b; } word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max) { word32 range = max-min; - const int maxBytes = BytePrecision(range); const int maxBits = BitPrecision(range); word32 value; do { - value = 0; - for (int i=0; i range); return value+min; } +void RandomNumberGenerator::GenerateBlock(byte *output, size_t size) +{ + ArraySink s(output, size); + GenerateIntoBufferedTransformation(s, BufferedTransformation::NULL_CHANNEL, size); +} + void RandomNumberGenerator::DiscardBytes(size_t n) { - while (n--) - GenerateByte(); + GenerateIntoBufferedTransformation(TheBitBucket(), BufferedTransformation::NULL_CHANNEL, n); +} + +void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) +{ + FixedSizeSecBlock buffer; + while (length) + { + size_t len = UnsignedMin(buffer.size(), length); + GenerateBlock(buffer, len); + target.ChannelPut(channel, buffer, len); + length -= len; + } } //! see NullRNG() @@ -156,7 +182,7 @@ class ClassNullRNG : public RandomNumberGenerator { public: std::string AlgorithmName() const {return "NullRNG";} - byte GenerateByte() {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");} + void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");} }; RandomNumberGenerator & NullRNG() diff --git a/cryptlib.h b/cryptlib.h index 1cd6c6a3..86b0cfcc 100644 --- a/cryptlib.h +++ b/cryptlib.h @@ -17,7 +17,7 @@
Message Authentication Codes
#MD5MAC, XMACC, HMAC, CBC_MAC, DMAC, PanamaMAC, TTMAC
Random Number Generators
- NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG + NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG
Password-based Cryptography
PasswordBasedKeyDerivationFunction
Public Key Cryptosystems
@@ -61,7 +61,7 @@ In the FIPS 140-2 validated DLL version of Crypto++, only the following implemen
Message Authentication Codes (replace template parameter H with one of the hash functions above)
HMAC\, CBC_MAC\, CBC_MAC\
Random Number Generators
- AutoSeededX917RNG\ + DefaultAutoSeededRNG (AutoSeededX917RNG\)
Key Agreement
#DH
Public Key Cryptosystems
@@ -84,6 +84,8 @@ NAMESPACE_BEGIN(CryptoPP) // forward declarations class Integer; +class RandomNumberGenerator; +class BufferedTransformation; //! used to specify a direction for a cipher to operate in (encrypt or decrypt) enum CipherDir {ENCRYPTION, DECRYPTION}; @@ -397,7 +399,7 @@ public: /*! This method should be called after you finish encrypting one message and are ready to start the next one. After calling it, you must call SetKey() or Resynchronize() before using this object again. This method is not implemented on decryption objects. */ - virtual void GetNextIV(byte *IV) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support GetNextIV()");} + virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV); protected: virtual const Algorithm & GetAlgorithm() const =0; @@ -438,7 +440,7 @@ public: virtual unsigned int BlockSize() const =0; //! block pointers must be divisible by this - virtual unsigned int BlockAlignment() const {return 4;} + virtual unsigned int BlockAlignment() const; // returns alignment of word32 by default //! returns true if this is a permutation (i.e. there is an inverse transformation) virtual bool IsPermutation() const {return true;} @@ -624,24 +626,31 @@ typedef SymmetricCipher StreamCipher; class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm { public: + //! update RNG state with additional unpredictable values + virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");} + + //! returns true if IncorporateEntropy is implemented + virtual bool CanIncorporateEntropy() const {return false;} + //! generate new random byte and return it - virtual byte GenerateByte() =0; + virtual byte GenerateByte(); //! generate new random bit and return it - /*! Default implementation is to call GenerateByte() and return its parity. */ + /*! Default implementation is to call GenerateByte() and return its lowest bit. */ virtual unsigned int GenerateBit(); //! generate a random 32 bit word in the range min to max, inclusive virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL); //! generate random array of bytes - /*! Default implementation is to call GenerateByte() size times. */ virtual void GenerateBlock(byte *output, size_t size); //! generate and discard n bytes - /*! Default implementation is to call GenerateByte() n times. */ virtual void DiscardBytes(size_t n); + //! generate random bytes as input to a BufferedTransformation + virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length); + //! randomly shuffle the specified array, resulting permutation is uniformly distributed template void Shuffle(IT begin, IT end) { diff --git a/filters.cpp b/filters.cpp index 1771e8cb..47a91a33 100644 --- a/filters.cpp +++ b/filters.cpp @@ -496,6 +496,17 @@ void ProxyFilter::NextPutModifiable(byte *s, size_t len) // ************************************************************* +void RandomNumberSink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng); +} + +size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + m_rng->IncorporateEntropy(begin, length); + return 0; +} + size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) { memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); @@ -952,9 +963,10 @@ size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &tra if (!blocking) throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object"); - lword transferMax = transferBytes; - for (transferBytes = 0; transferBytesGenerateByte()); + transferBytes = UnsignedMin(transferBytes, m_length - m_count); + m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes); + m_count += transferBytes; + return 0; } diff --git a/filters.h b/filters.h index fc5c6e80..750d976f 100644 --- a/filters.h +++ b/filters.h @@ -565,6 +565,23 @@ private: CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate; typedef StringSinkTemplate StringSink; +//! incorporates input into RNG as additional entropy +class RandomNumberSink : public Bufferless +{ +public: + RandomNumberSink() + : m_rng(NULL) {} + + RandomNumberSink(RandomNumberGenerator &rng) + : m_rng(&rng) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator *m_rng; +}; + //! Copy input to a memory buffer class CRYPTOPP_DLL ArraySink : public Bufferless { @@ -716,14 +733,20 @@ class CRYPTOPP_DLL StringSource : public SourceTemplate public: StringSource(BufferedTransformation *attachment = NULL) : SourceTemplate(attachment) {} + //! zero terminated string as source StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + //! binary byte array as source StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL) : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + //! std::string as source StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} }; +//! use the third constructor for an array source +typedef StringSource ArraySource; + //! RNG-based implementation of Source interface class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate { diff --git a/strciphr.cpp b/strciphr.cpp index 62947852..45dd4dec 100644 --- a/strciphr.cpp +++ b/strciphr.cpp @@ -23,20 +23,6 @@ void AdditiveCipherTemplate::UncheckedSetKey(const byte *key, unsigned int le policy.CipherResynchronize(m_buffer, this->GetIVAndThrowIfInvalid(params)); } -template -byte AdditiveCipherTemplate::GenerateByte() -{ - PolicyInterface &policy = this->AccessPolicy(); - - if (m_leftOver == 0) - { - policy.WriteKeystream(m_buffer, policy.GetIterationsToBuffer()); - m_leftOver = policy.GetBytesPerIteration(); - } - - return *(KeystreamBufferEnd()-m_leftOver--); -} - template void AdditiveCipherTemplate::GenerateBlock(byte *outString, size_t length) { @@ -59,9 +45,7 @@ void AdditiveCipherTemplate::GenerateBlock(byte *outString, size_t length) if (length >= bytesPerIteration) { size_t iterations = length / bytesPerIteration; - policy.WriteKeystream(outString, iterations); - outString += iterations * bytesPerIteration; length -= iterations * bytesPerIteration; diff --git a/test.cpp b/test.cpp index 34a73886..18453489 100644 --- a/test.cpp +++ b/test.cpp @@ -2,7 +2,7 @@ #define _CRT_SECURE_NO_DEPRECATE #define CRYPTOPP_DEFAULT_NO_DLL -#define CRYPTOPP_ENABLE_NAMESPACE_WEAK +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include "dll.h" #include "md5.h" @@ -355,7 +355,7 @@ int CRYPTOPP_API main(int argc, char *argv[]) void FIPS140_GenerateRandomFiles() { #ifdef OS_RNG_AVAILABLE - AutoSeededX917RNG rng; + DefaultAutoSeededRNG rng; RandomNumberStore store(rng, ULONG_MAX); for (unsigned int i=0; i<100000; i++) @@ -374,7 +374,7 @@ SecByteBlock HexDecodeString(const char *hex) return result; } -RandomPool & GlobalRNG() +RandomNumberGenerator & GlobalRNG() { static RandomPool randomPool; return randomPool; @@ -383,7 +383,7 @@ RandomPool & GlobalRNG() void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed) { RandomPool randPool; - randPool.Put((byte *)seed, strlen(seed)); + randPool.IncorporateEntropy((byte *)seed, strlen(seed)); RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength); HexEncoder privFile(new FileSink(privFilename)); @@ -402,7 +402,7 @@ string RSAEncryptString(const char *pubFilename, const char *seed, const char *m RSAES_OAEP_SHA_Encryptor pub(pubFile); RandomPool randPool; - randPool.Put((byte *)seed, strlen(seed)); + randPool.IncorporateEntropy((byte *)seed, strlen(seed)); string result; StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result)))); @@ -544,7 +544,7 @@ void SecretShareFile(int threshold, int nShares, const char *filename, const cha assert(nShares<=1000); RandomPool rng; - rng.Put((byte *)seed, strlen(seed)); + rng.IncorporateEntropy((byte *)seed, strlen(seed)); ChannelSwitch *channelSwitch; FileSource source(filename, false, new SecretSharing(rng, threshold, nShares, channelSwitch = new ChannelSwitch)); @@ -774,7 +774,7 @@ bool Validate(int alg, bool thorough, const char *seed) } cout << "Using seed: " << seed << endl << endl; - GlobalRNG().Put((const byte *)seed, strlen(seed)); + GlobalRNG().IncorporateEntropy((const byte *)seed, strlen(seed)); switch (alg) { @@ -843,6 +843,7 @@ bool Validate(int alg, bool thorough, const char *seed) case 63: result = ValidateTTMAC(); break; case 64: result = ValidateSalsa(); break; case 65: result = ValidateSosemanuk(); break; + case 66: result = ValidateVMAC(); break; default: return false; } diff --git a/validat2.cpp b/validat2.cpp index 4154f5e7..5ec0a2c2 100644 --- a/validat2.cpp +++ b/validat2.cpp @@ -2,7 +2,7 @@ #include "pch.h" -#define CRYPTOPP_ENABLE_NAMESPACE_WEAK +#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include "blumshub.h" #include "rsa.h" #include "md2.h" @@ -39,11 +39,9 @@ class FixedRNG : public RandomNumberGenerator public: FixedRNG(BufferedTransformation &source) : m_source(source) {} - byte GenerateByte() + void GenerateBlock(byte *output, size_t size) { - byte b; - m_source.Get(b); - return b; + m_source.Get(output, size); } private: diff --git a/validate.h b/validate.h index eb70c8bb..a1119655 100644 --- a/validate.h +++ b/validate.h @@ -2,7 +2,6 @@ #define CRYPTOPP_VALIDATE_H #include "cryptlib.h" -#include "randpool.h" bool ValidateAll(bool thorough); bool TestSettings(); @@ -51,6 +50,7 @@ bool ValidateSHACAL2(); bool ValidateCamellia(); bool ValidateSalsa(); bool ValidateSosemanuk(); +bool ValidateVMAC(); bool ValidateBBS(); bool ValidateDH(); @@ -72,7 +72,7 @@ bool ValidateEC2N(); bool ValidateECDSA(); bool ValidateESIGN(); -CryptoPP::RandomPool & GlobalRNG(); +CryptoPP::RandomNumberGenerator & GlobalRNG(); bool RunTestDataFile(const char *filename); #endif