diff --git a/config/Makefile.in b/config/Makefile.in index f6734a4a..08dc3fb7 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -302,7 +302,7 @@ Makefile: config/Makefile.in MAIN_SRCS=$(COMMON)/commonMain.ml ifeq ("$(DONKEY_SUI)", "yes") - CRYPTOPP_LIBS_flags += -cc '$(CXX) $(CXXFLAGS)' -ccopt '$(CRYPTOPPFLAGS)' + CRYPTOPP_LIBS_flags += -cc '$(CXX) $(CXXFLAGS)' -cclib '-lcryptopp' -ccopt '$(CRYPTOPPFLAGS)' DONKEY_SRCS += $(LIB)/CryptoPP.cc $(LIB)/CryptoPP_stubs.c $(SRC_DONKEY)/donkeySui1.ml $(SRC_DONKEY)/donkeySui.ml else DONKEY_SRCS += $(SRC_DONKEY)/donkeySui2.ml $(SRC_DONKEY)/donkeySui.ml diff --git a/src/utils/lib/CryptoPP.cc b/src/utils/lib/CryptoPP.cc index 51032f22..0a8d7383 100644 --- a/src/utils/lib/CryptoPP.cc +++ b/src/utils/lib/CryptoPP.cc @@ -1,9440 +1,7 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// This file contains a subset of the Crypto++ library (version 5.2.1), with -// kind permission from Wei Dai. Please note that this file should not reflect -// on the real Crypto++ library in any way, as this file been greatly mangled to -// reduce the code-size, since this app only makes use of RSA classes (for Secure -// Identification) and the MD4 hashing class (for FileIDs). -// -// For the full Crypto++ library, please refer to the official Crypto++ website, -// which can be found at, http://www.cryptopp.com -// -//////////////////////////////////////////////////////////////////////////////// -// -// Compilation Copyright (c) 1995-2004 by Wei Dai. All rights reserved. -// This copyright applies only to this software distribution package -// as a compilation, and does not imply a copyright on any particular -// file in the package. -// -// The following files are copyrighted by their respective original authors, -// and their use is subject to additional licenses included in these files. -// -// mars.cpp - Copyright 1998 Brian Gladman. - -// All other files in this compilation are placed in the public domain by -// Wei Dai and other contributors. -// -// I would like to thank the following authors for placing their works into -// the public domain: -// -// Joan Daemen - 3way.cpp -// Leonard Janke - cast.cpp, seal.cpp -// Steve Reid - cast.cpp -// Phil Karn - des.cpp -// Michael Paul Johnson - diamond.cpp -// Andrew M. Kuchling - md2.cpp, md4.cpp -// Colin Plumb - md5.cpp, md5mac.cpp -// Seal Woods - rc6.cpp -// Chris Morgan - rijndael.cpp -// Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp -// Richard De Moliner - safer.cpp -// Matthew Skala - twofish.cpp -// Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp -// -// Permission to use, copy, modify, and distribute this compilation for -// any purpose, including commercial applications, is hereby granted -// without fee, subject to the following restrictions: -// -// 1. Any copy or modification of this compilation in any form, except -// in object code form as part of an application software, must include -// the above copyright notice and this license. -// -// 2. Users of this software agree that any modification or extension -// they provide to Wei Dai will be considered public domain and not -// copyrighted unless it includes an explicit copyright notice. -// -// 3. Wei Dai makes no warranty or representation that the operation of the -// software in this compilation will be error-free, and Wei Dai is under no -// obligation to provide any services, by way of maintenance, update, or -// otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS" -// WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO, -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR -// DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -// -// 4. Users will not use Wei Dai or any other contributor's name in any -// publicity or advertising, without prior written consent in each case. -// -// 5. Export of this software from the United States may require a -// specific license from the United States Government. It is the -// responsibility of any person or organization contemplating export -// to obtain such a license before exporting. -// -// 6. Certain parts of this software may be protected by patents. It -// is the users' responsibility to obtain the appropriate -// licenses before using those parts. -// -// If this compilation is used in object code form in an application -// software, acknowledgement of the author is not required but would be -// appreciated. The contribution of any useful modifications or extensions -// to Wei Dai is not required but would also be appreciated. -// -//////////////////////////////////////////////////////////////////////////////// - -#include "CryptoPP.h" - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_FLTRIMPL_H -#define CRYPTOPP_FLTRIMPL_H - -#define FILTER_BEGIN \ - switch (m_continueAt) \ - { \ - case 0: \ - m_inputPosition = 0; - -#define FILTER_END_NO_MESSAGE_END_NO_RETURN \ - break; \ - default: \ - assert(false); \ - } - -#define FILTER_END_NO_MESSAGE_END \ - FILTER_END_NO_MESSAGE_END_NO_RETURN \ - return 0; - -/* -#define FILTER_END \ - case -1: \ - if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \ - return 1; \ - FILTER_END_NO_MESSAGE_END -*/ - -#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \ - {\ - case site: \ - statement; \ - if (Output(site, output, length, messageEnd, blocking)) \ - return STDMAX(1U, (unsigned int)length-m_inputPosition);\ - } - -#define FILTER_OUTPUT(site, output, length, messageEnd) \ - {\ - case site: \ - if (Output(site, output, length, messageEnd, blocking)) \ - return STDMAX(1U, (unsigned int)length-m_inputPosition);\ - } - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// cryptlib.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "cryptlib.h" -//- #include "misc.h" -//- #include "filters.h" -//- #include "algparam.h" -//- #include "fips140.h" -//- #include "argnames.h" -//- #include "fltrimpl.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_COMPILE_ASSERT_GLOBAL(sizeof(byte) == 1); -CRYPTOPP_COMPILE_ASSERT_GLOBAL(sizeof(word16) == 2); -CRYPTOPP_COMPILE_ASSERT_GLOBAL(sizeof(word32) == 4); -#ifdef WORD64_AVAILABLE -CRYPTOPP_COMPILE_ASSERT_GLOBAL(sizeof(word64) == 8); -#endif -#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE -CRYPTOPP_COMPILE_ASSERT_GLOBAL(sizeof(dword) == 2*sizeof(word)); -#endif - -const std::string BufferedTransformation::NULL_CHANNEL; -const NullNameValuePairs g_nullNameValuePairs; - -BufferedTransformation & TheBitBucket() -{ - static BitBucket bitBucket; - return bitBucket; -} - -Algorithm::Algorithm(bool /* checkSelfTestStatus */) -{ -} - -void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, unsigned int length, int rounds) -{ - SetKey(key, length, MakeParameters(Name::Rounds(), rounds)); -} - -void SimpleKeyingInterface::SetKeyWithIV(const byte *key, unsigned int length, const byte *iv) -{ - SetKey(key, length, MakeParameters(Name::IV(), iv)); -} - -void SimpleKeyingInterface::ThrowIfInvalidKeyLength(const Algorithm &algorithm, unsigned int length) -{ - if (!IsValidKeyLength(length)) - throw InvalidKeyLength(algorithm.AlgorithmName(), length); -} - -void SimpleKeyingInterface::ThrowIfResynchronizable() -{ - if (IsResynchronizable()) - throw InvalidArgument("SimpleKeyingInterface: this object requires an IV"); -} - -void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv) -{ - if (!iv && !(IVRequirement() == INTERNALLY_GENERATED_IV || IVRequirement() == STRUCTURED_IV || !IsResynchronizable())) - throw InvalidArgument("SimpleKeyingInterface: this object cannot use a null IV"); -} - -const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms) -{ - const byte *iv; - if (params.GetValue(Name::IV(), iv)) - ThrowIfInvalidIV(iv); - else - ThrowIfResynchronizable(); - return iv; -} - -void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, unsigned int numberOfBlocks) const -{ - unsigned int blockSize = BlockSize(); - while (numberOfBlocks--) - { - ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks); - inBlocks += blockSize; - outBlocks += blockSize; - if (xorBlocks) - xorBlocks += blockSize; - } -} - -void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length) -{ - assert(MinLastBlockSize() == 0); // this function should be overriden otherwise - - if (length == MandatoryBlockSize()) - ProcessData(outString, inString, length); - else if (length != 0) - throw NotImplemented("StreamTransformation: this object does't support a special last block"); -} - -unsigned int RandomNumberGenerator::GenerateBit() -{ - return Parity(GenerateByte()); -} - -void RandomNumberGenerator::GenerateBlock(byte *output, unsigned int size) -{ - while (size--) - *output++ = GenerateByte(); -} - -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::DiscardBytes(unsigned int n) -{ - while (n--) - GenerateByte(); -} - -//! see NullRNG() -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");} -}; - -RandomNumberGenerator & NullRNG() -{ - static ClassNullRNG s_nullRNG; - return s_nullRNG; -} - -bool HashTransformation::TruncatedVerify(const byte *digestIn, unsigned int digestLength) -{ - ThrowIfInvalidTruncatedSize(digestLength); - SecByteBlock digest(digestLength); - TruncatedFinal(digest, digestLength); - return memcmp(digest, digestIn, digestLength) == 0; -} - -void HashTransformation::ThrowIfInvalidTruncatedSize(unsigned int size) const -{ - if (size > DigestSize()) - throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize(), 10) + " byte digest to " + IntToString(size, 10) + " bytes"); -} - -unsigned int BufferedTransformation::GetMaxWaitObjectCount() const -{ - const BufferedTransformation *t = AttachedTransformation(); - return t ? t->GetMaxWaitObjectCount() : 0; -} - -void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container) -{ - BufferedTransformation *t = AttachedTransformation(); - if (t) - t->GetWaitObjects(container); -} - -void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int /* propagation */) -{ - assert(!AttachedTransformation()); - IsolatedInitialize(parameters); -} - -bool BufferedTransformation::Flush(bool hardFlush, int /* propagation */, bool blocking) -{ - assert(!AttachedTransformation()); - return IsolatedFlush(hardFlush, blocking); -} - -bool BufferedTransformation::MessageSeriesEnd(int /* propagation */, bool blocking) -{ - assert(!AttachedTransformation()); - return IsolatedMessageSeriesEnd(blocking); -} - -byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, unsigned int &size) -{ - if (channel.empty()) - return CreatePutSpace(size); - else - throw NoChannelSupport(); -} - -unsigned int BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking) -{ - if (channel.empty()) - return Put2(begin, length, messageEnd, blocking); - else - throw NoChannelSupport(); -} - -unsigned int BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking) -{ - if (channel.empty()) - return PutModifiable2(begin, length, messageEnd, blocking); - else - return ChannelPut2(channel, begin, length, messageEnd, blocking); -} - -bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking) -{ - if (channel.empty()) - return Flush(completeFlush, propagation, blocking); - else - throw NoChannelSupport(); -} - -bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) -{ - if (channel.empty()) - return MessageSeriesEnd(propagation, blocking); - else - throw NoChannelSupport(); -} - -unsigned long BufferedTransformation::MaxRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->MaxRetrievable(); - else - return CopyTo(TheBitBucket()); -} - -bool BufferedTransformation::AnyRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->AnyRetrievable(); - else - { - byte b; - return Peek(b) != 0; - } -} - -unsigned int BufferedTransformation::Get(byte &outByte) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outByte); - else - return Get(&outByte, 1); -} - -unsigned int BufferedTransformation::Get(byte *outString, unsigned int getMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outString, getMax); - else - { - ArraySink arraySink(outString, getMax); - return TransferTo(arraySink, getMax); - } -} - -unsigned int BufferedTransformation::Peek(byte &outByte) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outByte); - else - return Peek(&outByte, 1); -} - -unsigned int BufferedTransformation::Peek(byte *outString, unsigned int peekMax) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outString, peekMax); - else - { - ArraySink arraySink(outString, peekMax); - return CopyTo(arraySink, peekMax); - } -} - -unsigned long BufferedTransformation::Skip(unsigned long skipMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Skip(skipMax); - else - return TransferTo(TheBitBucket(), skipMax); -} - -unsigned long BufferedTransformation::TotalBytesRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->TotalBytesRetrievable(); - else - return MaxRetrievable(); -} - -unsigned int BufferedTransformation::NumberOfMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->NumberOfMessages(); - else - return CopyMessagesTo(TheBitBucket()); -} - -bool BufferedTransformation::AnyMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->AnyMessages(); - else - return NumberOfMessages() != 0; -} - -bool BufferedTransformation::GetNextMessage() -{ - if (AttachedTransformation()) - return AttachedTransformation()->GetNextMessage(); - else - { - assert(!AnyMessages()); - return false; - } -} - -unsigned int BufferedTransformation::SkipMessages(unsigned int count) -{ - if (AttachedTransformation()) - return AttachedTransformation()->SkipMessages(count); - else - return TransferMessagesTo(TheBitBucket(), count); -} - -unsigned int BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking); - else - { - unsigned int maxMessages = messageCount; - for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++) - { - unsigned int blockedBytes; - unsigned long transferredBytes; - - while (AnyRetrievable()) - { - transferredBytes = ULONG_MAX; - blockedBytes = TransferTo2(target, transferredBytes, channel, blocking); - if (blockedBytes > 0) - return blockedBytes; - } - - if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking)) - return 1; - - bool result = GetNextMessage(); - assert(result); - } - return 0; - } -} - -unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->CopyMessagesTo(target, count, channel); - else - return 0; -} - -void BufferedTransformation::SkipAll() -{ - if (AttachedTransformation()) - AttachedTransformation()->SkipAll(); - else - { - while (SkipMessages()) {} - while (Skip()) {} - } -} - -unsigned int BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferAllTo2(target, channel, blocking); - else - { - assert(!NumberOfMessageSeries()); - - unsigned int messageCount; - do - { - messageCount = UINT_MAX; - unsigned int blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking); - if (blockedBytes) - return blockedBytes; - } - while (messageCount != 0); - - unsigned long byteCount; - do - { - byteCount = ULONG_MAX; - unsigned int blockedBytes = TransferTo2(target, byteCount, channel, blocking); - if (blockedBytes) - return blockedBytes; - } - while (byteCount != 0); - - return 0; - } -} - -void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const -{ - if (AttachedTransformation()) - AttachedTransformation()->CopyAllTo(target, channel); - else - { - assert(!NumberOfMessageSeries()); - while (CopyMessagesTo(target, UINT_MAX, channel)) {} - } -} - -void BufferedTransformation::SetRetrievalChannel(const std::string &channel) -{ - if (AttachedTransformation()) - AttachedTransformation()->SetRetrievalChannel(channel); -} - -unsigned int BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking) -{ - FixedSizeSecBlock buf; - PutWord(false, order, buf, value); - return ChannelPut(channel, buf, 2, blocking); -} - -unsigned int BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking) -{ - FixedSizeSecBlock buf; - PutWord(false, order, buf, value); - return ChannelPut(channel, buf, 4, blocking); -} - -unsigned int BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking) -{ - return ChannelPutWord16(NULL_CHANNEL, value, order, blocking); -} - -unsigned int BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking) -{ - return ChannelPutWord32(NULL_CHANNEL, value, order, blocking); -} - -unsigned int BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) -{ - byte buf[2] = {0, 0}; - unsigned int len = Peek(buf, 2); - - if (order) - value = (buf[0] << 8) | buf[1]; - else - value = (buf[1] << 8) | buf[0]; - - return len; -} - -unsigned int BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) -{ - byte buf[4] = {0, 0, 0, 0}; - unsigned int len = Peek(buf, 4); - - if (order) - value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3]; - else - value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0]; - - return len; -} - -unsigned int BufferedTransformation::GetWord16(word16 &value, ByteOrder order) -{ - return Skip(PeekWord16(value, order)); -} - -unsigned int BufferedTransformation::GetWord32(word32 &value, ByteOrder order) -{ - return Skip(PeekWord32(value, order)); -} - -void BufferedTransformation::Attach(BufferedTransformation *newOut) -{ - if (AttachedTransformation() && AttachedTransformation()->Attachable()) - AttachedTransformation()->Attach(newOut); - else - Detach(newOut); -} - -void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize) -{ - GenerateRandom(rng, MakeParameters("KeySize", (int)keySize)); -} - -class PK_DefaultEncryptionFilter : public Unflushable -{ -public: - PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) - : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters) - { - Detach(attachment); - } - - unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) - { - FILTER_BEGIN; - m_plaintextQueue.Put(inString, length); - - if (messageEnd) - { - { - unsigned int plaintextLength = m_plaintextQueue.CurrentSize(); - unsigned int ciphertextLength = m_encryptor.CiphertextLength(plaintextLength); - - SecByteBlock plaintext(plaintextLength); - m_plaintextQueue.Get(plaintext, plaintextLength); - m_ciphertext.resize(ciphertextLength); - m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters); - } - - FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd); - } - FILTER_END_NO_MESSAGE_END; - } - - RandomNumberGenerator &m_rng; - const PK_Encryptor &m_encryptor; - const NameValuePairs &m_parameters; - ByteQueue m_plaintextQueue; - SecByteBlock m_ciphertext; -}; - -BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const -{ - return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters); -} - -unsigned int PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const -{ - std::auto_ptr m(messageAccumulator); - return SignAndRestart(rng, *m, signature, false); -} - -unsigned int PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const -{ - std::auto_ptr m(NewSignatureAccumulator(rng)); - m->Update(message, messageLen); - return SignAndRestart(rng, *m, signature, false); -} - -unsigned int PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, - const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength, byte *signature) const -{ - std::auto_ptr m(NewSignatureAccumulator(rng)); - InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength); - m->Update(nonrecoverableMessage, nonrecoverableMessageLength); - return SignAndRestart(rng, *m, signature, false); -} - -bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const -{ - std::auto_ptr m(messageAccumulator); - return VerifyAndRestart(*m); -} - -bool PK_Verifier::VerifyMessage(const byte *message, unsigned int messageLen, const byte *signature, unsigned int signatureLength) const -{ - std::auto_ptr m(NewVerificationAccumulator()); - InputSignature(*m, signature, signatureLength); - m->Update(message, messageLen); - return VerifyAndRestart(*m); -} - -DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const -{ - std::auto_ptr m(messageAccumulator); - return RecoverAndRestart(recoveredMessage, *m); -} - -DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage, - const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength, - const byte *signature, unsigned int signatureLength) const -{ - std::auto_ptr m(NewVerificationAccumulator()); - InputSignature(*m, signature, signatureLength); - m->Update(nonrecoverableMessage, nonrecoverableMessageLength); - return RecoverAndRestart(recoveredMessage, *m); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_WORDS_H -#define CRYPTOPP_WORDS_H - -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -inline unsigned int CountWords(const word *X, unsigned int N) -{ - while (N && X[N-1]==0) - N--; - return N; -} - -inline void SetWords(word *r, word a, unsigned int n) -{ - for (unsigned int i=0; i> (WORD_BITS-shiftBits); - } - return carry; -} - -inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits) -{ - assert (shiftBits=0; i--) - { - u = r[i]; - r[i] = (u >> shiftBits) | carry; - carry = u << (WORD_BITS-shiftBits); - } - return carry; -} - -inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (unsigned int i=n-1; i>=shiftWords; i--) - r[i] = r[i-shiftWords]; - SetWords(r, 0, shiftWords); - } -} - -inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (unsigned int i=0; i+shiftWords - -NAMESPACE_BEGIN(CryptoPP) - -void xorbuf(byte *buf, const byte *mask, unsigned int count) -{ - if (((size_t)buf | (size_t)mask | count) % WORD_SIZE == 0) - XorWords((word *)buf, (const word *)mask, count/WORD_SIZE); - else - { - for (unsigned int i=0; i0; i/=2) - value ^= value >> i; - return (unsigned int)value&1; -} - -unsigned long Crop(unsigned long value, unsigned int size) -{ - if (size < 8*sizeof(value)) - return (value & ((1L << size) - 1)); - else - return value; -} - -#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) -using std::new_handler; -using std::set_new_handler; -#endif - -void CallNewHandler() -{ - new_handler newHandler = set_new_handler(NULL); - if (newHandler) - set_new_handler(newHandler); - - if (newHandler) - newHandler(); - else - throw std::bad_alloc(); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// nbtheory.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_NBTHEORY_H -#define CRYPTOPP_NBTHEORY_H - -//- #include "integer.h" -//- #include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -// obtain pointer to small prime table and get its size -CRYPTOPP_DLL const word16 * GetPrimeTable(unsigned int &size); - -// ************ primality testing **************** - -CRYPTOPP_DLL bool IsSmallPrime(const Integer &p); - -// returns true if p is divisible by some prime less than bound -// bound not be greater than the largest entry in the prime table -CRYPTOPP_DLL bool TrialDivision(const Integer &p, unsigned bound); - -// returns true if p is NOT divisible by small primes -CRYPTOPP_DLL bool SmallDivisorsTest(const Integer &p); - -CRYPTOPP_DLL bool IsStrongProbablePrime(const Integer &n, const Integer &b); -CRYPTOPP_DLL bool IsStrongLucasProbablePrime(const Integer &n); - -// Rabin-Miller primality test, i.e. repeating the strong probable prime test -// for several rounds with random bases -CRYPTOPP_DLL bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds); - -// primality test, used to generate primes -CRYPTOPP_DLL bool IsPrime(const Integer &p); - -// more reliable than IsPrime(), used to verify primes generated by others -CRYPTOPP_DLL bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1); - -class PrimeSelector -{ -public: - virtual ~PrimeSelector() {}; - const PrimeSelector *GetSelectorPointer() const {return this;} - virtual bool IsAcceptable(const Integer &candidate) const =0; -}; - -// use a fast sieve to find the first probable prime in {x | p<=x<=max and x%mod==equiv} -// returns true iff successful, value of p is undefined if no such prime exists -CRYPTOPP_DLL bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector); - -CRYPTOPP_DLL unsigned int PrimeSearchInterval(const Integer &max); - -CRYPTOPP_DLL AlgorithmParameters, Integer>, Integer> - MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength); - -// ********** other number theoretic functions ************ - -inline Integer GCD(const Integer &a, const Integer &b) - {return Integer::Gcd(a,b);} -inline bool RelativelyPrime(const Integer &a, const Integer &b) - {return Integer::Gcd(a,b) == Integer::One();} -inline Integer LCM(const Integer &a, const Integer &b) - {return a/Integer::Gcd(a,b)*b;} -inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) - {return a.InverseMod(b);} - -// use Chinese Remainder Theorem to calculate x given x mod p and x mod q -CRYPTOPP_DLL Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q); -// use this one if u = inverse of p mod q has been precalculated -CRYPTOPP_DLL Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u); - -// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise -// check a number theory book for what Jacobi symbol means when b is not prime -CRYPTOPP_DLL int Jacobi(const Integer &a, const Integer &b); - -// calculates the Lucas function V_e(p, 1) mod n -CRYPTOPP_DLL Integer Lucas(const Integer &e, const Integer &p, const Integer &n); -// calculates x such that m==Lucas(e, x, p*q), p q primes -CRYPTOPP_DLL Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q); -// use this one if u=inverse of p mod q has been precalculated -CRYPTOPP_DLL Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u); - -inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m) - {return a_exp_b_mod_c(a, e, m);} -// returns x such that a==ModularExponentiation(x, e, p*q), p q primes, -// and e relatively prime to (p-1)*(q-1) -CRYPTOPP_DLL Integer ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q); -// use this one if dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1)) -// and u=inverse of p mod q have been precalculated -CRYPTOPP_DLL Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u); - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// nbtheory.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "nbtheory.h" -//- #include "modarith.h" -//- #include "algparam.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -const word s_lastSmallPrime = 32719; - -struct NewPrimeTable -{ - std::vector * operator()() const - { - const unsigned int maxPrimeTableSize = 3511; - - std::auto_ptr > pPrimeTable(new std::vector); - std::vector &primeTable = *pPrimeTable; - primeTable.reserve(maxPrimeTableSize); - - primeTable.push_back(2); - unsigned int testEntriesEnd = 1; - - for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) - { - unsigned int j; - for (j=1; j &primeTable = Singleton, NewPrimeTable>().Ref(); - size = primeTable.size(); - return &primeTable[0]; -} - -bool IsSmallPrime(const Integer &p) -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - if (p.IsPositive() && p <= primeTable[primeTableSize-1]) - return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong()); - else - return false; -} - -bool TrialDivision(const Integer &p, unsigned bound) -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - assert(primeTable[primeTableSize-1] >= bound); - - unsigned int i; - for (i = 0; primeTable[i]3 && b>1 && b>a; - - Integer z = a_exp_b_mod_c(b, m, n); - if (z==1 || z==nminus1) - return true; - for (unsigned j=1; j3); - - Integer b; - for (unsigned int i=0; i2); - - Integer b=3; - unsigned int i=0; - int j; - - while ((j=Jacobi(b.Squared()-4, n)) == 1) - { - if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square - return false; - ++b; ++b; - } - - if (j==0) - return false; - - Integer n1 = n+1; - unsigned int a; - - // calculate a = largest power of 2 that divides n1 - for (a=0; ; a++) - if (n1.GetBit(a)) - break; - Integer m = n1>>a; - - Integer z = Lucas(m, b, n); - if (z==2 || z==n-2) - return true; - for (i=1; i().Ref()) - return SmallDivisorsTest(p); - else - return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); -} - -bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level) -{ - bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1); - if (level >= 1) - pass = pass && RabinMillerTest(rng, p, 10); - return pass; -} - -unsigned int PrimeSearchInterval(const Integer &max) -{ - return max.BitCount(); -} - -static inline bool FastProbablePrimeTest(const Integer &n) -{ - return IsStrongProbablePrime(n,2); -} - -AlgorithmParameters, Integer>, Integer> - MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength) -{ - if (productBitLength < 16) - throw InvalidArgument("invalid bit length"); - - Integer minP, maxP; - - if (productBitLength%2==0) - { - minP = Integer(182) << (productBitLength/2-8); - maxP = Integer::Power2(productBitLength/2)-1; - } - else - { - minP = Integer::Power2((productBitLength-1)/2); - maxP = Integer(181) << ((productBitLength+1)/2-8); - } - - return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP); -} - -class PrimeSieve -{ -public: - // delta == 1 or -1 means double sieve with p = 2*q + delta - PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0); - bool NextCandidate(Integer &c); - - void DoSieve(); - static void SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv); - - Integer m_first, m_last, m_step; - signed int m_delta; - word m_next; - std::vector m_sieve; -}; - -PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta) - : m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0) -{ - DoSieve(); -} - -bool PrimeSieve::NextCandidate(Integer &c) -{ - m_next = std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(); - if (m_next == m_sieve.size()) - { - m_first += m_sieve.size()*m_step; - if (m_first > m_last) - return false; - else - { - m_next = 0; - DoSieve(); - return NextCandidate(c); - } - } - else - { - c = m_first + m_next*m_step; - ++m_next; - return true; - } -} - -void PrimeSieve::SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv) -{ - if (stepInv) - { - unsigned int sieveSize = sieve.size(); - word j = word((word32(p-(first%p))*stepInv) % p); - // if the first multiple of p is p, skip it - if (first.WordCount() <= 1 && first + step*j == p) - j += p; - for (; j < sieveSize; j += p) - sieve[j] = true; - } -} - -void PrimeSieve::DoSieve() -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - const unsigned int maxSieveSize = 32768; - unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong(); - - m_sieve.clear(); - m_sieve.resize(sieveSize, false); - - if (m_delta == 0) - { - for (unsigned int i = 0; i < primeTableSize; ++i) - SieveSingle(m_sieve, primeTable[i], m_first, m_step, m_step.InverseMod(primeTable[i])); - } - else - { - assert(m_step%2==0); - Integer qFirst = (m_first-m_delta) >> 1; - Integer halfStep = m_step >> 1; - for (unsigned int i = 0; i < primeTableSize; ++i) - { - word16 p = primeTable[i]; - word16 stepInv = m_step.InverseMod(p); - SieveSingle(m_sieve, p, m_first, m_step, stepInv); - - word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p; - SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv); - } - } -} - -bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) -{ - assert(!equiv.IsNegative() && equiv < mod); - - Integer gcd = GCD(equiv, mod); - if (gcd != Integer::One()) - { - // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) - if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) - { - p = gcd; - return true; - } - else - return false; - } - - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - if (p <= primeTable[primeTableSize-1]) - { - const word16 *pItr; - - --p; - if (p.IsPositive()) - pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); - else - pItr = primeTable; - - while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) - ++pItr; - - if (pItr < primeTable+primeTableSize) - { - p = *pItr; - return p <= max; - } - - p = primeTable[primeTableSize-1]+1; - } - - assert(p > primeTable[primeTableSize-1]); - - if (mod.IsOdd()) - return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); - - p += (equiv-p)%mod; - - if (p>max) - return false; - - PrimeSieve sieve(p, max, mod); - - while (sieve.NextCandidate(p)) - { - if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) - return true; - } - - return false; -} - -Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u) -{ - // isn't operator overloading great? - return p * (u * (xq-xp) % q) + xp; -} - -Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q) -{ - return CRT(xp, p, xq, q, EuclideanMultiplicativeInverse(p, q)); -} - -Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, - const Integer &p, const Integer &q, const Integer &u) -{ - Integer p2 = ModularExponentiation((a % p), dp, p); - Integer q2 = ModularExponentiation((a % q), dq, q); - return CRT(p2, p, q2, q, u); -} - -Integer ModularRoot(const Integer &a, const Integer &e, - const Integer &p, const Integer &q) -{ - Integer dp = EuclideanMultiplicativeInverse(e, p-1); - Integer dq = EuclideanMultiplicativeInverse(e, q-1); - Integer u = EuclideanMultiplicativeInverse(p, q); - assert(!!dp && !!dq && !!u); - return ModularRoot(a, dp, dq, p, q, u); -} - -int Jacobi(const Integer &aIn, const Integer &bIn) -{ - assert(bIn.IsOdd()); - - Integer b = bIn, a = aIn%bIn; - int result = 1; - - while (!!a) - { - unsigned i=0; - while (a.GetBit(i)==0) - i++; - a>>=i; - - if (i%2==1 && (b%8==3 || b%8==5)) - result = -result; - - if (a%4==3 && b%4==3) - result = -result; - - std::swap(a, b); - a %= b; - } - - return (b==1) ? result : 0; -} - -Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n) -{ - unsigned i = e.BitCount(); - if (i==0) - return Integer::Two(); - - MontgomeryRepresentation m(n); - Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two()); - Integer v=p, v1=m.Subtract(m.Square(p), two); - - i--; - while (i--) - { - if (e.GetBit(i)) - { - // v = (v*v1 - p) % m; - v = m.Subtract(m.Multiply(v,v1), p); - // v1 = (v1*v1 - 2) % m; - v1 = m.Subtract(m.Square(v1), two); - } - else - { - // v1 = (v*v1 - p) % m; - v1 = m.Subtract(m.Multiply(v,v1), p); - // v = (v*v - 2) % m; - v = m.Subtract(m.Square(v), two); - } - } - return m.ConvertOut(v); -} - -Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) -{ - Integer d = (m*m-4); - Integer p2 = p-Jacobi(d,p); - Integer q2 = q-Jacobi(d,q); - return CRT(Lucas(EuclideanMultiplicativeInverse(e,p2), m, p), p, Lucas(EuclideanMultiplicativeInverse(e,q2), m, q), q, u); -} - -Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q) -{ - return InverseLucas(e, m, p, q, EuclideanMultiplicativeInverse(p, q)); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_OIDS_H -#define CRYPTOPP_OIDS_H - -// crypto-related ASN.1 object identifiers - -//- #include "asn.h" - -NAMESPACE_BEGIN(CryptoPP) - -NAMESPACE_BEGIN(ASN1) - -#define DEFINE_OID(value, name) inline OID name() {return value;} - -DEFINE_OID(1, iso) - DEFINE_OID(iso()+2, member_body) - DEFINE_OID(member_body()+840, iso_us) - DEFINE_OID(iso_us()+10040, ansi_x9_57) - DEFINE_OID(ansi_x9_57()+4+1, id_dsa) - DEFINE_OID(iso_us()+10045, ansi_x9_62) - DEFINE_OID(ansi_x9_62()+1, id_fieldType) - DEFINE_OID(id_fieldType()+1, prime_field) - DEFINE_OID(id_fieldType()+2, characteristic_two_field) - DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis) - DEFINE_OID(id_characteristic_two_basis()+1, gnBasis) - DEFINE_OID(id_characteristic_two_basis()+2, tpBasis) - DEFINE_OID(id_characteristic_two_basis()+3, ppBasis) - DEFINE_OID(ansi_x9_62()+2, id_publicKeyType) - DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey) - DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves) - DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime) - DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1) - DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1) - DEFINE_OID(iso_us()+113549, rsadsi) - DEFINE_OID(rsadsi()+1, pkcs) - DEFINE_OID(pkcs()+1, pkcs_1) - DEFINE_OID(pkcs_1()+1, rsaEncryption) - DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm) - DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2) - DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5) - DEFINE_OID(iso()+3, identified_organization) - DEFINE_OID(identified_organization()+14, oiw) - DEFINE_OID(oiw()+14, oiw_secsig) - DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms) - DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1) - DEFINE_OID(identified_organization()+36, teletrust) - DEFINE_OID(teletrust()+3+2+1, id_ripemd160) - DEFINE_OID(identified_organization()+132, certicom) - DEFINE_OID(certicom()+0, certicom_ellipticCurve) - // these are sorted by curve type and then by OID - // first curves based on GF(p) - DEFINE_OID(certicom_ellipticCurve()+6, secp112r1) - DEFINE_OID(certicom_ellipticCurve()+7, secp112r2) - DEFINE_OID(certicom_ellipticCurve()+8, secp160r1) - DEFINE_OID(certicom_ellipticCurve()+9, secp160k1) - DEFINE_OID(certicom_ellipticCurve()+10, secp256k1) - DEFINE_OID(certicom_ellipticCurve()+28, secp128r1) - DEFINE_OID(certicom_ellipticCurve()+29, secp128r2) - DEFINE_OID(certicom_ellipticCurve()+30, secp160r2) - DEFINE_OID(certicom_ellipticCurve()+31, secp192k1) - DEFINE_OID(certicom_ellipticCurve()+32, secp224k1) - DEFINE_OID(certicom_ellipticCurve()+33, secp224r1) - DEFINE_OID(certicom_ellipticCurve()+34, secp384r1) - DEFINE_OID(certicom_ellipticCurve()+35, secp521r1) - // then curves based on GF(2^n) - DEFINE_OID(certicom_ellipticCurve()+1, sect163k1) - DEFINE_OID(certicom_ellipticCurve()+2, sect163r1) - DEFINE_OID(certicom_ellipticCurve()+3, sect239k1) - DEFINE_OID(certicom_ellipticCurve()+4, sect113r1) - DEFINE_OID(certicom_ellipticCurve()+5, sect113r2) - DEFINE_OID(certicom_ellipticCurve()+15, sect163r2) - DEFINE_OID(certicom_ellipticCurve()+16, sect283k1) - DEFINE_OID(certicom_ellipticCurve()+17, sect283r1) - DEFINE_OID(certicom_ellipticCurve()+22, sect131r1) - DEFINE_OID(certicom_ellipticCurve()+23, sect131r2) - DEFINE_OID(certicom_ellipticCurve()+24, sect193r1) - DEFINE_OID(certicom_ellipticCurve()+25, sect193r2) - DEFINE_OID(certicom_ellipticCurve()+26, sect233k1) - DEFINE_OID(certicom_ellipticCurve()+27, sect233r1) - DEFINE_OID(certicom_ellipticCurve()+36, sect409k1) - DEFINE_OID(certicom_ellipticCurve()+37, sect409r1) - DEFINE_OID(certicom_ellipticCurve()+38, sect571k1) - DEFINE_OID(certicom_ellipticCurve()+39, sect571r1) -DEFINE_OID(2, joint_iso_ccitt) - DEFINE_OID(joint_iso_ccitt()+16, country) - DEFINE_OID(country()+840, joint_iso_ccitt_us) - DEFINE_OID(joint_iso_ccitt_us()+1, us_organization) - DEFINE_OID(us_organization()+101, us_gov) - DEFINE_OID(us_gov()+3, csor) - DEFINE_OID(csor()+4, nistalgorithms) - DEFINE_OID(nistalgorithms()+1, aes) - DEFINE_OID(aes()+1, id_aes128_ECB) - DEFINE_OID(aes()+2, id_aes128_cbc) - DEFINE_OID(aes()+3, id_aes128_ofb) - DEFINE_OID(aes()+4, id_aes128_cfb) - DEFINE_OID(aes()+21, id_aes192_ECB) - DEFINE_OID(aes()+22, id_aes192_cbc) - DEFINE_OID(aes()+23, id_aes192_ofb) - DEFINE_OID(aes()+24, id_aes192_cfb) - DEFINE_OID(aes()+41, id_aes256_ECB) - DEFINE_OID(aes()+42, id_aes256_cbc) - DEFINE_OID(aes()+43, id_aes256_ofb) - DEFINE_OID(aes()+44, id_aes256_cfb) - DEFINE_OID(nistalgorithms()+2, nist_hashalgs) - DEFINE_OID(nist_hashalgs()+1, id_sha256) - DEFINE_OID(nist_hashalgs()+2, id_sha384) - DEFINE_OID(nist_hashalgs()+3, id_sha512) - -NAMESPACE_END - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// integer.cpp - written and placed in the public domain by Wei Dai -// contains public domain code contributed by Alister Lee and Leonard Janke - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "integer.h" -//- #include "modarith.h" -//- #include "nbtheory.h" -//- #include "asn.h" -//- #include "oids.h" -//- #include "words.h" -//- #include "algparam.h" -//- #include "pubkey.h" // for P1363_KDF2 -//- #include "sha.h" - -#include - -#ifdef SSE2_INTRINSICS_AVAILABLE - #ifdef __GNUC__ - #include - #include - #include - #ifdef CRYPTOPP_MEMALIGN_AVAILABLE - #include - #else - #include - #endif - #else - #include - #endif -#elif defined(_MSC_VER) && defined(_M_IX86) - #pragma message("You do not seem to have the Visual C++ Processor Pack installed, so use of SSE2 intrinsics will be disabled.") -#elif defined(__GNUC__) && defined(__i386__) - #warning "You do not have GCC 3.3 or later, or did not specify -msse2 compiler option, so use of SSE2 intrinsics will be disabled." -#endif - -NAMESPACE_BEGIN(CryptoPP) - -bool FunctionAssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt) -{ - if (valueType != typeid(Integer)) - return false; - *reinterpret_cast(pInteger) = *reinterpret_cast(pInt); - return true; -} - -static const char s_RunAtStartup = (AssignIntToInteger = FunctionAssignIntToInteger, 0); - -#ifdef SSE2_INTRINSICS_AVAILABLE -template -CPP_TYPENAME AllocatorBase::pointer AlignedAllocator::allocate(size_type n, const void *) -{ - this->CheckSize(n); - if (n == 0) - return NULL; - if (n >= 4) - { - void *p; - #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE - while (!(p = _mm_malloc(sizeof(T)*n, 16))) - #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE) - while (!(p = memalign(16, sizeof(T)*n))) - #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16) - while (!(p = malloc(sizeof(T)*n))) - #else - while (!(p = (byte *)malloc(sizeof(T)*n + 8))) // assume malloc alignment is at least 8 - #endif - CallNewHandler(); - - #ifdef CRYPTOPP_NO_ALIGNED_ALLOC - assert(m_pBlock == NULL); - m_pBlock = p; - if (!IsAlignedOn(p, 16)) - { - assert(IsAlignedOn(p, 8)); - p = (byte *)p + 8; - } - #endif - - assert(IsAlignedOn(p, 16)); - return (T*)p; - } - return new T[n]; -} - -template -void AlignedAllocator::deallocate(void *p, size_type n) -{ - memset(p, 0, n*sizeof(T)); - if (n >= 4) - { - #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE - _mm_free(p); - #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC) - assert(m_pBlock == p || (byte *)m_pBlock+8 == p); - free(m_pBlock); - m_pBlock = NULL; - #else - free(p); - #endif - } - else - delete [] (T *)p; -} -#endif - -static int Compare(const word *A, const word *B, unsigned int N) -{ - while (N--) - if (A[N] > B[N]) - return 1; - else if (A[N] < B[N]) - return -1; - - return 0; -} - -static word Increment(word *A, unsigned int N, word B=1) -{ - assert(N); - word t = A[0]; - A[0] = t+B; - if (A[0] >= t) - return 0; - for (unsigned i=1; i> 64; - r.m_halfs.low = tmp; - #elif defined(_M_IX86) - // for testing - word64 t = (word64)a * b; - r.m_halfs.high = ((word32 *)(&t))[1]; - r.m_halfs.low = (word32)t; - #else - #error can not implement DWord - #endif - return r; - } - - static DWord MultiplyAndAdd(word a, word b, word c) - { - DWord r = Multiply(a, b); - return r += c; - } - - DWord & operator+=(word a) - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - m_whole = m_whole + a; - #else - m_halfs.low += a; - m_halfs.high += (m_halfs.low < a); - #endif - return *this; - } - - DWord operator+(word a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole + a; - #else - r.m_halfs.low = m_halfs.low + a; - r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a); - #endif - return r; - } - - DWord operator-(DWord a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole - a.m_whole; - #else - r.m_halfs.low = m_halfs.low - a.m_halfs.low; - r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low); - #endif - return r; - } - - DWord operator-(word a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole - a; - #else - r.m_halfs.low = m_halfs.low - a; - r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low); - #endif - return r; - } - - // returns quotient, which must fit in a word - word operator/(word divisor); - - word operator%(word a); - - bool operator!() const - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return !m_whole; - #else - return !m_halfs.high && !m_halfs.low; - #endif - } - - word GetLowHalf() const {return m_halfs.low;} - word GetHighHalf() const {return m_halfs.high;} - word GetHighHalfAsBorrow() const {return 0-m_halfs.high;} - -private: - union - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - dword m_whole; - #endif - struct - { - #ifdef IS_LITTLE_ENDIAN - word low; - word high; - #else - word high; - word low; - #endif - } m_halfs; - }; -}; - -class Word -{ -public: - Word() {} - - Word(word value) - { - m_whole = value; - } - - Word(hword low, hword high) - { - m_whole = low | (word(high) << (WORD_BITS/2)); - } - - static Word Multiply(hword a, hword b) - { - Word r; - r.m_whole = (word)a * b; - return r; - } - - Word operator-(Word a) - { - Word r; - r.m_whole = m_whole - a.m_whole; - return r; - } - - Word operator-(hword a) - { - Word r; - r.m_whole = m_whole - a; - return r; - } - - // returns quotient, which must fit in a word - hword operator/(hword divisor) - { - return hword(m_whole / divisor); - } - - bool operator!() const - { - return !m_whole; - } - - word GetWhole() const {return m_whole;} - hword GetLowHalf() const {return hword(m_whole);} - hword GetHighHalf() const {return hword(m_whole>>(WORD_BITS/2));} - hword GetHighHalfAsBorrow() const {return 0-hword(m_whole>>(WORD_BITS/2));} - -private: - word m_whole; -}; - -// do a 3 word by 2 word divide, returns quotient and leaves remainder in A -template -S DivideThreeWordsByTwo(S *A, S B0, S B1, D* /* dummy */ = NULL) -{ - // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S - assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); - - // estimate the quotient: do a 2 S by 1 S divide - S Q; - if (S(B1+1) == 0) - Q = A[2]; - else - Q = D(A[1], A[2]) / S(B1+1); - - // now subtract Q*B from A - D p = D::Multiply(B0, Q); - D u = (D) A[0] - p.GetLowHalf(); - A[0] = u.GetLowHalf(); - u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - - // Q <= actual quotient, so fix it - while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) - { - u = (D) A[0] - B0; - A[0] = u.GetLowHalf(); - u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - Q++; - assert(Q); // shouldn't overflow - } - - return Q; -} - -// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 -template -inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) -{ - if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) - return D(Ah.GetLowHalf(), Ah.GetHighHalf()); - else - { - S Q[2]; - T[0] = Al.GetLowHalf(); - T[1] = Al.GetHighHalf(); - T[2] = Ah.GetLowHalf(); - T[3] = Ah.GetHighHalf(); - Q[1] = DivideThreeWordsByTwo(T+1, B.GetLowHalf(), B.GetHighHalf()); - Q[0] = DivideThreeWordsByTwo(T, B.GetLowHalf(), B.GetHighHalf()); - return D(Q[0], Q[1]); - } -} - -// returns quotient, which must fit in a word -inline word DWord::operator/(word a) -{ - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return word(m_whole / a); - #else - hword r[4]; - return DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a).GetWhole(); - #endif -} - -inline word DWord::operator%(word a) -{ - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return word(m_whole % a); - #else - if (a < (word(1) << (WORD_BITS/2))) - { - hword h = hword(a); - word r = m_halfs.high % h; - r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; - return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h); - } - else - { - hword r[4]; - DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a); - return Word(r[0], r[1]).GetWhole(); - } - #endif -} - -// ******************************************************** - -class Portable -{ -public: - static word Add(word *C, const word *A, const word *B, unsigned int N); - static word Subtract(word *C, const word *A, const word *B, unsigned int N); - - static inline void Multiply2(word *C, const word *A, const word *B); - static inline word Multiply2Add(word *C, const word *A, const word *B); - static void Multiply4(word *C, const word *A, const word *B); - static void Multiply8(word *C, const word *A, const word *B); - static inline unsigned int MultiplyRecursionLimit() {return 8;} - - static inline void Multiply2Bottom(word *C, const word *A, const word *B); - static void Multiply4Bottom(word *C, const word *A, const word *B); - static void Multiply8Bottom(word *C, const word *A, const word *B); - static inline unsigned int MultiplyBottomRecursionLimit() {return 8;} - - static void Square2(word *R, const word *A); - static void Square4(word *R, const word *A); - static void Square8(word* /* R */, const word* /* A */) {assert(false);} - static inline unsigned int SquareRecursionLimit() {return 4;} -}; - -word Portable::Add(word *C, const word *A, const word *B, unsigned int N) -{ - assert (N%2 == 0); - - DWord u(0, 0); - for (unsigned int i = 0; i < N; i+=2) - { - u = DWord(A[i]) + B[i] + u.GetHighHalf(); - C[i] = u.GetLowHalf(); - u = DWord(A[i+1]) + B[i+1] + u.GetHighHalf(); - C[i+1] = u.GetLowHalf(); - } - return u.GetHighHalf(); -} - -word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N) -{ - assert (N%2 == 0); - - DWord u(0, 0); - for (unsigned int i = 0; i < N; i+=2) - { - u = (DWord) A[i] - B[i] - u.GetHighHalfAsBorrow(); - C[i] = u.GetLowHalf(); - u = (DWord) A[i+1] - B[i+1] - u.GetHighHalfAsBorrow(); - C[i+1] = u.GetLowHalf(); - } - return 0-u.GetHighHalf(); -} - -void Portable::Multiply2(word *C, const word *A, const word *B) -{ - // this segment is the branchless equivalent of above - word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]}; - unsigned int ai = A[1] < A[0]; - unsigned int bi = B[0] < B[1]; - unsigned int di = ai & bi; - DWord d = DWord::Multiply(D[di], D[di+2]); - D[1] = D[3] = 0; - unsigned int si = ai + !bi; - word s = D[si]; - - DWord A0B0 = DWord::Multiply(A[0], B[0]); - C[0] = A0B0.GetLowHalf(); - - DWord A1B1 = DWord::Multiply(A[1], B[1]); - DWord t = (DWord) A0B0.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() + A1B1.GetLowHalf(); - C[1] = t.GetLowHalf(); - - t = A1B1 + t.GetHighHalf() + A0B0.GetHighHalf() + d.GetHighHalf() + A1B1.GetHighHalf() - s; - C[2] = t.GetLowHalf(); - C[3] = t.GetHighHalf(); -} - -inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B) -{ - DWord t = DWord::Multiply(A[0], B[0]); - C[0] = t.GetLowHalf(); - C[1] = t.GetHighHalf() + A[0]*B[1] + A[1]*B[0]; -} - -word Portable::Multiply2Add(word *C, const word *A, const word *B) -{ - word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]}; - unsigned int ai = A[1] < A[0]; - unsigned int bi = B[0] < B[1]; - unsigned int di = ai & bi; - DWord d = DWord::Multiply(D[di], D[di+2]); - D[1] = D[3] = 0; - unsigned int si = ai + !bi; - word s = D[si]; - - DWord A0B0 = DWord::Multiply(A[0], B[0]); - DWord t = A0B0 + C[0]; - C[0] = t.GetLowHalf(); - - DWord A1B1 = DWord::Multiply(A[1], B[1]); - t = (DWord) t.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() + A1B1.GetLowHalf() + C[1]; - C[1] = t.GetLowHalf(); - - t = (DWord) t.GetHighHalf() + A1B1.GetLowHalf() + A0B0.GetHighHalf() + d.GetHighHalf() + A1B1.GetHighHalf() - s + C[2]; - C[2] = t.GetLowHalf(); - - t = (DWord) t.GetHighHalf() + A1B1.GetHighHalf() + C[3]; - C[3] = t.GetLowHalf(); - return t.GetHighHalf(); -} - -#define MulAcc(x, y) \ - p = DWord::MultiplyAndAdd(A[x], B[y], c); \ - c = p.GetLowHalf(); \ - p = (DWord) d + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e += p.GetHighHalf(); - -#define SaveMulAcc(s, x, y) \ - R[s] = c; \ - p = DWord::MultiplyAndAdd(A[x], B[y], d); \ - c = p.GetLowHalf(); \ - p = (DWord) e + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e = p.GetHighHalf(); - -#define SquAcc(x, y) \ - q = DWord::Multiply(A[x], A[y]); \ - p = q + c; \ - c = p.GetLowHalf(); \ - p = (DWord) d + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e += p.GetHighHalf(); \ - p = q + c; \ - c = p.GetLowHalf(); \ - p = (DWord) d + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e += p.GetHighHalf(); - -#define SaveSquAcc(s, x, y) \ - R[s] = c; \ - q = DWord::Multiply(A[x], A[y]); \ - p = q + d; \ - c = p.GetLowHalf(); \ - p = (DWord) e + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e = p.GetHighHalf(); \ - p = q + c; \ - c = p.GetLowHalf(); \ - p = (DWord) d + p.GetHighHalf(); \ - d = p.GetLowHalf(); \ - e += p.GetHighHalf(); - -void Portable::Multiply4(word *R, const word *A, const word *B) -{ - DWord p; - word c, d, e; - - p = DWord::Multiply(A[0], B[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - MulAcc(0, 1); - MulAcc(1, 0); - - SaveMulAcc(1, 2, 0); - MulAcc(1, 1); - MulAcc(0, 2); - - SaveMulAcc(2, 0, 3); - MulAcc(1, 2); - MulAcc(2, 1); - MulAcc(3, 0); - - SaveMulAcc(3, 3, 1); - MulAcc(2, 2); - MulAcc(1, 3); - - SaveMulAcc(4, 2, 3); - MulAcc(3, 2); - - R[5] = c; - p = DWord::MultiplyAndAdd(A[3], B[3], d); - R[6] = p.GetLowHalf(); - R[7] = e + p.GetHighHalf(); -} - -void Portable::Square2(word *R, const word *A) -{ - DWord p, q; - word c, d, e; - - p = DWord::Multiply(A[0], A[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - SquAcc(0, 1); - - R[1] = c; - p = DWord::MultiplyAndAdd(A[1], A[1], d); - R[2] = p.GetLowHalf(); - R[3] = e + p.GetHighHalf(); -} - -void Portable::Square4(word *R, const word *A) -{ -#ifdef _MSC_VER - // VC60 workaround: MSVC 6.0 has an optimization bug that makes - // (dword)A*B where either A or B has been cast to a dword before - // very expensive. Revisit this function when this - // bug is fixed. - Multiply4(R, A, A); -#else - const word *B = A; - DWord p, q; - word c, d, e; - - p = DWord::Multiply(A[0], A[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - SquAcc(0, 1); - - SaveSquAcc(1, 2, 0); - MulAcc(1, 1); - - SaveSquAcc(2, 0, 3); - SquAcc(1, 2); - - SaveSquAcc(3, 3, 1); - MulAcc(2, 2); - - SaveSquAcc(4, 2, 3); - - R[5] = c; - p = DWord::MultiplyAndAdd(A[3], A[3], d); - R[6] = p.GetLowHalf(); - R[7] = e + p.GetHighHalf(); -#endif -} - -void Portable::Multiply8(word *R, const word *A, const word *B) -{ - DWord p; - word c, d, e; - - p = DWord::Multiply(A[0], B[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - MulAcc(0, 1); - MulAcc(1, 0); - - SaveMulAcc(1, 2, 0); - MulAcc(1, 1); - MulAcc(0, 2); - - SaveMulAcc(2, 0, 3); - MulAcc(1, 2); - MulAcc(2, 1); - MulAcc(3, 0); - - SaveMulAcc(3, 0, 4); - MulAcc(1, 3); - MulAcc(2, 2); - MulAcc(3, 1); - MulAcc(4, 0); - - SaveMulAcc(4, 0, 5); - MulAcc(1, 4); - MulAcc(2, 3); - MulAcc(3, 2); - MulAcc(4, 1); - MulAcc(5, 0); - - SaveMulAcc(5, 0, 6); - MulAcc(1, 5); - MulAcc(2, 4); - MulAcc(3, 3); - MulAcc(4, 2); - MulAcc(5, 1); - MulAcc(6, 0); - - SaveMulAcc(6, 0, 7); - MulAcc(1, 6); - MulAcc(2, 5); - MulAcc(3, 4); - MulAcc(4, 3); - MulAcc(5, 2); - MulAcc(6, 1); - MulAcc(7, 0); - - SaveMulAcc(7, 1, 7); - MulAcc(2, 6); - MulAcc(3, 5); - MulAcc(4, 4); - MulAcc(5, 3); - MulAcc(6, 2); - MulAcc(7, 1); - - SaveMulAcc(8, 2, 7); - MulAcc(3, 6); - MulAcc(4, 5); - MulAcc(5, 4); - MulAcc(6, 3); - MulAcc(7, 2); - - SaveMulAcc(9, 3, 7); - MulAcc(4, 6); - MulAcc(5, 5); - MulAcc(6, 4); - MulAcc(7, 3); - - SaveMulAcc(10, 4, 7); - MulAcc(5, 6); - MulAcc(6, 5); - MulAcc(7, 4); - - SaveMulAcc(11, 5, 7); - MulAcc(6, 6); - MulAcc(7, 5); - - SaveMulAcc(12, 6, 7); - MulAcc(7, 6); - - R[13] = c; - p = DWord::MultiplyAndAdd(A[7], B[7], d); - R[14] = p.GetLowHalf(); - R[15] = e + p.GetHighHalf(); -} - -void Portable::Multiply4Bottom(word *R, const word *A, const word *B) -{ - DWord p; - word c, d, e; - - p = DWord::Multiply(A[0], B[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - MulAcc(0, 1); - MulAcc(1, 0); - - SaveMulAcc(1, 2, 0); - MulAcc(1, 1); - MulAcc(0, 2); - - R[2] = c; - R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0]; -} - -void Portable::Multiply8Bottom(word *R, const word *A, const word *B) -{ - DWord p; - word c, d, e; - - p = DWord::Multiply(A[0], B[0]); - R[0] = p.GetLowHalf(); - c = p.GetHighHalf(); - d = e = 0; - - MulAcc(0, 1); - MulAcc(1, 0); - - SaveMulAcc(1, 2, 0); - MulAcc(1, 1); - MulAcc(0, 2); - - SaveMulAcc(2, 0, 3); - MulAcc(1, 2); - MulAcc(2, 1); - MulAcc(3, 0); - - SaveMulAcc(3, 0, 4); - MulAcc(1, 3); - MulAcc(2, 2); - MulAcc(3, 1); - MulAcc(4, 0); - - SaveMulAcc(4, 0, 5); - MulAcc(1, 4); - MulAcc(2, 3); - MulAcc(3, 2); - MulAcc(4, 1); - MulAcc(5, 0); - - SaveMulAcc(5, 0, 6); - MulAcc(1, 5); - MulAcc(2, 4); - MulAcc(3, 3); - MulAcc(4, 2); - MulAcc(5, 1); - MulAcc(6, 0); - - R[6] = c; - R[7] = d + A[0] * B[7] + A[1] * B[6] + A[2] * B[5] + A[3] * B[4] + - A[4] * B[3] + A[5] * B[2] + A[6] * B[1] + A[7] * B[0]; -} - -#undef MulAcc -#undef SaveMulAcc -#undef SquAcc -#undef SaveSquAcc - -#ifdef CRYPTOPP_X86ASM_AVAILABLE - -// ************** x86 feature detection *************** - -static void CpuId(word32 input, word32 *output) -{ -#ifdef __GNUC__ - __asm__ - ( - // save ebx in case -fPIC is being used - "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" - : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3]) - : "a" (input) - ); -#else - __asm - { - mov eax, input - cpuid - mov edi, output - mov [edi], eax - mov [edi+4], ebx - mov [edi+8], ecx - mov [edi+12], edx - } -#endif -} - -static bool IsP4() -{ - word32 cpuid[4]; - - CpuId(0, cpuid); - std::swap(cpuid[2], cpuid[3]); - if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) - return false; - - CpuId(1, cpuid); - return ((cpuid[0] >> 8) & 0xf) == 0xf; - -} - - -// ************** Pentium/P4 optimizations *************** - -class PentiumOptimized : public Portable -{ -public: - static word CRYPTOPP_CDECL Add(word *C, const word *A, const word *B, unsigned int N); - static word CRYPTOPP_CDECL Subtract(word *C, const word *A, const word *B, unsigned int N); - static void CRYPTOPP_CDECL Multiply4(word *C, const word *A, const word *B); - static void CRYPTOPP_CDECL Multiply8(word *C, const word *A, const word *B); - static void CRYPTOPP_CDECL Multiply8Bottom(word *C, const word *A, const word *B); -}; - -class P4Optimized -{ -public: - static word CRYPTOPP_CDECL Add(word *C, const word *A, const word *B, unsigned int N); - static word CRYPTOPP_CDECL Subtract(word *C, const word *A, const word *B, unsigned int N); -}; - -typedef word (CRYPTOPP_CDECL * PAddSub)(word *C, const word *A, const word *B, unsigned int N); -typedef void (CRYPTOPP_CDECL * PMul)(word *C, const word *A, const word *B); - -static PAddSub s_pAdd, s_pSub; -#ifdef SSE2_INTRINSICS_AVAILABLE -static PMul s_pMul4, s_pMul8, s_pMul8B; -#endif - -static void SetPentiumFunctionPointers() -{ - if (IsP4()) - { - s_pAdd = &P4Optimized::Add; - s_pSub = &P4Optimized::Subtract; - } - else - { - s_pAdd = &PentiumOptimized::Add; - s_pSub = &PentiumOptimized::Subtract; - } - -#ifdef SSE2_INTRINSICS_AVAILABLE - s_pMul4 = &PentiumOptimized::Multiply4; - s_pMul8 = &PentiumOptimized::Multiply8; - s_pMul8B = &PentiumOptimized::Multiply8Bottom; -#endif -} - -static const char s_RunAtStartupSetPentiumFunctionPointers = (SetPentiumFunctionPointers(), 0); - -class LowLevel : public PentiumOptimized -{ -public: - inline static word Add(word *C, const word *A, const word *B, unsigned int N) - {return s_pAdd(C, A, B, N);} - inline static word Subtract(word *C, const word *A, const word *B, unsigned int N) - {return s_pSub(C, A, B, N);} - inline static void Square4(word *R, const word *A) - {Multiply4(R, A, A);} -#ifdef SSE2_INTRINSICS_AVAILABLE - inline static void Multiply4(word *C, const word *A, const word *B) - {s_pMul4(C, A, B);} - inline static void Multiply8(word *C, const word *A, const word *B) - {s_pMul8(C, A, B);} - inline static void Multiply8Bottom(word *C, const word *A, const word *B) - {s_pMul8B(C, A, B);} -#endif -}; - -// use some tricks to share assembly code between MSVC and GCC -#ifdef _MSC_VER - #define CRYPTOPP_NAKED __declspec(naked) - #define AS1(x) __asm x - #define AS2(x, y) __asm x, y - #define AddPrologue \ - __asm push ebp \ - __asm push ebx \ - __asm push esi \ - __asm push edi \ - __asm mov ecx, [esp+20] \ - __asm mov edx, [esp+24] \ - __asm mov ebx, [esp+28] \ - __asm mov esi, [esp+32] - #define AddEpilogue \ - __asm pop edi \ - __asm pop esi \ - __asm pop ebx \ - __asm pop ebp \ - __asm ret - #define MulPrologue \ - __asm push ebp \ - __asm push ebx \ - __asm push esi \ - __asm push edi \ - __asm mov ecx, [esp+28] \ - __asm mov esi, [esp+24] \ - __asm push [esp+20] - #define MulEpilogue \ - __asm add esp, 4 \ - __asm pop edi \ - __asm pop esi \ - __asm pop ebx \ - __asm pop ebp \ - __asm ret -#else - #define CRYPTOPP_NAKED - #define AS1(x) #x ";" - #define AS2(x, y) #x ", " #y ";" - #define AddPrologue \ - __asm__ __volatile__ \ - ( \ - "push %%ebx;" /* save this manually, in case of -fPIC */ \ - "mov %2, %%ebx;" \ - ".intel_syntax noprefix;" \ - "push ebp;" - #define AddEpilogue \ - "pop ebp;" \ - ".att_syntax prefix;" \ - "pop %%ebx;" \ - : \ - : "c" (C), "d" (A), "m" (B), "S" (N) \ - : "%edi", "memory", "cc" \ - ); - #define MulPrologue \ - __asm__ __volatile__ \ - ( \ - "push %%ebx;" /* save this manually, in case of -fPIC */ \ - "push %%ebp;" \ - "push %0;" \ - ".intel_syntax noprefix;" - #define MulEpilogue \ - "add esp, 4;" \ - "pop ebp;" \ - "pop ebx;" \ - ".att_syntax prefix;" \ - : \ - : "rm" (Z), "S" (X), "c" (Y) \ - : "%eax", "%edx", "%edi", "memory", "cc" \ - ); -#endif - -CRYPTOPP_NAKED word PentiumOptimized::Add(word *C, const word *A, const word *B, unsigned int N) -{ - AddPrologue - - // now: ebx = B, ecx = C, edx = A, esi = N - AS2( sub ecx, edx) // hold the distance between C & A so we can add this to A to get C - AS2( xor eax, eax) // clear eax - - AS2( sub eax, esi) // eax is a negative index from end of B - AS2( lea ebx, [ebx+4*esi]) // ebx is end of B - - AS2( sar eax, 1) // unit of eax is now dwords; this also clears the carry flag - AS1( jz loopendAdd) // if no dwords then nothing to do - - AS1(loopstartAdd:) - AS2( mov esi,[edx]) // load lower word of A - AS2( mov ebp,[edx+4]) // load higher word of A - - AS2( mov edi,[ebx+8*eax]) // load lower word of B - AS2( lea edx,[edx+8]) // advance A and C - - AS2( adc esi,edi) // add lower words - AS2( mov edi,[ebx+8*eax+4]) // load higher word of B - - AS2( adc ebp,edi) // add higher words - AS1( inc eax) // advance B - - AS2( mov [edx+ecx-8],esi) // store lower word result - AS2( mov [edx+ecx-4],ebp) // store higher word result - - AS1( jnz loopstartAdd) // loop until eax overflows and becomes zero - - AS1(loopendAdd:) - AS2( adc eax, 0) // store carry into eax (return result register) - - AddEpilogue - - // Just to get rid of warnings - // return 0; -} - -CRYPTOPP_NAKED word PentiumOptimized::Subtract(word *C, const word *A, const word *B, unsigned int N) -{ - AddPrologue - - // now: ebx = B, ecx = C, edx = A, esi = N - AS2( sub ecx, edx) // hold the distance between C & A so we can add this to A to get C - AS2( xor eax, eax) // clear eax - - AS2( sub eax, esi) // eax is a negative index from end of B - AS2( lea ebx, [ebx+4*esi]) // ebx is end of B - - AS2( sar eax, 1) // unit of eax is now dwords; this also clears the carry flag - AS1( jz loopendSub) // if no dwords then nothing to do - - AS1(loopstartSub:) - AS2( mov esi,[edx]) // load lower word of A - AS2( mov ebp,[edx+4]) // load higher word of A - - AS2( mov edi,[ebx+8*eax]) // load lower word of B - AS2( lea edx,[edx+8]) // advance A and C - - AS2( sbb esi,edi) // subtract lower words - AS2( mov edi,[ebx+8*eax+4]) // load higher word of B - - AS2( sbb ebp,edi) // subtract higher words - AS1( inc eax) // advance B - - AS2( mov [edx+ecx-8],esi) // store lower word result - AS2( mov [edx+ecx-4],ebp) // store higher word result - - AS1( jnz loopstartSub) // loop until eax overflows and becomes zero - - AS1(loopendSub:) - AS2( adc eax, 0) // store carry into eax (return result register) - - AddEpilogue - - // Just to get rid of warnings - // return 0; -} - -// On Pentium 4, the adc and sbb instructions are very expensive, so avoid them. - -CRYPTOPP_NAKED word P4Optimized::Add(word *C, const word *A, const word *B, unsigned int N) -{ - AddPrologue - - // now: ebx = B, ecx = C, edx = A, esi = N - AS2( xor eax, eax) - AS1( neg esi) - AS1( jz loopendAddP4) // if no dwords then nothing to do - - AS2( mov edi, [edx]) - AS2( mov ebp, [ebx]) - AS1( jmp carry1AddP4) - - AS1(loopstartAddP4:) - AS2( mov edi, [edx+8]) - AS2( add ecx, 8) - AS2( add edx, 8) - AS2( mov ebp, [ebx]) - AS2( add edi, eax) - AS1( jc carry1AddP4) - AS2( xor eax, eax) - - AS1(carry1AddP4:) - AS2( add edi, ebp) - AS2( mov ebp, 1) - AS2( mov [ecx], edi) - AS2( mov edi, [edx+4]) - AS2( cmovc eax, ebp) - AS2( mov ebp, [ebx+4]) - AS2( add ebx, 8) - AS2( add edi, eax) - AS1( jc carry2AddP4) - AS2( xor eax, eax) - - AS1(carry2AddP4:) - AS2( add edi, ebp) - AS2( mov ebp, 1) - AS2( cmovc eax, ebp) - AS2( mov [ecx+4], edi) - AS2( add esi, 2) - AS1( jnz loopstartAddP4) - - AS1(loopendAddP4:) - - AddEpilogue - - // Just to get rid of warnings - // return 0; -} - -CRYPTOPP_NAKED word P4Optimized::Subtract(word *C, const word *A, const word *B, unsigned int N) -{ - AddPrologue - - // now: ebx = B, ecx = C, edx = A, esi = N - AS2( xor eax, eax) - AS1( neg esi) - AS1( jz loopendSubP4) // if no dwords then nothing to do - - AS2( mov edi, [edx]) - AS2( mov ebp, [ebx]) - AS1( jmp carry1SubP4) - - AS1(loopstartSubP4:) - AS2( mov edi, [edx+8]) - AS2( add edx, 8) - AS2( add ecx, 8) - AS2( mov ebp, [ebx]) - AS2( sub edi, eax) - AS1( jc carry1SubP4) - AS2( xor eax, eax) - - AS1(carry1SubP4:) - AS2( sub edi, ebp) - AS2( mov ebp, 1) - AS2( mov [ecx], edi) - AS2( mov edi, [edx+4]) - AS2( cmovc eax, ebp) - AS2( mov ebp, [ebx+4]) - AS2( add ebx, 8) - AS2( sub edi, eax) - AS1( jc carry2SubP4) - AS2( xor eax, eax) - - AS1(carry2SubP4:) - AS2( sub edi, ebp) - AS2( mov ebp, 1) - AS2( cmovc eax, ebp) - AS2( mov [ecx+4], edi) - AS2( add esi, 2) - AS1( jnz loopstartSubP4) - - AS1(loopendSubP4:) - - AddEpilogue - - // Just to get rid of warnings - // return 0; -} - -// multiply assembly code originally contributed by Leonard Janke - -#define MulStartup \ - AS2(xor ebp, ebp) \ - AS2(xor edi, edi) \ - AS2(xor ebx, ebx) - -#define MulShiftCarry \ - AS2(mov ebp, edx) \ - AS2(mov edi, ebx) \ - AS2(xor ebx, ebx) - -#define MulAccumulateBottom(i,j) \ - AS2(mov eax, [ecx+4*j]) \ - AS2(imul eax, dword ptr [esi+4*i]) \ - AS2(add ebp, eax) - -#define MulAccumulate(i,j) \ - AS2(mov eax, [ecx+4*j]) \ - AS1(mul dword ptr [esi+4*i]) \ - AS2(add ebp, eax) \ - AS2(adc edi, edx) \ - AS2(adc bl, bh) - -#define MulStoreDigit(i) \ - AS2(mov edx, edi) \ - AS2(mov edi, [esp]) \ - AS2(mov [edi+4*i], ebp) - -#define MulLastDiagonal(digits) \ - AS2(mov eax, [ecx+4*(digits-1)]) \ - AS1(mul dword ptr [esi+4*(digits-1)]) \ - AS2(add ebp, eax) \ - AS2(adc edx, edi) \ - AS2(mov edi, [esp]) \ - AS2(mov [edi+4*(2*digits-2)], ebp) \ - AS2(mov [edi+4*(2*digits-1)], edx) - -CRYPTOPP_NAKED void PentiumOptimized::Multiply4(word* Z, const word* X, const word* Y) -{ - MulPrologue - // now: [esp] = Z, esi = X, ecx = Y - MulStartup - MulAccumulate(0,0) - MulStoreDigit(0) - MulShiftCarry - - MulAccumulate(1,0) - MulAccumulate(0,1) - MulStoreDigit(1) - MulShiftCarry - - MulAccumulate(2,0) - MulAccumulate(1,1) - MulAccumulate(0,2) - MulStoreDigit(2) - MulShiftCarry - - MulAccumulate(3,0) - MulAccumulate(2,1) - MulAccumulate(1,2) - MulAccumulate(0,3) - MulStoreDigit(3) - MulShiftCarry - - MulAccumulate(3,1) - MulAccumulate(2,2) - MulAccumulate(1,3) - MulStoreDigit(4) - MulShiftCarry - - MulAccumulate(3,2) - MulAccumulate(2,3) - MulStoreDigit(5) - MulShiftCarry - - MulLastDiagonal(4) - MulEpilogue -} - -CRYPTOPP_NAKED void PentiumOptimized::Multiply8(word* Z, const word* X, const word* Y) -{ - MulPrologue - // now: [esp] = Z, esi = X, ecx = Y - MulStartup - MulAccumulate(0,0) - MulStoreDigit(0) - MulShiftCarry - - MulAccumulate(1,0) - MulAccumulate(0,1) - MulStoreDigit(1) - MulShiftCarry - - MulAccumulate(2,0) - MulAccumulate(1,1) - MulAccumulate(0,2) - MulStoreDigit(2) - MulShiftCarry - - MulAccumulate(3,0) - MulAccumulate(2,1) - MulAccumulate(1,2) - MulAccumulate(0,3) - MulStoreDigit(3) - MulShiftCarry - - MulAccumulate(4,0) - MulAccumulate(3,1) - MulAccumulate(2,2) - MulAccumulate(1,3) - MulAccumulate(0,4) - MulStoreDigit(4) - MulShiftCarry - - MulAccumulate(5,0) - MulAccumulate(4,1) - MulAccumulate(3,2) - MulAccumulate(2,3) - MulAccumulate(1,4) - MulAccumulate(0,5) - MulStoreDigit(5) - MulShiftCarry - - MulAccumulate(6,0) - MulAccumulate(5,1) - MulAccumulate(4,2) - MulAccumulate(3,3) - MulAccumulate(2,4) - MulAccumulate(1,5) - MulAccumulate(0,6) - MulStoreDigit(6) - MulShiftCarry - - MulAccumulate(7,0) - MulAccumulate(6,1) - MulAccumulate(5,2) - MulAccumulate(4,3) - MulAccumulate(3,4) - MulAccumulate(2,5) - MulAccumulate(1,6) - MulAccumulate(0,7) - MulStoreDigit(7) - MulShiftCarry - - MulAccumulate(7,1) - MulAccumulate(6,2) - MulAccumulate(5,3) - MulAccumulate(4,4) - MulAccumulate(3,5) - MulAccumulate(2,6) - MulAccumulate(1,7) - MulStoreDigit(8) - MulShiftCarry - - MulAccumulate(7,2) - MulAccumulate(6,3) - MulAccumulate(5,4) - MulAccumulate(4,5) - MulAccumulate(3,6) - MulAccumulate(2,7) - MulStoreDigit(9) - MulShiftCarry - - MulAccumulate(7,3) - MulAccumulate(6,4) - MulAccumulate(5,5) - MulAccumulate(4,6) - MulAccumulate(3,7) - MulStoreDigit(10) - MulShiftCarry - - MulAccumulate(7,4) - MulAccumulate(6,5) - MulAccumulate(5,6) - MulAccumulate(4,7) - MulStoreDigit(11) - MulShiftCarry - - MulAccumulate(7,5) - MulAccumulate(6,6) - MulAccumulate(5,7) - MulStoreDigit(12) - MulShiftCarry - - MulAccumulate(7,6) - MulAccumulate(6,7) - MulStoreDigit(13) - MulShiftCarry - - MulLastDiagonal(8) - MulEpilogue -} - -CRYPTOPP_NAKED void PentiumOptimized::Multiply8Bottom(word* Z, const word* X, const word* Y) -{ - MulPrologue - // now: [esp] = Z, esi = X, ecx = Y - MulStartup - MulAccumulate(0,0) - MulStoreDigit(0) - MulShiftCarry - - MulAccumulate(1,0) - MulAccumulate(0,1) - MulStoreDigit(1) - MulShiftCarry - - MulAccumulate(2,0) - MulAccumulate(1,1) - MulAccumulate(0,2) - MulStoreDigit(2) - MulShiftCarry - - MulAccumulate(3,0) - MulAccumulate(2,1) - MulAccumulate(1,2) - MulAccumulate(0,3) - MulStoreDigit(3) - MulShiftCarry - - MulAccumulate(4,0) - MulAccumulate(3,1) - MulAccumulate(2,2) - MulAccumulate(1,3) - MulAccumulate(0,4) - MulStoreDigit(4) - MulShiftCarry - - MulAccumulate(5,0) - MulAccumulate(4,1) - MulAccumulate(3,2) - MulAccumulate(2,3) - MulAccumulate(1,4) - MulAccumulate(0,5) - MulStoreDigit(5) - MulShiftCarry - - MulAccumulate(6,0) - MulAccumulate(5,1) - MulAccumulate(4,2) - MulAccumulate(3,3) - MulAccumulate(2,4) - MulAccumulate(1,5) - MulAccumulate(0,6) - MulStoreDigit(6) - MulShiftCarry - - MulAccumulateBottom(7,0) - MulAccumulateBottom(6,1) - MulAccumulateBottom(5,2) - MulAccumulateBottom(4,3) - MulAccumulateBottom(3,4) - MulAccumulateBottom(2,5) - MulAccumulateBottom(1,6) - MulAccumulateBottom(0,7) - MulStoreDigit(7) - MulEpilogue -} - -#undef AS1 -#undef AS2 - -#else // not x86 - no processor specific code at this layer - -typedef Portable LowLevel; - -#endif - -#ifdef SSE2_INTRINSICS_AVAILABLE - -#ifdef __GNUC__ -#define CRYPTOPP_FASTCALL -#else -#define CRYPTOPP_FASTCALL __fastcall -#endif - -static void CRYPTOPP_FASTCALL P4_Mul(__m128i *C, const __m128i *A, const __m128i *B) -{ - __m128i a3210 = _mm_load_si128(A); - __m128i b3210 = _mm_load_si128(B); - - __m128i sum; - - __m128i z = _mm_setzero_si128(); - __m128i a2b2_a0b0 = _mm_mul_epu32(a3210, b3210); - C[0] = a2b2_a0b0; - - __m128i a3120 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(3, 1, 2, 0)); - __m128i b3021 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 2, 1)); - __m128i a1b0_a0b1 = _mm_mul_epu32(a3120, b3021); - __m128i a1b0 = _mm_unpackhi_epi32(a1b0_a0b1, z); - __m128i a0b1 = _mm_unpacklo_epi32(a1b0_a0b1, z); - C[1] = _mm_add_epi64(a1b0, a0b1); - - __m128i a31 = _mm_srli_epi64(a3210, 32); - __m128i b31 = _mm_srli_epi64(b3210, 32); - __m128i a3b3_a1b1 = _mm_mul_epu32(a31, b31); - C[6] = a3b3_a1b1; - - __m128i a1b1 = _mm_unpacklo_epi32(a3b3_a1b1, z); - __m128i b3012 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 1, 2)); - __m128i a2b0_a0b2 = _mm_mul_epu32(a3210, b3012); - __m128i a0b2 = _mm_unpacklo_epi32(a2b0_a0b2, z); - __m128i a2b0 = _mm_unpackhi_epi32(a2b0_a0b2, z); - sum = _mm_add_epi64(a1b1, a0b2); - C[2] = _mm_add_epi64(sum, a2b0); - - __m128i a2301 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(2, 3, 0, 1)); - __m128i b2103 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(2, 1, 0, 3)); - __m128i a3b0_a1b2 = _mm_mul_epu32(a2301, b3012); - __m128i a2b1_a0b3 = _mm_mul_epu32(a3210, b2103); - __m128i a3b0 = _mm_unpackhi_epi32(a3b0_a1b2, z); - __m128i a1b2 = _mm_unpacklo_epi32(a3b0_a1b2, z); - __m128i a2b1 = _mm_unpackhi_epi32(a2b1_a0b3, z); - __m128i a0b3 = _mm_unpacklo_epi32(a2b1_a0b3, z); - __m128i sum1 = _mm_add_epi64(a3b0, a1b2); - sum = _mm_add_epi64(a2b1, a0b3); - C[3] = _mm_add_epi64(sum, sum1); - - __m128i a3b1_a1b3 = _mm_mul_epu32(a2301, b2103); - __m128i a2b2 = _mm_unpackhi_epi32(a2b2_a0b0, z); - __m128i a3b1 = _mm_unpackhi_epi32(a3b1_a1b3, z); - __m128i a1b3 = _mm_unpacklo_epi32(a3b1_a1b3, z); - sum = _mm_add_epi64(a2b2, a3b1); - C[4] = _mm_add_epi64(sum, a1b3); - - __m128i a1302 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(1, 3, 0, 2)); - __m128i b1203 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(1, 2, 0, 3)); - __m128i a3b2_a2b3 = _mm_mul_epu32(a1302, b1203); - __m128i a3b2 = _mm_unpackhi_epi32(a3b2_a2b3, z); - __m128i a2b3 = _mm_unpacklo_epi32(a3b2_a2b3, z); - C[5] = _mm_add_epi64(a3b2, a2b3); -} - -#endif // #ifdef SSE2_INTRINSICS_AVAILABLE - -// ******************************************************** - -#define A0 A -#define A1 (A+N2) -#define B0 B -#define B1 (B+N2) - -#define T0 T -#define T1 (T+N2) -#define T2 (T+N) -#define T3 (T+N+N2) - -#define R0 R -#define R1 (R+N2) -#define R2 (R+N) -#define R3 (R+N+N2) - -// R[2*N] - result = A*B -// T[2*N] - temporary work space -// A[N] --- multiplier -// B[N] --- multiplicant - -void RecursiveMultiply(word *R, word *T, const word *A, const word *B, unsigned int N) -{ - assert(N>=2 && N%2==0); - - if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8) - LowLevel::Multiply8(R, A, B); - else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4) - LowLevel::Multiply4(R, A, B); - else if (N==2) - LowLevel::Multiply2(R, A, B); - else - { - const unsigned int N2 = N/2; - int carry; - - int aComp = Compare(A0, A1, N2); - int bComp = Compare(B0, B1, N2); - - switch (2*aComp + aComp + bComp) - { - case -4: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - LowLevel::Subtract(T1, T1, R0, N2); - carry = -1; - break; - case -2: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - carry = 0; - break; - case 2: - LowLevel::Subtract(R0, A0, A1, N2); - LowLevel::Subtract(R1, B1, B0, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - carry = 0; - break; - case 4: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - LowLevel::Subtract(T1, T1, R1, N2); - carry = -1; - break; - default: - SetWords(T0, 0, N); - carry = 0; - } - - RecursiveMultiply(R0, T2, A0, B0, N2); - RecursiveMultiply(R2, T2, A1, B1, N2); - - // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1 - - carry += LowLevel::Add(T0, T0, R0, N); - carry += LowLevel::Add(T0, T0, R2, N); - carry += LowLevel::Add(R1, R1, T0, N); - - assert (carry >= 0 && carry <= 2); - Increment(R3, N2, carry); - } -} - -// R[2*N] - result = A*A -// T[2*N] - temporary work space -// A[N] --- number to be squared - -void RecursiveSquare(word *R, word *T, const word *A, unsigned int N) -{ - assert(N && N%2==0); - if (LowLevel::SquareRecursionLimit() >= 8 && N==8) - LowLevel::Square8(R, A); - if (LowLevel::SquareRecursionLimit() >= 4 && N==4) - LowLevel::Square4(R, A); - else if (N==2) - LowLevel::Square2(R, A); - else - { - const unsigned int N2 = N/2; - - RecursiveSquare(R0, T2, A0, N2); - RecursiveSquare(R2, T2, A1, N2); - RecursiveMultiply(T0, T2, A0, A1, N2); - - word carry = LowLevel::Add(R1, R1, T0, N); - carry += LowLevel::Add(R1, R1, T0, N); - Increment(R3, N2, carry); - } -} - -// R[N] - bottom half of A*B -// T[N] - temporary work space -// A[N] - multiplier -// B[N] - multiplicant - -void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, unsigned int N) -{ - assert(N>=2 && N%2==0); - if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8) - LowLevel::Multiply8Bottom(R, A, B); - else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4) - LowLevel::Multiply4Bottom(R, A, B); - else if (N==2) - LowLevel::Multiply2Bottom(R, A, B); - else - { - const unsigned int N2 = N/2; - - RecursiveMultiply(R, T, A0, B0, N2); - RecursiveMultiplyBottom(T0, T1, A1, B0, N2); - LowLevel::Add(R1, R1, T0, N2); - RecursiveMultiplyBottom(T0, T1, A0, B1, N2); - LowLevel::Add(R1, R1, T0, N2); - } -} - -// R[N] --- upper half of A*B -// T[2*N] - temporary work space -// L[N] --- lower half of A*B -// A[N] --- multiplier -// B[N] --- multiplicant - -void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, unsigned int N) -{ - assert(N>=2 && N%2==0); - - if (N==4) - { - LowLevel::Multiply4(T, A, B); - memcpy(R, T+4, 4*WORD_SIZE); - } - else if (N==2) - { - LowLevel::Multiply2(T, A, B); - memcpy(R, T+2, 2*WORD_SIZE); - } - else - { - const unsigned int N2 = N/2; - int carry; - - int aComp = Compare(A0, A1, N2); - int bComp = Compare(B0, B1, N2); - - switch (2*aComp + aComp + bComp) - { - case -4: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - LowLevel::Subtract(T1, T1, R0, N2); - carry = -1; - break; - case -2: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - carry = 0; - break; - case 2: - LowLevel::Subtract(R0, A0, A1, N2); - LowLevel::Subtract(R1, B1, B0, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - carry = 0; - break; - case 4: - LowLevel::Subtract(R0, A1, A0, N2); - LowLevel::Subtract(R1, B0, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - LowLevel::Subtract(T1, T1, R1, N2); - carry = -1; - break; - default: - SetWords(T0, 0, N); - carry = 0; - } - - RecursiveMultiply(T2, R0, A1, B1, N2); - - // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1 - - word c2 = LowLevel::Subtract(R0, L+N2, L, N2); - c2 += LowLevel::Subtract(R0, R0, T0, N2); - word t = (Compare(R0, T2, N2) == -1); - - carry += t; - carry += Increment(R0, N2, c2+t); - carry += LowLevel::Add(R0, R0, T1, N2); - carry += LowLevel::Add(R0, R0, T3, N2); - assert (carry >= 0 && carry <= 2); - - CopyWords(R1, T3, N2); - Increment(R1, N2, carry); - } -} - -inline word Add(word *C, const word *A, const word *B, unsigned int N) -{ - return LowLevel::Add(C, A, B, N); -} - -inline word Subtract(word *C, const word *A, const word *B, unsigned int N) -{ - return LowLevel::Subtract(C, A, B, N); -} - -inline void Multiply(word *R, word *T, const word *A, const word *B, unsigned int N) -{ - RecursiveMultiply(R, T, A, B, N); -} - -inline void Square(word *R, word *T, const word *A, unsigned int N) -{ - RecursiveSquare(R, T, A, N); -} - -inline void MultiplyBottom(word *R, word *T, const word *A, const word *B, unsigned int N) -{ - RecursiveMultiplyBottom(R, T, A, B, N); -} - -inline void MultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, unsigned int N) -{ - RecursiveMultiplyTop(R, T, L, A, B, N); -} - -static word LinearMultiply(word *C, const word *A, word B, unsigned int N) -{ - word carry=0; - for(unsigned i=0; i NB) - { - std::swap(A, B); - std::swap(NA, NB); - } - - assert(NB % NA == 0); - assert((NB/NA)%2 == 0); // NB is an even multiple of NA - - if (NA==2 && !A[1]) - { - switch (A[0]) - { - case 0: - SetWords(R, 0, NB+2); - return; - case 1: - CopyWords(R, B, NB); - R[NB] = R[NB+1] = 0; - return; - default: - R[NB] = LinearMultiply(R, B, A[0], NB); - R[NB+1] = 0; - return; - } - } - - Multiply(R, T, A, B, NA); - CopyWords(T+2*NA, R+NA, NA); - - unsigned i; - - for (i=2*NA; i=4); - -#define M0 M -#define M1 (M+N2) -#define V0 V -#define V1 (V+N2) - -#define X0 X -#define X1 (X+N2) -#define X2 (X+N) -#define X3 (X+N+N2) - - const unsigned int N2 = N/2; - Multiply(T0, T2, V0, X3, N2); - int c2 = Add(T0, T0, X0, N); - MultiplyBottom(T3, T2, T0, U, N2); - MultiplyTop(T2, R, T0, T3, M0, N2); - c2 -= Subtract(T2, T1, T2, N2); - Multiply(T0, R, T3, M1, N2); - c2 -= Subtract(T0, T2, T0, N2); - int c3 = -(int)Subtract(T1, X2, T1, N2); - Multiply(R0, T2, V1, X3, N2); - c3 += Add(R, R, T, N); - - if (c2>0) - c3 += Increment(R1, N2); - else if (c2<0) - c3 -= Decrement(R1, N2, -c2); - - assert(c3>=-1 && c3<=1); - if (c3>0) - Subtract(R, R, M, N); - else if (c3<0) - Add(R, R, M, N); - -#undef M0 -#undef M1 -#undef V0 -#undef V1 - -#undef X0 -#undef X1 -#undef X2 -#undef X3 -} - -#undef A0 -#undef A1 -#undef B0 -#undef B1 - -#undef T0 -#undef T1 -#undef T2 -#undef T3 - -#undef R0 -#undef R1 -#undef R2 -#undef R3 - -static inline void AtomicDivide(word *Q, const word *A, const word *B) -{ - word T[4]; - DWord q = DivideFourWordsByTwo(T, DWord(A[0], A[1]), DWord(A[2], A[3]), DWord(B[0], B[1])); - Q[0] = q.GetLowHalf(); - Q[1] = q.GetHighHalf(); -} - -// for use by Divide(), corrects the underestimated quotient {Q1,Q0} -static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, unsigned int N) -{ - assert(N && N%2==0); - - if (Q[1]) - { - T[N] = T[N+1] = 0; - unsigned i; - for (i=0; i= 0) - { - R[N] -= Subtract(R, R, B, N); - Q[1] += (++Q[0]==0); - assert(Q[0] || Q[1]); // no overflow - } -} - -// R[NB] -------- remainder = A%B -// Q[NA-NB+2] --- quotient = A/B -// T[NA+2*NB+4] - temp work space -// A[NA] -------- dividend -// B[NB] -------- divisor - -void Divide(word *R, word *Q, word *T, const word *A, unsigned int NA, const word *B, unsigned int NB) -{ - assert(NA && NB && NA%2==0 && NB%2==0); - assert(B[NB-1] || B[NB-2]); - assert(NB <= NA); - - // set up temporary work space - word *const TA=T; - word *const TB=T+NA+2; - word *const TP=T+NA+2+NB; - - // copy B into TB and normalize it so that TB has highest bit set to 1 - unsigned shiftWords = (B[NB-1]==0); - TB[0] = TB[NB-1] = 0; - CopyWords(TB+shiftWords, B, NB-shiftWords); - unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); - assert(shiftBits < WORD_BITS); - ShiftWordsLeftByBits(TB, NB, shiftBits); - - // copy A into TA and normalize it - TA[0] = TA[NA] = TA[NA+1] = 0; - CopyWords(TA+shiftWords, A, NA); - ShiftWordsLeftByBits(TA, NA+2, shiftBits); - - if (TA[NA+1]==0 && TA[NA] <= 1) - { - Q[NA-NB+1] = Q[NA-NB] = 0; - while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) - { - TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); - ++Q[NA-NB]; - } - } - else - { - NA+=2; - assert(Compare(TA+NA-NB, TB, NB) < 0); - } - - word BT[2]; - BT[0] = TB[NB-2] + 1; - BT[1] = TB[NB-1] + (BT[0]==0); - - // start reducing TA mod TB, 2 words at a time - for (unsigned i=NA-2; i>=NB; i-=2) - { - AtomicDivide(Q+i-NB, TA+i-2, BT); - CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB); - } - - // copy TA into R, and denormalize it - CopyWords(R, TA+shiftWords, NB); - ShiftWordsRightByBits(R, NB, shiftBits); -} - -static inline unsigned int EvenWordCount(const word *X, unsigned int N) -{ - while (N && X[N-2]==0 && X[N-1]==0) - N-=2; - return N; -} - -// return k -// R[N] --- result = A^(-1) * 2^k mod M -// T[4*N] - temporary work space -// A[NA] -- number to take inverse of -// M[N] --- modulus - -unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, const word *M, unsigned int N) -{ - assert(NA<=N && N && N%2==0); - - word *b = T; - word *c = T+N; - word *f = T+2*N; - word *g = T+3*N; - unsigned int bcLen=2, fgLen=EvenWordCount(M, N); - unsigned int k=0, s=0; - - SetWords(T, 0, 3*N); - b[0]=1; - CopyWords(f, A, NA); - CopyWords(g, M, N); - - while (1) - { - word t=f[0]; - while (!t) - { - if (EvenWordCount(f, fgLen)==0) - { - SetWords(R, 0, N); - return 0; - } - - ShiftWordsRightByWords(f, fgLen, 1); - if (c[bcLen-1]) bcLen+=2; - assert(bcLen <= N); - ShiftWordsLeftByWords(c, bcLen, 1); - k+=WORD_BITS; - t=f[0]; - } - - unsigned int i=0; - while (t%2 == 0) - { - t>>=1; - i++; - } - k+=i; - - if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2) - { - if (s%2==0) - CopyWords(R, b, N); - else - Subtract(R, M, b, N); - return k; - } - - ShiftWordsRightByBits(f, fgLen, i); - t=ShiftWordsLeftByBits(c, bcLen, i); - if (t) - { - c[bcLen] = t; - bcLen+=2; - assert(bcLen <= N); - } - - if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) - fgLen-=2; - - if (Compare(f, g, fgLen)==-1) - { - std::swap(f, g); - std::swap(b, c); - s++; - } - - Subtract(f, f, g, fgLen); - - if (Add(b, b, c, bcLen)) - { - b[bcLen] = 1; - bcLen+=2; - assert(bcLen <= N); - } - } -} - -// R[N] - result = A/(2^k) mod M -// A[N] - input -// M[N] - modulus - -void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M, unsigned int N) -{ - CopyWords(R, A, N); - - while (k--) - { - if (R[0]%2==0) - ShiftWordsRightByBits(R, N, 1); - else - { - word carry = Add(R, R, M, N); - ShiftWordsRightByBits(R, N, 1); - R[N-1] += carry<<(WORD_BITS-1); - } - } -} - -// R[N] - result = A*(2^k) mod M -// A[N] - input -// M[N] - modulus - -void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M, unsigned int N) -{ - CopyWords(R, A, N); - - while (k--) - if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) - Subtract(R, R, M, N); -} - -// ****************************************************************** - -static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; - -static inline unsigned int RoundupSize(unsigned int n) -{ - if (n<=8) - return RoundupSizeTable[n]; - else if (n<=16) - return 16; - else if (n<=32) - return 32; - else if (n<=64) - return 64; - else return 1U << BitPrecision(n-1); -} - -Integer::Integer() - : reg(2), sign(POSITIVE) -{ - reg[0] = reg[1] = 0; -} - -Integer::Integer(const Integer& t) - : ASN1Object(), reg(RoundupSize(t.WordCount())), sign(t.sign) -{ - CopyWords(reg, t.reg, reg.size()); -} - -Integer::Integer(Sign s, lword value) - : reg(2), sign(s) -{ - reg[0] = word(value); - reg[1] = word(SafeRightShift(value)); -} - -Integer::Integer(signed long value) - : reg(2) -{ - if (value >= 0) - sign = POSITIVE; - else - { - sign = NEGATIVE; - value = -value; - } - reg[0] = word(value); - reg[1] = word(SafeRightShift((unsigned long)value)); -} - -Integer::Integer(Sign s, word high, word low) - : reg(2), sign(s) -{ - reg[0] = low; - reg[1] = high; -} - -bool Integer::IsConvertableToLong() const -{ - if (ByteCount() > sizeof(long)) - return false; - - unsigned long value = reg[0]; - value += SafeLeftShift(reg[1]); - - if (sign==POSITIVE) - return (signed long)value >= 0; - else - return -(signed long)value < 0; -} - -signed long Integer::ConvertToLong() const -{ - assert(IsConvertableToLong()); - - unsigned long value = reg[0]; - value += SafeLeftShift(reg[1]); - return sign==POSITIVE ? value : -(signed long)value; -} - -Integer::Integer(BufferedTransformation &encodedInteger, unsigned int byteCount, Signedness s) -{ - Decode(encodedInteger, byteCount, s); -} - -Integer::Integer(const byte *encodedInteger, unsigned int byteCount, Signedness s) -{ - Decode(encodedInteger, byteCount, s); -} - -Integer::Integer(BufferedTransformation &bt) -{ - BERDecode(bt); -} - -Integer::Integer(RandomNumberGenerator &rng, unsigned int bitcount) -{ - Randomize(rng, bitcount); -} - -Integer::Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) -{ - if (!Randomize(rng, min, max, rnType, equiv, mod)) - throw Integer::RandomNumberNotFound(); -} - -Integer Integer::Power2(unsigned int e) -{ - Integer r((word)0, BitsToWords(e+1)); - r.SetBit(e); - return r; -} - -template -struct NewInteger -{ - Integer * operator()() const - { - return new Integer(i); - } -}; - -const Integer &Integer::Zero() -{ - return Singleton().Ref(); -} - -const Integer &Integer::One() -{ - return Singleton >().Ref(); -} - -const Integer &Integer::Two() -{ - return Singleton >().Ref(); -} - -bool Integer::operator!() const -{ - return IsNegative() ? false : (reg[0]==0 && WordCount()==0); -} - -Integer& Integer::operator=(const Integer& t) -{ - if (this != &t) - { - reg.New(RoundupSize(t.WordCount())); - CopyWords(reg, t.reg, reg.size()); - sign = t.sign; - } - return *this; -} - -bool Integer::GetBit(unsigned int n) const -{ - if (n/WORD_BITS >= reg.size()) - return 0; - else - return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); -} - -void Integer::SetBit(unsigned int n, bool value) -{ - if (value) - { - reg.CleanGrow(RoundupSize(BitsToWords(n+1))); - reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); - } - else - { - if (n/WORD_BITS < reg.size()) - reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); - } -} - -byte Integer::GetByte(unsigned int n) const -{ - if (n/WORD_SIZE >= reg.size()) - return 0; - else - return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); -} - -void Integer::SetByte(unsigned int n, byte value) -{ - reg.CleanGrow(RoundupSize(BytesToWords(n+1))); - reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); - reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); -} - -unsigned long Integer::GetBits(unsigned int i, unsigned int n) const -{ - assert(n <= sizeof(unsigned long)*8); - unsigned long v = 0; - for (unsigned int j=0; j -static Integer StringToInteger(const T *str) -{ - word radix; - // GCC workaround - // std::char_traits doesn't exist in GCC 2.x - // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 - unsigned int length; - for (length = 0; str[length] != 0; length++) {} - - Integer v; - - if (length == 0) - return v; - - switch (str[length-1]) - { - case 'h': - case 'H': - radix=16; - break; - case 'o': - case 'O': - radix=8; - break; - case 'b': - case 'B': - radix=2; - break; - default: - radix=10; - } - - if (length > 2 && str[0] == '0' && str[1] == 'x') - radix = 16; - - for (unsigned i=0; i= '0' && str[i] <= '9') - digit = str[i] - '0'; - else if (str[i] >= 'A' && str[i] <= 'F') - digit = str[i] - 'A' + 10; - else if (str[i] >= 'a' && str[i] <= 'f') - digit = str[i] - 'a' + 10; - else - digit = radix; - - if (digit < radix) - { - v *= radix; - v += digit; - } - } - - if (str[0] == '-') - v.Negate(); - - return v; -} - -Integer::Integer(const char *str) - : reg(2), sign(POSITIVE) -{ - *this = StringToInteger(str); -} - -Integer::Integer(const wchar_t *str) - : reg(2), sign(POSITIVE) -{ - *this = StringToInteger(str); -} - -unsigned int Integer::WordCount() const -{ - return CountWords(reg, reg.size()); -} - -unsigned int Integer::ByteCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); - else - return 0; -} - -unsigned int Integer::BitCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); - else - return 0; -} - -void Integer::Decode(const byte *input, unsigned int inputLen, Signedness s) -{ - StringStore store(input, inputLen); - Decode(store, inputLen, s); -} - -void Integer::Decode(BufferedTransformation &bt, unsigned int inputLen, Signedness s) -{ - assert(bt.MaxRetrievable() >= inputLen); - - byte b; - bt.Peek(b); - sign = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE; - - while (inputLen>0 && (sign==POSITIVE ? b==0 : b==0xff)) - { - bt.Skip(1); - inputLen--; - bt.Peek(b); - } - - reg.CleanNew(RoundupSize(BytesToWords(inputLen))); - - for (unsigned int i=inputLen; i > 0; i--) - { - bt.Get(b); - reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; - } - - if (sign == NEGATIVE) - { - for (unsigned i=inputLen; i 0; i--) - bt.Put(GetByte(i-1)); - } - else - { - // take two's complement of *this - Integer temp = Integer::Power2(8*STDMAX(ByteCount(), outputLen)) + *this; - for (unsigned i=0; i max) - throw InvalidArgument("Integer: Min must be no greater than Max"); - - Integer range = max - min; - const unsigned int nbits = range.BitCount(); - - do - { - Randomize(rng, nbits); - } - while (*this > range); - - *this += min; -} - -bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) -{ - return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod)); -} - -class KDF2_RNG : public RandomNumberGenerator -{ -public: - KDF2_RNG(const byte *seed, unsigned int seedSize) - : m_counter(0), m_counterAndSeed(seedSize + 4) - { - memcpy(m_counterAndSeed + 4, seed, seedSize); - } - - byte GenerateByte() - { - byte b; - GenerateBlock(&b, 1); - return b; - } - - void GenerateBlock(byte *output, unsigned int size) - { - UnalignedPutWord(BIG_ENDIAN_ORDER, m_counterAndSeed, m_counter); - ++m_counter; - P1363_KDF2::DeriveKey(output, size, m_counterAndSeed, m_counterAndSeed.size(), NULL, 0); - } - -private: - word32 m_counter; - SecByteBlock m_counterAndSeed; -}; - -bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValuePairs ¶ms) -{ - Integer min = params.GetValueWithDefault("Min", Integer::Zero()); - Integer max; - if (!params.GetValue("Max", max)) - { - int bitLength; - if (params.GetIntValue("BitLength", bitLength)) - max = Integer::Power2(bitLength); - else - throw InvalidArgument("Integer: missing Max argument"); - } - if (min > max) - throw InvalidArgument("Integer: Min must be no greater than Max"); - - Integer equiv = params.GetValueWithDefault("EquivalentTo", Integer::Zero()); - Integer mod = params.GetValueWithDefault("Mod", Integer::One()); - - if (equiv.IsNegative() || equiv >= mod) - throw InvalidArgument("Integer: invalid EquivalentTo and/or Mod argument"); - - Integer::RandomNumberType rnType = params.GetValueWithDefault("RandomNumberType", Integer::ANY); - - member_ptr kdf2Rng; - ConstByteArrayParameter seed; - if (params.GetValue("Seed", seed)) - { - ByteQueue bq; - DERSequenceEncoder seq(bq); - min.DEREncode(seq); - max.DEREncode(seq); - equiv.DEREncode(seq); - mod.DEREncode(seq); - DEREncodeUnsigned(seq, rnType); - DEREncodeOctetString(seq, seed.begin(), seed.size()); - seq.MessageEnd(); - - SecByteBlock finalSeed(bq.MaxRetrievable()); - bq.Get(finalSeed, finalSeed.size()); - kdf2Rng.reset(new KDF2_RNG(finalSeed.begin(), finalSeed.size())); - } - RandomNumberGenerator &rng = kdf2Rng.get() ? (RandomNumberGenerator &)*kdf2Rng : i_rng; - - switch (rnType) - { - case ANY: - if (mod == One()) - Randomize(rng, min, max); - else - { - Integer min1 = min + (equiv-min)%mod; - if (max < min1) - return false; - Randomize(rng, Zero(), (max - min1) / mod); - *this *= mod; - *this += min1; - } - return true; - - case PRIME: - { - const PrimeSelector *pSelector = params.GetValueWithDefault(Name::PointerToPrimeSelector(), (const PrimeSelector *)NULL); - - int i; - i = 0; - while (1) - { - if (++i==16) - { - // check if there are any suitable primes in [min, max] - Integer first = min; - if (FirstPrime(first, max, equiv, mod, pSelector)) - { - // if there is only one suitable prime, we're done - *this = first; - if (!FirstPrime(first, max, equiv, mod, pSelector)) - return true; - } - else - return false; - } - - Randomize(rng, min, max); - if (FirstPrime(*this, STDMIN(*this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector)) - return true; - } - } - - default: - throw InvalidArgument("Integer: invalid RandomNumberType argument"); - } -} - -std::istream& operator>>(std::istream& in, Integer &a) -{ - char c; - unsigned int length = 0; - SecBlock str(length + 16); - - std::ws(in); - - do - { - in.read(&c, 1); - str[length++] = c; - if (length >= str.size()) - str.Grow(length + 16); - } - while (in && (c=='-' || c=='x' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.')); - - if (in.gcount()) - in.putback(c); - str[length-1] = '\0'; - a = Integer(str); - - return in; -} - -std::ostream& operator<<(std::ostream& out, const Integer &a) -{ - // Get relevant conversion specifications from ostream. - long f = out.flags() & std::ios::basefield; // Get base digits. - int base, block; - char suffix; - switch(f) - { - case std::ios::oct : - base = 8; - block = 8; - suffix = 'o'; - break; - case std::ios::hex : - base = 16; - block = 4; - suffix = 'h'; - break; - default : - base = 10; - block = 3; - suffix = '.'; - } - - SecBlock s(a.BitCount() / (BitPrecision(base)-1) + 1); - Integer temp1=a, temp2; - unsigned i=0; - const char vec[]="0123456789ABCDEF"; - - if (a.IsNegative()) - { - out << '-'; - temp1.Negate(); - } - - if (!a) - out << '0'; - - while (!!temp1) - { - word digit; - Integer::Divide(digit, temp2, temp1, base); - s[i++]=vec[digit]; - temp1=temp2; - } - - while (i--) - { - out << s[i]; -// if (i && !(i%block)) -// out << ","; - } - return out << suffix; -} - -Integer& Integer::operator++() -{ - if (NotNegative()) - { - if (Increment(reg, reg.size())) - { - reg.CleanGrow(2*reg.size()); - reg[reg.size()/2]=1; - } - } - else - { - word borrow = Decrement(reg, reg.size()); - assert(!borrow); - if (WordCount()==0) - *this = Zero(); - } - return *this; -} - -Integer& Integer::operator--() -{ - if (IsNegative()) - { - if (Increment(reg, reg.size())) - { - reg.CleanGrow(2*reg.size()); - reg[reg.size()/2]=1; - } - } - else - { - if (Decrement(reg, reg.size())) - *this = -One(); - } - return *this; -} - -void PositiveAdd(Integer &sum, const Integer &a, const Integer& b) -{ - word carry; - if (a.reg.size() == b.reg.size()) - carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); - else if (a.reg.size() > b.reg.size()) - { - carry = Add(sum.reg, a.reg, b.reg, b.reg.size()); - CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size()); - carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry); - } - else - { - carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); - CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size()); - carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry); - } - - if (carry) - { - sum.reg.CleanGrow(2*sum.reg.size()); - sum.reg[sum.reg.size()/2] = 1; - } - sum.sign = Integer::POSITIVE; -} - -void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) -{ - unsigned aSize = a.WordCount(); - aSize += aSize%2; - unsigned bSize = b.WordCount(); - bSize += bSize%2; - - if (aSize == bSize) - { - if (Compare(a.reg, b.reg, aSize) >= 0) - { - Subtract(diff.reg, a.reg, b.reg, aSize); - diff.sign = Integer::POSITIVE; - } - else - { - Subtract(diff.reg, b.reg, a.reg, aSize); - diff.sign = Integer::NEGATIVE; - } - } - else if (aSize > bSize) - { - word borrow = Subtract(diff.reg, a.reg, b.reg, bSize); - CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize); - borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow); - assert(!borrow); - diff.sign = Integer::POSITIVE; - } - else - { - word borrow = Subtract(diff.reg, b.reg, a.reg, aSize); - CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize); - borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow); - assert(!borrow); - diff.sign = Integer::NEGATIVE; - } -} - -Integer Integer::Plus(const Integer& b) const -{ - Integer sum((word)0, STDMAX(reg.size(), b.reg.size())); - if (NotNegative()) - { - if (b.NotNegative()) - PositiveAdd(sum, *this, b); - else - PositiveSubtract(sum, *this, b); - } - else - { - if (b.NotNegative()) - PositiveSubtract(sum, b, *this); - else - { - PositiveAdd(sum, *this, b); - sum.sign = Integer::NEGATIVE; - } - } - return sum; -} - -Integer& Integer::operator+=(const Integer& t) -{ - reg.CleanGrow(t.reg.size()); - if (NotNegative()) - { - if (t.NotNegative()) - PositiveAdd(*this, *this, t); - else - PositiveSubtract(*this, *this, t); - } - else - { - if (t.NotNegative()) - PositiveSubtract(*this, t, *this); - else - { - PositiveAdd(*this, *this, t); - sign = Integer::NEGATIVE; - } - } - return *this; -} - -Integer Integer::Minus(const Integer& b) const -{ - Integer diff((word)0, STDMAX(reg.size(), b.reg.size())); - if (NotNegative()) - { - if (b.NotNegative()) - PositiveSubtract(diff, *this, b); - else - PositiveAdd(diff, *this, b); - } - else - { - if (b.NotNegative()) - { - PositiveAdd(diff, *this, b); - diff.sign = Integer::NEGATIVE; - } - else - PositiveSubtract(diff, b, *this); - } - return diff; -} - -Integer& Integer::operator-=(const Integer& t) -{ - reg.CleanGrow(t.reg.size()); - if (NotNegative()) - { - if (t.NotNegative()) - PositiveSubtract(*this, *this, t); - else - PositiveAdd(*this, *this, t); - } - else - { - if (t.NotNegative()) - { - PositiveAdd(*this, *this, t); - sign = Integer::NEGATIVE; - } - else - PositiveSubtract(*this, t, *this); - } - return *this; -} - -Integer& Integer::operator<<=(unsigned int n) -{ - const unsigned int wordCount = WordCount(); - const unsigned int shiftWords = n / WORD_BITS; - const unsigned int shiftBits = n % WORD_BITS; - - reg.CleanGrow(RoundupSize(wordCount+BitsToWords(n))); - ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords); - ShiftWordsLeftByBits(reg+shiftWords, wordCount+BitsToWords(shiftBits), shiftBits); - return *this; -} - -Integer& Integer::operator>>=(unsigned int n) -{ - const unsigned int wordCount = WordCount(); - const unsigned int shiftWords = n / WORD_BITS; - const unsigned int shiftBits = n % WORD_BITS; - - ShiftWordsRightByWords(reg, wordCount, shiftWords); - if (wordCount > shiftWords) - ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits); - if (IsNegative() && WordCount()==0) // avoid -0 - *this = Zero(); - return *this; -} - -void PositiveMultiply(Integer &product, const Integer &a, const Integer &b) -{ - unsigned aSize = RoundupSize(a.WordCount()); - unsigned bSize = RoundupSize(b.WordCount()); - - product.reg.CleanNew(RoundupSize(aSize+bSize)); - product.sign = Integer::POSITIVE; - - SecAlignedWordBlock workspace(aSize + bSize); - AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize); -} - -void Multiply(Integer &product, const Integer &a, const Integer &b) -{ - PositiveMultiply(product, a, b); - - if (a.NotNegative() != b.NotNegative()) - product.Negate(); -} - -Integer Integer::Times(const Integer &b) const -{ - Integer product; - Multiply(product, *this, b); - return product; -} - -void PositiveDivide(Integer &remainder, Integer "ient, - const Integer &a, const Integer &b) -{ - unsigned aSize = a.WordCount(); - unsigned bSize = b.WordCount(); - - if (!bSize) - throw Integer::DivideByZero(); - - if (a.PositiveCompare(b) == -1) - { - remainder = a; - remainder.sign = Integer::POSITIVE; - quotient = Integer::Zero(); - return; - } - - aSize += aSize%2; // round up to next even number - bSize += bSize%2; - - remainder.reg.CleanNew(RoundupSize(bSize)); - remainder.sign = Integer::POSITIVE; - quotient.reg.CleanNew(RoundupSize(aSize-bSize+2)); - quotient.sign = Integer::POSITIVE; - - SecAlignedWordBlock T(aSize+2*bSize+4); - Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize); -} - -void Integer::Divide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor) -{ - PositiveDivide(remainder, quotient, dividend, divisor); - - if (dividend.IsNegative()) - { - quotient.Negate(); - if (remainder.NotZero()) - { - --quotient; - remainder = divisor.AbsoluteValue() - remainder; - } - } - - if (divisor.IsNegative()) - quotient.Negate(); -} - -void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n) -{ - q = a; - q >>= n; - - const unsigned int wordCount = BitsToWords(n); - if (wordCount <= a.WordCount()) - { - r.reg.resize(RoundupSize(wordCount)); - CopyWords(r.reg, a.reg, wordCount); - SetWords(r.reg+wordCount, 0, r.reg.size()-wordCount); - if (n % WORD_BITS != 0) - r.reg[wordCount-1] %= (1 << (n % WORD_BITS)); - } - else - { - r.reg.resize(RoundupSize(a.WordCount())); - CopyWords(r.reg, a.reg, r.reg.size()); - } - r.sign = POSITIVE; - - if (a.IsNegative() && r.NotZero()) - { - --q; - r = Power2(n) - r; - } -} - -Integer Integer::DividedBy(const Integer &b) const -{ - Integer remainder, quotient; - Integer::Divide(remainder, quotient, *this, b); - return quotient; -} - -Integer Integer::Modulo(const Integer &b) const -{ - Integer remainder, quotient; - Integer::Divide(remainder, quotient, *this, b); - return remainder; -} - -void Integer::Divide(word &remainder, Integer "ient, const Integer ÷nd, word divisor) -{ - if (!divisor) - throw Integer::DivideByZero(); - - assert(divisor); - - if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 - { - quotient = dividend >> (BitPrecision(divisor)-1); - remainder = dividend.reg[0] & (divisor-1); - return; - } - - unsigned int i = dividend.WordCount(); - quotient.reg.CleanNew(RoundupSize(i)); - remainder = 0; - while (i--) - { - quotient.reg[i] = DWord(dividend.reg[i], remainder) / divisor; - remainder = DWord(dividend.reg[i], remainder) % divisor; - } - - if (dividend.NotNegative()) - quotient.sign = POSITIVE; - else - { - quotient.sign = NEGATIVE; - if (remainder) - { - --quotient; - remainder = divisor - remainder; - } - } -} - -Integer Integer::DividedBy(word b) const -{ - word remainder; - Integer quotient; - Integer::Divide(remainder, quotient, *this, b); - return quotient; -} - -word Integer::Modulo(word divisor) const -{ - if (!divisor) - throw Integer::DivideByZero(); - - assert(divisor); - - word remainder; - - if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 - remainder = reg[0] & (divisor-1); - else - { - unsigned int i = WordCount(); - - if (divisor <= 5) - { - DWord sum(0, 0); - while (i--) - sum += reg[i]; - remainder = sum % divisor; - } - else - { - remainder = 0; - while (i--) - remainder = DWord(reg[i], remainder) % divisor; - } - } - - if (IsNegative() && remainder) - remainder = divisor - remainder; - - return remainder; -} - -void Integer::Negate() -{ - if (!!(*this)) // don't flip sign if *this==0 - sign = Sign(1-sign); -} - -int Integer::PositiveCompare(const Integer& t) const -{ - unsigned size = WordCount(), tSize = t.WordCount(); - - if (size == tSize) - return CryptoPP::Compare(reg, t.reg, size); - else - return size > tSize ? 1 : -1; -} - -int Integer::Compare(const Integer& t) const -{ - if (NotNegative()) - { - if (t.NotNegative()) - return PositiveCompare(t); - else - return 1; - } - else - { - if (t.NotNegative()) - return -1; - else - return -PositiveCompare(t); - } -} - -Integer Integer::SquareRoot() const -{ - if (!IsPositive()) - return Zero(); - - // overestimate square root - Integer x, y = Power2((BitCount()+1)/2); - assert(y*y >= *this); - - do - { - x = y; - y = (x + *this/x) >> 1; - } while (y().Gcd(a, b); -} - -Integer Integer::InverseMod(const Integer &m) const -{ - assert(m.NotNegative()); - - if (IsNegative() || *this>=m) - return (*this%m).InverseMod(m); - - if (m.IsEven()) - { - if (!m || IsEven()) - return Zero(); // no inverse - if (*this == One()) - return One(); - - Integer u = m.InverseMod(*this); - return !u ? Zero() : (m*(*this-u)+1)/(*this); - } - - SecBlock T(m.reg.size() * 4); - Integer r((word)0, m.reg.size()); - unsigned k = AlmostInverse(r.reg, T, reg, reg.size(), m.reg, m.reg.size()); - DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size()); - return r; -} - -word Integer::InverseMod(const word mod) const -{ - word g0 = mod, g1 = *this % mod; - word v0 = 0, v1 = 1; - word y; - - while (g1) - { - if (g1 == 1) - return v1; - y = g0 / g1; - g0 = g0 % g1; - v0 += y * v1; - - if (!g0) - break; - if (g0 == 1) - return mod-v0; - y = g1 / g0; - g1 = g1 % g0; - v1 += y * v0; - } - return 0; -} - -// ******************************************************** - -ModularArithmetic::ModularArithmetic(BufferedTransformation &bt) -{ - BERSequenceDecoder seq(bt); - OID oid(seq); - if (oid != ASN1::prime_field()) - BERDecodeError(); - modulus.BERDecode(seq); - seq.MessageEnd(); - result.reg.resize(modulus.reg.size()); -} - -void ModularArithmetic::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - ASN1::prime_field().DEREncode(seq); - modulus.DEREncode(seq); - seq.MessageEnd(); -} - -void ModularArithmetic::DEREncodeElement(BufferedTransformation &out, const Element &a) const -{ - a.DEREncodeAsOctetString(out, MaxElementByteLength()); -} - -void ModularArithmetic::BERDecodeElement(BufferedTransformation &in, Element &a) const -{ - a.BERDecodeAsOctetString(in, MaxElementByteLength()); -} - -const Integer& ModularArithmetic::Half(const Integer &a) const -{ - if (a.reg.size()==modulus.reg.size()) - { - CryptoPP::DivideByPower2Mod(result.reg.begin(), a.reg, 1, modulus.reg, a.reg.size()); - return result; - } - else - return result1 = (a.IsEven() ? (a >> 1) : ((a+modulus) >> 1)); -} - -const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const -{ - if (a.reg.size()==modulus.reg.size() && b.reg.size()==modulus.reg.size()) - { - if (CryptoPP::Add(result.reg.begin(), a.reg, b.reg, a.reg.size()) - || Compare(result.reg, modulus.reg, a.reg.size()) >= 0) - { - CryptoPP::Subtract(result.reg.begin(), result.reg, modulus.reg, a.reg.size()); - } - return result; - } - else - { - result1 = a+b; - if (result1 >= modulus) - result1 -= modulus; - return result1; - } -} - -Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const -{ - if (a.reg.size()==modulus.reg.size() && b.reg.size()==modulus.reg.size()) - { - if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size()) - || Compare(a.reg, modulus.reg, a.reg.size()) >= 0) - { - CryptoPP::Subtract(a.reg, a.reg, modulus.reg, a.reg.size()); - } - } - else - { - a+=b; - if (a>=modulus) - a-=modulus; - } - - return a; -} - -const Integer& ModularArithmetic::Subtract(const Integer &a, const Integer &b) const -{ - if (a.reg.size()==modulus.reg.size() && b.reg.size()==modulus.reg.size()) - { - if (CryptoPP::Subtract(result.reg.begin(), a.reg, b.reg, a.reg.size())) - CryptoPP::Add(result.reg.begin(), result.reg, modulus.reg, a.reg.size()); - return result; - } - else - { - result1 = a-b; - if (result1.IsNegative()) - result1 += modulus; - return result1; - } -} - -Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const -{ - if (a.reg.size()==modulus.reg.size() && b.reg.size()==modulus.reg.size()) - { - if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size())) - CryptoPP::Add(a.reg, a.reg, modulus.reg, a.reg.size()); - } - else - { - a-=b; - if (a.IsNegative()) - a+=modulus; - } - - return a; -} - -const Integer& ModularArithmetic::Inverse(const Integer &a) const -{ - if (!a) - return a; - - CopyWords(result.reg.begin(), modulus.reg, modulus.reg.size()); - if (CryptoPP::Subtract(result.reg.begin(), result.reg, a.reg, a.reg.size())) - Decrement(result.reg.begin()+a.reg.size(), 1, modulus.reg.size()-a.reg.size()); - - return result; -} - -Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const -{ - if (modulus.IsOdd()) - { - MontgomeryRepresentation dr(modulus); - return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2)); - } - else - return AbstractRing::CascadeExponentiate(x, e1, y, e2); -} - -void ModularArithmetic::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int exponentsCount) const -{ - if (modulus.IsOdd()) - { - MontgomeryRepresentation dr(modulus); - dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, exponentsCount); - for (unsigned int i=0; i::SimultaneousExponentiate(results, base, exponents, exponentsCount); -} - -MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd - : ModularArithmetic(m), - u((word)0, modulus.reg.size()), - workspace(5*modulus.reg.size()) -{ - if (!modulus.IsOdd()) - throw InvalidArgument("MontgomeryRepresentation: Montgomery representation requires an odd modulus"); - - RecursiveInverseModPower2(u.reg, workspace, modulus.reg, modulus.reg.size()); -} - -const Integer& MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const -{ - word *const T = workspace.begin(); - word *const R = result.reg.begin(); - const unsigned int N = modulus.reg.size(); - assert(a.reg.size()<=N && b.reg.size()<=N); - - AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size()); - SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size()); - MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); - return result; -} - -const Integer& MontgomeryRepresentation::Square(const Integer &a) const -{ - word *const T = workspace.begin(); - word *const R = result.reg.begin(); - const unsigned int N = modulus.reg.size(); - assert(a.reg.size()<=N); - - CryptoPP::Square(T, T+2*N, a.reg, a.reg.size()); - SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size()); - MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); - return result; -} - -Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const -{ - word *const T = workspace.begin(); - word *const R = result.reg.begin(); - const unsigned int N = modulus.reg.size(); - assert(a.reg.size()<=N); - - CopyWords(T, a.reg, a.reg.size()); - SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); - MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); - return result; -} - -const Integer& MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const -{ -// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size()))%modulus; - word *const T = workspace.begin(); - word *const R = result.reg.begin(); - const unsigned int N = modulus.reg.size(); - assert(a.reg.size()<=N); - - CopyWords(T, a.reg, a.reg.size()); - SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); - MontgomeryReduce(R, T+2*N, T, modulus.reg, u.reg, N); - unsigned k = AlmostInverse(R, T, R, N, modulus.reg, N); - -// cout << "k=" << k << " N*32=" << 32*N << endl; - - if (k>N*WORD_BITS) - DivideByPower2Mod(R, R, k-N*WORD_BITS, modulus.reg, N); - else - MultiplyByPower2Mod(R, R, N*WORD_BITS-k, modulus.reg, N); - - return result; -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// algebra.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" -//- #include "algebra.h" -//- #include "integer.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -template const T& AbstractGroup::Double(const Element &a) const -{ - return Add(a, a); -} - -template const T& AbstractGroup::Subtract(const Element &a, const Element &b) const -{ - // make copy of a in case Inverse() overwrites it - Element a1(a); - return Add(a1, Inverse(b)); -} - -template T& AbstractGroup::Accumulate(Element &a, const Element &b) const -{ - return a = Add(a, b); -} - -template T& AbstractGroup::Reduce(Element &a, const Element &b) const -{ - return a = Subtract(a, b); -} - -template const T& AbstractRing::Square(const Element &a) const -{ - return Multiply(a, a); -} - -template const T& AbstractRing::Divide(const Element &a, const Element &b) const -{ - // make copy of a in case MultiplicativeInverse() overwrites it - Element a1(a); - return Multiply(a1, MultiplicativeInverse(b)); -} - -template const T& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const -{ - Element q; - DivisionAlgorithm(result, q, a, b); - return result; -} - -template const T& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const -{ - Element g[3]={b, a}; - unsigned int i0=0, i1=1, i2=2; - - while (!this->Equal(g[i1], this->Identity())) - { - g[i2] = Mod(g[i0], g[i1]); - unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; - } - - return result = g[i0]; -} - -template T AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const -{ - Element result; - SimultaneousMultiply(&result, base, &exponent, 1); - return result; -} - -template T AbstractGroup::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const -{ - const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount()); - if (expLen==0) - return Identity(); - - const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); - const unsigned tableSize = 1< powerTable(tableSize << w); - - powerTable[1] = x; - powerTable[tableSize] = y; - if (w==1) - powerTable[3] = Add(x,y); - else - { - powerTable[2] = Double(x); - powerTable[2*tableSize] = Double(y); - - unsigned i, j; - - for (i=3; i=0; i--) - { - power1 = 2*power1 + e1.GetBit(i); - power2 = 2*power2 + e2.GetBit(i); - - if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) - { - unsigned squaresBefore = prevPosition-i; - unsigned squaresAfter = 0; - prevPosition = i; - while ((power1 || power2) && power1%2 == 0 && power2%2==0) - { - power1 /= 2; - power2 /= 2; - squaresBefore--; - squaresAfter++; - } - if (firstTime) - { - result = powerTable[(power2<= expLen) - { - finished = true; - return; - } - skipCount++; - } - - exp >>= skipCount; - windowBegin += skipCount; - expWindow = exp % (1 << windowSize); - - if (fastNegate && exp.GetBit(windowSize)) - { - negateNext = true; - expWindow = (1 << windowSize) - expWindow; - exp += windowModulus; - } - else - negateNext = false; - } - - Integer exp, windowModulus; - unsigned int windowSize, windowBegin, expWindow; - bool fastNegate, negateNext, firstTime, finished; -}; - -template -void AbstractGroup::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const -{ - std::vector > buckets(expCount); - std::vector exponents; - exponents.reserve(expCount); - unsigned int i; - - for (i=0; iNotNegative()); - exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0)); - exponents[i].FindNextWindow(); - buckets[i].resize(1<<(exponents[i].windowSize-1), Identity()); - } - - unsigned int expBitPosition = 0; - Element g = base; - bool notDone = true; - - while (notDone) - { - notDone = false; - for (i=0; i 1) - { - for (int j = buckets[i].size()-2; j >= 1; j--) - { - Accumulate(buckets[i][j], buckets[i][j+1]); - Accumulate(r, buckets[i][j]); - } - Accumulate(buckets[i][0], buckets[i][1]); - r = Add(Double(r), buckets[i][0]); - } - } -} - -template T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const -{ - Element result; - SimultaneousExponentiate(&result, base, &exponent, 1); - return result; -} - -template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const -{ - return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(x, e1, y, e2); -} - -template -void AbstractRing::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const -{ - MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, exponents, expCount); -} - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// queue.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "queue.h" -//- #include "filters.h" - -NAMESPACE_BEGIN(CryptoPP) - -static const unsigned int s_maxAutoNodeSize = 16*1024; - -// this class for use by ByteQueue only -class ByteQueueNode -{ -public: - ByteQueueNode(unsigned int maxSize) - : buf(maxSize) - { - m_head = m_tail = 0; - next = 0; - } - - inline unsigned int MaxSize() const {return buf.size();} - - inline unsigned int CurrentSize() const - { - return m_tail-m_head; - } - - inline bool UsedUp() const - { - return (m_head==MaxSize()); - } - - inline void Clear() - { - m_head = m_tail = 0; - } - - inline unsigned int Put(const byte *begin, unsigned int length) - { - unsigned int l = STDMIN(length, MaxSize()-m_tail); - if (buf+m_tail != begin) - memcpy(buf+m_tail, begin, l); - m_tail += l; - return l; - } - - inline unsigned int Peek(byte &outByte) const - { - if (m_tail==m_head) - return 0; - - outByte=buf[m_head]; - return 1; - } - - inline unsigned int Peek(byte *target, unsigned int copyMax) const - { - unsigned int len = STDMIN(copyMax, m_tail-m_head); - memcpy(target, buf+m_head, len); - return len; - } - - inline unsigned int CopyTo(BufferedTransformation &target, const std::string &channel=BufferedTransformation::NULL_CHANNEL) const - { - unsigned int len = m_tail-m_head; - target.ChannelPut(channel, buf+m_head, len); - return len; - } - - inline unsigned int CopyTo(BufferedTransformation &target, unsigned int copyMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL) const - { - unsigned int len = STDMIN(copyMax, m_tail-m_head); - target.ChannelPut(channel, buf+m_head, len); - return len; - } - - inline unsigned int Get(byte &outByte) - { - unsigned int len = Peek(outByte); - m_head += len; - return len; - } - - inline unsigned int Get(byte *outString, unsigned int getMax) - { - unsigned int len = Peek(outString, getMax); - m_head += len; - return len; - } - - inline unsigned int TransferTo(BufferedTransformation &target, const std::string &channel=BufferedTransformation::NULL_CHANNEL) - { - unsigned int len = m_tail-m_head; - target.ChannelPutModifiable(channel, buf+m_head, len); - m_head = m_tail; - return len; - } - - inline unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL) - { - unsigned int len = STDMIN(transferMax, m_tail-m_head); - target.ChannelPutModifiable(channel, buf+m_head, len); - m_head += len; - return len; - } - - inline unsigned int Skip(unsigned int skipMax) - { - unsigned int len = STDMIN(skipMax, m_tail-m_head); - m_head += len; - return len; - } - - inline byte operator[](unsigned int i) const - { - return buf[m_head+i]; - } - - ByteQueueNode *next; - - SecByteBlock buf; - unsigned int m_head, m_tail; -}; - -// ******************************************************** - -ByteQueue::ByteQueue(unsigned int nodeSize) - : m_lazyLength(0) -{ - SetNodeSize(nodeSize); - m_head = m_tail = new ByteQueueNode(m_nodeSize); -} - -void ByteQueue::SetNodeSize(unsigned int nodeSize) -{ - m_autoNodeSize = !nodeSize; - m_nodeSize = m_autoNodeSize ? 256 : nodeSize; -} - -ByteQueue::ByteQueue(const ByteQueue ©) - : Bufferless() -{ - CopyFrom(copy); -} - -void ByteQueue::CopyFrom(const ByteQueue ©) -{ - m_lazyLength = 0; - m_autoNodeSize = copy.m_autoNodeSize; - m_nodeSize = copy.m_nodeSize; - m_head = m_tail = new ByteQueueNode(*copy.m_head); - - for (ByteQueueNode *current=copy.m_head->next; current; current=current->next) - { - m_tail->next = new ByteQueueNode(*current); - m_tail = m_tail->next; - } - - m_tail->next = NULL; - - Put(copy.m_lazyString, copy.m_lazyLength); -} - -ByteQueue::~ByteQueue() -{ - Destroy(); -} - -void ByteQueue::Destroy() -{ - for (ByteQueueNode *next, *current=m_head; current; current=next) - { - next=current->next; - delete current; - } -} - -void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256); - Clear(); -} - -unsigned long ByteQueue::CurrentSize() const -{ - unsigned long size=0; - - for (ByteQueueNode *current=m_head; current; current=current->next) - size += current->CurrentSize(); - - return size + m_lazyLength; -} - -bool ByteQueue::IsEmpty() const -{ - return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0; -} - -void ByteQueue::Clear() -{ - for (ByteQueueNode *next, *current=m_head->next; current; current=next) - { - next=current->next; - delete current; - } - - m_tail = m_head; - m_head->Clear(); - m_head->next = NULL; - m_lazyLength = 0; -} - -unsigned int ByteQueue::Put2(const byte *inString, unsigned int length, int /* messageEnd */, bool /* blocking */) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - unsigned int len; - while ((len=m_tail->Put(inString, length)) < length) - { - inString += len; - length -= len; - if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize) - do - { - m_nodeSize *= 2; - } - while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize); - m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length)); - m_tail = m_tail->next; - } - - return 0; -} - -void ByteQueue::CleanupUsedNodes() -{ - while (m_head != m_tail && m_head->UsedUp()) - { - ByteQueueNode *temp=m_head; - m_head=m_head->next; - delete temp; - } - - if (m_head->CurrentSize() == 0) - m_head->Clear(); -} - -void ByteQueue::LazyPut(const byte *inString, unsigned int size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (inString == m_tail->buf+m_tail->m_tail) - Put(inString, size); - else - { - m_lazyString = const_cast(inString); - m_lazyLength = size; - m_lazyStringModifiable = false; - } -} - -void ByteQueue::LazyPutModifiable(byte *inString, unsigned int size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - m_lazyString = inString; - m_lazyLength = size; - m_lazyStringModifiable = true; -} - -void ByteQueue::UndoLazyPut(unsigned int size) -{ - if (m_lazyLength < size) - throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large"); - - m_lazyLength -= size; -} - -void ByteQueue::FinalizeLazyPut() -{ - unsigned int len = m_lazyLength; - m_lazyLength = 0; - if (len) - Put(m_lazyString, len); -} - -unsigned int ByteQueue::Get(byte &outByte) -{ - if (m_head->Get(outByte)) - { - if (m_head->UsedUp()) - CleanupUsedNodes(); - return 1; - } - else if (m_lazyLength > 0) - { - outByte = *m_lazyString++; - m_lazyLength--; - return 1; - } - else - return 0; -} - -unsigned int ByteQueue::Get(byte *outString, unsigned int getMax) -{ - ArraySink sink(outString, getMax); - return TransferTo(sink, getMax); -} - -unsigned int ByteQueue::Peek(byte &outByte) const -{ - if (m_head->Peek(outByte)) - return 1; - else if (m_lazyLength > 0) - { - outByte = *m_lazyString; - return 1; - } - else - return 0; -} - -unsigned int ByteQueue::Peek(byte *outString, unsigned int peekMax) const -{ - ArraySink sink(outString, peekMax); - return CopyTo(sink, peekMax); -} - -unsigned int ByteQueue::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - if (blocking) - { - unsigned long bytesLeft = transferBytes; - for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next) - bytesLeft -= current->TransferTo(target, bytesLeft, channel); - CleanupUsedNodes(); - - unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength); - if (len) - { - if (m_lazyStringModifiable) - target.ChannelPutModifiable(channel, m_lazyString, len); - else - target.ChannelPut(channel, m_lazyString, len); - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - transferBytes -= bytesLeft; - return 0; - } - else - { - Walker walker(*this); - unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - Skip(transferBytes); - return blockedBytes; - } -} - -unsigned int ByteQueue::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - Walker walker(*this); - walker.Skip(begin); - unsigned long transferBytes = end-begin; - unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - begin += transferBytes; - return blockedBytes; -} - -void ByteQueue::Unget(byte inByte) -{ - Unget(&inByte, 1); -} - -void ByteQueue::Unget(const byte *inString, unsigned int length) -{ - unsigned int len = STDMIN(length, m_head->m_head); - length -= len; - m_head->m_head -= len; - memcpy(m_head->buf + m_head->m_head, inString + length, len); - - if (length > 0) - { - ByteQueueNode *newHead = new ByteQueueNode(length); - newHead->next = m_head; - m_head = newHead; - m_head->Put(inString, length); - } -} - -const byte * ByteQueue::Spy(unsigned int &contiguousSize) const -{ - contiguousSize = m_head->m_tail - m_head->m_head; - if (contiguousSize == 0 && m_lazyLength > 0) - { - contiguousSize = m_lazyLength; - return m_lazyString; - } - else - return m_head->buf + m_head->m_head; -} - -byte * ByteQueue::CreatePutSpace(unsigned int &size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (m_tail->m_tail == m_tail->MaxSize()) - { - m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size)); - m_tail = m_tail->next; - } - - size = m_tail->MaxSize() - m_tail->m_tail; - return m_tail->buf + m_tail->m_tail; -} - -ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) -{ - Destroy(); - CopyFrom(rhs); - return *this; -} - -bool ByteQueue::operator==(const ByteQueue &rhs) const -{ - const unsigned long currentSize = CurrentSize(); - - if (currentSize != rhs.CurrentSize()) - return false; - - Walker walker1(*this), walker2(rhs); - byte b1, b2; - - while (walker1.Get(b1) && walker2.Get(b2)) - if (b1 != b2) - return false; - - return true; -} - -byte ByteQueue::operator[](unsigned long i) const -{ - for (ByteQueueNode *current=m_head; current; current=current->next) - { - if (i < current->CurrentSize()) - return (*current)[i]; - - i -= current->CurrentSize(); - } - - assert(i < m_lazyLength); - return m_lazyString[i]; -} - -void ByteQueue::swap(ByteQueue &rhs) -{ - std::swap(m_autoNodeSize, rhs.m_autoNodeSize); - std::swap(m_nodeSize, rhs.m_nodeSize); - std::swap(m_head, rhs.m_head); - std::swap(m_tail, rhs.m_tail); - std::swap(m_lazyString, rhs.m_lazyString); - std::swap(m_lazyLength, rhs.m_lazyLength); - std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable); -} - -// ******************************************************** - -void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs& /* parameters */) -{ - m_node = m_queue.m_head; - m_position = 0; - m_offset = 0; - m_lazyString = m_queue.m_lazyString; - m_lazyLength = m_queue.m_lazyLength; -} - -unsigned int ByteQueue::Walker::Get(byte &outByte) -{ - ArraySink sink(&outByte, 1); - return TransferTo(sink, 1); -} - -unsigned int ByteQueue::Walker::Get(byte *outString, unsigned int getMax) -{ - ArraySink sink(outString, getMax); - return TransferTo(sink, getMax); -} - -unsigned int ByteQueue::Walker::Peek(byte &outByte) const -{ - ArraySink sink(&outByte, 1); - return CopyTo(sink, 1); -} - -unsigned int ByteQueue::Walker::Peek(byte *outString, unsigned int peekMax) const -{ - ArraySink sink(outString, peekMax); - return CopyTo(sink, peekMax); -} - -unsigned int ByteQueue::Walker::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - unsigned long bytesLeft = transferBytes; - unsigned int blockedBytes = 0; - - while (m_node) - { - unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize()-m_offset); - blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking); - - if (blockedBytes) - goto done; - - m_position += len; - bytesLeft -= len; - - if (!bytesLeft) - { - m_offset += len; - goto done; - } - - m_node = m_node->next; - m_offset = 0; - } - - if (bytesLeft && m_lazyLength) - { - unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength); - unsigned int BlockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking); - if (BlockedBytes) - goto done; - - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - -done: - transferBytes -= bytesLeft; - return blockedBytes; -} - -unsigned int ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - Walker walker(*this); - walker.Skip(begin); - unsigned long transferBytes = end-begin; - unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - begin += transferBytes; - return blockedBytes; -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// algparam.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -bool (*AssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt) = NULL; - -bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (strcmp(name, "ValueNames") == 0) - return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue); - else - return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue); -} - -bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (strcmp(name, "ValueNames") == 0) - { - ThrowIfTypeMismatch(name, typeid(std::string), valueType); - GetParent().GetVoidValue(name, valueType, pValue); - (*reinterpret_cast(pValue) += m_name) += ";"; - return true; - } - else if (strcmp(name, m_name) == 0) - { - AssignValue(name, valueType, pValue); - m_used = true; - return true; - } - else - return GetParent().GetVoidValue(name, valueType, pValue); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_MQUEUE_H -#define CRYPTOPP_MQUEUE_H - -//- #include "queue.h" -//- #include "filters.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! Message Queue -class CRYPTOPP_DLL MessageQueue : public AutoSignaling -{ -public: - MessageQueue(unsigned int nodeSize=256); - - void IsolatedInitialize(const NameValuePairs ¶meters) - {m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);} - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool /* blocking */) - { - m_queue.Put(begin, length); - m_lengths.back() += length; - if (messageEnd) - { - m_lengths.push_back(0); - m_messageCounts.back()++; - } - return 0; - } - bool IsolatedFlush(bool /* hardFlush */, bool /* blocking */) {return false;} - bool IsolatedMessageSeriesEnd(bool /* blocking */) - {m_messageCounts.push_back(0); return false;} - - unsigned long MaxRetrievable() const - {return m_lengths.front();} - bool AnyRetrievable() const - {return m_lengths.front() > 0;} - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - - unsigned long TotalBytesRetrievable() const - {return m_queue.MaxRetrievable();} - unsigned int NumberOfMessages() const - {return m_lengths.size()-1;} - bool GetNextMessage(); - - unsigned int NumberOfMessagesInThisSeries() const - {return m_messageCounts[0];} - unsigned int NumberOfMessageSeries() const - {return m_messageCounts.size()-1;} - - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const; - - const byte * Spy(unsigned int &contiguousSize) const; - - void swap(MessageQueue &rhs); - -private: - ByteQueue m_queue; - std::deque m_lengths, m_messageCounts; -}; - - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b) -{ - a.swap(b); -} -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// mqueue.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "mqueue.h" - -NAMESPACE_BEGIN(CryptoPP) - -MessageQueue::MessageQueue(unsigned int nodeSize) - : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U) -{ -} - -unsigned int MessageQueue::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - if (begin >= MaxRetrievable()) - return 0; - - return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking); -} - -unsigned int MessageQueue::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - transferBytes = STDMIN(MaxRetrievable(), transferBytes); - unsigned int blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking); - m_lengths.front() -= transferBytes; - return blockedBytes; -} - -bool MessageQueue::GetNextMessage() -{ - if (NumberOfMessages() > 0 && !AnyRetrievable()) - { - m_lengths.pop_front(); - if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1) - m_messageCounts.pop_front(); - return true; - } - else - return false; -} - -unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - ByteQueue::Walker walker(m_queue); - std::deque::const_iterator it = m_lengths.begin(); - unsigned int i; - for (i=0; i -#include - -NAMESPACE_BEGIN(CryptoPP) - -Filter::Filter(BufferedTransformation *attachment) - : m_attachment(attachment), m_continueAt(0) -{ -} - -BufferedTransformation * Filter::NewDefaultAttachment() const -{ - return new MessageQueue; -} - -BufferedTransformation * Filter::AttachedTransformation() -{ - if (m_attachment.get() == NULL) - m_attachment.reset(NewDefaultAttachment()); - return m_attachment.get(); -} - -const BufferedTransformation *Filter::AttachedTransformation() const -{ - if (m_attachment.get() == NULL) - const_cast(this)->m_attachment.reset(NewDefaultAttachment()); - return m_attachment.get(); -} - -void Filter::Detach(BufferedTransformation *newOut) -{ - m_attachment.reset(newOut); -} - -void Filter::Insert(Filter *filter) -{ - filter->m_attachment.reset(m_attachment.release()); - m_attachment.reset(filter); -} - -unsigned int Filter::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking); -} - -unsigned int Filter::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking); -} - -void Filter::Initialize(const NameValuePairs ¶meters, int propagation) -{ - m_continueAt = 0; - IsolatedInitialize(parameters); - PropagateInitialize(parameters, propagation); -} - -bool Filter::Flush(bool hardFlush, int propagation, bool blocking) -{ - switch (m_continueAt) - { - case 0: - if (IsolatedFlush(hardFlush, blocking)) - return true; - case 1: - if (OutputFlush(1, hardFlush, propagation, blocking)) - return true; - } - return false; -} - -bool Filter::MessageSeriesEnd(int propagation, bool blocking) -{ - switch (m_continueAt) - { - case 0: - if (IsolatedMessageSeriesEnd(blocking)) - return true; - case 1: - if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking)) - return true; - } - return false; -} - -void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation) -{ - if (propagation) - AttachedTransformation()->Initialize(parameters, propagation-1); -} - -unsigned int Filter::OutputModifiable(int outputSite, byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string& /* channel */) -{ - if (messageEnd) - messageEnd--; - unsigned int result = AttachedTransformation()->PutModifiable2(inString, length, messageEnd, blocking); - m_continueAt = result ? outputSite : 0; - return result; -} - -unsigned int Filter::Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string& /* channel */) -{ - if (messageEnd) - messageEnd--; - unsigned int result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking); - m_continueAt = result ? outputSite : 0; - return result; -} - -bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel) -{ - if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking)) - { - m_continueAt = outputSite; - return true; - } - m_continueAt = 0; - return false; -} - -bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel) -{ - if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking)) - { - m_continueAt = outputSite; - return true; - } - m_continueAt = 0; - return false; -} - -// ************************************************************* - -void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks) -{ - m_buffer.New(blockSize * maxBlocks); - m_blockSize = blockSize; - m_maxBlocks = maxBlocks; - m_size = 0; - m_begin = m_buffer; -} - -byte *FilterWithBufferedInput::BlockQueue::GetBlock() -{ - if (m_size >= m_blockSize) - { - byte *ptr = m_begin; - if ((m_begin+=m_blockSize) == m_buffer.end()) - m_begin = m_buffer; - m_size -= m_blockSize; - return ptr; - } - else - return NULL; -} - -byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBytes) -{ - numberOfBytes = STDMIN(numberOfBytes, STDMIN((unsigned int)(m_buffer.end()-m_begin), m_size)); - byte *ptr = m_begin; - m_begin += numberOfBytes; - m_size -= numberOfBytes; - if (m_size == 0 || m_begin == m_buffer.end()) - m_begin = m_buffer; - return ptr; -} - -unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString) -{ - unsigned int size = m_size; - unsigned int numberOfBytes = m_maxBlocks*m_blockSize; - const byte *ptr = GetContigousBlocks(numberOfBytes); - memcpy(outString, ptr, numberOfBytes); - memcpy(outString+numberOfBytes, m_begin, m_size); - m_size = 0; - return size; -} - -void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length) -{ - assert(m_size + length <= m_buffer.size()); - byte *end = (m_size < (unsigned int)(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size(); - unsigned int len = STDMIN(length, (unsigned int)(m_buffer.end()-end)); - memcpy(end, inString, len); - if (len < length) - memcpy(m_buffer, inString+len, length-len); - m_size += length; -} - -FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment) - : Filter(attachment) -{ -} - -FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment) - : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize) - , m_firstInputDone(false) -{ - if (m_blockSize < 1) - throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); - - m_queue.ResetQueue(1, m_firstSize); -} - -void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters) -{ - InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize); - if (m_blockSize < 1) - throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); - m_queue.ResetQueue(1, m_firstSize); - m_firstInputDone = false; -} - -bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking) -{ - if (!blocking) - throw BlockingInputOnly("FilterWithBufferedInput"); - - if (hardFlush) - ForceNextPut(); - FlushDerived(); - - return false; -} - -unsigned int FilterWithBufferedInput::PutMaybeModifiable(byte *inString, unsigned int length, int messageEnd, bool blocking, bool modifiable) -{ - if (!blocking) - throw BlockingInputOnly("FilterWithBufferedInput"); - - if (length != 0) - { - unsigned int newLength = m_queue.CurrentSize() + length; - - if (!m_firstInputDone && newLength >= m_firstSize) - { - unsigned int len = m_firstSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - FirstPut(m_queue.GetContigousBlocks(m_firstSize)); - assert(m_queue.CurrentSize() == 0); - m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize); - - inString += len; - newLength -= m_firstSize; - m_firstInputDone = true; - } - - if (m_firstInputDone) - { - if (m_blockSize == 1) - { - while (newLength > m_lastSize && m_queue.CurrentSize() > 0) - { - unsigned int len = newLength - m_lastSize; - byte *ptr = m_queue.GetContigousBlocks(len); - NextPutModifiable(ptr, len); - newLength -= len; - } - - if (newLength > m_lastSize) - { - unsigned int len = newLength - m_lastSize; - NextPutMaybeModifiable(inString, len, modifiable); - inString += len; - newLength -= len; - } - } - else - { - while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize) - { - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0) - { - assert(m_queue.CurrentSize() < m_blockSize); - unsigned int len = m_blockSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - inString += len; - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - if (newLength >= m_blockSize + m_lastSize) - { - unsigned int len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize); - NextPutMaybeModifiable(inString, len, modifiable); - inString += len; - newLength -= len; - } - } - } - - m_queue.Put(inString, newLength - m_queue.CurrentSize()); - } - - if (messageEnd) - { - if (!m_firstInputDone && m_firstSize==0) - FirstPut(NULL); - - SecByteBlock temp(m_queue.CurrentSize()); - m_queue.GetAll(temp); - LastPut(temp, temp.size()); - - m_firstInputDone = false; - m_queue.ResetQueue(1, m_firstSize); - - Output(1, NULL, 0, messageEnd, blocking); - } - return 0; -} - -void FilterWithBufferedInput::ForceNextPut() -{ - if (!m_firstInputDone) - return; - - if (m_blockSize > 1) - { - while (m_queue.CurrentSize() >= m_blockSize) - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - } - else - { - unsigned int len; - while ((len = m_queue.CurrentSize()) > 0) - NextPutModifiable(m_queue.GetContigousBlocks(len), len); - } -} - -void FilterWithBufferedInput::NextPutMultiple(const byte *inString, unsigned int length) -{ - assert(m_blockSize > 1); // m_blockSize = 1 should always override this function - while (length > 0) - { - assert(length >= m_blockSize); - NextPutSingle(inString); - inString += m_blockSize; - length -= m_blockSize; - } -} - -// ************************************************************* - -ProxyFilter::ProxyFilter(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment) - : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter) -{ - if (m_filter.get()) - m_filter->Attach(new OutputProxy(*this, false)); -} - -bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking) -{ - return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false; -} - -void ProxyFilter::SetFilter(Filter *filter) -{ - m_filter.reset(filter); - if (filter) - { - OutputProxy *proxy; - std::auto_ptr temp(proxy = new OutputProxy(*this, false)); - m_filter->TransferAllTo(*proxy); - m_filter->Attach(temp.release()); - } -} - -void ProxyFilter::NextPutMultiple(const byte *s, unsigned int len) -{ - if (m_filter.get()) - m_filter->Put(s, len); -} - -void ProxyFilter::NextPutModifiable(byte *s, unsigned int len) -{ - if (m_filter.get()) - m_filter->PutModifiable(s, len); -} - -// ************************************************************* - -unsigned int ArraySink::Put2(const byte *begin, unsigned int length, int /* messageEnd */, bool /* blocking */) -{ - memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); - m_total += length; - return 0; -} - -byte * ArraySink::CreatePutSpace(unsigned int &size) -{ - size = m_size - m_total; - return m_buf + m_total; -} - -void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters) -{ - ByteArrayParameter array; - if (!parameters.GetValue(Name::OutputBuffer(), array)) - throw InvalidArgument("ArraySink: missing OutputBuffer argument"); - m_buf = array.begin(); - m_size = array.size(); - m_total = 0; -} - -unsigned int ArrayXorSink::Put2(const byte *begin, unsigned int length, int /* messageEnd */, bool /* blocking */) -{ - xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); - m_total += length; - return 0; -} - -// ************************************************************* - -void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); - m_hashModule.Restart(); -} - -unsigned int HashFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - m_hashModule.Update(inString, length); - if (m_putMessage) - FILTER_OUTPUT(1, inString, length, 0); - if (messageEnd) - { - { - unsigned int size, digestSize = m_hashModule.DigestSize(); - m_space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, digestSize, digestSize, size = digestSize); - m_hashModule.Final(m_space); - } - FILTER_OUTPUT(2, m_space, m_hashModule.DigestSize(), messageEnd); - } - FILTER_END_NO_MESSAGE_END; -} - -// ************************************************************* - -unsigned int Source::PumpAll2(bool blocking) -{ - // TODO: switch length type - unsigned long i = UINT_MAX; - RETURN_IF_NONZERO(Pump2(i, blocking)); - unsigned int j = UINT_MAX; - return PumpMessages2(j, blocking); -} - -bool Store::GetNextMessage() -{ - if (!m_messageEnd && !AnyRetrievable()) - { - m_messageEnd=true; - return true; - } - else - return false; -} - -unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - if (m_messageEnd || count == 0) - return 0; - else - { - CopyTo(target, ULONG_MAX, channel); - if (GetAutoSignalPropagation()) - target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1); - return 1; - } -} - -void StringStore::StoreInitialize(const NameValuePairs ¶meters) -{ - ConstByteArrayParameter array; - if (!parameters.GetValue(Name::InputBuffer(), array)) - throw InvalidArgument("StringStore: missing InputBuffer argument"); - m_store = array.begin(); - m_length = array.size(); - m_count = 0; -} - -unsigned int StringStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - unsigned long position = 0; - unsigned int blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking); - m_count += position; - transferBytes = position; - return blockedBytes; -} - -unsigned int StringStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - unsigned int i = (unsigned int)STDMIN((unsigned long)m_count+begin, (unsigned long)m_length); - unsigned int len = (unsigned int)STDMIN((unsigned long)m_length-i, end-begin); - unsigned int blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking); - if (!blockedBytes) - begin += len; - return blockedBytes; -} - - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// pubkey.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, const byte *derivationParams, unsigned int derivationParamsLength, bool mask, unsigned int counterStart) -{ - ArraySink *sink; - HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength)); - word32 counter = counterStart; - while (sink->AvailableSize() > 0) - { - filter.Put(input, inputLength); - filter.PutWord32(counter++); - filter.Put(derivationParams, derivationParamsLength); - filter.MessageEnd(); - } -} - -bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, unsigned int representativeBitLength) const -{ - SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength)); - ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); - return memcmp(representative, computedRepresentative, computedRepresentative.size()) == 0; -} - -void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - const MessageEncodingInterface &mei = GetMessageEncodingInterface(); - unsigned int maxRecoverableLength = mei.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize()); - - if (maxRecoverableLength == 0) - {throw NotImplemented("TF_SignerBase: this algorithm does not support message recovery or the key is too short");} - if (recoverableMessageLength > maxRecoverableLength) - throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm"); - - ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); - mei.ProcessRecoverableMessage( - ma.AccessHash(), - recoverableMessage, recoverableMessageLength, - NULL, 0, ma.m_semisignature); -} - -unsigned int TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool /* restart */) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - SecByteBlock representative(MessageRepresentativeLength()); - GetMessageEncodingInterface().ComputeMessageRepresentative(rng, - ma.m_recoverableMessage, ma.m_recoverableMessage.size(), - ma.AccessHash(), GetHashIdentifier(), ma.m_empty, - representative, MessageRepresentativeBitLength()); - ma.m_empty = true; - - Integer r(representative, representative.size()); - unsigned int signatureLength = SignatureLength(); - GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength); - return signatureLength; -} - -void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - ma.m_representative.New(MessageRepresentativeLength()); - Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength)); - if (x.BitCount() > MessageRepresentativeBitLength()) - x = Integer::Zero(); // don't return false here to prevent timing attack - x.Encode(ma.m_representative, ma.m_representative.size()); -} - -bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - bool result = GetMessageEncodingInterface().VerifyMessageRepresentative( - ma.AccessHash(), GetHashIdentifier(), ma.m_empty, ma.m_representative, MessageRepresentativeBitLength()); - ma.m_empty = true; - return result; -} - -DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - DecodingResult result = GetMessageEncodingInterface().RecoverMessageFromRepresentative( - ma.AccessHash(), GetHashIdentifier(), ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage); - ma.m_empty = true; - return result; -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// iterhash.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" -//- #include "iterhash.h" -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -template void IteratedHashBase::Update(const byte *input, unsigned int len) -{ - HashWordType tmp = m_countLo; - if ((m_countLo = tmp + len) < tmp) - m_countHi++; // carry from low to high - m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len); - - unsigned int blockSize = BlockSize(); - unsigned int num = ModPowerOf2(tmp, blockSize); - - if (num != 0) // process left over data - { - if ((num+len) >= blockSize) - { - memcpy((byte *)m_data.begin()+num, input, blockSize-num); - HashBlock(m_data); - input += (blockSize-num); - len-=(blockSize - num); - num=0; - // drop through and do the rest - } - else - { - memcpy((byte *)m_data.begin()+num, input, len); - return; - } - } - - // now process the input data in blocks of blockSize bytes and save the leftovers to m_data - if (len >= blockSize) - { - if (input == (byte *)m_data.begin()) - { - assert(len == blockSize); - HashBlock(m_data); - return; - } - else if (IsAligned(input)) - { - unsigned int leftOver = HashMultipleBlocks((T *)input, len); - input += (len - leftOver); - len = leftOver; - } - else - do - { // copy input first if it's not aligned correctly - memcpy(m_data, input, blockSize); - HashBlock(m_data); - input+=blockSize; - len-=blockSize; - } while (len >= blockSize); - } - - memcpy(m_data, input, len); -} - -template byte * IteratedHashBase::CreateUpdateSpace(unsigned int &size) -{ - unsigned int blockSize = BlockSize(); - unsigned int num = ModPowerOf2(m_countLo, blockSize); - size = blockSize - num; - return (byte *)m_data.begin() + num; -} - -template unsigned int IteratedHashBase::HashMultipleBlocks(const T *input, unsigned int length) -{ - unsigned int blockSize = BlockSize(); - do - { - HashBlock(input); - input += blockSize/sizeof(T); - length -= blockSize; - } - while (length >= blockSize); - return length; -} - -template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) -{ - unsigned int blockSize = BlockSize(); - unsigned int num = ModPowerOf2(m_countLo, blockSize); - ((byte *)m_data.begin())[num++]=padFirst; - if (num <= lastBlockSize) - memset((byte *)m_data.begin()+num, 0, lastBlockSize-num); - else - { - memset((byte *)m_data.begin()+num, 0, blockSize-num); - HashBlock(m_data); - memset(m_data, 0, lastBlockSize); - } -} - -template void IteratedHashBase::Restart() -{ - m_countLo = m_countHi = 0; - Init(); -} - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c - -// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. -// Both are in the public domain. - -//- #include "pch.h" -//- #include "sha.h" -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -// start of Steve Reid's code - -#define blk0(i) (W[i] = data[i]) -#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) - -#ifndef CRYPTOPP_IMPORTS - -void SHA::InitState(HashWordType *state) -{ - state[0] = 0x67452301L; - state[1] = 0xEFCDAB89L; - state[2] = 0x98BADCFEL; - state[3] = 0x10325476L; - state[4] = 0xC3D2E1F0L; -} - -#define f1(x,y,z) (z^(x&(y^z))) -#define f2(x,y,z) (x^y^z) -#define f3(x,y,z) ((x&y)|(z&(x|y))) -#define f4(x,y,z) (x^y^z) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); -#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); -#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30); -#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30); -#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30); - -void SHA::Transform(word32 *state, const word32 *data) -{ - word32 W[16]; - /* Copy context->state[] to working vars */ - word32 a = state[0]; - word32 b = state[1]; - word32 c = state[2]; - word32 d = state[3]; - word32 e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; - memset(W, 0, sizeof(W)); -} - -#endif // #ifndef CRYPTOPP_IMPORTS - -// end of Steve Reid's code - -// ************************************************************* - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// pkcspad.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -//- #include "pkcspad.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -unsigned int PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(unsigned int paddedLength) const -{ - return SaturatingSubtract(paddedLength/8, 10U); -} - -void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator &rng, const byte *input, unsigned int inputLen, byte *pkcsBlock, unsigned int pkcsBlockLen, const NameValuePairs& /* parameters */) const -{ - assert (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller - - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - pkcsBlock[0] = 0; - pkcsBlock++; - } - pkcsBlockLen /= 8; - - pkcsBlock[0] = 2; // block type 2 - - // pad with non-zero random bytes - for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++) - pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff); - - pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator - memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); -} - -DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, unsigned int pkcsBlockLen, byte *output, const NameValuePairs& /* parameters */) const -{ - bool invalid = false; - unsigned int maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); - - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - invalid = (pkcsBlock[0] != 0) || invalid; - pkcsBlock++; - } - pkcsBlockLen /= 8; - - // Require block type 2. - invalid = (pkcsBlock[0] != 2) || invalid; - - // skip past the padding until we find the separator - unsigned i=1; - while (i maxOutputLen) || invalid; - - if (invalid) - return DecodingResult(); - - memcpy (output, pkcsBlock+i, outputLen); - return DecodingResult(outputLen); -} - -// ******************************************************** - -#ifndef CRYPTOPP_IMPORTS - -void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator& /* rng */, - const byte* /* recoverableMessage */, unsigned int /* recoverableMessageLength */, - HashTransformation &hash, HashIdentifier hashIdentifier, bool /* messageEmpty */, - byte *representative, unsigned int representativeBitLength) const -{ - unsigned int digestSize = hash.DigestSize(); - if (digestSize + hashIdentifier.second + 10 > representativeBitLength/8) - throw PK_Signer::KeyTooShort(); - - unsigned int pkcsBlockLen = representativeBitLength; - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - representative[0] = 0; - representative++; - } - pkcsBlockLen /= 8; - - representative[0] = 1; // block type 1 - - byte *pPadding = representative + 1; - byte *pDigest = representative + pkcsBlockLen - digestSize; - byte *pHashId = pDigest - hashIdentifier.second; - byte *pSeparator = pHashId - 1; - - // pad with 0xff - memset(pPadding, 0xff, pSeparator-pPadding); - *pSeparator = 0; - memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); - hash.Final(pDigest); -} - -#endif - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// asn.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "asn.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) -USING_NAMESPACE(std) - -/// DER Length -unsigned int DERLengthEncode(BufferedTransformation &bt, unsigned int length) -{ - unsigned int i=0; - if (length <= 0x7f) - { - bt.Put(byte(length)); - i++; - } - else - { - bt.Put(byte(BytePrecision(length) | 0x80)); - i++; - for (int j=BytePrecision(length); j; --j) - { - bt.Put(byte(length >> (j-1)*8)); - i++; - } - } - return i; -} - -bool BERLengthDecode(BufferedTransformation &bt, unsigned int &length, bool &definiteLength) -{ - byte b; - - if (!bt.Get(b)) - return false; - - if (!(b & 0x80)) - { - definiteLength = true; - length = b; - } - else - { - unsigned int lengthBytes = b & 0x7f; - - if (lengthBytes == 0) - { - definiteLength = false; - return true; - } - - definiteLength = true; - length = 0; - while (lengthBytes--) - { - if (length >> (8*(sizeof(length)-1))) - BERDecodeError(); // length about to overflow - - if (!bt.Get(b)) - return false; - - length = (length << 8) | b; - } - } - return true; -} - -bool BERLengthDecode(BufferedTransformation &bt, unsigned int &length) -{ - bool definiteLength; - if (!BERLengthDecode(bt, length, definiteLength)) - BERDecodeError(); - return definiteLength; -} - -void DEREncodeNull(BufferedTransformation &out) -{ - out.Put(TAG_NULL); - out.Put(0); -} - -void BERDecodeNull(BufferedTransformation &in) -{ - byte b; - if (!in.Get(b) || b != TAG_NULL) - BERDecodeError(); - unsigned int length; - if (!BERLengthDecode(in, length) || length != 0) - BERDecodeError(); -} - -/// ASN Strings -unsigned int DEREncodeOctetString(BufferedTransformation &bt, const byte *str, unsigned int strLen) -{ - bt.Put(OCTET_STRING); - unsigned int lengthBytes = DERLengthEncode(bt, strLen); - bt.Put(str, strLen); - return 1+lengthBytes+strLen; -} - -unsigned int DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str) -{ - return DEREncodeOctetString(bt, str.begin(), str.size()); -} - -void DERReencode(BufferedTransformation &source, BufferedTransformation &dest) -{ - byte tag; - source.Peek(tag); - BERGeneralDecoder decoder(source, tag); - DERGeneralEncoder encoder(dest, tag); - if (decoder.IsDefiniteLength()) - decoder.TransferTo(encoder, decoder.RemainingLength()); - else - { - while (!decoder.EndReached()) - DERReencode(decoder, encoder); - } - decoder.MessageEnd(); - encoder.MessageEnd(); -} - -void OID::EncodeValue(BufferedTransformation &bt, unsigned long v) -{ - for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7) - bt.Put((byte)(0x80 | ((v >> i) & 0x7f))); - bt.Put((byte)(v & 0x7f)); -} - -unsigned int OID::DecodeValue(BufferedTransformation &bt, unsigned long &v) -{ - byte b; - unsigned int i=0; - v = 0; - while (true) - { - if (!bt.Get(b)) - BERDecodeError(); - i++; - v <<= 7; - v += b & 0x7f; - if (!(b & 0x80)) - return i; - } -} - -void OID::DEREncode(BufferedTransformation &bt) const -{ - assert(m_values.size() >= 2); - ByteQueue temp; - temp.Put(byte(m_values[0] * 40 + m_values[1])); - for (unsigned int i=2; i 0) - { - unsigned long v; - unsigned int valueLen = DecodeValue(bt, v); - if (valueLen > length) - BERDecodeError(); - m_values.push_back(v); - length -= valueLen; - } -} - -void OID::BERDecodeAndCheck(BufferedTransformation &bt) const -{ - OID oid(bt); - if (*this != oid) - BERDecodeError(); -} - -BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) - : m_inQueue(inQueue), m_finished(false) -{ - Init(asnTag); -} - -BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) - : m_inQueue(inQueue), m_finished(false) -{ - Init(asnTag); -} - -void BERGeneralDecoder::Init(byte asnTag) -{ - byte b; - if (!m_inQueue.Get(b) || b != asnTag) - BERDecodeError(); - - m_definiteLength = BERLengthDecode(m_inQueue, m_length); - if (!m_definiteLength && !(asnTag & CONSTRUCTED)) - BERDecodeError(); // cannot be primitive and have indefinite length -} - -BERGeneralDecoder::~BERGeneralDecoder() -{ - try // avoid throwing in constructor - { - if (!m_finished) - MessageEnd(); - } - catch (...) - { - } -} - -bool BERGeneralDecoder::EndReached() const -{ - if (m_definiteLength) - return m_length == 0; - else - { // check end-of-content octets - word16 i; - return (m_inQueue.PeekWord16(i)==2 && i==0); - } -} - -byte BERGeneralDecoder::PeekByte() const -{ - byte b; - if (!Peek(b)) - BERDecodeError(); - return b; -} - -void BERGeneralDecoder::CheckByte(byte check) -{ - byte b; - if (!Get(b) || b != check) - BERDecodeError(); -} - -void BERGeneralDecoder::MessageEnd() -{ - m_finished = true; - if (m_definiteLength) - { - if (m_length != 0) - BERDecodeError(); - } - else - { // remove end-of-content octets - word16 i; - if (m_inQueue.GetWord16(i) != 2 || i != 0) - BERDecodeError(); - } -} - -unsigned int BERGeneralDecoder::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - if (m_definiteLength && transferBytes > m_length) - transferBytes = m_length; - unsigned int blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking); - ReduceLength(transferBytes); - return blockedBytes; -} - -unsigned int BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - if (m_definiteLength) - end = STDMIN((unsigned long)m_length, end); - return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking); -} - -unsigned int BERGeneralDecoder::ReduceLength(unsigned int delta) -{ - if (m_definiteLength) - { - if (m_length < delta) - BERDecodeError(); - m_length -= delta; - } - return delta; -} - -DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) - : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) -{ -} - -DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) - : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) -{ -} - -DERGeneralEncoder::~DERGeneralEncoder() -{ - try // avoid throwing in constructor - { - if (!m_finished) - MessageEnd(); - } - catch (...) - { - } -} - -void DERGeneralEncoder::MessageEnd() -{ - m_finished = true; - unsigned int length = (unsigned int)CurrentSize(); - m_outQueue.Put(m_asnTag); - DERLengthEncode(m_outQueue, length); - TransferTo(m_outQueue); -} - -// ************************************************************* - -void X509PublicKey::BERDecode(BufferedTransformation &bt) -{ - BERSequenceDecoder subjectPublicKeyInfo(bt); - BERSequenceDecoder algorithm(subjectPublicKeyInfo); - GetAlgorithmID().BERDecodeAndCheck(algorithm); - bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); - subjectPublicKey.CheckByte(0); // unused bits - BERDecodeKey2(subjectPublicKey, parametersPresent, subjectPublicKey.RemainingLength()); - subjectPublicKey.MessageEnd(); - subjectPublicKeyInfo.MessageEnd(); -} - -void X509PublicKey::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder subjectPublicKeyInfo(bt); - - DERSequenceEncoder algorithm(subjectPublicKeyInfo); - GetAlgorithmID().DEREncode(algorithm); - DEREncodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); - subjectPublicKey.Put(0); // unused bits - DEREncodeKey(subjectPublicKey); - subjectPublicKey.MessageEnd(); - - subjectPublicKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt) -{ - BERSequenceDecoder privateKeyInfo(bt); - word32 version; - BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 0); // check version - - BERSequenceDecoder algorithm(privateKeyInfo); - GetAlgorithmID().BERDecodeAndCheck(algorithm); - bool parametersPresent = BERDecodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); - BERDecodeKey2(octetString, parametersPresent, privateKeyInfo.RemainingLength()); - octetString.MessageEnd(); - - if (!privateKeyInfo.EndReached()) - BERDecodeOptionalAttributes(privateKeyInfo); - privateKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder privateKeyInfo(bt); - DEREncodeUnsigned(privateKeyInfo, 0); // version - - DERSequenceEncoder algorithm(privateKeyInfo); - GetAlgorithmID().DEREncode(algorithm); - DEREncodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); - DEREncodeKey(octetString); - octetString.MessageEnd(); - - DEREncodeOptionalAttributes(privateKeyInfo); - privateKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt) -{ - DERReencode(bt, m_optionalAttributes); -} - -void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const -{ - m_optionalAttributes.CopyTo(bt); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// rsa.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" -//- #include "rsa.h" -//- #include "asn.h" -//- #include "oids.h" -//- #include "modarith.h" -//- #include "nbtheory.h" -//- #include "sha.h" -//- #include "algparam.h" -//- #include "fips140.h" - -#ifndef CRYPTOPP_IMPORTS - -NAMESPACE_BEGIN(CryptoPP) - -OID RSAFunction::GetAlgorithmID() const -{ - return ASN1::rsaEncryption(); -} - -void RSAFunction::BERDecodeKey(BufferedTransformation &bt) -{ - BERSequenceDecoder seq(bt); - m_n.BERDecode(seq); - m_e.BERDecode(seq); - seq.MessageEnd(); -} - -void RSAFunction::DEREncodeKey(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - m_n.DEREncode(seq); - m_e.DEREncode(seq); - seq.MessageEnd(); -} - -Integer RSAFunction::ApplyFunction(const Integer &x) const -{ - DoQuickSanityCheck(); - return a_exp_b_mod_c(x, m_e, m_n); -} - -bool RSAFunction::Validate(RandomNumberGenerator& /* rng */, unsigned int /* level */) const -{ - bool pass = true; - pass = pass && m_n > Integer::One() && m_n.IsOdd(); - pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n; - return pass; -} - -bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - return GetValueHelper(this, name, valueType, pValue).Assignable() - CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) - CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) - ; -} - -void RSAFunction::AssignFrom(const NameValuePairs &source) -{ - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) - CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) - ; -} - -// ***************************************************************************** - -class RSAPrimeSelector : public PrimeSelector -{ -public: - RSAPrimeSelector(const Integer &e) : m_e(e) {} - virtual ~RSAPrimeSelector() {}; - - bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());} - Integer m_e; -}; - -void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) -{ - int modulusSize = 2048; - alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize); - - if (modulusSize < 16) - throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small"); - - m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17)); - - if (m_e < 3 || m_e.IsEven()) - throw InvalidArgument("InvertibleRSAFunction: invalid public exponent"); - - RSAPrimeSelector selector(m_e); - const NameValuePairs &primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) - (Name::PointerToPrimeSelector(), selector.GetSelectorPointer()); - m_p.GenerateRandom(rng, primeParam); - m_q.GenerateRandom(rng, primeParam); - - m_d = EuclideanMultiplicativeInverse(m_e, LCM(m_p-1, m_q-1)); - assert(m_d.IsPositive()); - - m_dp = m_d % (m_p-1); - m_dq = m_d % (m_q-1); - m_n = m_p * m_q; - m_u = m_q.InverseMod(m_p); - -} - -void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e) -{ - GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven())); -} - -void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d) -{ - if (n.IsEven() || e.IsEven() | d.IsEven()) - throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); - - m_n = n; - m_e = e; - m_d = d; - - Integer r = --(d*e); - unsigned int s = 0; - while (r.IsEven()) - { - r >>= 1; - s++; - } - - ModularArithmetic modn(n); - for (Integer i = 2; ; ++i) - { - Integer a = modn.Exponentiate(i, r); - if (a == 1) - continue; - Integer b; - unsigned int j = 0; - while (a != n-1) - { - b = modn.Square(a); - if (b == 1) - { - m_p = GCD(a-1, n); - m_q = n/m_p; - m_dp = m_d % (m_p-1); - m_dq = m_d % (m_q-1); - m_u = m_q.InverseMod(m_p); - return; - } - if (++j == s) - throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); - a = b; - } - } -} - -void InvertibleRSAFunction::BERDecodeKey(BufferedTransformation &bt) -{ - BERSequenceDecoder privateKey(bt); - word32 version; - BERDecodeUnsigned(privateKey, version, INTEGER, 0, 0); // check version - m_n.BERDecode(privateKey); - m_e.BERDecode(privateKey); - m_d.BERDecode(privateKey); - m_p.BERDecode(privateKey); - m_q.BERDecode(privateKey); - m_dp.BERDecode(privateKey); - m_dq.BERDecode(privateKey); - m_u.BERDecode(privateKey); - privateKey.MessageEnd(); -} - -void InvertibleRSAFunction::DEREncodeKey(BufferedTransformation &bt) const -{ - DERSequenceEncoder privateKey(bt); - DEREncodeUnsigned(privateKey, 0); // version - m_n.DEREncode(privateKey); - m_e.DEREncode(privateKey); - m_d.DEREncode(privateKey); - m_p.DEREncode(privateKey); - m_q.DEREncode(privateKey); - m_dp.DEREncode(privateKey); - m_dq.DEREncode(privateKey); - m_u.DEREncode(privateKey); - privateKey.MessageEnd(); -} - -Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const -{ - DoQuickSanityCheck(); - ModularArithmetic modn(m_n); - Integer r, rInv; - do { // do this loop for people using small numbers for testing - r.Randomize(rng, Integer::One(), m_n - Integer::One()); - rInv = modn.MultiplicativeInverse(r); - } while (rInv.IsZero()); - Integer re = modn.Exponentiate(r, m_e); - re = modn.Multiply(re, x); // blind - // here we follow the notation of PKCS #1 and let u=q inverse mod p - // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q - Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u); - y = modn.Multiply(y, rInv); // unblind - if (modn.Exponentiate(y, m_e) != x) // check - throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation"); - return y; -} - -bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = RSAFunction::Validate(rng, level); - pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; - pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; - pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n; - pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p; - pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q; - pass = pass && m_u.IsPositive() && m_u < m_p; - if (level >= 1) - { - pass = pass && m_p * m_q == m_n; - pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1; - pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1); - pass = pass && m_u * m_q % m_p == 1; - } - if (level >= 2) - pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); - return pass; -} - -bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - return GetValueHelper(this, name, valueType, pValue).Assignable() - CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) - CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) - CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) - ; -} - -void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source) -{ - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) - CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) - CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) - ; -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// basecode.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "basecode.h" -//- #include "fltrimpl.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet); - - parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar); - if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) - throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive"); - - byte padding; - bool pad; - if (parameters.GetValue(Name::PaddingByte(), padding)) - pad = parameters.GetValueWithDefault(Name::Pad(), true); - else - pad = false; - m_padding = pad ? padding : -1; - - m_bytePos = m_bitPos = 0; - - int i = 8; - while (i%m_bitsPerChar != 0) - i += 8; - m_outputBlockSize = i/m_bitsPerChar; - - m_outBuf.New(m_outputBlockSize); -} - -unsigned int BaseN_Encoder::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - while (m_inputPosition < length) - { - if (m_bytePos == 0) - memset(m_outBuf, 0, m_outputBlockSize); - - { - unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8; - while (true) - { - assert(m_bitPos < m_bitsPerChar); - unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos; - m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget); - if (bitsLeftInSource >= bitsLeftInTarget) - { - m_bitPos = 0; - ++m_bytePos; - bitsLeftInSource -= bitsLeftInTarget; - if (bitsLeftInSource == 0) - break; - b <<= bitsLeftInTarget; - b &= 0xff; - } - else - { - m_bitPos += bitsLeftInSource; - break; - } - } - } - - assert(m_bytePos <= m_outputBlockSize); - if (m_bytePos == m_outputBlockSize) - { - int i; - for (i=0; i 0) - ++m_bytePos; - - int i; - for (i=0; i 0) - { - memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos); - m_bytePos = m_outputBlockSize; - } - FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); - m_bytePos = m_bitPos = 0; - } - FILTER_END_NO_MESSAGE_END; -} - -void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup); - - parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar); - if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) - throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive"); - - m_bytePos = m_bitPos = 0; - - int i = m_bitsPerChar; - while (i%8 != 0) - i += m_bitsPerChar; - m_outputBlockSize = i/8; - - m_outBuf.New(m_outputBlockSize); -} - -unsigned int BaseN_Decoder::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - while (m_inputPosition < length) - { - unsigned int value; - value = m_lookup[begin[m_inputPosition++]]; - if (value >= 256) - continue; - - if (m_bytePos == 0 && m_bitPos == 0) - memset(m_outBuf, 0, m_outputBlockSize); - - { - int newBitPos = m_bitPos + m_bitsPerChar; - if (newBitPos <= 8) - m_outBuf[m_bytePos] |= value << (8-newBitPos); - else - { - m_outBuf[m_bytePos] |= value >> (newBitPos-8); - m_outBuf[m_bytePos+1] |= value << (16-newBitPos); - } - - m_bitPos = newBitPos; - while (m_bitPos >= 8) - { - m_bitPos -= 8; - ++m_bytePos; - } - } - - if (m_bytePos == m_outputBlockSize) - { - FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0); - m_bytePos = m_bitPos = 0; - } - } - if (messageEnd) - { - FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); - m_bytePos = m_bitPos = 0; - } - FILTER_END_NO_MESSAGE_END; -} - -void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive) -{ - std::fill(lookup, lookup+256, -1); - - for (unsigned int i=0; iInitialize(CombinedNameValuePairs( - parameters, - MakeParameters(Name::EncodingLookupArray(), &s_vec[0], false) - (Name::PaddingByte(), s_padding) - (Name::GroupSize(), insertLineBreaks ? maxLineLength : 0) - (Name::Separator(), ConstByteArrayParameter(lineBreak)) - (Name::Terminator(), ConstByteArrayParameter(lineBreak)) - (Name::Log2Base(), 6, true))); -} - -const int *Base64Decoder::GetDecodingLookupArray() -{ - static bool s_initialized = false; - static int s_array[256]; - - if (!s_initialized) - { - InitializeDecodingLookupArray(s_array, s_vec, 64, false); - s_initialized = true; - } - return s_array; -} - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// files.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "files.h" - -NAMESPACE_BEGIN(CryptoPP) - -using namespace std; - -void FileStore::StoreInitialize(const NameValuePairs ¶meters) -{ - m_file.reset(new std::ifstream); - const char *fileName; - if (parameters.GetValue(Name::InputFileName(), fileName)) - { - ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0); - m_file->open(fileName, ios::in | binary); - if (!*m_file) - throw OpenErr(fileName); - m_stream = m_file.get(); - } - else - { - m_stream = NULL; - parameters.GetValue(Name::InputStreamPointer(), m_stream); - } - m_waiting = false; -} - -unsigned long FileStore::MaxRetrievable() const -{ - if (!m_stream) - return 0; - - streampos current = m_stream->tellg(); - streampos end = m_stream->seekg(0, ios::end).tellg(); - m_stream->seekg(current); - return end-current; -} - -unsigned int FileStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - if (!m_stream) - { - transferBytes = 0; - return 0; - } - - unsigned long size=transferBytes; - transferBytes = 0; - - if (m_waiting) - goto output; - - while (size && m_stream->good()) - { - { - unsigned int spaceSize = 1024; - m_space = HelpCreatePutSpace(target, channel, 1, (unsigned int)STDMIN(size, (unsigned long)UINT_MAX), spaceSize); - - m_stream->read((char *)m_space, STDMIN(size, (unsigned long)spaceSize)); - } - m_len = m_stream->gcount(); - unsigned int blockedBytes; -output: - blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking); - m_waiting = blockedBytes > 0; - if (m_waiting) - return blockedBytes; - size -= m_len; - transferBytes += m_len; - } - - if (!m_stream->good() && !m_stream->eof()) - throw ReadErr(); - - return 0; -} - -unsigned int FileStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const -{ - if (!m_stream) - return 0; - - if (begin == 0 && end == 1) - { - int result = m_stream->peek(); - if (result == EOF) // GCC workaround: 2.95.2 doesn't have char_traits::eof() - return 0; - else - { - unsigned int blockedBytes = target.ChannelPut(channel, byte(result), blocking); - begin += 1-blockedBytes; - return blockedBytes; - } - } - - // TODO: figure out what happens on cin - streampos current = m_stream->tellg(); - streampos endPosition = m_stream->seekg(0, ios::end).tellg(); - streampos newPosition = current + (streamoff)begin; - - if (newPosition >= endPosition) - { - m_stream->seekg(current); - return 0; // don't try to seek beyond the end of file - } - m_stream->seekg(newPosition); - try - { - assert(!m_waiting); - unsigned long copyMax = end-begin; - unsigned int blockedBytes = const_cast(this)->TransferTo2(target, copyMax, channel, blocking); - begin += copyMax; - if (blockedBytes) - { - const_cast(this)->m_waiting = false; - return blockedBytes; - } - } - catch(...) - { - m_stream->clear(); - m_stream->seekg(current); - throw; - } - m_stream->clear(); - m_stream->seekg(current); - - return 0; -} - -unsigned long FileStore::Skip(unsigned long skipMax) -{ - unsigned long oldPos = m_stream->tellg(); - m_stream->seekg(skipMax, ios::cur); - return (unsigned long)m_stream->tellg() - oldPos; -} - -void FileSink::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_file.reset(new std::ofstream); - const char *fileName; - if (parameters.GetValue(Name::OutputFileName(), fileName)) - { - ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0); - m_file->open(fileName, ios::out | ios::trunc | binary); - if (!*m_file) - throw OpenErr(fileName); - m_stream = m_file.get(); - } - else - { - m_stream = NULL; - parameters.GetValue(Name::OutputStreamPointer(), m_stream); - } -} - -bool FileSink::IsolatedFlush(bool /* hardFlush */, bool /* blocking */) -{ - if (!m_stream) - throw Err("FileSink: output stream not opened"); - - m_stream->flush(); - if (!m_stream->good()) - throw WriteErr(); - - return false; -} - -unsigned int FileSink::Put2(const byte *inString, unsigned int length, int messageEnd, bool /* blocking */) -{ - if (!m_stream) - throw Err("FileSink: output stream not opened"); - - m_stream->write((const char *)inString, length); - - if (messageEnd) - m_stream->flush(); - - if (!m_stream->good()) - throw WriteErr(); - - return 0; -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// - // mdc.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_MDC_H -#define CRYPTOPP_MDC_H - -/** \file -*/ - -//- #include "seckey.h" -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -template -struct MDC_Info : public FixedBlockSize, public FixedKeyLength -{ - static std::string StaticAlgorithmName() {return std::string("MDC/")+T::StaticAlgorithmName();} -}; - -//! MDC -/*! a construction by Peter Gutmann to turn an iterated hash function into a PRF */ -template -class MDC : public MDC_Info -{ - class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl > - { - typedef typename T::HashWordType HashWordType; - - public: - void UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length) - { - assert(direction == ENCRYPTION); - this->AssertValidKeyLength(length); - memcpy(Key(), userKey, this->KEYLENGTH); - T::CorrectEndianess(Key(), Key(), this->KEYLENGTH); - } - - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const - { - T::CorrectEndianess(Buffer(), (HashWordType *)inBlock, this->BLOCKSIZE); - T::Transform(Buffer(), Key()); - if (xorBlock) - { - T::CorrectEndianess(Buffer(), Buffer(), this->BLOCKSIZE); - xorbuf(outBlock, xorBlock, m_buffer, this->BLOCKSIZE); - } - else - T::CorrectEndianess((HashWordType *)outBlock, Buffer(), this->BLOCKSIZE); - } - - bool IsPermutation() const {return false;} - - unsigned int GetAlignment() const {return sizeof(HashWordType);} - - private: - HashWordType *Key() {return (HashWordType *)m_key.data();} - const HashWordType *Key() const {return (const HashWordType *)m_key.data();} - HashWordType *Buffer() const {return (HashWordType *)m_buffer.data();} - - // VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup - FixedSizeSecBlock::KEYLENGTH, AllocatorWithCleanup > m_key; - mutable FixedSizeSecBlock::BLOCKSIZE, AllocatorWithCleanup > m_buffer; - }; - -public: - //! use BlockCipher interface - typedef BlockCipherFinal Encryption; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -/*! \file - This file contains helper classes for implementing stream ciphers. - - All this infrastructure may look very complex compared to what's in Crypto++ 4.x, - but stream ciphers implementations now support a lot of new functionality, - including better performance (minimizing copying), resetting of keys and IVs, and methods to - query which features are supported by a cipher. - - Here's an explanation of these classes. The word "policy" is used here to mean a class with a - set of methods that must be implemented by individual stream cipher implementations. - This is usually much simpler than the full stream cipher API, which is implemented by - either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an - implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface - (since it's an additive cipher, i.e., it xors a keystream into the plaintext). - See this line in seal.h: - - typedef SymmetricCipherFinal\, AdditiveCipherTemplate\<\> \> \> Encryption; - - AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need - to take a policy class as a template parameter (although this is allowed), so that - their code is not duplicated for each new cipher. Instead they each - get a reference to an abstract policy interface by calling AccessPolicy() on itself, so - AccessPolicy() must be overriden to return the actual policy reference. This is done - by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and - other functions that must be implemented by the most derived class. -*/ - -#ifndef CRYPTOPP_STRCIPHR_H -#define CRYPTOPP_STRCIPHR_H - -//- #include "seckey.h" -//- #include "secblock.h" -//- #include "argnames.h" - -NAMESPACE_BEGIN(CryptoPP) - -template -class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE -{ -public: - typedef POLICY_INTERFACE PolicyInterface; - -protected: - virtual const POLICY_INTERFACE & GetPolicy() const =0; - virtual POLICY_INTERFACE & AccessPolicy() =0; -}; - -template -class ConcretePolicyHolder : public BASE, protected POLICY -{ -protected: - const POLICY_INTERFACE & GetPolicy() const {return *this;} - POLICY_INTERFACE & AccessPolicy() {return *this;} -}; - -enum KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy -{ -public: - virtual ~CFB_CipherAbstractPolicy() {}; - virtual unsigned int GetAlignment() const =0; - virtual unsigned int GetBytesPerIteration() const =0; - virtual byte * GetRegisterBegin() =0; - virtual void TransformRegister() =0; - virtual bool CanIterate() const {return false;} - virtual void Iterate(byte* /* output */, const byte* /* input */, CipherDir /* dir */, unsigned int /* iterationCount */) {assert(false);} - virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0; - virtual void CipherResynchronize(const byte* /* iv */) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");} -}; - -template -class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE -{ -public: - void ProcessData(byte *outString, const byte *inString, unsigned int length); - void Resynchronize(const byte *iv); - unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} - unsigned int GetOptimalNextBlockSize() const {return m_leftOver;} - unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} - bool IsRandomAccess() const {return false;} - bool IsSelfInverting() const {return false;} - - typedef typename BASE::PolicyInterface PolicyInterface; - -protected: - virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0; - - void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv); - - unsigned int m_leftOver; -}; - -template > -class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate -{ - bool IsForwardTransformation() const {return true;} - void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); -}; - -template > -class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate -{ - bool IsForwardTransformation() const {return false;} - void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); -}; - -template -void CFB_CipherTemplate::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv) -{ - PolicyInterface &policy = this->AccessPolicy(); - policy.CipherSetKey(params, key, length); - - if (this->IsResynchronizable()) - policy.CipherResynchronize(iv); - - m_leftOver = policy.GetBytesPerIteration(); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// strciphr.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "strciphr.h" - -NAMESPACE_BEGIN(CryptoPP) - -template -void CFB_CipherTemplate::Resynchronize(const byte *iv) -{ - PolicyInterface &policy = this->AccessPolicy(); - policy.CipherResynchronize(iv); - m_leftOver = policy.GetBytesPerIteration(); -} - -template -void CFB_CipherTemplate::ProcessData(byte *outString, const byte *inString, unsigned int length) -{ - assert(length % this->MandatoryBlockSize() == 0); - - PolicyInterface &policy = this->AccessPolicy(); - unsigned int bytesPerIteration = policy.GetBytesPerIteration(); - unsigned int alignment = policy.GetAlignment(); - byte *reg = policy.GetRegisterBegin(); - - if (m_leftOver) - { - unsigned int len = STDMIN(m_leftOver, length); - CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len); - m_leftOver -= len; - length -= len; - inString += len; - outString += len; - } - - if (!length) - return; - - assert(m_leftOver == 0); - - if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) - { - if (IsAlignedOn(inString, alignment)) - policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration); - else - { - memcpy(outString, inString, length); - policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration); - } - inString += length - length % bytesPerIteration; - outString += length - length % bytesPerIteration; - length %= bytesPerIteration; - } - - while (length >= bytesPerIteration) - { - policy.TransformRegister(); - CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); - length -= bytesPerIteration; - inString += bytesPerIteration; - outString += bytesPerIteration; - } - - if (length > 0) - { - policy.TransformRegister(); - CombineMessageAndShiftRegister(outString, reg, inString, length); - m_leftOver = bytesPerIteration - length; - } -} - -template -void CFB_EncryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) -{ - xorbuf(reg, message, length); - memcpy(output, reg, length); -} - -template -void CFB_DecryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) -{ - for (unsigned int i=0; iMinKeyLength();} - unsigned int MaxKeyLength() const {return m_cipher->MaxKeyLength();} - unsigned int DefaultKeyLength() const {return m_cipher->DefaultKeyLength();} - unsigned int GetValidKeyLength(unsigned int n) const {return m_cipher->GetValidKeyLength(n);} - bool IsValidKeyLength(unsigned int n) const {return m_cipher->IsValidKeyLength(n);} - - void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms = g_nullNameValuePairs); - - unsigned int OptimalDataAlignment() const {return BlockSize();} - - unsigned int IVSize() const {return BlockSize();} - void GetNextIV(byte *IV); - virtual IV_Requirement IVRequirement() const =0; - -protected: - inline unsigned int BlockSize() const {assert(m_register.size() > 0); return m_register.size();} - virtual void SetFeedbackSize(unsigned int feedbackSize) - { - if (!(feedbackSize == 0 || feedbackSize == BlockSize())) - throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode"); - } - virtual void ResizeBuffers() - { - m_register.New(m_cipher->BlockSize()); - } - virtual void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv) =0; - - BlockCipher *m_cipher; - SecByteBlock m_register; -}; - -template -class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE -{ - unsigned int GetAlignment() const {return m_cipher->BlockAlignment();} - void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length); -}; - -template -void ModePolicyCommonTemplate::CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) -{ - m_cipher->SetKey(key, length, params); - ResizeBuffers(); - int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0); - SetFeedbackSize(feedbackSize); -} - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate -{ -public: - IV_Requirement IVRequirement() const {return RANDOM_IV;} - static const char *StaticAlgorithmName() {return "CFB";} - -protected: - unsigned int GetBytesPerIteration() const {return m_feedbackSize;} - byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;} - void TransformRegister() - { - m_cipher->ProcessBlock(m_register, m_temp); - memmove(m_register, m_register+m_feedbackSize, BlockSize()-m_feedbackSize); - memcpy(m_register+BlockSize()-m_feedbackSize, m_temp, m_feedbackSize); - } - void CipherResynchronize(const byte *iv) - { - memcpy(m_register, iv, BlockSize()); - TransformRegister(); - } - void SetFeedbackSize(unsigned int feedbackSize) - { - if (feedbackSize > BlockSize()) - throw InvalidArgument("CFB_Mode: invalid feedback size"); - m_feedbackSize = feedbackSize ? feedbackSize : BlockSize(); - } - void ResizeBuffers() - { - CipherModeBase::ResizeBuffers(); - m_temp.New(BlockSize()); - } - - SecByteBlock m_temp; - unsigned int m_feedbackSize; -}; - -//! _ -template -class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder, public AlgorithmImpl > -{ -public: - CipherModeFinalTemplate_CipherHolder() - { - this->m_cipher = &this->m_object; - this->ResizeBuffers(); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length, MakeParameters(Name::IV(), iv)); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv, int feedbackSize) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length, MakeParameters(Name::IV(), iv)(Name::FeedbackSize(), feedbackSize)); - } - - static std::string StaticAlgorithmName() - {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();} -}; - -//! CFB mode -template -struct CFB_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; - typedef CipherModeFinalTemplate_CipherHolder > > > Decryption; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// modes.cpp - written and placed in the public domain by Wei Dai - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "modes.h" - -NAMESPACE_BEGIN(CryptoPP) - -void CipherModeBase::SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) -{ - UncheckedSetKey(params, key, length, GetIVAndThrowIfInvalid(params)); // the underlying cipher will check the key length -} - -void CipherModeBase::GetNextIV(byte *IV) -{ - if (!IsForwardTransformation()) - throw NotImplemented("CipherModeBase: GetNextIV() must be called on an encryption object"); - - m_cipher->ProcessBlock(m_register); - memcpy(IV, m_register, BlockSize()); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// randpool.cpp - written and placed in the public domain by Wei Dai -// The algorithm in this module comes from PGP's randpool.c - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "randpool.h" -//- #include "mdc.h" -//- #include "sha.h" -//- #include "modes.h" - -NAMESPACE_BEGIN(CryptoPP) - -typedef MDC RandomPoolCipher; - -RandomPool::RandomPool(unsigned int poolSize) - : pool(poolSize), key(RandomPoolCipher::DEFAULT_KEYLENGTH) -{ - assert(poolSize > key.size()); - - addPos=0; - getPos=poolSize; - memset(pool, 0, poolSize); - memset(key, 0, key.size()); -} - -void RandomPool::Stir() -{ - CFB_Mode::Encryption cipher; - - for (int i=0; i<2; i++) - { - cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize()); - cipher.ProcessString(pool, pool.size()); - memcpy(key, pool, key.size()); - } - - addPos = 0; - getPos = key.size(); -} - -unsigned int RandomPool::Put2(const byte *inString, unsigned int length, int /* messageEnd */, bool /* blocking */) -{ - unsigned t; - - while (length > (t = pool.size() - addPos)) - { - xorbuf(pool+addPos, inString, t); - inString += t; - length -= t; - Stir(); - } - - if (length) - { - xorbuf(pool+addPos, inString, length); - addPos += length; - getPos = pool.size(); // Force stir on get - } - - return 0; -} - -unsigned int RandomPool::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking) -{ - if (!blocking) - throw NotImplemented("RandomPool: nonblocking transfer is not implemented by this object"); - - unsigned int t; - unsigned long size = transferBytes; - - while (size > (t = pool.size() - getPos)) - { - target.ChannelPut(channel, pool+getPos, t); - size -= t; - Stir(); - } - - if (size) - { - target.ChannelPut(channel, pool+getPos, size); - getPos += size; - } - - return 0; -} - -byte RandomPool::GenerateByte() -{ - if (getPos == pool.size()) - Stir(); - - return pool[getPos++]; -} - -void RandomPool::GenerateBlock(byte *outString, unsigned int size) -{ - ArraySink sink(outString, size); - TransferTo(sink, size); -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// osrng.cpp - written and placed in the public domain by Wei Dai - -// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. - -//- #include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -//- #include "osrng.h" - -#ifdef OS_RNG_AVAILABLE - -//- #include "rng.h" - -#ifdef CRYPTOPP_WIN32_AVAILABLE -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif -#include -#include -#endif - -#ifdef CRYPTOPP_UNIX_AVAILABLE -#include -#include -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) -OS_RNG_Err::OS_RNG_Err(const std::string &operation) - : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " + -#ifdef CRYPTOPP_WIN32_AVAILABLE - "0x" + IntToString(GetLastError(), 16) -#else - IntToString(errno) -#endif - ) -{ -} -#endif - -#ifdef NONBLOCKING_RNG_AVAILABLE - -#ifdef CRYPTOPP_WIN32_AVAILABLE - -MicrosoftCryptoProvider::MicrosoftCryptoProvider() -{ - if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - throw OS_RNG_Err("CryptAcquireContext"); -} - -MicrosoftCryptoProvider::~MicrosoftCryptoProvider() -{ - CryptReleaseContext(m_hProvider, 0); -} - -#endif - -NonblockingRng::NonblockingRng() -{ -#ifndef CRYPTOPP_WIN32_AVAILABLE - m_fd = open("/dev/urandom",O_RDONLY); - if (m_fd == -1) - throw OS_RNG_Err("open /dev/urandom"); -#endif -} - -NonblockingRng::~NonblockingRng() -{ -#ifndef CRYPTOPP_WIN32_AVAILABLE - close(m_fd); -#endif -} - -byte NonblockingRng::GenerateByte() -{ - byte b; - GenerateBlock(&b, 1); - return b; -} - -void NonblockingRng::GenerateBlock(byte *output, unsigned int size) -{ -#ifdef CRYPTOPP_WIN32_AVAILABLE -# ifdef WORKAROUND_MS_BUG_Q258000 - static MicrosoftCryptoProvider m_Provider; -# endif - if (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output)) - throw OS_RNG_Err("CryptGenRandom"); -#else - if ((unsigned int)read(m_fd, output, size) != size) { - // Kernel 2.6.10 has non-concurrent access to /dev/urandom, retry at least once - // printf("Shamelessly retrying a random generation attempt\n"); - if ((unsigned int)read(m_fd, output, size) != size) { - // printf("Error reading /dev/urandom! (kernel 2.6.10?)\n"); - throw OS_RNG_Err("read /dev/urandom"); - } - } -#endif -} - -#endif - -// ************************************************************* - -#ifdef BLOCKING_RNG_AVAILABLE - -BlockingRng::BlockingRng() -{ - m_fd = open("/dev/random",O_RDONLY); - if (m_fd == -1) - throw OS_RNG_Err("open /dev/random"); -} - -BlockingRng::~BlockingRng() -{ - close(m_fd); -} - -byte BlockingRng::GenerateByte() -{ - byte b; - GenerateBlock(&b, 1); - return b; -} - -void BlockingRng::GenerateBlock(byte *output, unsigned int size) -{ - while (size) - { - // on some systems /dev/random will block until all bytes - // are available, on others it will returns immediately - int len = read(m_fd, output, STDMIN(size, (unsigned int)INT_MAX)); - if (len == -1) - throw OS_RNG_Err("read /dev/random"); - size -= len; - output += len; - if (size) - sleep(1); - } -} - -#endif - -// ************************************************************* - -void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size) -{ -#ifdef NONBLOCKING_RNG_AVAILABLE - if (blocking) -#endif - { -#ifdef BLOCKING_RNG_AVAILABLE - BlockingRng rng; - rng.GenerateBlock(output, size); -#endif - } - -#ifdef BLOCKING_RNG_AVAILABLE - if (!blocking) -#endif - { -#ifdef NONBLOCKING_RNG_AVAILABLE - NonblockingRng rng; - rng.GenerateBlock(output, size); -#endif - } -} - -void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) -{ - SecByteBlock seed(seedSize); - OS_GenerateRandomBlock(blocking, seed, seedSize); - Put(seed, seedSize); -} - -NAMESPACE_END - -#endif - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// md4.cpp - modified by Wei Dai from Andrew M. Kuchling's md4.c -// The original code and all modifications are in the public domain. - -// This is the original introductory comment: - -/* - * md4.c : MD4 hash algorithm. - * - * Part of the Python Cryptography Toolkit, version 1.1 - * - * Distribute and use freely; there are no restrictions on further - * dissemination and usage except those imposed by the laws of your - * country of residence. - * - */ - -//- #include "pch.h" -//- #include "md4.h" -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -void MD4::InitState(HashWordType *state) -{ - state[0] = 0x67452301L; - state[1] = 0xefcdab89L; - state[2] = 0x98badcfeL; - state[3] = 0x10325476L; -} - -void MD4::Transform (word32 *digest, const word32 *in) -{ -// #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - - word32 A, B, C, D; - - A=digest[0]; - B=digest[1]; - C=digest[2]; - D=digest[3]; - -#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+in[k],s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 1, 7); - function(C,D,A,B, 2,11); - function(B,C,D,A, 3,19); - function(A,B,C,D, 4, 3); - function(D,A,B,C, 5, 7); - function(C,D,A,B, 6,11); - function(B,C,D,A, 7,19); - function(A,B,C,D, 8, 3); - function(D,A,B,C, 9, 7); - function(C,D,A,B,10,11); - function(B,C,D,A,11,19); - function(A,B,C,D,12, 3); - function(D,A,B,C,13, 7); - function(C,D,A,B,14,11); - function(B,C,D,A,15,19); - -#undef function -#define function(a,b,c,d,k,s) a=rotlFixed(a+G(b,c,d)+in[k]+0x5a827999,s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 4, 5); - function(C,D,A,B, 8, 9); - function(B,C,D,A,12,13); - function(A,B,C,D, 1, 3); - function(D,A,B,C, 5, 5); - function(C,D,A,B, 9, 9); - function(B,C,D,A,13,13); - function(A,B,C,D, 2, 3); - function(D,A,B,C, 6, 5); - function(C,D,A,B,10, 9); - function(B,C,D,A,14,13); - function(A,B,C,D, 3, 3); - function(D,A,B,C, 7, 5); - function(C,D,A,B,11, 9); - function(B,C,D,A,15,13); - -#undef function -#define function(a,b,c,d,k,s) a=rotlFixed(a+H(b,c,d)+in[k]+0x6ed9eba1,s); - function(A,B,C,D, 0, 3); - function(D,A,B,C, 8, 9); - function(C,D,A,B, 4,11); - function(B,C,D,A,12,15); - function(A,B,C,D, 2, 3); - function(D,A,B,C,10, 9); - function(C,D,A,B, 6,11); - function(B,C,D,A,14,15); - function(A,B,C,D, 1, 3); - function(D,A,B,C, 9, 9); - function(C,D,A,B, 5,11); - function(B,C,D,A,13,15); - function(A,B,C,D, 3, 3); - function(D,A,B,C,11, 9); - function(C,D,A,B, 7,11); - function(B,C,D,A,15,15); - - digest[0]+=A; - digest[1]+=B; - digest[2]+=C; - digest[3]+=D; -} - -NAMESPACE_END -//////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include // Standard stuff from other gpl clients, external for mldonkey. @@ -9534,7 +101,7 @@ unsigned long loadKey(char privateKeyBase64[], char buf[]) { Verifier verifier(*((Signer*)s_signer)); ArraySink aSink(m_publicKey, 80); - verifier.DEREncode(aSink); + verifier.GetMaterial().Save(aSink); m_publicKeyLen = aSink.TotalPutLength(); aSink.MessageEnd(); diff --git a/src/utils/lib/CryptoPP.h b/src/utils/lib/CryptoPP.h deleted file mode 100644 index fb7950df..00000000 --- a/src/utils/lib/CryptoPP.h +++ /dev/null @@ -1,6681 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// This file contains a subset of the Crypto++ library (version 5.2.1), with -// kind permission from Wei Dai. Please note that this file should not reflect -// on the real Crypto++ library in any way, as this file been greatly mangled to -// reduce the code-size, since this app only makes use of RSA classes (for Secure -// Identification) and the MD4 hashing class (for FileIDs). -// -// For the full Crypto++ library, please refer to the official Crypto++ website, -// which can be found at, http://www.cryptopp.com -// -//////////////////////////////////////////////////////////////////////////////// -// -// Compilation Copyright (c) 1995-2004 by Wei Dai. All rights reserved. -// This copyright applies only to this software distribution package -// as a compilation, and does not imply a copyright on any particular -// file in the package. -// -// The following files are copyrighted by their respective original authors, -// and their use is subject to additional licenses included in these files. -// -// mars.cpp - Copyright 1998 Brian Gladman. - -// All other files in this compilation are placed in the public domain by -// Wei Dai and other contributors. -// -// I would like to thank the following authors for placing their works into -// the public domain: -// -// Joan Daemen - 3way.cpp -// Leonard Janke - cast.cpp, seal.cpp -// Steve Reid - cast.cpp -// Phil Karn - des.cpp -// Michael Paul Johnson - diamond.cpp -// Andrew M. Kuchling - md2.cpp, md4.cpp -// Colin Plumb - md5.cpp, md5mac.cpp -// Seal Woods - rc6.cpp -// Chris Morgan - rijndael.cpp -// Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp -// Richard De Moliner - safer.cpp -// Matthew Skala - twofish.cpp -// Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp -// -// Permission to use, copy, modify, and distribute this compilation for -// any purpose, including commercial applications, is hereby granted -// without fee, subject to the following restrictions: -// -// 1. Any copy or modification of this compilation in any form, except -// in object code form as part of an application software, must include -// the above copyright notice and this license. -// -// 2. Users of this software agree that any modification or extension -// they provide to Wei Dai will be considered public domain and not -// copyrighted unless it includes an explicit copyright notice. -// -// 3. Wei Dai makes no warranty or representation that the operation of the -// software in this compilation will be error-free, and Wei Dai is under no -// obligation to provide any services, by way of maintenance, update, or -// otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS" -// WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO, -// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR -// DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -// -// 4. Users will not use Wei Dai or any other contributor's name in any -// publicity or advertising, without prior written consent in each case. -// -// 5. Export of this software from the United States may require a -// specific license from the United States Government. It is the -// responsibility of any person or organization contemplating export -// to obtain such a license before exporting. -// -// 6. Certain parts of this software may be protected by patents. It -// is the users' responsibility to obtain the appropriate -// licenses before using those parts. -// -// If this compilation is used in object code form in an application -// software, acknowledgement of the author is not required but would be -// appreciated. The contribution of any useful modifications or extensions -// to Wei Dai is not required but would also be appreciated. -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef CRYPTOPP_H -#define CRYPTOPP_H - -#include -#include - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_CONFIG_H5392 -#define CRYPTOPP_CONFIG_H - -// ***************** Important Settings ******************** - -// define this if running on a little-endian CPU -// big endian will be assumed if IS_LITTLE_ENDIAN is not defined -#ifndef ARCH_BIG_ENDIAN -# define IS_LITTLE_ENDIAN -#endif - -// define this if you want to disable all OS-dependent features, -// such as sockets and OS-provided random number generators -// #define NO_OS_DEPENDENCE - -// Define this to use features provided by Microsoft's CryptoAPI. -// Currently the only feature used is random number generation. -// This macro will be ignored if NO_OS_DEPENDENCE is defined. -#define USE_MS_CRYPTOAPI - -// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used -#ifndef DSA_1024_BIT_MODULUS_ONLY -# define DSA_1024_BIT_MODULUS_ONLY 1 -#endif - -// ***************** Less Important Settings *************** - -#define GZIP_OS_CODE 0 - -// Try this if your CPU has 256K internal cache or a slow multiply instruction -// and you want a (possibly) faster IDEA implementation using log tables -// #define IDEA_LARGECACHE - -// Define this if, for the linear congruential RNG, you want to use -// the original constants as specified in S.K. Park and K.W. Miller's -// CACM paper. -// #define LCRNG_ORIGINAL_NUMBERS - -// choose which style of sockets to wrap (mostly useful for cygwin which has both) -#define PREFER_BERKELEY_STYLE_SOCKETS -// #define PREFER_WINDOWS_STYLE_SOCKETS - -// ***************** Important Settings Again ******************** -// But the defaults should be ok. - -// namespace support is now required -#ifdef NO_NAMESPACE -# error namespace support is now required -#endif - -// Define this to workaround a Microsoft CryptoAPI bug where -// each call to CryptAcquireContext causes a 100 KB memory leak. -// Defining this will cause Crypto++ to make only one call to CryptAcquireContext. -#define WORKAROUND_MS_BUG_Q258000 - -#ifdef CRYPTOPP_DOXYGEN_PROCESSING -// Avoid putting "CryptoPP::" in front of everything in Doxygen output -# define CryptoPP -# define NAMESPACE_BEGIN(x) -# define NAMESPACE_END -// Get Doxygen to generate better documentation for these typedefs -# define DOCUMENTED_TYPEDEF(x, y) class y : public x {}; -#else -# define NAMESPACE_BEGIN(x) namespace x { -# define NAMESPACE_END } -# define DOCUMENTED_TYPEDEF(x, y) typedef x y; -#endif -#define ANONYMOUS_NAMESPACE_BEGIN namespace { -#define USING_NAMESPACE(x) using namespace x; -#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x { -#define DOCUMENTED_NAMESPACE_END } - -// What is the type of the third parameter to bind? -// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int. -// Unfortunately there is no way to tell whether or not socklen_t is defined. -// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile. -#ifndef TYPE_OF_SOCKLEN_T -# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MACH__) -# define TYPE_OF_SOCKLEN_T int -# else -# define TYPE_OF_SOCKLEN_T ::socklen_t -# endif -#endif - -#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS) -# define __USE_W32_SOCKETS -#endif - -NAMESPACE_BEGIN(CryptoPP) - -typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs -typedef unsigned short word16; -typedef unsigned int word32; - -#if defined(__GNUC__) || defined(__MWERKS__) - #define WORD64_AVAILABLE - typedef uint64_t word64; - #define W64LIT(x) x##LL -#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__) - #define WORD64_AVAILABLE - typedef unsigned __int64 word64; - #define W64LIT(x) x##ui64 -#endif - -// define largest word type -#ifdef WORD64_AVAILABLE - typedef word64 lword; -#else - typedef word32 lword; -#endif - -#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) - // These platforms have 64-bit CPU registers. Unfortunately most C++ compilers doesn't - // allow any way to access the 64-bit by 64-bit multiply instruction without using - // assembly, so in order to use word64 as word, the assembly instruction must be defined - // in Dword::Multiply(). - typedef word32 hword; - typedef word64 word; -#else - #define CRYPTOPP_NATIVE_DWORD_AVAILABLE - #ifdef WORD64_AVAILABLE - #define CRYPTOPP_SLOW_WORD64 // defined this if your CPU is not 64-bit to use alternative code that avoids word64 - typedef word16 hword; - typedef word32 word; - typedef word64 dword; - #else - typedef word8 hword; - typedef word16 word; - typedef word32 dword; - #endif -#endif - -const unsigned int WORD_SIZE = sizeof(word); -const unsigned int WORD_BITS = WORD_SIZE * 8; - -#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) - #define INTEL_INTRINSICS - #define FAST_ROTATE -#elif defined(__MWERKS__) && TARGET_CPU_PPC - #define PPC_INTRINSICS - #define FAST_ROTATE -#elif defined(__GNUC__) && defined(__i386__) - // GCC does peephole optimizations which should result in using rotate instructions - #define FAST_ROTATE -#endif - -NAMESPACE_END - -// VC60 workaround: it doesn't allow typename in some places -#if defined(_MSC_VER) && (_MSC_VER < 1300) -#define CPP_TYPENAME -#else -#define CPP_TYPENAME typename -#endif - -#define CRYPTOPP_NO_VTABLE - -#ifdef _MSC_VER - // 4231: nonstandard extension used : 'extern' before template explicit instantiation - // 4250: dominance - // 4251: member needs to have dll-interface - // 4275: base needs to have dll-interface - // 4660: explicitly instantiating a class that's already implicitly instantiated - // 4661: no suitable definition provided for explicit template instantiation request - // 4786: identifer was truncated in debug information - // 4355: 'this' : used in base member initializer list -# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355) -#endif - -#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) -#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION -#endif - -#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION -#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE -#endif - -// CodeWarrior defines _MSC_VER -#if !defined(CRYPTOPP_DISABLE_X86ASM) && ((defined(_MSC_VER) && !defined(__MWERKS__) && defined(_M_IX86)) || (defined(__GNUC__) && defined(__i386__))) - // The x86 version of MacOSX fails when asm is enabled. - #if !defined(__APPLE__) && !defined(__clang__) - #define CRYPTOPP_X86ASM_AVAILABLE - #endif -#endif - -// ***************** determine availability of OS features ******************** - -#ifndef NO_OS_DEPENDENCE - -#if defined(_WIN32) || defined(__CYGWIN__) -#define CRYPTOPP_WIN32_AVAILABLE -#endif - -#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__BEOS__) || defined(__MORPHOS__) -#define CRYPTOPP_UNIX_AVAILABLE -#endif - -#if defined(WORD64_AVAILABLE) && (defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)) -# define HIGHRES_TIMER_AVAILABLE -#endif - -#ifdef CRYPTOPP_UNIX_AVAILABLE -# define HAS_BERKELEY_STYLE_SOCKETS -#endif - -#ifdef CRYPTOPP_WIN32_AVAILABLE -# define HAS_WINDOWS_STYLE_SOCKETS -#endif - -#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS)) -# define SOCKETS_AVAILABLE -#endif - -#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS)) -# define USE_WINDOWS_STYLE_SOCKETS -#else -# define USE_BERKELEY_STYLE_SOCKETS -#endif - -#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS) -# define WINDOWS_PIPES_AVAILABLE -#endif - -#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI) -# define NONBLOCKING_RNG_AVAILABLE -# define OS_RNG_AVAILABLE -#endif - -#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) -# define NONBLOCKING_RNG_AVAILABLE -# define BLOCKING_RNG_AVAILABLE -# define OS_RNG_AVAILABLE -# define HAS_PTHREADS -# define THREADS_AVAILABLE -#endif - -#ifdef CRYPTOPP_WIN32_AVAILABLE -# define HAS_WINTHREADS -# define THREADS_AVAILABLE -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) -# define CRYPTOPP_MALLOC_ALIGNMENT_IS_16 -#endif - -#if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__) -# define CRYPTOPP_MEMALIGN_AVAILABLE -#endif - -#endif // NO_OS_DEPENDENCE - -// ***************** DLL related ******************** - -#define CRYPTOPP_DLL -#define CRYPTOPP_API -#define CRYPTOPP_CDECL - -#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS) -#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class -#elif defined(__MWERKS__) -#define CRYPTOPP_STATIC_TEMPLATE_CLASS extern class -#else -#define CRYPTOPP_STATIC_TEMPLATE_CLASS extern template class -#endif - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_STDCPP_H -#define CRYPTOPP_STDCPP_H - -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef _MSC_VER -#include -#include -#include -#include - -// re-disable this -#pragma warning(disable: 4231) -#endif - -#if defined(_MSC_VER) && defined(_CRTAPI1) -#define CRYPTOPP_MSVCRT6 -#endif - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// cryptlib.h - written and placed in the public domain by Wei Dai -/*! \file - This file contains the declarations for the abstract base - classes that provide a uniform interface to this library. -*/ - -/*! \mainpage Crypto++TM Library 5.2.1 Reference Manual -
-
Abstract Base Classes
- cryptlib.h -
Symmetric Ciphers
- SymmetricCipherDocumentation -
Hash Functions
- HAVAL, MD2, MD4, MD5, PanamaHash, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, SHA, SHA256, SHA384, SHA512, Tiger, Whirlpool -
Non-Cryptographic Checksums
- CRC32, Adler32 -
Message Authentication Codes
- #MD5MAC, XMACC, HMAC, CBC_MAC, DMAC, PanamaMAC, TTMAC -
Random Number Generators
- NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG -
Password-based Cryptography
- PasswordBasedKeyDerivationFunction -
Public Key Cryptosystems
- DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES -
Public Key Signature Schemes
- DSA, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RabinSS, RWSS, ESIGN -
Key Agreement
- #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH -
Algebraic Structures
- Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, - ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, - GF2NP, GF256, GF2_32, EC2N, ECP -
Secret Sharing and Information Dispersal
- SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery -
Compression
- Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor -
Input Source Classes
- StringSource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource -
Output Sink Classes
- StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink -
Filter Wrappers
- StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter -
Binary to Text Encoders and Decoders
- HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder -
Wrappers for OS features
- Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer -
FIPS 140 related
- fips140.h -
- -In the FIPS 140-2 validated DLL version of Crypto++, only the following implementation class are available. -
-
Block Ciphers
- AES, DES_EDE2, DES_EDE3, SKIPJACK -
Cipher Modes (replace template parameter BC with one of the block ciphers above)
- ECB_Mode\, CTR_Mode\, CBC_Mode\, CFB_Mode\, OFB_Mode\ -
Hash Functions
- SHA -
Public Key Signature Schemes
- RSASS\, DSA, ECDSA\, ECDSA\ -
Message Authentication Codes
- HMAC\, CBC_MAC\, CBC_MAC\ -
Random Number Generators
- AutoSeededX917RNG\ -
Key Agreement
- #DH -
Public Key Cryptosystems
- RSAES\ \> -
- -

This reference manual is a work in progress. Some classes are still lacking detailed descriptions. -

Click here to download a zip archive containing this manual. -

Thanks to Ryan Phillips for providing the Doxygen configuration file -and getting me started with this manual. -*/ - -#ifndef CRYPTOPP_CRYPTLIB_H -#define CRYPTOPP_CRYPTLIB_H - -//- #include "config.h" -//- #include "stdcpp.h" - -NAMESPACE_BEGIN(CryptoPP) - -// forward declarations -class Integer; - -//! used to specify a direction for a cipher to operate in (encrypt or decrypt) -enum CipherDir {ENCRYPTION, DECRYPTION}; - -// VC60 workaround: using enums as template parameters causes problems -template -struct EnumToType -{ - static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;} -}; - -enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1}; -typedef EnumToType LittleEndian; -typedef EnumToType BigEndian; - -//! base class for all exceptions thrown by Crypto++ -class CRYPTOPP_DLL Exception : public std::exception -{ -public: - //! error types - enum ErrorType { - //! a method is not implemented - NOT_IMPLEMENTED, - //! invalid function argument - INVALID_ARGUMENT, - //! BufferedTransformation received a Flush(true) signal but can't flush buffers - CANNOT_FLUSH, - //! data integerity check (such as CRC or MAC) failed - DATA_INTEGRITY_CHECK_FAILED, - //! received input data that doesn't conform to expected format - INVALID_DATA_FORMAT, - //! error reading from input device or writing to output device - IO_ERROR, - //! some error not belong to any of the above categories - OTHER_ERROR - }; - - explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {} - virtual ~Exception() throw() {} - const char *what() const throw() {return (m_what.c_str());} - const std::string &GetWhat() const {return m_what;} - void SetWhat(const std::string &s) {m_what = s;} - ErrorType GetErrorType() const {return m_errorType;} - void SetErrorType(ErrorType errorType) {m_errorType = errorType;} - -private: - ErrorType m_errorType; - std::string m_what; -}; - -//! exception thrown when an invalid argument is detected -class CRYPTOPP_DLL InvalidArgument : public Exception -{ -public: - explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {} -}; - -//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext -class CRYPTOPP_DLL InvalidDataFormat : public Exception -{ -public: - explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {} -}; - -//! exception thrown by a class if a non-implemented method is called -class CRYPTOPP_DLL NotImplemented : public Exception -{ -public: - explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {} -}; - -//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers -class CRYPTOPP_DLL CannotFlush : public Exception -{ -public: - explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {} -}; - -//! error reported by the operating system -class CRYPTOPP_DLL OS_Error : public Exception -{ -public: - OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode) - : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {} - ~OS_Error() throw() {} - - // the operating system API that reported the error - const std::string & GetOperation() const {return m_operation;} - // the error code return by the operating system - int GetErrorCode() const {return m_errorCode;} - -protected: - std::string m_operation; - int m_errorCode; -}; - -//! used to return decoding results -struct CRYPTOPP_DLL DecodingResult -{ - explicit DecodingResult() : isValidCoding(false), messageLength(0) {} - explicit DecodingResult(unsigned int len) : isValidCoding(true), messageLength(len) {} - - bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;} - bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);} - - bool isValidCoding; - unsigned int messageLength; - -}; - -//! interface for retrieving values given their names -/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions - and to read values from keys and crypto parameters. - \note To obtain an object that implements NameValuePairs for the purpose of parameter - passing, use the MakeParameters() function. - \note To get a value from NameValuePairs, you need to know the name and the type of the value. - Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports. - Then look at the Name namespace documentation to see what the type of each value is, or - alternatively, call GetIntValue() with the value name, and if the type is not int, a - ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object. -*/ -class CRYPTOPP_NO_VTABLE NameValuePairs -{ -public: - virtual ~NameValuePairs() {} - - //! exception thrown when trying to retrieve a value using a different type than expected - class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument - { - public: - ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving) - : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'") - , m_stored(stored), m_retrieving(retrieving) {} - - const std::type_info & GetStoredTypeInfo() const {return m_stored;} - const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;} - - private: - const std::type_info &m_stored; - const std::type_info &m_retrieving; - }; - - //! get a copy of this object or a subobject of it - template - bool GetThisObject(T &object) const - { - return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object); - } - - //! get a pointer to this object, as a pointer to T - template - bool GetThisPointer(T *&p) const - { - return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p); - } - - //! get a named value, returns true if the name exists - template - bool GetValue(const char *name, T &value) const - { - return GetVoidValue(name, typeid(T), &value); - } - - //! get a named value, returns the default if the name doesn't exist - template - T GetValueWithDefault(const char *name, T defaultValue) const - { - GetValue(name, defaultValue); - return defaultValue; - } - - //! get a list of value names that can be retrieved - CRYPTOPP_DLL std::string GetValueNames() const - {std::string result; GetValue("ValueNames", result); return result;} - - //! get a named value with type int - /*! used to ensure we don't accidentally try to get an unsigned int - or some other type when we mean int (which is the most common case) */ - CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const - {return GetValue(name, value);} - - //! get a named value with type int, with default - CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const - {return GetValueWithDefault(name, defaultValue);} - - //! used by derived classes to check for type mismatch - CRYPTOPP_DLL static void ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving) - {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);} - - template - void GetRequiredParameter(const char *className, const char *name, T &value) const - { - if (!GetValue(name, value)) - throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); - } - - CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const - { - if (!GetIntValue(name, value)) - throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); - } - - //! to be implemented by derived classes, users should use one of the above functions instead - CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0; -}; - -//! empty set of name-value pairs -class CRYPTOPP_DLL NullNameValuePairs : public NameValuePairs -{ -public: - bool GetVoidValue(const char* /* name */, const std::type_info& /* valueType */, void* /* pValue */) const {return false;} - NullNameValuePairs() {} -}; - -//! _ -extern CRYPTOPP_DLL const NullNameValuePairs g_nullNameValuePairs; - -// ******************************************************** - -//! interface for cloning objects, this is not implemented by most classes yet -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable -{ -public: - virtual ~Clonable() {} - //! this is not implemented by most classes yet - virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");} // TODO: make this =0 -}; - -//! interface for all crypto algorithms - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable -{ -public: - /*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true, - this constructor throws SelfTestFailure if the self test hasn't been run or fails. */ - Algorithm(bool checkSelfTestStatus = true); - //! returns name of this algorithm, not universally implemented yet - virtual std::string AlgorithmName() const {return "unknown";} -}; - -//! keying interface for crypto algorithms that take byte strings as keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface -{ -public: - virtual ~SimpleKeyingInterface() {}; - - //! returns smallest valid key length in bytes */ - virtual unsigned int MinKeyLength() const =0; - //! returns largest valid key length in bytes */ - virtual unsigned int MaxKeyLength() const =0; - //! returns default (recommended) key length in bytes */ - virtual unsigned int DefaultKeyLength() const =0; - - //! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength()) - virtual unsigned int GetValidKeyLength(unsigned int n) const =0; - - //! returns whether n is a valid key length - virtual bool IsValidKeyLength(unsigned int n) const - {return n == GetValidKeyLength(n);} - - //! set or reset the key of this object - /*! \param params is used to specify Rounds, BlockSize, etc */ - virtual void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms = g_nullNameValuePairs) =0; - - //! calls SetKey() with an NameValuePairs object that just specifies "Rounds" - void SetKeyWithRounds(const byte *key, unsigned int length, int rounds); - - //! calls SetKey() with an NameValuePairs object that just specifies "IV" - void SetKeyWithIV(const byte *key, unsigned int length, const byte *iv); - - enum IV_Requirement {STRUCTURED_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE}; - //! returns the minimal requirement for secure IVs - virtual IV_Requirement IVRequirement() const =0; - - //! returns whether this object can be resynchronized (i.e. supports initialization vectors) - /*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */ - bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;} - //! returns whether this object can use random IVs (in addition to ones returned by GetNextIV) - bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;} - //! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV) - bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;} - //! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV) - bool CanUseStructuredIVs() const {return IVRequirement() <= STRUCTURED_IV;} - - //! returns size of IVs used by this object - virtual unsigned int IVSize() const {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} - //! resynchronize with an IV - virtual void Resynchronize(const byte* /* IV */) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} - //! get a secure IV for the next message - /*! 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()");} - -protected: - void ThrowIfInvalidKeyLength(const Algorithm &algorithm, unsigned int length); - void ThrowIfResynchronizable(); // to be called when no IV is passed - void ThrowIfInvalidIV(const byte *iv); // check for NULL IV if it can't be used - const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms); - - inline void AssertValidKeyLength(unsigned int length) const - { - assert(IsValidKeyLength(length)); - } -}; - -//! interface for the data processing part of block ciphers - -/*! Classes derived from BlockTransformation are block ciphers - in ECB mode (for example the DES::Encryption class), which are stateless, - and they can make assumptions about the memory alignment of their inputs and outputs. - These classes should not be used directly, but only in combination with - a mode class (see CipherModeDocumentation in modes.h). -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm -{ -public: - //! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock - virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0; - - //! encrypt or decrypt one block - /*! \pre size of inBlock and outBlock == BlockSize() */ - void ProcessBlock(const byte *inBlock, byte *outBlock) const - {ProcessAndXorBlock(inBlock, NULL, outBlock);} - - //! encrypt or decrypt one block in place - void ProcessBlock(byte *inoutBlock) const - {ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);} - - //! block size of the cipher in bytes - virtual unsigned int BlockSize() const =0; - - //! block pointers must be divisible by this - virtual unsigned int BlockAlignment() const {return 4;} - - //! returns true if this is a permutation (i.e. there is an inverse transformation) - virtual bool IsPermutation() const {return true;} - - //! returns true if this is an encryption object - virtual bool IsForwardTransformation() const =0; - - //! return number of blocks that can be processed in parallel, for bit-slicing implementations - virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;} - - //! encrypt or decrypt multiple blocks, for bit-slicing implementations - virtual void ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, unsigned int numberOfBlocks) const; -}; - -//! interface for the data processing part of stream ciphers - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm -{ -public: - //! return a reference to this object, - /*! This function is useful for passing a temporary StreamTransformation object to a - function that takes a non-const reference. */ - StreamTransformation& Ref() {return *this;} - - //! returns block size, if input must be processed in blocks, otherwise 1 - virtual unsigned int MandatoryBlockSize() const {return 1;} - - //! returns the input block size that is most efficient for this cipher - /*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */ - virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();} - //! returns how much of the current block is used up - virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;} - - //! returns how input should be aligned for optimal performance - virtual unsigned int OptimalDataAlignment() const {return 1;} - - //! encrypt or decrypt an array of bytes of specified length - /*! \note either inString == outString, or they don't overlap */ - virtual void ProcessData(byte *outString, const byte *inString, unsigned int length) =0; - - //! for ciphers where the last block of data is special, encrypt or decrypt the last block of data - /*! For now the only use of this function is for CBC-CTS mode. */ - virtual void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length); - //! returns the minimum size of the last block, 0 indicating the last block is not special - virtual unsigned int MinLastBlockSize() const {return 0;} - - //! same as ProcessData(inoutString, inoutString, length) - inline void ProcessString(byte *inoutString, unsigned int length) - {ProcessData(inoutString, inoutString, length);} - //! same as ProcessData(outString, inString, length) - inline void ProcessString(byte *outString, const byte *inString, unsigned int length) - {ProcessData(outString, inString, length);} - //! implemented as {ProcessData(&input, &input, 1); return input;} - inline byte ProcessByte(byte input) - {ProcessData(&input, &input, 1); return input;} - - //! returns whether this cipher supports random access - virtual bool IsRandomAccess() const =0; - //! for random access ciphers, seek to an absolute position - virtual void Seek(lword /* n */) - { - assert(!IsRandomAccess()); - throw NotImplemented("StreamTransformation: this object doesn't support random access"); - } - - //! returns whether this transformation is self-inverting (e.g. xor with a keystream) - virtual bool IsSelfInverting() const =0; - //! returns whether this is an encryption object - virtual bool IsForwardTransformation() const =0; -}; - -//! interface for hash functions and data processing part of MACs - -/*! HashTransformation objects are stateful. They are created in an initial state, - change state as Update() is called, and return to the initial - state when Final() is called. This interface allows a large message to - be hashed in pieces by calling Update() on each piece followed by - calling Final(). -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm -{ -public: - //! process more input - virtual void Update(const byte *input, unsigned int length) =0; - - //! request space to write input into - virtual byte * CreateUpdateSpace(unsigned int &size) {size=0; return NULL;} - - //! compute hash for current message, then restart for a new message - /*! \pre size of digest == DigestSize(). */ - virtual void Final(byte *digest) - {TruncatedFinal(digest, DigestSize());} - - //! discard the current state, and restart with a new message - virtual void Restart() - {TruncatedFinal(NULL, 0);} - - //! size of the hash returned by Final() - virtual unsigned int DigestSize() const =0; - - //! block size of underlying compression function, or 0 if not block based - virtual unsigned int BlockSize() const {return 0;} - - //! input to Update() should have length a multiple of this for optimal speed - virtual unsigned int OptimalBlockSize() const {return 1;} - - //! returns how input should be aligned for optimal performance - virtual unsigned int OptimalDataAlignment() const {return 1;} - - //! use this if your input is in one piece and you don't want to call Update() and Final() separately - virtual void CalculateDigest(byte *digest, const byte *input, unsigned int length) - {Update(input, length); Final(digest);} - - //! verify that digest is a valid digest for the current message, then reinitialize the object - /*! Default implementation is to call Final() and do a bitwise comparison - between its output and digest. */ - virtual bool Verify(const byte *digest) - {return TruncatedVerify(digest, DigestSize());} - - //! use this if your input is in one piece and you don't want to call Update() and Verify() separately - virtual bool VerifyDigest(const byte *digest, const byte *input, unsigned int length) - {Update(input, length); return Verify(digest);} - - //! truncated version of Final() - virtual void TruncatedFinal(byte *digest, unsigned int digestSize) =0; - - //! truncated version of CalculateDigest() - virtual void CalculateTruncatedDigest(byte *digest, unsigned int digestSize, const byte *input, unsigned int length) - {Update(input, length); TruncatedFinal(digest, digestSize);} - - //! truncated version of Verify() - virtual bool TruncatedVerify(const byte *digest, unsigned int digestLength); - - //! truncated version of VerifyDigest() - virtual bool VerifyTruncatedDigest(const byte *digest, unsigned int digestLength, const byte *input, unsigned int length) - {Update(input, length); return TruncatedVerify(digest, digestLength);} - -protected: - void ThrowIfInvalidTruncatedSize(unsigned int size) const; -}; - -typedef HashTransformation HashFunction; - -template -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyedTransformation : public T, public SimpleKeyingInterface -{ -public: - void ThrowIfInvalidKeyLength(unsigned int length) - {SimpleKeyingInterface::ThrowIfInvalidKeyLength(*this, length);} -}; - -typedef SimpleKeyedTransformation BlockCipher; -typedef SimpleKeyedTransformation SymmetricCipher; -typedef SimpleKeyedTransformation MessageAuthenticationCode; - -//! interface for random number generators -/*! All return values are uniformly distributed over the range specified. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm -{ -public: - //! generate new random byte and return it - virtual byte GenerateByte() =0; - - //! generate new random bit and return it - /*! Default implementation is to call GenerateByte() and return its parity. */ - 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, unsigned int size); - - //! generate and discard n bytes - /*! Default implementation is to call GenerateByte() n times. */ - virtual void DiscardBytes(unsigned int n); - - //! randomly shuffle the specified array, resulting permutation is uniformly distributed - template void Shuffle(IT begin, IT end) - { - for (; begin != end; ++begin) - std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1)); - } - -}; - -//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it -CRYPTOPP_DLL RandomNumberGenerator & NullRNG(); - -class WaitObjectContainer; - -//! interface for objects that you can wait for - -class CRYPTOPP_NO_VTABLE Waitable -{ -public: - virtual ~Waitable() {}; - - //! maximum number of wait objects that this object can return - virtual unsigned int GetMaxWaitObjectCount() const =0; - //! put wait objects into container - virtual void GetWaitObjects(WaitObjectContainer &container) =0; - //! wait on this object - /*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */ - bool Wait(unsigned long milliseconds); -}; - -//! interface for buffered transformations - -/*! BufferedTransformation is a generalization of BlockTransformation, - StreamTransformation, and HashTransformation. - - A buffered transformation is an object that takes a stream of bytes - as input (this may be done in stages), does some computation on them, and - then places the result into an internal buffer for later retrieval. Any - partial result already in the output buffer is not modified by further - input. - - If a method takes a "blocking" parameter, and you - pass "false" for it, the method will return before all input has been processed if - the input cannot be processed without waiting (for network buffers to become available, for example). - In this case the method will return true - or a non-zero integer value. When this happens you must continue to call the method with the same - parameters until it returns false or zero, before calling any other method on it or - attached BufferedTransformation. The integer return value in this case is approximately - the number of bytes left to be processed, and can be used to implement a progress bar. - - For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached - BufferedTransformation objects, with propagation decremented at each step until it reaches 0. - -1 means unlimited propagation. - - \nosubgrouping -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable -{ -public: - // placed up here for CW8 - static const std::string NULL_CHANNEL; // the empty string "" - - BufferedTransformation() : Algorithm(false) {} - - //! return a reference to this object - /*! This function is useful for passing a temporary BufferedTransformation object to a - function that takes a non-const reference. */ - BufferedTransformation& Ref() {return *this;} - - //! \name INPUT - //@{ - //! input a byte for processing - unsigned int Put(byte inByte, bool blocking=true) - {return Put(&inByte, 1, blocking);} - //! input multiple bytes - unsigned int Put(const byte *inString, unsigned int length, bool blocking=true) - {return Put2(inString, length, 0, blocking);} - - //! input a 16-bit word - unsigned int PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - //! input a 32-bit word - unsigned int PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - - //! request space which can be written into by the caller, and then used as input to Put() - /*! \param size is requested size (as a hint) for input, and size of the returned space for output */ - /*! \note The purpose of this method is to help avoid doing extra memory allocations. */ - virtual byte * CreatePutSpace(unsigned int &size) {size=0; return NULL;} - - virtual bool CanModifyInput() const {return false;} - - //! input multiple bytes that may be modified by callee - unsigned int PutModifiable(byte *inString, unsigned int length, bool blocking=true) - {return PutModifiable2(inString, length, 0, blocking);} - - bool MessageEnd(int propagation=-1, bool blocking=true) - {return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} - unsigned int PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1, bool blocking=true) - {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);} - - //! input multiple bytes for blocking or non-blocking processing - /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ - virtual unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) =0; - //! input multiple bytes that may be modified by callee for blocking or non-blocking processing - /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ - virtual unsigned int PutModifiable2(byte *inString, unsigned int length, int messageEnd, bool blocking) - {return Put2(inString, length, messageEnd, blocking);} - - //! thrown by objects that have not implemented nonblocking input processing - struct BlockingInputOnly : public NotImplemented - {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}}; - //@} - - //! \name WAITING - //@{ - unsigned int GetMaxWaitObjectCount() const; - void GetWaitObjects(WaitObjectContainer &container); - //@} - - //! \name SIGNALS - //@{ - virtual void IsolatedInitialize(const NameValuePairs& /* parameters */) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");} - virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0; - virtual bool IsolatedMessageSeriesEnd(bool /* blocking */) {return false;} - - //! initialize or reinitialize this object - virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); - //! flush buffered input and/or output - /*! \param hardFlush is used to indicate whether all data should be flushed - \note Hard flushes must be used with care. It means try to process and output everything, even if - there may not be enough data to complete the action. For example, hard flushing a HexDecoder would - cause an error if you do it after inputing an odd number of hex encoded characters. - For some types of filters, for example ZlibDecompressor, hard flushes can only - be done at "synchronization points". These synchronization points are positions in the data - stream that are created by hard flushes on the corresponding reverse filters, in this - example ZlibCompressor. This is useful when zlib compressed data is moved across a - network in packets and compression state is preserved across packets, as in the ssh2 protocol. - */ - virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); - //! mark end of a series of messages - /*! There should be a MessageEnd immediately before MessageSeriesEnd. */ - virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true); - - //! set propagation of automatically generated and transferred signals - /*! propagation == 0 means do not automaticly generate signals */ - virtual void SetAutoSignalPropagation(int /* propagation */) {} - - //! - virtual int GetAutoSignalPropagation() const {return 0;} -public: - - //@} - - //! \name RETRIEVAL OF ONE MESSAGE - //@{ - //! returns number of bytes that is currently ready for retrieval - /*! All retrieval functions return the actual number of bytes - retrieved, which is the lesser of the request number and - MaxRetrievable(). */ - virtual unsigned long MaxRetrievable() const; - - //! returns whether any bytes are currently ready for retrieval - virtual bool AnyRetrievable() const; - - //! try to retrieve a single byte - virtual unsigned int Get(byte &outByte); - //! try to retrieve multiple bytes - virtual unsigned int Get(byte *outString, unsigned int getMax); - - //! peek at the next byte without removing it from the output buffer - virtual unsigned int Peek(byte &outByte) const; - //! peek at multiple bytes without removing them from the output buffer - virtual unsigned int Peek(byte *outString, unsigned int peekMax) const; - - //! try to retrieve a 16-bit word - unsigned int GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER); - //! try to retrieve a 32-bit word - unsigned int GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER); - - //! try to peek at a 16-bit word - unsigned int PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER); - //! try to peek at a 32-bit word - unsigned int PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER); - - //! move transferMax bytes of the buffered output to target as input - unsigned long TransferTo(BufferedTransformation &target, unsigned long transferMax=ULONG_MAX, const std::string &channel=NULL_CHANNEL) - {TransferTo2(target, transferMax, channel); return transferMax;} - - //! discard skipMax bytes from the output buffer - virtual unsigned long Skip(unsigned long skipMax=ULONG_MAX); - - //! copy copyMax bytes of the buffered output to target as input - unsigned long CopyTo(BufferedTransformation &target, unsigned long copyMax=ULONG_MAX, const std::string &channel=NULL_CHANNEL) const - {return CopyRangeTo(target, 0, copyMax, channel);} - - //! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input - unsigned long CopyRangeTo(BufferedTransformation &target, unsigned long position, unsigned long copyMax=ULONG_MAX, const std::string &channel=NULL_CHANNEL) const - {unsigned long i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;} - - //@} - - //! \name RETRIEVAL OF MULTIPLE MESSAGES - //@{ - //! - virtual unsigned long TotalBytesRetrievable() const; - //! number of times MessageEnd() has been received minus messages retrieved or skipped - virtual unsigned int NumberOfMessages() const; - //! returns true if NumberOfMessages() > 0 - virtual bool AnyMessages() const; - //! start retrieving the next message - /*! - Returns false if no more messages exist or this message - is not completely retrieved. - */ - virtual bool GetNextMessage(); - //! skip count number of messages - virtual unsigned int SkipMessages(unsigned int count=UINT_MAX); - //! - unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) - {TransferMessagesTo2(target, count, channel); return count;} - //! - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const; - - //! - virtual void SkipAll(); - //! - void TransferAllTo(BufferedTransformation &target, const std::string &channel=NULL_CHANNEL) - {TransferAllTo2(target, channel);} - //! - void CopyAllTo(BufferedTransformation &target, const std::string &channel=NULL_CHANNEL) const; - - virtual bool GetNextMessageSeries() {return false;} - virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();} - virtual unsigned int NumberOfMessageSeries() const {return 0;} - //@} - - //! \name NON-BLOCKING TRANSFER OF OUTPUT - //@{ - virtual unsigned int TransferTo2(BufferedTransformation &target, unsigned long &byteCount, const std::string &channel=NULL_CHANNEL, bool blocking=true) =0; - virtual unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const =0; - unsigned int TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int TransferAllTo2(BufferedTransformation &target, const std::string &channel=NULL_CHANNEL, bool blocking=true); - //@} - - //! \name CHANNELS - //@{ - struct NoChannelSupport : public NotImplemented - {NoChannelSupport() : NotImplemented("BufferedTransformation: this object doesn't support multiple channels") {}}; - - unsigned int ChannelPut(const std::string &channel, byte inByte, bool blocking=true) - {return ChannelPut(channel, &inByte, 1, blocking);} - unsigned int ChannelPut(const std::string &channel, const byte *inString, unsigned int length, bool blocking=true) - {return ChannelPut2(channel, inString, length, 0, blocking);} - - unsigned int ChannelPutModifiable(const std::string &channel, byte *inString, unsigned int length, bool blocking=true) - {return ChannelPutModifiable2(channel, inString, length, 0, blocking);} - - unsigned int ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - unsigned int ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - - bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} - unsigned int ChannelPutMessageEnd(const std::string &channel, const byte *inString, unsigned int length, int propagation=-1, bool blocking=true) - {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);} - - virtual byte * ChannelCreatePutSpace(const std::string &channel, unsigned int &size); - - virtual unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking); - virtual unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking); - - virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true); - virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); - - virtual void SetRetrievalChannel(const std::string &channel); - //@} - - //! \name ATTACHMENT - /*! Some BufferedTransformation objects (e.g. Filter objects) - allow other BufferedTransformation objects to be attached. When - this is done, the first object instead of buffering its output, - sents that output to the attached object as input. The entire - attachment chain is deleted when the anchor object is destructed. - */ - //@{ - //! returns whether this object allows attachment - virtual bool Attachable() {return false;} - //! returns the object immediately attached to this object or NULL for no attachment - virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;} - //! - virtual const BufferedTransformation *AttachedTransformation() const - {return const_cast(this)->AttachedTransformation();} - //! delete the current attachment chain and replace it with newAttachment - virtual void Detach(BufferedTransformation* /* newAttachment */ = 0) - {assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");} - //! add newAttachment to the end of attachment chain - virtual void Attach(BufferedTransformation *newAttachment); - //@} - -protected: - static int DecrementPropagation(int propagation) - {return propagation != 0 ? propagation - 1 : 0;} -}; - -//! returns a reference to a BufferedTransformation object that discards all input -BufferedTransformation & TheBitBucket(); - -//! interface for crypto material, such as public and private keys, and crypto parameters - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs -{ -public: - //! exception thrown when invalid crypto material is detected - class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat - { - public: - explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {} - }; - - //! assign values from source to this object - /*! \note This function can be used to create a public key from a private key. */ - virtual void AssignFrom(const NameValuePairs &source) =0; - - //! check this object for errors - /*! \param level denotes the level of thoroughness: - 0 - using this object won't cause a crash or exception (rng is ignored) - 1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such) - 2 - make sure this object will function correctly, and do reasonable security checks - 3 - do checks that may take a long time - \return true if the tests pass */ - virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0; - - //! throws InvalidMaterial if this object fails Validate() test - virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const - {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");} - -// virtual std::vector GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false); - - //! save key into a BufferedTransformation - virtual void Save(BufferedTransformation& /* bt */) const - {throw NotImplemented("CryptoMaterial: this object does not support saving");} - - //! load key from a BufferedTransformation - /*! \throws KeyingErr if decode fails - \note Generally does not check that the key is valid. - Call ValidateKey() or ThrowIfInvalidKey() to check that. */ - virtual void Load(BufferedTransformation& /* bt */) - {throw NotImplemented("CryptoMaterial: this object does not support loading");} - - //! \return whether this object supports precomputation - virtual bool SupportsPrecomputation() const {return false;} - //! do precomputation - /*! The exact semantics of Precompute() is varies, but - typically it means calculate a table of n objects - that can be used later to speed up computation. */ - virtual void Precompute(unsigned int /* n */) - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - //! retrieve previously saved precomputation - virtual void LoadPrecomputation(BufferedTransformation& /* storedPrecomputation */) - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - //! save precomputation for later use - virtual void SavePrecomputation(BufferedTransformation& /* storedPrecomputation */) const - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - - // for internal library use - void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);} -}; - -//! interface for generatable crypto material, such as private keys and crypto parameters - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial -{ -public: - //! generate a random key or crypto parameters - /*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated - (e.g., if this is a public key object) */ - virtual void GenerateRandom(RandomNumberGenerator& /* rng */, const NameValuePairs& /* params */ = g_nullNameValuePairs) - {throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");} - - //! calls the above function with a NameValuePairs object that just specifies "KeySize" - void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize); -}; - -//! interface for public keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial -{ -}; - -//! interface for private keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial -{ -}; - -//! interface for asymmetric algorithms - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm -{ -public: - //! returns a reference to the crypto material used by this object - virtual CryptoMaterial & AccessMaterial() =0; - //! returns a const reference to the crypto material used by this object - virtual const CryptoMaterial & GetMaterial() const =0; - - //! for backwards compatibility, calls AccessMaterial().Load(bt) - void BERDecode(BufferedTransformation &bt) - {AccessMaterial().Load(bt);} - //! for backwards compatibility, calls GetMaterial().Save(bt) - void DEREncode(BufferedTransformation &bt) const - {GetMaterial().Save(bt);} -}; - -//! interface for asymmetric algorithms using public keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm -{ -public: - // VC60 workaround: no co-variant return type - CryptoMaterial & AccessMaterial() {return AccessPublicKey();} - const CryptoMaterial & GetMaterial() const {return GetPublicKey();} - - virtual PublicKey & AccessPublicKey() =0; - virtual const PublicKey & GetPublicKey() const {return const_cast(this)->AccessPublicKey();} -}; - -//! interface for asymmetric algorithms using private keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm -{ -public: - CryptoMaterial & AccessMaterial() {return AccessPrivateKey();} - const CryptoMaterial & GetMaterial() const {return GetPrivateKey();} - - virtual PrivateKey & AccessPrivateKey() =0; - virtual const PrivateKey & GetPrivateKey() const {return const_cast(this)->AccessPrivateKey();} -}; - -/*! This class provides an interface common to encryptors and decryptors - for querying their plaintext and ciphertext lengths. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem -{ -public: - virtual ~PK_CryptoSystem() {} - - //! maximum length of plaintext for a given ciphertext length - /*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */ - virtual unsigned int MaxPlaintextLength(unsigned int ciphertextLength) const =0; - - //! calculate length of ciphertext given length of plaintext - /*! \note This function returns 0 if plaintextLength is not valid (too long). */ - virtual unsigned int CiphertextLength(unsigned int plaintextLength) const =0; - - //! this object supports the use of the parameter with the given name - /*! some possible parameter names: EncodingParameters, KeyDerivationParameters */ - virtual bool ParameterSupported(const char *name) const =0; - - //! return fixed ciphertext length, if one exists, otherwise return 0 - /*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext. - It usually does depend on the key length. */ - virtual unsigned int FixedCiphertextLength() const {return 0;} - - //! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0 - virtual unsigned int FixedMaxPlaintextLength() const {return 0;} - -}; - -//! interface for public-key encryptors -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : virtual public PK_CryptoSystem, public PublicKeyAlgorithm -{ -public: - //! exception thrown when trying to encrypt plaintext of invalid length - class CRYPTOPP_DLL InvalidPlaintextLength : public Exception - { - public: - InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {} - }; - - //! encrypt a byte string - /*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long) - \pre size of ciphertext == CiphertextLength(plaintextLength) - */ - virtual void Encrypt(RandomNumberGenerator &rng, - const byte *plaintext, unsigned int plaintextLength, - byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; - - //! create a new encryption filter - /*! \note The caller is responsible for deleting the returned pointer. - \note Encoding parameters should be passed in the "EP" channel. - */ - virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, - BufferedTransformation *attachment=NULL, const NameValuePairs ¶meters = g_nullNameValuePairs) const; -}; - -//! interface for public-key signers and verifiers - -/*! This class provides an interface common to signers and verifiers - for querying scheme properties. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme -{ -public: - //! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used - class CRYPTOPP_DLL InvalidKeyLength : public Exception - { - public: - InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {} - }; - - //! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything - class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength - { - public: - KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {} - }; - - virtual ~PK_SignatureScheme() {} - - //! signature length if it only depends on the key, otherwise 0 - virtual unsigned int SignatureLength() const =0; - - //! maximum signature length produced for a given length of recoverable message part - virtual unsigned int MaxSignatureLength(unsigned int /* recoverablePartLength */ = 0) const {return SignatureLength();} - - //! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery - virtual unsigned int MaxRecoverableLength() const =0; - - //! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery - virtual unsigned int MaxRecoverableLengthFromSignatureLength(unsigned int signatureLength) const =0; - - //! requires a random number generator to sign - /*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */ - virtual bool IsProbabilistic() const =0; - - //! whether or not a non-recoverable message part can be signed - virtual bool AllowNonrecoverablePart() const =0; - - //! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */ - virtual bool SignatureUpfront() const {return false;} - - //! whether you must input the recoverable part before the non-recoverable part during signing - virtual bool RecoverablePartFirst() const =0; -}; - -//! interface for accumulating messages to be signed or verified -/*! Only Update() should be called - on this class. No other functions inherited from HashTransformation should be called. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation -{ -public: - //! should not be called on PK_MessageAccumulator - unsigned int DigestSize() const - {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");} - //! should not be called on PK_MessageAccumulator - void TruncatedFinal(byte* /* digest */, unsigned int /* digestSize */) - {throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");} -}; - -//! interface for public-key signers - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm -{ -public: - //! create a new HashTransformation to accumulate the message to be signed - virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0; - - virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const =0; - - //! sign and delete messageAccumulator (even in case of exception thrown) - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual unsigned int Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const; - - //! sign and restart messageAccumulator - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual unsigned int SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0; - - //! sign a message - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual unsigned int SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const; - - //! sign a recoverable message - /*! \pre size of signature == MaxSignatureLength(recoverableMessageLength) - \return actual signature length - */ - virtual unsigned int SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength, - const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength, byte *signature) const; -}; - -//! interface for public-key signature verifiers -/*! The Recover* functions throw NotImplemented if the signature scheme does not support - message recovery. - The Verify* functions throw InvalidDataFormat if the scheme does support message - recovery and the signature contains a non-empty recoverable message part. The - Recovery* functions should be used in that case. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm -{ -public: - //! create a new HashTransformation to accumulate the message to be verified - virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0; - - //! input signature into a message accumulator - virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const =0; - - //! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown) - virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const; - - //! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator - virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0; - - //! check whether input signature is a valid signature for input message - virtual bool VerifyMessage(const byte *message, unsigned int messageLen, - const byte *signature, unsigned int signatureLength) const; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult RecoverMessage(byte *recoveredMessage, - const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength, - const byte *signature, unsigned int signatureLength) const; -}; - -//! interface for domains of authenticated key agreement protocols - -//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation -class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument -{ -public: - BERDecodeErr() : InvalidArgument("BER decode error") {} - BERDecodeErr(const std::string &s) : InvalidArgument(s) {} -}; - -//! interface for encoding and decoding ASN1 objects -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object -{ -public: - virtual ~ASN1Object() {} - //! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules) - virtual void BERDecode(BufferedTransformation &bt) =0; - //! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules) - virtual void DEREncode(BufferedTransformation &bt) const =0; - //! encode this object into a BufferedTransformation, using BER - /*! this may be useful if DEREncode() would be too inefficient */ - virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);} -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_SMARTPTR_H -#define CRYPTOPP_SMARTPTR_H - -//- #include "config.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -template class simple_ptr -{ -public: - simple_ptr() : m_p(NULL) {} - ~simple_ptr() {delete m_p;} - T *m_p; -}; - -template class member_ptr -{ -public: - explicit member_ptr(T *p = NULL) : m_p(p) {} - - ~member_ptr(); - - const T& operator*() const { return *m_p; } - T& operator*() { return *m_p; } - - const T* operator->() const { return m_p; } - T* operator->() { return m_p; } - - const T* get() const { return m_p; } - T* get() { return m_p; } - - T* release() - { - T *old_p = m_p; - m_p = 0; - return old_p; - } - - void reset(T *p = 0); - -protected: - member_ptr(const member_ptr& rhs); // copy not allowed - void operator=(const member_ptr& rhs); // assignment not allowed - - T *m_p; -}; - -template member_ptr::~member_ptr() {delete m_p;} -template void member_ptr::reset(T *p) {delete m_p; m_p = p;} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_MISC_H -#define CRYPTOPP_MISC_H - -//- #include "cryptlib.h" -//- #include "smartptr.h" - -#ifdef INTEL_INTRINSICS -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -// ************** compile-time assertion *************** - -template -struct CompileTimeAssert; - -template<> -struct CompileTimeAssert {}; - -#if defined(_WIN32) || defined(__CYGWIN__) -#define CRYPTOPP_COMPILE_ASSERT( x ) -#define CRYPTOPP_COMPILE_ASSERT_GLOBAL(assertion) -#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) -#define CRYPTOPP_ASSERT_JOIN(X, Y) -#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) - -#else -#define CRYPTOPP_COMPILE_ASSERT( x ) \ - { CompileTimeAssert<((x) != 0)> ERROR; (void)ERROR; } - -#define CRYPTOPP_COMPILE_ASSERT_GLOBAL(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__) -#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS) -#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) -#else -#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) \ - CompileTimeAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance) -#endif -#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y) -#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y -#endif - -// ************** misc classes *************** - -class CRYPTOPP_DLL Empty -{ -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2 -{ -}; - -template -class ObjectHolder -{ -protected: - T m_object; -}; - -class NotCopyable -{ -public: - NotCopyable() {} -private: - NotCopyable(const NotCopyable &); - void operator=(const NotCopyable &); -}; - -template -struct NewObject -{ - T* operator()() const {return new T;} -}; - -/*! This function safely initializes a static object in a multithreaded environment without using locks. - It may leak memory when two threads try to initialize the static object at the same time - but this should be acceptable since each static object is only initialized once per session. -*/ -template , int instance=0> -class Singleton -{ -public: - Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} - - // VC60 workaround: use "..." to prevent this function from being inlined - const T & Ref(...) const; - -private: - F m_objectFactory; -}; - -template -const T & Singleton::Ref(...) const -{ - static simple_ptr s_pObject; - static char s_objectState = 0; - -retry: - switch (s_objectState) - { - case 0: - s_objectState = 1; - try - { - s_pObject.m_p = m_objectFactory(); - } - catch(...) - { - s_objectState = 0; - throw; - } - s_objectState = 2; - break; - case 1: - goto retry; - default: - break; - } - return *s_pObject.m_p; -} - -// ************** misc functions *************** - -// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0 -template inline const T& STDMIN(const T& a, const T& b) -{ - return b < a ? b : a; -} - -template inline const T& STDMAX(const T& a, const T& b) -{ - return a < b ? b : a; -} - -#define RETURN_IF_NONZERO(x) unsigned int returnedValue = x; if (returnedValue) return returnedValue - -// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack -#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y))) -// these may be faster on other CPUs/compilers -// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255) -// #define GETBYTE(x, y) (((byte *)&(x))[y]) - -CRYPTOPP_DLL unsigned int Parity(unsigned long); -CRYPTOPP_DLL unsigned long Crop(unsigned long, unsigned int size); - -template -unsigned int BitPrecision(const T &value) -{ - if (!value) - return 0; - - unsigned int l=0, h=8*sizeof(value); - - while (h-l > 1) - { - unsigned int t = (l+h)/2; - if (value >> t) - l = t; - else - h = t; - } - - return h; -} - -template -unsigned int BytePrecision(const T &value) -{ - unsigned int i; - for (i=sizeof(value); i; --i) - if (value >> (i-1)*8) - break; - - return i; -} - -inline unsigned int BitsToBytes(unsigned int bitCount) -{ - return ((bitCount+7)/(8)); -} - -inline unsigned int BytesToWords(unsigned int byteCount) -{ - return ((byteCount+WORD_SIZE-1)/WORD_SIZE); -} - -inline unsigned int BitsToWords(unsigned int bitCount) -{ - return ((bitCount+WORD_BITS-1)/(WORD_BITS)); -} - -inline unsigned int BitsToDwords(unsigned int bitCount) -{ - return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS)); -} - -CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, unsigned int count); -CRYPTOPP_DLL void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count); - -template -inline bool IsPowerOf2(T n) -{ - return n > 0 && (n & (n-1)) == 0; -} - -template -inline T2 ModPowerOf2(T1 a, T2 b) -{ - assert(IsPowerOf2(b)); - return T2(a) & (b-1); -} - -template -inline T RoundDownToMultipleOf(T n, T m) -{ - return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m)); -} - -template -inline T RoundUpToMultipleOf(T n, T m) -{ - return RoundDownToMultipleOf(n+m-1, m); -} - -template -inline unsigned int GetAlignment(T* /* dummy */ = NULL) // VC60 workaround -{ -#if defined(__GNUC__) - return __alignof__(T); -#elif defined(_MSC_VER) and (_MSC_VER >= 1300) - return __alignof(T); -#else - return sizeof(T); -#endif -} - -inline bool IsAlignedOn(const void *p, unsigned int alignment) -{ - return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0; -} - -template -inline bool IsAligned(const void *p, T* /* dummy */ = NULL) // VC60 workaround -{ - return IsAlignedOn(p, GetAlignment()); -} - -#ifdef IS_LITTLE_ENDIAN - typedef LittleEndian NativeByteOrder; -#else - typedef BigEndian NativeByteOrder; -#endif - -inline ByteOrder GetNativeByteOrder() -{ - return NativeByteOrder::ToEnum(); -} - -inline bool NativeByteOrderIs(ByteOrder order) -{ - return order == GetNativeByteOrder(); -} - -template // can't use because GCC 2.95.2 doesn't have it -inline std::string IntToString(T a, unsigned int base = 10) -{ - if (a == 0) - return "0"; - bool negate = false; - if (a < 0) - { - negate = true; - a = 0-a; // VC .NET does not like -a - } - std::string result; - while (a > 0) - { - T digit = a % base; - result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result; - a /= base; - } - if (negate) - result = "-" + result; - return result; -} - -// Avoid warnings about compare against zero for unsigned -template <> // can't use because GCC 2.95.2 doesn't have it -inline std::string IntToString(unsigned int a, unsigned int base) -{ - if (a == 0) - return "0"; - std::string result; - while (a > 0) - { - unsigned digit = a % base; - result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result; - a /= base; - } - return result; -} - -template -inline T1 SaturatingSubtract(T1 a, T2 b) -{ - CRYPTOPP_COMPILE_ASSERT(T1(-1)>0); // T1 is unsigned type - CRYPTOPP_COMPILE_ASSERT(T2(-1)>0); // T2 is unsigned type - return T1((a > b) ? (a - b) : 0); -} - -template -inline CipherDir GetCipherDir(const T &obj) -{ - return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; -} - -void CallNewHandler(); - -// ************** rotate functions *************** - -template inline T rotlFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -template inline T rotlVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -template inline T rotlMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return (x<>(sizeof(T)*8-y)); -} - -template inline T rotrMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return (x>>y) | (x<<(sizeof(T)*8-y)); -} - -#ifdef INTEL_INTRINSICS - -#pragma intrinsic(_lrotl, _lrotr) - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? _lrotl(x, y) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? _lrotr(x, y) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return _lrotl(x, y); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return _lrotr(x, y); -} - -template<> inline word32 rotlMod(word32 x, unsigned int y) -{ - return _lrotl(x, y); -} - -template<> inline word32 rotrMod(word32 x, unsigned int y) -{ - return _lrotr(x, y); -} - -#endif // #ifdef INTEL_INTRINSICS - -#ifdef PPC_INTRINSICS - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,y,0,31) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,32-y,0,31) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return (__rlwnm(x,y,0,31)); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return (__rlwnm(x,32-y,0,31)); -} - -template<> inline word32 rotlMod(word32 x, unsigned int y) -{ - return (__rlwnm(x,y,0,31)); -} - -template<> inline word32 rotrMod(word32 x, unsigned int y) -{ - return (__rlwnm(x,32-y,0,31)); -} - -#endif // #ifdef PPC_INTRINSICS - -// ************** endian reversal *************** - -template -inline unsigned int GetByte(ByteOrder order, T value, unsigned int index) -{ - if (order == LITTLE_ENDIAN_ORDER) - return GETBYTE(value, index); - else - return GETBYTE(value, sizeof(T)-index-1); -} - -inline byte ByteReverse(byte value) -{ - return value; -} - -inline word16 ByteReverse(word16 value) -{ - return rotlFixed(value, 8U); -} - -inline word32 ByteReverse(word32 value) -{ -#ifdef PPC_INTRINSICS - // PPC: load reverse indexed instruction - return (word32)__lwbrx(&value,0); -#elif defined(FAST_ROTATE) - // 5 instructions with rotate instruction, 9 without - return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); -#else - // 6 instructions with rotate instruction, 8 without - value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); - return rotlFixed(value, 16U); -#endif -} - -#ifdef WORD64_AVAILABLE -inline word64 ByteReverse(word64 value) -{ -#ifdef CRYPTOPP_SLOW_WORD64 - return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); - value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); - return rotlFixed(value, 32U); -#endif -} -#endif - -inline byte BitReverse(byte value) -{ - value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); - value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); - return rotlFixed(value, 4); -} - -inline word16 BitReverse(word16 value) -{ - value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1); - value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2); - value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4); - return ByteReverse(value); -} - -inline word32 BitReverse(word32 value) -{ - value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4); - return ByteReverse(value); -} - -#ifdef WORD64_AVAILABLE -inline word64 BitReverse(word64 value) -{ -#ifdef CRYPTOPP_SLOW_WORD64 - return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1); - value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2); - value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4); - return ByteReverse(value); -#endif -} -#endif - -template -inline T BitReverse(T value) -{ - if (sizeof(T) == 1) - return (T)BitReverse((byte)value); - else if (sizeof(T) == 2) - return (T)BitReverse((word16)value); - else if (sizeof(T) == 4) - return (T)BitReverse((word32)value); - else - { -#ifdef WORD64_AVAILABLE - assert(sizeof(T) == 8); - return (T)BitReverse((word64)value); -#else - assert(false); - return 0; -#endif - } -} - -template -inline T ConditionalByteReverse(ByteOrder order, T value) -{ - return NativeByteOrderIs(order) ? value : ByteReverse(value); -} - -template -void ByteReverse(T *out, const T *in, unsigned int byteCount) -{ - assert(byteCount % sizeof(T) == 0); - unsigned int count = byteCount/sizeof(T); - for (unsigned int i=0; i -inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount) -{ - if (!NativeByteOrderIs(order)) - ByteReverse(out, in, byteCount); - else if (in != out) - memcpy(out, in, byteCount); -} - -template -inline void GetUserKey(ByteOrder order, T *out, unsigned int outlen, const byte *in, unsigned int inlen) -{ - const unsigned int U = sizeof(T); - assert(inlen <= outlen*U); - memcpy(out, in, inlen); - memset((byte *)out+inlen, 0, outlen*U-inlen); - ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U)); -} - -inline byte UnalignedGetWordNonTemplate(ByteOrder /*order*/, const byte *block, byte*) -{ - return block[0]; -} - -inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*) -{ - return (order == BIG_ENDIAN_ORDER) - ? block[1] | (block[0] << 8) - : block[0] | (block[1] << 8); -} - -inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*) -{ - return (order == BIG_ENDIAN_ORDER) - ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24) - : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24); -} - -#ifdef WORD64_AVAILABLE -inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word64*) -{ - return (order == BIG_ENDIAN_ORDER) - ? - (word64(block[7]) | - (word64(block[6]) << 8) | - (word64(block[5]) << 16) | - (word64(block[4]) << 24) | - (word64(block[3]) << 32) | - (word64(block[2]) << 40) | - (word64(block[1]) << 48) | - (word64(block[0]) << 56)) - : - (word64(block[0]) | - (word64(block[1]) << 8) | - (word64(block[2]) << 16) | - (word64(block[3]) << 24) | - (word64(block[4]) << 32) | - (word64(block[5]) << 40) | - (word64(block[6]) << 48) | - (word64(block[7]) << 56)); -} -#endif - -template -inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL) -{ - return UnalignedGetWordNonTemplate(order, block, dummy); -} - -inline void UnalignedPutWord(ByteOrder /*order*/, byte *block, byte value, const byte *xorBlock = NULL) -{ - block[0] = xorBlock ? (value ^ xorBlock[0]) : value; -} - -inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL) -{ - if (order == BIG_ENDIAN_ORDER) - { - block[0] = GETBYTE(value, 1); - block[1] = GETBYTE(value, 0); - } - else - { - block[0] = GETBYTE(value, 0); - block[1] = GETBYTE(value, 1); - } - - if (xorBlock) - { - block[0] ^= xorBlock[0]; - block[1] ^= xorBlock[1]; - } -} - -inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL) -{ - if (order == BIG_ENDIAN_ORDER) - { - block[0] = GETBYTE(value, 3); - block[1] = GETBYTE(value, 2); - block[2] = GETBYTE(value, 1); - block[3] = GETBYTE(value, 0); - } - else - { - block[0] = GETBYTE(value, 0); - block[1] = GETBYTE(value, 1); - block[2] = GETBYTE(value, 2); - block[3] = GETBYTE(value, 3); - } - - if (xorBlock) - { - block[0] ^= xorBlock[0]; - block[1] ^= xorBlock[1]; - block[2] ^= xorBlock[2]; - block[3] ^= xorBlock[3]; - } -} - -#ifdef WORD64_AVAILABLE -inline void UnalignedPutWord(ByteOrder order, byte *block, word64 value, const byte *xorBlock = NULL) -{ - if (order == BIG_ENDIAN_ORDER) - { - block[0] = GETBYTE(value, 7); - block[1] = GETBYTE(value, 6); - block[2] = GETBYTE(value, 5); - block[3] = GETBYTE(value, 4); - block[4] = GETBYTE(value, 3); - block[5] = GETBYTE(value, 2); - block[6] = GETBYTE(value, 1); - block[7] = GETBYTE(value, 0); - } - else - { - block[0] = GETBYTE(value, 0); - block[1] = GETBYTE(value, 1); - block[2] = GETBYTE(value, 2); - block[3] = GETBYTE(value, 3); - block[4] = GETBYTE(value, 4); - block[5] = GETBYTE(value, 5); - block[6] = GETBYTE(value, 6); - block[7] = GETBYTE(value, 7); - } - - if (xorBlock) - { - block[0] ^= xorBlock[0]; - block[1] ^= xorBlock[1]; - block[2] ^= xorBlock[2]; - block[3] ^= xorBlock[3]; - block[4] ^= xorBlock[4]; - block[5] ^= xorBlock[5]; - block[6] ^= xorBlock[6]; - block[7] ^= xorBlock[7]; - } -} -#endif - -template -inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) -{ - if (assumeAligned) - { - assert(IsAligned(block)); - return ConditionalByteReverse(order, *reinterpret_cast(block)); - } - else - return UnalignedGetWord(order, block); -} - -template -inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block) -{ - result = GetWord(assumeAligned, order, block); -} - -template -inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL) -{ - if (assumeAligned) - { - assert(IsAligned(block)); - if (xorBlock) - *reinterpret_cast(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast(xorBlock); - else - *reinterpret_cast(block) = ConditionalByteReverse(order, value); - } - else - UnalignedPutWord(order, block, value, xorBlock); -} - -template -class GetBlock -{ -public: - GetBlock(const void *block) - : m_block((const byte *)block) {} - - template - inline GetBlock & operator()(U &x) - { - CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); - x = GetWord(A, B::ToEnum(), m_block); - m_block += sizeof(T); - return *this; - } - -private: - const byte *m_block; -}; - -// ************** help remove warning on g++ *************** - -template struct SafeShifter; - -template<> struct SafeShifter -{ - template - static inline T RightShift(T /* value */, unsigned int /* bits */) - { - return 0; - } - - template - static inline T LeftShift(T /* value */, unsigned int /* bits */) - { - return 0; - } -}; - -template<> struct SafeShifter -{ - template - static inline T RightShift(T value, unsigned int bits) - { - return value >> bits; - } - - template - static inline T LeftShift(T value, unsigned int bits) - { - return value << bits; - } -}; - -template -inline T SafeRightShift(T value) -{ - return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); -} - -template -inline T SafeLeftShift(T value) -{ - return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits); -} - -NAMESPACE_END - -#endif // MISC_H -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// secblock.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_SECBLOCK_H -#define CRYPTOPP_SECBLOCK_H - -//- #include "config.h" -//- #include "misc.h" -#include // CodeWarrior doesn't have memory.h -#include - -NAMESPACE_BEGIN(CryptoPP) - -// ************** secure memory allocation *************** - -template -class AllocatorBase -{ -public: - typedef T value_type; - typedef size_t size_type; -#ifdef CRYPTOPP_MSVCRT6 - typedef ptrdiff_t difference_type; -#else - typedef std::ptrdiff_t difference_type; -#endif - typedef T * pointer; - typedef const T * const_pointer; - typedef T & reference; - typedef const T & const_reference; - - pointer address(reference r) const {return (&r);} - const_pointer address(const_reference r) const {return (&r); } - void construct(pointer p, const T& val) {new (p) T(val);} - void destroy(pointer p) {p->~T();} - size_type max_size() const {return ~size_type(0)/sizeof(T);} // switch to std::numeric_limits::max later - -protected: - static void CheckSize(size_t n) - { - if (n > ~size_t(0) / sizeof(T)) - throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); - } -}; - -#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ -typedef typename AllocatorBase::value_type value_type;\ -typedef typename AllocatorBase::size_type size_type;\ -typedef typename AllocatorBase::difference_type difference_type;\ -typedef typename AllocatorBase::pointer pointer;\ -typedef typename AllocatorBase::const_pointer const_pointer;\ -typedef typename AllocatorBase::reference reference;\ -typedef typename AllocatorBase::const_reference const_reference; - -template -typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) -{ - if (oldSize == newSize) - return p; - - if (preserve) - { - A b; - typename A::pointer newPointer = b.allocate(newSize, NULL); - memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize)); - a.deallocate(p, oldSize); - std::swap(a, b); - return newPointer; - } - else - { - a.deallocate(p, oldSize); - return a.allocate(newSize, NULL); - } -} - -template -class AllocatorWithCleanup : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - pointer allocate(size_type n, const void * = NULL) - { - this->CheckSize(n); - if (n == 0) - return NULL; - return new T[n]; - } - - void deallocate(void *p, size_type n) - { - memset(p, 0, n*sizeof(T)); - delete [] (T *)p; - } - - pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve) - { - return StandardReallocate(*this, p, oldSize, newSize, preserve); - } - - // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a - // template class member called rebind". - template struct rebind { typedef AllocatorWithCleanup other; }; -}; - -template -class NullAllocator : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - pointer allocate(size_type /* n */, const void * = NULL) - { - assert(false); - return NULL; - } - - void deallocate(void* /* p */, size_type /* n */) - { - assert(false); - } - - size_type max_size() const {return 0;} -}; - -// This allocator can't be used with standard collections because -// they require that all objects of the same allocator type are equivalent. -// So this is for use with SecBlock only. -template > -class FixedSizeAllocatorWithCleanup : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - FixedSizeAllocatorWithCleanup() : m_allocated(false) {} - - pointer allocate(size_type n) - { - if (n <= S && !m_allocated) - { - m_allocated = true; - return m_array; - } - else - return m_fallbackAllocator.allocate(n); - } - - pointer allocate(size_type n, const void *hint) - { - if (n <= S && !m_allocated) - { - m_allocated = true; - return m_array; - } - else - return m_fallbackAllocator.allocate(n, hint); - } - - void deallocate(void *p, size_type n) - { - if (p == m_array) - { - assert(n <= S); - assert(m_allocated); - m_allocated = false; - memset(p, 0, n*sizeof(T)); - } - else - m_fallbackAllocator.deallocate(p, n); - } - - pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve) - { - if (p == m_array && newSize <= S) - { - assert(oldSize <= S); - if (oldSize > newSize) - memset(p + newSize, 0, (oldSize-newSize)*sizeof(T)); - return p; - } - - pointer newPointer = allocate(newSize, NULL); - if (preserve) - memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize)); - deallocate(p, oldSize); - return newPointer; - } - - size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);} - -private: - T m_array[S]; - A m_fallbackAllocator; - bool m_allocated; -}; - -//! a block of memory allocated using A -template > -class SecBlock -{ -public: - explicit SecBlock(unsigned int blocksize=0) - : m_size(blocksize) {m_ptr = m_alloc.allocate(blocksize, NULL);} - SecBlock(const SecBlock &t) - : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));} - SecBlock(const T *t, unsigned int len) - : m_size(len) - { - m_ptr = m_alloc.allocate(len, NULL); - if (t == NULL) - memset(m_ptr, 0, len*sizeof(T)); - else - memcpy(m_ptr, t, len*sizeof(T)); - } - - ~SecBlock() - {m_alloc.deallocate(m_ptr, m_size);} - - operator const void *() const - {return m_ptr;} - operator void *() - {return m_ptr;} -#if defined(__GNUC__) && __GNUC__ < 3 // reduce warnings - operator const void *() - {return m_ptr;} -#endif - - operator const T *() const - {return m_ptr;} - operator T *() - {return m_ptr;} -#if defined(__GNUC__) && __GNUC__ < 3 // reduce warnings - operator const T *() - {return m_ptr;} -#endif - - template - T *operator +(I offset) - {return m_ptr+offset;} - - template - const T *operator +(I offset) const - {return m_ptr+offset;} - - template - T& operator[](I index) - {assert((unsigned int)index < m_size); return m_ptr[index];} - - template - const T& operator[](I index) const - {assert((unsigned int)index < m_size); return m_ptr[index];} - - typedef typename A::value_type value_type; - typedef typename A::pointer iterator; - typedef typename A::const_pointer const_iterator; - typedef typename A::size_type size_type; - - iterator begin() - {return m_ptr;} - const_iterator begin() const - {return m_ptr;} - iterator end() - {return m_ptr+m_size;} - const_iterator end() const - {return m_ptr+m_size;} - - typename A::pointer data() {return m_ptr;} - typename A::const_pointer data() const {return m_ptr;} - - size_type size() const {return m_size;} - bool empty() const {return m_size == 0;} - - void Assign(const T *t, unsigned int len) - { - New(len); - memcpy(m_ptr, t, len*sizeof(T)); - } - - void Assign(const SecBlock &t) - { - New(t.m_size); - memcpy(m_ptr, t.m_ptr, m_size*sizeof(T)); - } - - SecBlock& operator=(const SecBlock &t) - { - Assign(t); - return *this; - } - - bool operator==(const SecBlock &t) const - { - return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0; - } - - bool operator!=(const SecBlock &t) const - { - return !operator==(t); - } - - void New(unsigned int newSize) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); - m_size = newSize; - } - - void CleanNew(unsigned int newSize) - { - New(newSize); - memset(m_ptr, 0, m_size*sizeof(T)); - } - - void Grow(unsigned int newSize) - { - if (newSize > m_size) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - m_size = newSize; - } - } - - void CleanGrow(unsigned int newSize) - { - if (newSize > m_size) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); - m_size = newSize; - } - } - - void resize(unsigned int newSize) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - m_size = newSize; - } - - void swap(SecBlock &b) - { - std::swap(m_alloc, b.m_alloc); - std::swap(m_size, b.m_size); - std::swap(m_ptr, b.m_ptr); - } - -//private: - A m_alloc; - unsigned int m_size; - T *m_ptr; -}; - -typedef SecBlock SecByteBlock; -typedef SecBlock SecWordBlock; - -template > -class FixedSizeSecBlock : public SecBlock -{ -public: - explicit FixedSizeSecBlock() : SecBlock(S) {} -}; - -template -inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} -template -inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template -inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) -{ - a.swap(b); -} - -#if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES) -template -inline CryptoPP::AllocatorWithCleanup<_Tp2>& -__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) -{ - return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); -} -#endif - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_INTEGER_H -#define CRYPTOPP_INTEGER_H - -/** \file */ - -//- #include "cryptlib.h" -//- #include "secblock.h" - -#include -#include - -#ifdef CRYPTOPP_X86ASM_AVAILABLE - -#ifdef _M_IX86 - #if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || (defined(__ICL) && (__ICL >= 500)) - #define SSE2_INTRINSICS_AVAILABLE - #define CRYPTOPP_MM_MALLOC_AVAILABLE - #elif defined(_MSC_VER) - // _mm_free seems to be the only way to tell if the Processor Pack is installed or not - #include - #if defined(_mm_free) - #define SSE2_INTRINSICS_AVAILABLE - #define CRYPTOPP_MM_MALLOC_AVAILABLE - #endif - #endif -#endif - -// SSE2 intrinsics work in GCC 3.3 or later -#if defined(__SSE2__) && (__GNUC__ > 3 || __GNUC_MINOR__ > 2) - #define SSE2_INTRINSICS_AVAILABLE -#endif - -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#if defined(SSE2_INTRINSICS_AVAILABLE) - template - class AlignedAllocator : public AllocatorBase - { - public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - pointer allocate(size_type n, const void *); - void deallocate(void *p, size_type n); - pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve) - { - return StandardReallocate(*this, p, oldSize, newSize, preserve); - } - - #if !(defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16) || defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE)) - #define CRYPTOPP_NO_ALIGNED_ALLOC - AlignedAllocator() : m_pBlock(NULL) {} - protected: - void *m_pBlock; - #endif - }; - - template class CRYPTOPP_DLL AlignedAllocator; - typedef SecBlock > SecAlignedWordBlock; -#else - typedef SecWordBlock SecAlignedWordBlock; -#endif - -void CRYPTOPP_DLL DisableSSE2(); - -//! multiple precision integer and basic arithmetics -/*! This class can represent positive and negative integers - with absolute value less than (256**sizeof(word)) ** (256**sizeof(int)). - \nosubgrouping -*/ -class CRYPTOPP_DLL Integer : public ASN1Object -{ -public: - //! \name ENUMS, EXCEPTIONS, and TYPEDEFS - //@{ - //! division by zero exception - class DivideByZero : public Exception - { - public: - DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {} - }; - - //! - class RandomNumberNotFound : public Exception - { - public: - RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {} - }; - - //! - enum Sign {POSITIVE=0, NEGATIVE=1}; - - //! - enum Signedness { - //! - UNSIGNED, - //! - SIGNED}; - - //! - enum RandomNumberType { - //! - ANY, - //! - PRIME}; - //@} - - //! \name CREATORS - //@{ - //! creates the zero integer - Integer(); - - //! copy constructor - Integer(const Integer& t); - - //! convert from signed long - Integer(signed long value); - - //! convert from lword - Integer(Sign s, lword value); - - //! convert from two words - Integer(Sign s, word highWord, word lowWord); - - //! convert from string - /*! str can be in base 2, 8, 10, or 16. Base is determined by a - case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. - */ - explicit Integer(const char *str); - explicit Integer(const wchar_t *str); - - //! convert from big-endian byte array - Integer(const byte *encodedInteger, unsigned int byteCount, Signedness s=UNSIGNED); - - //! convert from big-endian form stored in a BufferedTransformation - Integer(BufferedTransformation &bt, unsigned int byteCount, Signedness s=UNSIGNED); - - //! convert from BER encoded byte array stored in a BufferedTransformation object - explicit Integer(BufferedTransformation &bt); - - //! create a random integer - /*! The random integer created is uniformly distributed over [0, 2**bitcount). */ - Integer(RandomNumberGenerator &rng, unsigned int bitcount); - - //! avoid calling constructors for these frequently used integers - static const Integer &Zero(); - //! avoid calling constructors for these frequently used integers - static const Integer &One(); - //! avoid calling constructors for these frequently used integers - static const Integer &Two(); - - //! create a random integer of special type - /*! Ideally, the random integer created should be uniformly distributed - over {x | min <= x <= max and x is of rnType and x % mod == equiv}. - However the actual distribution may not be uniform because sequential - search is used to find an appropriate number from a random starting - point. - May return (with very small probability) a pseudoprime when a prime - is requested and max > lastSmallPrime*lastSmallPrime (lastSmallPrime - is declared in nbtheory.h). - \throw RandomNumberNotFound if the set is empty. - */ - Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One()); - - //! return the integer 2**e - static Integer Power2(unsigned int e); - //@} - - //! \name ENCODE/DECODE - //@{ - //! minimum number of bytes to encode this integer - /*! MinEncodedSize of 0 is 1 */ - unsigned int MinEncodedSize(Signedness=UNSIGNED) const; - //! encode in big-endian format - /*! unsigned means encode absolute value, signed means encode two's complement if negative. - if outputLen < MinEncodedSize, the most significant bytes will be dropped - if outputLen > MinEncodedSize, the most significant bytes will be padded - */ - unsigned int Encode(byte *output, unsigned int outputLen, Signedness=UNSIGNED) const; - //! - unsigned int Encode(BufferedTransformation &bt, unsigned int outputLen, Signedness=UNSIGNED) const; - - //! encode using Distinguished Encoding Rules, put result into a BufferedTransformation object - void DEREncode(BufferedTransformation &bt) const; - - //! encode absolute value as big-endian octet string - void DEREncodeAsOctetString(BufferedTransformation &bt, unsigned int length) const; - - //! encode absolute value in OpenPGP format, return length of output - unsigned int OpenPGPEncode(byte *output, unsigned int bufferSize) const; - //! encode absolute value in OpenPGP format, put result into a BufferedTransformation object - unsigned int OpenPGPEncode(BufferedTransformation &bt) const; - - //! - void Decode(const byte *input, unsigned int inputLen, Signedness=UNSIGNED); - //! - //* Precondition: bt.MaxRetrievable() >= inputLen - void Decode(BufferedTransformation &bt, unsigned int inputLen, Signedness=UNSIGNED); - - //! - void BERDecode(const byte *input, unsigned int inputLen); - //! - void BERDecode(BufferedTransformation &bt); - - //! decode nonnegative value as big-endian octet string - void BERDecodeAsOctetString(BufferedTransformation &bt, unsigned int length); - - class OpenPGPDecodeErr : public Exception - { - public: - OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {} - }; - - //! - void OpenPGPDecode(const byte *input, unsigned int inputLen); - //! - void OpenPGPDecode(BufferedTransformation &bt); - //@} - - //! \name ACCESSORS - //@{ - //! return true if *this can be represented as a signed long - bool IsConvertableToLong() const; - //! return equivalent signed long if possible, otherwise undefined - signed long ConvertToLong() const; - - //! number of significant bits = floor(log2(abs(*this))) + 1 - unsigned int BitCount() const; - //! number of significant bytes = ceiling(BitCount()/8) - unsigned int ByteCount() const; - //! number of significant words = ceiling(ByteCount()/sizeof(word)) - unsigned int WordCount() const; - - //! return the i-th bit, i=0 being the least significant bit - bool GetBit(unsigned int i) const; - //! return the i-th byte - byte GetByte(unsigned int i) const; - //! return n lowest bits of *this >> i - unsigned long GetBits(unsigned int i, unsigned int n) const; - - //! - bool IsZero() const {return !*this;} - //! - bool NotZero() const {return !IsZero();} - //! - bool IsNegative() const {return sign == NEGATIVE;} - //! - bool NotNegative() const {return !IsNegative();} - //! - bool IsPositive() const {return NotNegative() && NotZero();} - //! - bool NotPositive() const {return !IsPositive();} - //! - bool IsEven() const {return GetBit(0) == 0;} - //! - bool IsOdd() const {return GetBit(0) == 1;} - //@} - - //! \name MANIPULATORS - //@{ - //! - Integer& operator=(const Integer& t); - - //! - Integer& operator+=(const Integer& t); - //! - Integer& operator-=(const Integer& t); - //! - Integer& operator*=(const Integer& t) {return *this = Times(t);} - //! - Integer& operator/=(const Integer& t) {return *this = DividedBy(t);} - //! - Integer& operator%=(const Integer& t) {return *this = Modulo(t);} - //! - Integer& operator/=(word t) {return *this = DividedBy(t);} - //! - Integer& operator%=(word t) {return *this = Modulo(t);} - - //! - Integer& operator<<=(unsigned int); - //! - Integer& operator>>=(unsigned int); - - //! - void Randomize(RandomNumberGenerator &rng, unsigned int bitcount); - //! - void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max); - //! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv} - /*! returns false if the set is empty */ - bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One()); - - bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs); - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) - { - if (!GenerateRandomNoThrow(rng, params)) - throw RandomNumberNotFound(); - } - - //! set the n-th bit to value - void SetBit(unsigned int n, bool value=1); - //! set the n-th byte to value - void SetByte(unsigned int n, byte value); - - //! - void Negate(); - //! - void SetPositive() {sign = POSITIVE;} - //! - void SetNegative() {if (!!(*this)) sign = NEGATIVE;} - - //! - void swap(Integer &a); - //@} - - //! \name UNARY OPERATORS - //@{ - //! - bool operator!() const; - //! - Integer operator+() const {return *this;} - //! - Integer operator-() const; - //! - Integer& operator++(); - //! - Integer& operator--(); - //! - Integer operator++(int) {Integer temp = *this; ++*this; return temp;} - //! - Integer operator--(int) {Integer temp = *this; --*this; return temp;} - //@} - - //! \name BINARY OPERATORS - //@{ - //! signed comparison - /*! \retval -1 if *this < a - \retval 0 if *this = a - \retval 1 if *this > a - */ - int Compare(const Integer& a) const; - - //! - Integer Plus(const Integer &b) const; - //! - Integer Minus(const Integer &b) const; - //! - Integer Times(const Integer &b) const; - //! - Integer DividedBy(const Integer &b) const; - //! - Integer Modulo(const Integer &b) const; - //! - Integer DividedBy(word b) const; - //! - word Modulo(word b) const; - - //! - Integer operator>>(unsigned int n) const {return Integer(*this)>>=n;} - //! - Integer operator<<(unsigned int n) const {return Integer(*this)<<=n;} - //@} - - //! \name OTHER ARITHMETIC FUNCTIONS - //@{ - //! - Integer AbsoluteValue() const; - //! - Integer Doubled() const {return Plus(*this);} - //! - Integer Squared() const {return Times(*this);} - //! extract square root, if negative return 0, else return floor of square root - Integer SquareRoot() const; - //! return whether this integer is a perfect square - bool IsSquare() const; - - //! is 1 or -1 - bool IsUnit() const; - //! return inverse if 1 or -1, otherwise return 0 - Integer MultiplicativeInverse() const; - - //! modular multiplication - CRYPTOPP_DLL friend Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m); - //! modular exponentiation - CRYPTOPP_DLL friend Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m); - - //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) - static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d); - //! use a faster division algorithm when divisor is short - static void Divide(word &r, Integer &q, const Integer &a, word d); - - //! returns same result as Divide(r, q, a, Power2(n)), but faster - static void DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n); - - //! greatest common divisor - static Integer Gcd(const Integer &a, const Integer &n); - //! calculate multiplicative inverse of *this mod n - Integer InverseMod(const Integer &n) const; - //! - word InverseMod(word n) const; - //@} - - //! \name INPUT/OUTPUT - //@{ - //! - friend CRYPTOPP_DLL std::istream& operator>>(std::istream& in, Integer &a); - //! - friend CRYPTOPP_DLL std::ostream& operator<<(std::ostream& out, const Integer &a); - //@} - -private: - friend class ModularArithmetic; - friend class MontgomeryRepresentation; - friend class HalfMontgomeryRepresentation; - - Integer(word value, unsigned int length); - - int PositiveCompare(const Integer &t) const; - friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b); - friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b); - friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b); - friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor); - - SecAlignedWordBlock reg; - Sign sign; -}; - -//! -inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;} -//! -inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;} -//! -inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;} -//! -inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;} -//! -inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;} -//! -inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;} -//! -inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);} -//! -inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);} -//! -inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);} -//! -inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);} -//! -inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);} -//! -inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);} -//! -inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);} - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b) -{ - a.swap(b); -} -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_ALGEBRA_H -#define CRYPTOPP_ALGEBRA_H - -//- #include "config.h" - -NAMESPACE_BEGIN(CryptoPP) - -class Integer; - -// "const Element&" returned by member functions are references -// to internal data members. Since each object may have only -// one such data member for holding results, the following code -// will produce incorrect results: -// abcd = group.Add(group.Add(a,b), group.Add(c,d)); -// But this should be fine: -// abcd = group.Add(a, group.Add(b, group.Add(c,d)); - -//! Abstract Group -template class CRYPTOPP_NO_VTABLE AbstractGroup -{ -public: - typedef T Element; - - virtual ~AbstractGroup() {} - - virtual bool Equal(const Element &a, const Element &b) const =0; - virtual const Element& Identity() const =0; - virtual const Element& Add(const Element &a, const Element &b) const =0; - virtual const Element& Inverse(const Element &a) const =0; - virtual bool InversionIsFast() const {return false;} - - virtual const Element& Double(const Element &a) const; - virtual const Element& Subtract(const Element &a, const Element &b) const; - virtual Element& Accumulate(Element &a, const Element &b) const; - virtual Element& Reduce(Element &a, const Element &b) const; - - virtual Element ScalarMultiply(const Element &a, const Integer &e) const; - virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; - - virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; -}; - -//! Abstract Ring -template class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup -{ -public: - typedef T Element; - - AbstractRing() {m_mg.m_pRing = this;} - AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;} - AbstractRing& operator=(const AbstractRing &source) {return *this;} - - virtual bool IsUnit(const Element &a) const =0; - virtual const Element& MultiplicativeIdentity() const =0; - virtual const Element& Multiply(const Element &a, const Element &b) const =0; - virtual const Element& MultiplicativeInverse(const Element &a) const =0; - - virtual const Element& Square(const Element &a) const; - virtual const Element& Divide(const Element &a, const Element &b) const; - - virtual Element Exponentiate(const Element &a, const Integer &e) const; - virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; - - virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - - virtual const AbstractGroup& MultiplicativeGroup() const - {return m_mg;} - -private: - class MultiplicativeGroupT : public AbstractGroup - { - public: - const AbstractRing& GetRing() const - {return *m_pRing;} - - bool Equal(const Element &a, const Element &b) const - {return GetRing().Equal(a, b);} - - const Element& Identity() const - {return GetRing().MultiplicativeIdentity();} - - const Element& Add(const Element &a, const Element &b) const - {return GetRing().Multiply(a, b);} - - Element& Accumulate(Element &a, const Element &b) const - {return a = GetRing().Multiply(a, b);} - - const Element& Inverse(const Element &a) const - {return GetRing().MultiplicativeInverse(a);} - - const Element& Subtract(const Element &a, const Element &b) const - {return GetRing().Divide(a, b);} - - Element& Reduce(Element &a, const Element &b) const - {return a = GetRing().Divide(a, b);} - - const Element& Double(const Element &a) const - {return GetRing().Square(a);} - - Element ScalarMultiply(const Element &a, const Integer &e) const - {return GetRing().Exponentiate(a, e);} - - Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const - {return GetRing().CascadeExponentiate(x, e1, y, e2);} - - void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const - {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);} - - const AbstractRing *m_pRing; - }; - - MultiplicativeGroupT m_mg; -}; - -// ******************************************************** - -//! Abstract Euclidean Domain -template class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing -{ -public: - typedef T Element; - - virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0; - - virtual const Element& Mod(const Element &a, const Element &b) const =0; - virtual const Element& Gcd(const Element &a, const Element &b) const; - -protected: - mutable Element result; -}; - -// ******************************************************** - -//! EuclideanDomainOf -template class EuclideanDomainOf : public AbstractEuclideanDomain -{ -public: - typedef T Element; - - EuclideanDomainOf() {} - - bool Equal(const Element &a, const Element &b) const - {return a==b;} - - const Element& Identity() const - {return Element::Zero();} - - const Element& Add(const Element &a, const Element &b) const - {return result = a+b;} - - Element& Accumulate(Element &a, const Element &b) const - {return a+=b;} - - const Element& Inverse(const Element &a) const - {return result = -a;} - - const Element& Subtract(const Element &a, const Element &b) const - {return result = a-b;} - - Element& Reduce(Element &a, const Element &b) const - {return a-=b;} - - const Element& Double(const Element &a) const - {return result = a.Doubled();} - - const Element& MultiplicativeIdentity() const - {return Element::One();} - - const Element& Multiply(const Element &a, const Element &b) const - {return result = a*b;} - - const Element& Square(const Element &a) const - {return result = a.Squared();} - - bool IsUnit(const Element &a) const - {return a.IsUnit();} - - const Element& MultiplicativeInverse(const Element &a) const - {return result = a.MultiplicativeInverse();} - - const Element& Divide(const Element &a, const Element &b) const - {return result = a/b;} - - const Element& Mod(const Element &a, const Element &b) const - {return result = a%b;} - - void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const - {Element::Divide(r, q, a, d);} - - bool operator==(const EuclideanDomainOf &rhs) const - {return true;} - -private: - mutable Element result; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_MODARITH_H -#define CRYPTOPP_MODARITH_H - -// implementations are in integer.cpp - -//- #include "cryptlib.h" -//- #include "misc.h" -//- #include "integer.h" -//- #include "algebra.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! ring of congruence classes modulo n -/*! \note this implementation represents each congruence class as the smallest non-negative integer in that class */ -class CRYPTOPP_DLL ModularArithmetic : public AbstractRing -{ -public: - - typedef int RandomizationParameter; - typedef Integer Element; - - ModularArithmetic(const Integer &mod = Integer::One()) - : AbstractRing(), - modulus(mod), result((word)0, modulus.reg.size()) {} - - ModularArithmetic(const ModularArithmetic &ma) - : AbstractRing(), - modulus(ma.modulus), result((word)0, modulus.reg.size()) {} - - ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters - - virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);} - - void DEREncode(BufferedTransformation &bt) const; - - void DEREncodeElement(BufferedTransformation &out, const Element &a) const; - void BERDecodeElement(BufferedTransformation &in, Element &a) const; - - const Integer& GetModulus() const {return modulus;} - void SetModulus(const Integer &newModulus) {modulus = newModulus; result.reg.resize(modulus.reg.size());} - - virtual bool IsMontgomeryRepresentation() const {return false;} - - virtual Integer ConvertIn(const Integer &a) const - {return a%modulus;} - - virtual Integer ConvertOut(const Integer &a) const - {return a;} - - const Integer& Half(const Integer &a) const; - - bool Equal(const Integer &a, const Integer &b) const - {return a==b;} - - const Integer& Identity() const - {return Integer::Zero();} - - const Integer& Add(const Integer &a, const Integer &b) const; - - Integer& Accumulate(Integer &a, const Integer &b) const; - - const Integer& Inverse(const Integer &a) const; - - const Integer& Subtract(const Integer &a, const Integer &b) const; - - Integer& Reduce(Integer &a, const Integer &b) const; - - const Integer& Double(const Integer &a) const - {return Add(a, a);} - - const Integer& MultiplicativeIdentity() const - {return Integer::One();} - - const Integer& Multiply(const Integer &a, const Integer &b) const - {return result1 = a*b%modulus;} - - const Integer& Square(const Integer &a) const - {return result1 = a.Squared()%modulus;} - - bool IsUnit(const Integer &a) const - {return Integer::Gcd(a, modulus).IsUnit();} - - const Integer& MultiplicativeInverse(const Integer &a) const - {return result1 = a.InverseMod(modulus);} - - const Integer& Divide(const Integer &a, const Integer &b) const - {return Multiply(a, MultiplicativeInverse(b));} - - Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const; - - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - - unsigned int MaxElementBitLength() const - {return (modulus-1).BitCount();} - - unsigned int MaxElementByteLength() const - {return (modulus-1).ByteCount();} - - Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter& /*ignore_for_now*/ = 0 ) const - // left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct - { - return Element( rng , Integer( (long) 0) , modulus - Integer( (long) 1 ) ) ; - } - - bool operator==(const ModularArithmetic &rhs) const - {return modulus == rhs.modulus;} - - static const RandomizationParameter DefaultRandomizationParameter ; - -protected: - Integer modulus; - mutable Integer result, result1; - -}; - -// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ; - -//! do modular arithmetics in Montgomery representation for increased speed -/*! \note the Montgomery representation represents each congruence class [a] as a*r%n, where r is a convenient power of 2 */ -class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic -{ -public: - MontgomeryRepresentation(const Integer &modulus); // modulus must be odd - - virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);} - - bool IsMontgomeryRepresentation() const {return true;} - - Integer ConvertIn(const Integer &a) const - {return (a<<(WORD_BITS*modulus.reg.size()))%modulus;} - - Integer ConvertOut(const Integer &a) const; - - const Integer& MultiplicativeIdentity() const - {return result1 = Integer::Power2(WORD_BITS*modulus.reg.size())%modulus;} - - const Integer& Multiply(const Integer &a, const Integer &b) const; - - const Integer& Square(const Integer &a) const; - - const Integer& MultiplicativeInverse(const Integer &a) const; - - Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const - {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} - - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const - {AbstractRing::SimultaneousExponentiate(results, base, exponents, exponentsCount);} - -private: - Integer u; - mutable SecAlignedWordBlock workspace; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -// simple.h - written and placed in the public domain by Wei Dai -/*! \file - Simple non-interface classes derived from classes in cryptlib.h. -*/ - -#ifndef CRYPTOPP_SIMPLE_H -#define CRYPTOPP_SIMPLE_H - -//- #include "cryptlib.h" -//- #include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -template -class CRYPTOPP_NO_VTABLE ClonableImpl : public BASE -{ -public: - Clonable * Clone() const {return new DERIVED(*static_cast(this));} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE AlgorithmImpl : public BASE -{ -public: - static std::string StaticAlgorithmName() {return ALGORITHM_INFO::StaticAlgorithmName();} - std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();} -}; - -//! _ -class CRYPTOPP_DLL InvalidKeyLength : public InvalidArgument -{ -public: - explicit InvalidKeyLength(const std::string &algorithm, unsigned int length) : InvalidArgument(algorithm + ": " + IntToString(length, 10) + " is not a valid key length") {} -}; - -//! _ -// TODO: look into this virtual inheritance -class CRYPTOPP_DLL ASN1CryptoMaterial : virtual public ASN1Object, virtual public CryptoMaterial -{ -public: - void Save(BufferedTransformation &bt) const - {BEREncode(bt);} - void Load(BufferedTransformation &bt) - {BERDecode(bt);} -}; - -// ***************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE Bufferless : public T -{ -public: - bool IsolatedFlush(bool /* hardFlush */, bool /* blocking */) {return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE Unflushable : public T -{ -public: - bool Flush(bool completeFlush, int propagation=-1, bool blocking=true) - {return ChannelFlush(this->NULL_CHANNEL, completeFlush, propagation, blocking);} - bool IsolatedFlush(bool /* hardFlush */, bool /* blocking */) - {assert(false); return false;} - bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) - { - if (hardFlush && !InputBufferIsEmpty()) - throw CannotFlush("Unflushable: this object has buffered input that cannot be flushed"); - else - { - BufferedTransformation *attached = this->AttachedTransformation(); - return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false; - } - } - -protected: - virtual bool InputBufferIsEmpty() const {return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE InputRejecting : public T -{ -public: - struct InputRejected : public NotImplemented - {InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}}; - - // shouldn't be calling these functions on this class - unsigned int Put2(const byte* /* begin */, unsigned int /* length */, int /* messageEnd */, bool /* blocking */) - {throw InputRejected();} - bool IsolatedFlush(bool, bool) {return false;} - bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();} - - unsigned int ChannelPut2(const std::string& /* channel */, const byte* /* begin */, unsigned int /* length */, int /* messageEnd */, bool /* blocking */) - {throw InputRejected();} - bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE CustomFlushPropagation : public T -{ -public: - virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0; - -private: - bool IsolatedFlush(bool /* hardFlush */, bool /* blocking */) {assert(false); return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation -{ -public: - virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0; - -private: - void IsolatedInitialize(const NameValuePairs& /* parameters */) {assert(false);} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE AutoSignaling : public T -{ -public: - AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {} - - void SetAutoSignalPropagation(int propagation) - {m_autoSignalPropagation = propagation;} - int GetAutoSignalPropagation() const - {return m_autoSignalPropagation;} - -private: - int m_autoSignalPropagation; -}; - -//! A BufferedTransformation that only contains pre-existing data as "output" -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Store : public AutoSignaling > -{ -public: - Store() : m_messageEnd(false) {} - - void IsolatedInitialize(const NameValuePairs ¶meters) - { - m_messageEnd = false; - StoreInitialize(parameters); - } - - unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;} - bool GetNextMessage(); - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const; - -protected: - virtual void StoreInitialize(const NameValuePairs ¶meters) =0; - - bool m_messageEnd; -}; - -//! A BufferedTransformation that doesn't produce any retrievable output -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Sink : public BufferedTransformation -{ -protected: - // make these functions protected to help prevent unintentional calls to them - BufferedTransformation::Get; - BufferedTransformation::Peek; - BufferedTransformation::TransferTo; - BufferedTransformation::CopyTo; - BufferedTransformation::CopyRangeTo; - BufferedTransformation::TransferMessagesTo; - BufferedTransformation::CopyMessagesTo; - BufferedTransformation::TransferAllTo; - BufferedTransformation::CopyAllTo; - unsigned int TransferTo2(BufferedTransformation& /* target */, unsigned long &transferBytes, const std::string& /* channel */ = NULL_CHANNEL, bool /* blocking */ = true) - {transferBytes = 0; return 0;} - unsigned int CopyRangeTo2(BufferedTransformation& /* target */, unsigned long& /* begin */, unsigned long /* end */ = ULONG_MAX, const std::string& /* channel */ = NULL_CHANNEL, bool /* blocking */ = true) const - {return 0;} -}; - -class CRYPTOPP_DLL BitBucket : public Bufferless -{ -public: - std::string AlgorithmName() const {return "BitBucket";} - void IsolatedInitialize(const NameValuePairs& /* parameters */) {} - unsigned int Put2(const byte* /* begin */, unsigned int /* length */, int /* messageEnd */, bool /* blocking */) - {return 0;} -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -// specification file for an unlimited queue for storing bytes - -#ifndef CRYPTOPP_QUEUE_H -#define CRYPTOPP_QUEUE_H - -//- #include "simple.h" -//#include - -NAMESPACE_BEGIN(CryptoPP) - -/** The queue is implemented as a linked list of byte arrays, but you don't need to - know about that. So just ignore this next line. :) */ -class ByteQueueNode; - -//! Byte Queue -class CRYPTOPP_DLL ByteQueue : public Bufferless -{ -public: - ByteQueue(unsigned int nodeSize=0); - ByteQueue(const ByteQueue ©); - ~ByteQueue(); - - unsigned long MaxRetrievable() const - {return CurrentSize();} - bool AnyRetrievable() const - {return !IsEmpty();} - - void IsolatedInitialize(const NameValuePairs ¶meters); - byte * CreatePutSpace(unsigned int &size); - unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking); - - unsigned int Get(byte &outByte); - unsigned int Get(byte *outString, unsigned int getMax); - - unsigned int Peek(byte &outByte) const; - unsigned int Peek(byte *outString, unsigned int peekMax) const; - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - - // these member functions are not inherited - void SetNodeSize(unsigned int nodeSize); - - unsigned long CurrentSize() const; - bool IsEmpty() const; - - void Clear(); - - void Unget(byte inByte); - void Unget(const byte *inString, unsigned int length); - - const byte * Spy(unsigned int &contiguousSize) const; - - void LazyPut(const byte *inString, unsigned int size); - void LazyPutModifiable(byte *inString, unsigned int size); - void UndoLazyPut(unsigned int size); - void FinalizeLazyPut(); - - ByteQueue & operator=(const ByteQueue &rhs); - bool operator==(const ByteQueue &rhs) const; - byte operator[](unsigned long i) const; - void swap(ByteQueue &rhs); - - class Walker : public InputRejecting - { - public: - Walker(const ByteQueue &queue) - : m_queue(queue) {Initialize();} - - unsigned long GetCurrentPosition() {return m_position;} - - unsigned long MaxRetrievable() const - {return m_queue.CurrentSize() - m_position;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - - unsigned int Get(byte &outByte); - unsigned int Get(byte *outString, unsigned int getMax); - - unsigned int Peek(byte &outByte) const; - unsigned int Peek(byte *outString, unsigned int peekMax) const; - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - - private: - const ByteQueue &m_queue; - const ByteQueueNode *m_node; - unsigned long m_position; - unsigned int m_offset; - const byte *m_lazyString; - unsigned int m_lazyLength; - }; - - friend class Walker; - -private: - void CleanupUsedNodes(); - void CopyFrom(const ByteQueue ©); - void Destroy(); - - bool m_autoNodeSize; - unsigned int m_nodeSize; - ByteQueueNode *m_head, *m_tail; - byte *m_lazyString; - unsigned int m_lazyLength; - bool m_lazyStringModifiable; -}; - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b) -{ - a.swap(b); -} -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_ALGPARAM_H -#define CRYPTOPP_ALGPARAM_H - -//- #include "cryptlib.h" -//- #include "smartptr.h" -//- #include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! used to pass byte array input as part of a NameValuePairs object -/*! the deepCopy option is used when the NameValuePairs object can't - keep a copy of the data available */ -class ConstByteArrayParameter -{ -public: - ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false) - { - Assign((const byte *)data, data ? strlen(data) : 0, deepCopy); - } - ConstByteArrayParameter(const byte *data, unsigned int datasize, bool deepCopy = false) - { - Assign(data, datasize, deepCopy); - } - template ConstByteArrayParameter(const T &string, bool deepCopy = false) - { - CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1); - Assign((const byte *)string.data(), string.size(), deepCopy); - } - - void Assign(const byte *data, unsigned int datasize, bool deepCopy) - { - if (deepCopy) - m_block.Assign(data, datasize); - else - { - m_data = data; - m_size = datasize; - } - m_deepCopy = deepCopy; - } - - const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;} - const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;} - unsigned int size() const {return m_deepCopy ? m_block.size() : m_size;} - -private: - bool m_deepCopy; - const byte *m_data; - unsigned int m_size; - SecByteBlock m_block; -}; - -class ByteArrayParameter -{ -public: - ByteArrayParameter(byte *data = NULL, unsigned int datasize = 0) - : m_data(data), m_size(datasize) {} - ByteArrayParameter(SecByteBlock &block) - : m_data(block.begin()), m_size(block.size()) {} - - byte *begin() const {return m_data;} - byte *end() const {return m_data + m_size;} - unsigned int size() const {return m_size;} - -private: - byte *m_data; - unsigned int m_size; -}; - -class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs -{ -public: - CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2) - : m_pairs1(pairs1), m_pairs2(pairs2) {} - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - -private: - const NameValuePairs &m_pairs1, &m_pairs2; -}; - -template -class GetValueHelperClass -{ -public: - GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst) - : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false) - { - if (strcmp(m_name, "ValueNames") == 0) - { - m_found = m_getValueNames = true; - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType); - if (searchFirst) - searchFirst->GetVoidValue(m_name, valueType, pValue); - if (typeid(T) != typeid(BASE)) - pObject->BASE::GetVoidValue(m_name, valueType, pValue); - ((*reinterpret_cast(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';'; - } - - if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType); - *reinterpret_cast(pValue) = pObject; - m_found = true; - return; - } - - if (!m_found && searchFirst) - m_found = searchFirst->GetVoidValue(m_name, valueType, pValue); - - if (!m_found && typeid(T) != typeid(BASE)) - m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue); - } - - operator bool() const {return m_found;} - - template - GetValueHelperClass & operator()(const char *name, const R & (T::*pm)() const) - { - if (m_getValueNames) - (*reinterpret_cast(m_pValue) += name) += ";"; - if (!m_found && strcmp(name, m_name) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType); - *reinterpret_cast(m_pValue) = (m_pObject->*pm)(); - m_found = true; - } - return *this; - } - - GetValueHelperClass &Assignable() - { - if (m_getValueNames) - ((*reinterpret_cast(m_pValue) += "ThisObject:") += typeid(T).name()) += ';'; - if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType); - *reinterpret_cast(m_pValue) = *m_pObject; - m_found = true; - } - return *this; - } - -private: - const T *m_pObject; - const char *m_name; - const std::type_info *m_valueType; - void *m_pValue; - bool m_found, m_getValueNames; -}; - -template -GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE* /* dummy */ = NULL) -{ - return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); -} - -template -GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL) -{ - return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); -} - -// ******************************************************** - -template -R Hack_DefaultValueFromConstReferenceType(const R &) -{ - return R(); -} - -template -bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value) -{ - return source.GetValue(name, const_cast(value)); -} - -template -class AssignFromHelperClass -{ -public: - AssignFromHelperClass(T *pObject, const NameValuePairs &source) - : m_pObject(pObject), m_source(source), m_done(false) - { - if (source.GetThisObject(*pObject)) - m_done = true; - else if (typeid(BASE) != typeid(T)) - pObject->BASE::AssignFrom(source); - } - - template - AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error - { - if (!m_done) - { - R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name, value)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'"); - (m_pObject->*pm)(value); - } - return *this; - } - - template - AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error - { - if (!m_done) - { - R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name1, value1)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'"); - S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name2, value2)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'"); - (m_pObject->*pm)(value1, value2); - } - return *this; - } - -private: - T *m_pObject; - const NameValuePairs &m_source; - bool m_done; -}; - -template -AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source, BASE* /* dummy */ = NULL) -{ - return AssignFromHelperClass(pObject, source); -} - -template -AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) -{ - return AssignFromHelperClass(pObject, source); -} - -// ******************************************************** - -// This should allow the linker to discard Integer code if not needed. -CRYPTOPP_DLL extern bool (*AssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt); - -CRYPTOPP_DLL const std::type_info & IntegerTypeId(); - -class CRYPTOPP_DLL AlgorithmParametersBase : public NameValuePairs -{ -public: - class ParameterNotUsed : public Exception - { - public: - ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {} - }; - - AlgorithmParametersBase(const char *name, bool throwIfNotUsed) - : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {} - - ~AlgorithmParametersBase() - { -#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE - if (!std::uncaught_exception()) -#else - try -#endif - { - if (m_throwIfNotUsed && !m_used) - throw ParameterNotUsed(m_name); - } -#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE - catch(...) - { - } -#endif - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - -protected: - virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0; - virtual const NameValuePairs & GetParent() const =0; - - const char *m_name; - bool m_throwIfNotUsed; - mutable bool m_used; -}; - -template -class AlgorithmParametersBase2 : public AlgorithmParametersBase -{ -public: - AlgorithmParametersBase2(const char *name, const T &value, bool throwIfNotUsed) : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value) {} - - void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const - { - // special case for retrieving an Integer parameter when an int was passed in - if (!(AssignIntToInteger != NULL && typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value))) - { - ThrowIfTypeMismatch(name, typeid(T), valueType); - *reinterpret_cast(pValue) = m_value; - } - } - -protected: - T m_value; -}; - -template -class AlgorithmParameters : public AlgorithmParametersBase2 -{ -public: - AlgorithmParameters(const PARENT &parent, const char *name, const T &value, bool throwIfNotUsed) - : AlgorithmParametersBase2(name, value, throwIfNotUsed), m_parent(parent) - {} - - AlgorithmParameters(const AlgorithmParameters ©) - : AlgorithmParametersBase2(copy), m_parent(copy.m_parent) - { - copy.m_used = true; - } - - template - AlgorithmParameters, R> operator()(const char *name, const R &value) const - { - return AlgorithmParameters, R>(*this, name, value, this->m_throwIfNotUsed); - } - - template - AlgorithmParameters, R> operator()(const char *name, const R &value, bool throwIfNotUsed) const - { - return AlgorithmParameters, R>(*this, name, value, throwIfNotUsed); - } - -private: - const NameValuePairs & GetParent() const {return m_parent;} - PARENT m_parent; -}; - -//! Create an object that implements NameValuePairs for passing parameters -/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed - \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(), - such as MSVC 7.0 and earlier. - \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by - repeatedly using operator() on the object returned by MakeParameters, for example: - const NameValuePairs ¶meters = MakeParameters(name1, value1)(name2, value2)(name3, value3); -*/ -template -AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true) -{ - return AlgorithmParameters(g_nullNameValuePairs, name, value, throwIfNotUsed); -} - -#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name) -#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name) -#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2) - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_FILTERS_H -#define CRYPTOPP_FILTERS_H - -//- #include "simple.h" -//- #include "secblock.h" -//- #include "misc.h" -//- #include "smartptr.h" -//- #include "queue.h" -//- #include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// provides an implementation of BufferedTransformation's attachment interface -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable -{ -public: - Filter(BufferedTransformation *attachment = NULL); - - bool Attachable() {return true;} - BufferedTransformation *AttachedTransformation(); - const BufferedTransformation *AttachedTransformation() const; - void Detach(BufferedTransformation *newAttachment = NULL); - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - - void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); - bool MessageSeriesEnd(int propagation=-1, bool blocking=true); - -protected: - virtual BufferedTransformation * NewDefaultAttachment() const; - void Insert(Filter *nextFilter); // insert filter after this one - - virtual bool ShouldPropagateMessageEnd() const {return true;} - virtual bool ShouldPropagateMessageSeriesEnd() const {return true;} - - void PropagateInitialize(const NameValuePairs ¶meters, int propagation); - - unsigned int Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel=NULL_CHANNEL); - unsigned int OutputModifiable(int outputSite, byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel=NULL_CHANNEL); - bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL); - bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL); - bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL); - -private: - member_ptr m_attachment; - -protected: - unsigned int m_inputPosition; - int m_continueAt; -}; - -struct CRYPTOPP_DLL FilterPutSpaceHelper -{ - // desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int desiredSize, unsigned int &bufferSize) - { - assert(desiredSize >= minSize && bufferSize >= minSize); - if (m_tempSpace.size() < minSize) - { - byte *result = target.ChannelCreatePutSpace(channel, desiredSize); - if (desiredSize >= minSize) - { - bufferSize = desiredSize; - return result; - } - m_tempSpace.New(bufferSize); - } - - bufferSize = m_tempSpace.size(); - return m_tempSpace.begin(); - } - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize) - {return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);} - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int bufferSize) - {return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);} - SecByteBlock m_tempSpace; -}; - -/*! FilterWithBufferedInput divides up the input stream into - a first block, a number of middle blocks, and a last block. - First and last blocks are optional, and middle blocks may - be a stream instead (i.e. blockSize == 1). -*/ -class CRYPTOPP_DLL FilterWithBufferedInput : public Filter -{ -public: - FilterWithBufferedInput(BufferedTransformation *attachment); - //! firstSize and lastSize may be 0, blockSize must be at least 1 - FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment); - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) - { - return PutMaybeModifiable(const_cast(inString), length, messageEnd, blocking, false); - } - unsigned int PutModifiable2(byte *inString, unsigned int length, int messageEnd, bool blocking) - { - return PutMaybeModifiable(inString, length, messageEnd, blocking, true); - } - /*! calls ForceNextPut() if hardFlush is true */ - bool IsolatedFlush(bool hardFlush, bool blocking); - - /*! The input buffer may contain more than blockSize bytes if lastSize != 0. - ForceNextPut() forces a call to NextPut() if this is the case. - */ - void ForceNextPut(); - -protected: - bool DidFirstPut() {return m_firstInputDone;} - - virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs& parameters, unsigned int& /* firstSize */, unsigned int& /* blockSize */, unsigned int& /* lastSize */) - {InitializeDerived(parameters);} - virtual void InitializeDerived(const NameValuePairs& /* parameters */) {} - // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize) - // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)) - virtual void FirstPut(const byte *inString) =0; - // NextPut() is called if totalLength >= firstSize+blockSize+lastSize - virtual void NextPutSingle(const byte* /* inString */) {assert(false);} - // Same as NextPut() except length can be a multiple of blockSize - // Either NextPut() or NextPutMultiple() must be overriden - virtual void NextPutMultiple(const byte *inString, unsigned int length); - // Same as NextPutMultiple(), but inString can be modified - virtual void NextPutModifiable(byte *inString, unsigned int length) - {NextPutMultiple(inString, length);} - // LastPut() is always called - // if totalLength < firstSize then length == totalLength - // else if totalLength <= firstSize+lastSize then length == totalLength-firstSize - // else lastSize <= length < lastSize+blockSize - virtual void LastPut(const byte *inString, unsigned int length) =0; - virtual void FlushDerived() {} - -private: - unsigned int PutMaybeModifiable(byte *begin, unsigned int length, int messageEnd, bool blocking, bool modifiable); - void NextPutMaybeModifiable(byte *inString, unsigned int length, bool modifiable) - { - if (modifiable) NextPutModifiable(inString, length); - else NextPutMultiple(inString, length); - } - - // This function should no longer be used, put this here to cause a compiler error - // if someone tries to override NextPut(). - virtual int NextPut(const byte* /* inString */, unsigned int /* length */) {assert(false); return 0;} - - class BlockQueue - { - public: - void ResetQueue(unsigned int blockSize, unsigned int maxBlocks); - byte *GetBlock(); - byte *GetContigousBlocks(unsigned int &numberOfBytes); - unsigned int GetAll(byte *outString); - void Put(const byte *inString, unsigned int length); - unsigned int CurrentSize() const {return m_size;} - unsigned int MaxSize() const {return m_buffer.size();} - - private: - SecByteBlock m_buffer; - unsigned int m_blockSize, m_maxBlocks, m_size; - byte *m_begin; - }; - - unsigned int m_firstSize, m_blockSize, m_lastSize; - bool m_firstInputDone; - BlockQueue m_queue; -}; - -//! Filter Wrapper for HashTransformation -class CRYPTOPP_DLL HashFilter : public Bufferless, private FilterPutSpaceHelper -{ -public: - HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false) - : m_hashModule(hm), m_putMessage(putMessage) {Detach(attachment);} - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - - byte * CreatePutSpace(unsigned int &size) {return m_hashModule.CreateUpdateSpace(size);} - -private: - HashTransformation &m_hashModule; - bool m_putMessage; - byte *m_space; -}; - -// Used By ProxyFilter -class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation -{ -public: - OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {} - - bool GetPassSignal() const {return m_passSignal;} - void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} - - byte * CreatePutSpace(unsigned int &size) - {return m_owner.AttachedTransformation()->CreatePutSpace(size);} - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);} - unsigned int PutModifiable2(byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);} - void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);} - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;} - bool MessageSeriesEnd(int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;} - - unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} - unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} - bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} - bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} - -private: - BufferedTransformation &m_owner; - bool m_passSignal; -}; - -//! Base class for Filter classes that are proxies for a chain of other filters. -class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput -{ -public: - ProxyFilter(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment); - - bool IsolatedFlush(bool hardFlush, bool blocking); - - void SetFilter(Filter *filter); - void NextPutMultiple(const byte *s, unsigned int len); - void NextPutModifiable(byte *inString, unsigned int length); - -protected: - member_ptr m_filter; -}; - -//! simple proxy filter that doesn't modify the underlying filter's input or output -class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter -{ -public: - SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment) - : ProxyFilter(filter, 0, 0, attachment) {} - - void FirstPut(const byte *) {} - void LastPut(const byte *, unsigned int) {m_filter->MessageEnd();} -}; - -//! Append input to a string object -template -class StringSinkTemplate : public Bufferless -{ -public: - // VC60 workaround: no T::char_type - typedef typename T::traits_type::char_type char_type; - - StringSinkTemplate(T &output) - : m_output(&output) {assert(sizeof(output[0])==1);} - - void IsolatedInitialize(const NameValuePairs ¶meters) - {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");} - - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) - { - if (length > 0) - { - typename T::size_type size = m_output->size(); - if (length < size && size + length > m_output->capacity()) - m_output->reserve(2*size); - m_output->append((const char_type *)begin, (const char_type *)begin+length); - } - return 0; - } - -private: - T *m_output; -}; - -//! Append input to an std::string -typedef StringSinkTemplate StringSink; - -//! Copy input to a memory buffer -class CRYPTOPP_DLL ArraySink : public Bufferless -{ -public: - ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);} - ArraySink(byte *buf, unsigned int size) : m_buf(buf), m_size(size), m_total(0) {} - - unsigned int AvailableSize() {return m_size - STDMIN(m_total, (unsigned long)m_size);} - unsigned long TotalPutLength() {return m_total;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - byte * CreatePutSpace(unsigned int &size); - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - -protected: - byte *m_buf; - unsigned int m_size; - unsigned long m_total; -}; - -//! Xor input to a memory buffer -class CRYPTOPP_DLL ArrayXorSink : public ArraySink -{ -public: - ArrayXorSink(byte *buf, unsigned int size) - : ArraySink(buf, size) {} - - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - byte * CreatePutSpace(unsigned int &size) {return BufferedTransformation::CreatePutSpace(size);} -}; - -//! string-based implementation of Store interface -class StringStore : public Store -{ -public: - StringStore(const char *string = NULL) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - StringStore(const byte *string, unsigned int length) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} - template StringStore(const T &string) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - - CRYPTOPP_DLL unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - CRYPTOPP_DLL unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - -private: - CRYPTOPP_DLL void StoreInitialize(const NameValuePairs ¶meters); - - const byte *m_store; - unsigned int m_length, m_count; -}; - -//! A Filter that pumps data into its attachment as input -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting -{ -public: - Source(BufferedTransformation *attachment = NULL) - {Source::Detach(attachment);} - - unsigned long Pump(unsigned long pumpMax=ULONG_MAX) - {Pump2(pumpMax); return pumpMax;} - unsigned int PumpMessages(unsigned int count=UINT_MAX) - {PumpMessages2(count); return count;} - void PumpAll() - {PumpAll2();} - virtual unsigned int Pump2(unsigned long &byteCount, bool blocking=true) =0; - virtual unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true) =0; - virtual unsigned int PumpAll2(bool blocking=true); - virtual bool SourceExhausted() const =0; - -protected: - void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters) - { - IsolatedInitialize(parameters); - if (pumpAll) - PumpAll(); - } -}; - -//! Turn a Store into a Source -template -class SourceTemplate : public Source -{ -public: - SourceTemplate(BufferedTransformation *attachment) - : Source(attachment) {} - void IsolatedInitialize(const NameValuePairs ¶meters) - {m_store.IsolatedInitialize(parameters);} - unsigned int Pump2(unsigned long &byteCount, bool blocking=true) - {return m_store.TransferTo2(*AttachedTransformation(), byteCount, NULL_CHANNEL, blocking);} - unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true) - {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, NULL_CHANNEL, blocking);} - unsigned int PumpAll2(bool blocking=true) - {return m_store.TransferAllTo2(*AttachedTransformation(), NULL_CHANNEL, blocking);} - bool SourceExhausted() const - {return !m_store.AnyRetrievable() && !m_store.AnyMessages();} - void SetAutoSignalPropagation(int propagation) - {m_store.SetAutoSignalPropagation(propagation);} - int GetAutoSignalPropagation() const - {return m_store.GetAutoSignalPropagation();} - -protected: - T m_store; -}; - -//! string-based implementation of Source interface -class CRYPTOPP_DLL StringSource : public SourceTemplate -{ -public: - StringSource(BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {} - StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} - StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_ARGNAMES_H -#define CRYPTOPP_ARGNAMES_H - -//- #include "cryptlib.h" - -NAMESPACE_BEGIN(CryptoPP) - -DOCUMENTED_NAMESPACE_BEGIN(Name) - -#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;} - -CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name -CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int -CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(IV) //!< const byte * -CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte * -CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int -CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int -CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point -CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N -CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID -CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector * -CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(XMACC_Counter) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char * -CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream * -CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char * -CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream * -CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool -CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int -CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool -CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte -CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int -CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte * -CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte * -CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool -CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int - -DOCUMENTED_NAMESPACE_END - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////// -// pubkey.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_PUBKEY_H -#define CRYPTOPP_PUBKEY_H - -/** \file - - This file contains helper classes/functions for implementing public key algorithms. - - The class hierachies in this .h file tend to look like this: -

-                  x1
-                 / \
-                y1  z1
-                 |  |
-            x2  x2
-                 |  |
-                y2  z2
-                 |  |
-            x3  x3
-                 |  |
-                y3  z3
-
- - x1, y1, z1 are abstract interface classes defined in cryptlib.h - - x2, y2, z2 are implementations of the interfaces using "abstract policies", which - are pure virtual functions that should return interfaces to interchangeable algorithms. - These classes have "Base" suffixes. - - x3, y3, z3 hold actual algorithms and implement those virtual functions. - These classes have "Impl" suffixes. - - The "TF_" prefix means an implementation using trapdoor functions on integers. - The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard). -*/ - -//- #include "modarith.h" -//- #include "filters.h" -//- #include "eprecomp.h" -//- #include "fips140.h" -//- #include "argnames.h" -#include - -// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file -#undef INTERFACE - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds -{ -public: - virtual ~TrapdoorFunctionBounds() {} - - virtual Integer PreimageBound() const =0; - virtual Integer ImageBound() const =0; - virtual Integer MaxPreimage() const {return --PreimageBound();} - virtual Integer MaxImage() const {return --ImageBound();} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds -{ -public: - virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; - virtual bool IsRandomized() const {return true;} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction -{ -public: - Integer ApplyRandomizedFunction(RandomNumberGenerator& /* rng */, const Integer &x) const - {return ApplyFunction(x);} - bool IsRandomized() const {return false;} - - virtual Integer ApplyFunction(const Integer &x) const =0; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse -{ -public: - virtual ~RandomizedTrapdoorFunctionInverse() {} - - virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; - virtual bool IsRandomized() const {return true;} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse -{ -public: - virtual ~TrapdoorFunctionInverse() {} - - Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const - {return CalculateInverse(rng, x);} - bool IsRandomized() const {return false;} - - virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; -}; - -// ******************************************************** - -//! message encoding method for public key encryption -class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod -{ -public: - virtual ~PK_EncryptionMessageEncodingMethod() {} - - virtual bool ParameterSupported(const char* /* name */) const {return false;} - - //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) - virtual unsigned int MaxUnpaddedLength(unsigned int paddedLength) const =0; - - virtual void Pad(RandomNumberGenerator &rng, const byte *raw, unsigned int inputLength, byte *padded, unsigned int paddedBitLength, const NameValuePairs ¶meters) const =0; - - virtual DecodingResult Unpad(const byte *padded, unsigned int paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; -}; - -// ******************************************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_Base -{ -protected: - virtual ~TF_Base() {}; - - virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; - - typedef TFI TrapdoorFunctionInterface; - virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; - - typedef MEI MessageEncodingInterface; - virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; -}; - -// ******************************************************** - -typedef std::pair HashIdentifier; - -//! interface for message encoding method for public key signature schemes -class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod -{ -public: - virtual ~PK_SignatureMessageEncodingMethod() {} - - virtual unsigned int MaxRecoverableLength(unsigned int /* representativeBitLength */, unsigned int /* hashIdentifierLength */, unsigned int /* digestLength */) const - {return 0;} - - bool IsProbabilistic() const - {return true;} - bool AllowNonrecoverablePart() const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - virtual bool RecoverablePartFirst() const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - // for verification, DL - virtual void ProcessSemisignature(HashTransformation& /* hash */, const byte* /* semisignature */, unsigned int /* semisignatureLength */) const {} - - // for signature - virtual void ProcessRecoverableMessage(HashTransformation& /* hash */, - const byte* /* recoverableMessage */, unsigned int /* recoverableMessageLength */, - const byte* /* presignature */, unsigned int /* presignatureLength */, - SecByteBlock& /* semisignature */) const - { - if (RecoverablePartFirst()) - assert(!"ProcessRecoverableMessage() not implemented"); - } - - virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, unsigned int recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, unsigned int representativeBitLength) const =0; - - virtual bool VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, unsigned int representativeBitLength) const =0; - - virtual DecodingResult RecoverMessageFromRepresentative( // for TF - HashTransformation& /* hash */, HashIdentifier /* hashIdentifier */, bool /* messageEmpty */, - byte* /* representative */, unsigned int /* representativeBitLength */, - byte* /* recoveredMessage */) const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - virtual DecodingResult RecoverMessageFromSemisignature( // for DL - HashTransformation& /* hash */, HashIdentifier /* hashIdentifier */, - const byte* /* presignature */, unsigned int /* presignatureLength */, - const byte* /* semisignature */, unsigned int /* semisignatureLength */, - byte* /* recoveredMessage */) const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - // VC60 workaround - struct HashIdentifierLookup - { - template struct HashIdentifierLookup2 - { - static HashIdentifier Lookup() - { - return HashIdentifier(NULL, 0); - } - }; - }; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod -{ -public: - bool VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, unsigned int representativeBitLength) const; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator -{ -public: - PK_MessageAccumulatorBase() : m_empty(true) {} - - virtual HashTransformation & AccessHash() =0; - - void Update(const byte *input, unsigned int length) - { - AccessHash().Update(input, length); - m_empty = m_empty && length == 0; - } - - SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; - Integer m_k, m_s; - bool m_empty; -}; - -template -class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder -{ -public: - HashTransformation & AccessHash() {return this->m_object;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE -{ -public: - unsigned int SignatureLength() const - {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} - unsigned int MaxRecoverableLength() const - {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} - unsigned int MaxRecoverableLengthFromSignatureLength(unsigned int /* signatureLength */) const - {return this->MaxRecoverableLength();} - - bool IsProbabilistic() const - {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();} - bool AllowNonrecoverablePart() const - {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();} - bool RecoverablePartFirst() const - {return this->GetMessageEncodingInterface().RecoverablePartFirst();} - -protected: - unsigned int MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} - unsigned int MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;} - virtual HashIdentifier GetHashIdentifier() const =0; - virtual unsigned int GetDigestSize() const =0; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase > -{ -public: - void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const; - unsigned int SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase > -{ -public: - void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const; - bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; - DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; -}; - -// ******************************************************** - -//! _ -template -struct TF_CryptoSchemeOptions -{ - typedef T1 AlgorithmInfo; - typedef T2 Keys; - typedef typename Keys::PrivateKey PrivateKey; - typedef typename Keys::PublicKey PublicKey; - typedef T3 MessageEncodingMethod; -}; - -//! _ -template -struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions -{ - typedef T4 HashFunction; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE PublicKeyCopier -{ -public: - virtual ~PublicKeyCopier() {}; - - typedef typename KEYS::PublicKey KeyClass; - virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE PrivateKeyCopier -{ -public: - virtual ~PrivateKeyCopier() {}; - - typedef typename KEYS::PrivateKey KeyClass; - virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0; - virtual void CopyKeyInto(typename KEYS::PrivateKey &key) const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl -{ -public: - typedef SCHEME_OPTIONS SchemeOptions; - typedef KEY KeyClass; - - PublicKey & AccessPublicKey() {return AccessKey();} - const PublicKey & GetPublicKey() const {return GetKey();} - - PrivateKey & AccessPrivateKey() {return AccessKey();} - const PrivateKey & GetPrivateKey() const {return GetKey();} - - virtual const KeyClass & GetKey() const =0; - virtual KeyClass & AccessKey() =0; - - const KeyClass & GetTrapdoorFunction() const {return GetKey();} - - PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator& /* rng */) const - { - return new PK_MessageAccumulatorImpl; - } - PK_MessageAccumulator * NewVerificationAccumulator() const - { - return new PK_MessageAccumulatorImpl; - } - -protected: - const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const - {return Singleton().Ref();} - const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const - {return GetKey();} - const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const - {return GetKey();} - - // for signature scheme - HashIdentifier GetHashIdentifier() const - { - typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2 L; - return L::Lookup(); - } - unsigned int GetDigestSize() const - { - typedef CPP_TYPENAME SchemeOptions::HashFunction H; - return H::DIGESTSIZE; - } -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase, SCHEME_OPTIONS, typename KEY_COPIER::KeyClass> -{ -public: - typedef typename KEY_COPIER::KeyClass KeyClass; - - const KeyClass & GetKey() const {return m_trapdoorFunction;} - KeyClass & AccessKey() {return m_trapdoorFunction;} - - void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const {key = GetKey();} - void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {key = GetKey();} - -private: - KeyClass m_trapdoorFunction; -}; - -//! _ -template -class TF_SignerImpl : public TF_ObjectImpl > -{ -}; - -//! _ -template -class TF_VerifierImpl : public TF_ObjectImpl > -{ -}; - -// ******************************************************** - -CRYPTOPP_DLL void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, const byte *derivationParams, unsigned int derivationParamsLength, bool mask, unsigned int counterStart); - -// ******************************************************** - -//! _ -template -class P1363_KDF2 -{ -public: - static void DeriveKey(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, const byte *derivationParams, unsigned int derivationParamsLength) - { - H h; - P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1); - } -}; - -// ******************************************************** - -//! A template implementing constructors for public key algorithm classes -template -class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE -{ -public: - PK_FinalTemplate() {} - - PK_FinalTemplate(const Integer &v1) - {this->AccessKey().Initialize(v1);} - - PK_FinalTemplate(const typename BASE::KeyClass &key) {this->AccessKey().operator=(key);} - - template - PK_FinalTemplate(const PublicKeyCopier &key) - {key.CopyKeyInto(this->AccessKey());} - - template - PK_FinalTemplate(const PrivateKeyCopier &key) - {key.CopyKeyInto(this->AccessKey());} - - PK_FinalTemplate(BufferedTransformation &bt) {this->AccessKey().BERDecode(bt);} - -#if (defined(_MSC_VER) && _MSC_VER < 1300) - - template - PK_FinalTemplate(T1 &v1, T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - -#else - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - -#endif -}; - -//! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. -struct EncryptionStandard {}; - -//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. -struct SignatureStandard {}; - -template // VC60 workaround: doesn't work if KEYS is first parameter -class TF_SS; - -//! Trapdoor Function Based Signature Scheme -template > // VC60 workaround: doesn't work if KEYS is first parameter -class TF_SS : public KEYS -{ -public: - //! see SignatureStandard for a list of standards - typedef STANDARD Standard; - typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; - typedef TF_SignatureSchemeOptions SchemeOptions; - - static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} - - //! implements PK_Signer interface - typedef PK_FinalTemplate > Signer; - //! implements PK_Verifier interface - typedef PK_FinalTemplate > Verifier; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_ITERHASH_H -#define CRYPTOPP_ITERHASH_H - -//- #include "cryptlib.h" -//- #include "secblock.h" -//- #include "misc.h" -//- #include "simple.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE -{ -public: - typedef T HashWordType; - - IteratedHashBase() : m_countLo(0), m_countHi(0) {} - unsigned int BlockSize() const {return m_data.size() * sizeof(T);} - unsigned int OptimalBlockSize() const {return BlockSize();} - unsigned int OptimalDataAlignment() const {return sizeof(T);} - void Update(const byte *input, unsigned int length); - byte * CreateUpdateSpace(unsigned int &size); - void Restart(); - -protected: - void SetBlockSize(unsigned int blockSize) {m_data.resize(blockSize / sizeof(HashWordType));} - void SetStateSize(unsigned int stateSize) {m_digest.resize(stateSize / sizeof(HashWordType));} - - T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);} - T GetBitCountLo() const {return m_countLo << 3;} - - virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length); - void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); - virtual void Init() =0; - virtual void HashBlock(const T *input) =0; - - SecBlock m_data; // Data buffer - SecBlock m_digest; // Message digest - -private: - T m_countLo, m_countHi; -}; - - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHashBase2 : public IteratedHashBase -{ -public: - typedef B ByteOrderClass; - typedef typename IteratedHashBase::HashWordType HashWordType; - - inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount) - { - ConditionalByteReverse(B::ToEnum(), out, in, byteCount); - } - - void TruncatedFinal(byte *digest, unsigned int size); - -protected: - void HashBlock(const HashWordType *input); - virtual void HashEndianCorrectedBlock(const HashWordType *data) =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase2 -{ -public: - enum {BLOCKSIZE = T_BlockSize}; - CRYPTOPP_COMPILE_ASSERT_GLOBAL((BLOCKSIZE & (BLOCKSIZE - 1)) == 0); // blockSize is a power of 2 - -protected: - IteratedHash() - : IteratedHashBase2() - {this->SetBlockSize(T_BlockSize);} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform - : public ClonableImpl, T_Transform> > -{ -public: - enum {DIGESTSIZE = T_DigestSize}; - unsigned int DigestSize() const {return DIGESTSIZE;}; - -protected: - IteratedHashWithStaticTransform() - { - this->SetStateSize(T_StateSize); - Init(); - } - void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_digest, data);} - void Init() {T_Transform::InitState(this->m_digest);} -}; - -// ************************************************************* - -template void IteratedHashBase2::TruncatedFinal(byte *digest, unsigned int size) -{ - this->ThrowIfInvalidTruncatedSize(size); - - this->PadLastBlock(this->BlockSize() - 2*sizeof(HashWordType)); - CorrectEndianess(this->m_data, this->m_data, this->BlockSize() - 2*sizeof(HashWordType)); - - this->m_data[this->m_data.size()-2] = B::ToEnum() ? this->GetBitCountHi() : this->GetBitCountLo(); - this->m_data[this->m_data.size()-1] = B::ToEnum() ? this->GetBitCountLo() : this->GetBitCountHi(); - - HashEndianCorrectedBlock(this->m_data); - CorrectEndianess(this->m_digest, this->m_digest, this->DigestSize()); - memcpy(digest, this->m_digest, size); - - this->Restart(); // reinit for next use -} - -template void IteratedHashBase2::HashBlock(const HashWordType *input) -{ - if (NativeByteOrderIs(B::ToEnum())) - HashEndianCorrectedBlock(input); - else - { - ByteReverse(this->m_data.begin(), input, this->BlockSize()); - HashEndianCorrectedBlock(this->m_data); - } -} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_SHA_H -#define CRYPTOPP_SHA_H - -//- #include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// SHA-1 -class CRYPTOPP_DLL SHA : public IteratedHashWithStaticTransform -{ -public: - static void InitState(HashWordType *state); - static void Transform(word32 *digest, const word32 *data); - static const char *StaticAlgorithmName() {return "SHA-1";} -}; - -typedef SHA SHA1; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_PKCSPAD_H -#define CRYPTOPP_PKCSPAD_H - -//- #include "cryptlib.h" -//- #include "pubkey.h" - -#ifdef CRYPTOPP_IS_DLL -//- #include "sha.h" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -//! EME-PKCS1-v1_5 -class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod -{ -public: - static const char * StaticAlgorithmName() {return "EME-PKCS1-v1_5";} - - unsigned int MaxUnpaddedLength(unsigned int paddedLength) const; - void Pad(RandomNumberGenerator &rng, const byte *raw, unsigned int inputLength, byte *padded, unsigned int paddedLength, const NameValuePairs ¶meters) const; - DecodingResult Unpad(const byte *padded, unsigned int paddedLength, byte *raw, const NameValuePairs ¶meters) const; -}; - -template class PKCS_DigestDecoration -{ -public: - static const byte decoration[]; - static const unsigned int length; -}; - -// PKCS_DigestDecoration can be instantiated with the following -// classes as specified in PKCS#1 v2.0 and P1363a -class SHA; -// end of list - -//! EMSA-PKCS1-v1_5 -class CRYPTOPP_DLL PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod -{ -public: - static const char * StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";} - - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, unsigned int recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, unsigned int representativeBitLength) const; - - struct HashIdentifierLookup - { - template struct HashIdentifierLookup2 - { - static HashIdentifier Lookup() - { - return HashIdentifier(PKCS_DigestDecoration::decoration, PKCS_DigestDecoration::length); - } - }; - }; -}; - -//! PKCS #1 version 1.5, for use with RSAES and RSASS -/*! Only the following hash functions are supported by this signature standard: - \dontinclude pkcspad.h - \skip can be instantiated - \until end of list -*/ -struct PKCS1v15 : public SignatureStandard, public EncryptionStandard -{ - typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod; - typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_ASN_H -#define CRYPTOPP_ASN_H - -//- #include "filters.h" -//- #include "queue.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -// these tags and flags are not complete -enum ASNTag -{ - BOOLEAN = 0x01, - INTEGER = 0x02, - BIT_STRING = 0x03, - OCTET_STRING = 0x04, - TAG_NULL = 0x05, - OBJECT_IDENTIFIER = 0x06, - OBJECT_DESCRIPTOR = 0x07, - EXTERNAL = 0x08, - REAL = 0x09, - ENUMERATED = 0x0a, - UTF8_STRING = 0x0c, - SEQUENCE = 0x10, - SET = 0x11, - NUMERIC_STRING = 0x12, - PRINTABLE_STRING = 0x13, - T61_STRING = 0x14, - VIDEOTEXT_STRING = 0x15, - IA5_STRING = 0x16, - UTC_TIME = 0x17, - GENERALIZED_TIME = 0x18, - GRAPHIC_STRING = 0x19, - VISIBLE_STRING = 0x1a, - GENERAL_STRING = 0x1b -}; - -enum ASNIdFlag -{ - UNIVERSAL = 0x00, -// DATA = 0x01, -// HEADER = 0x02, - CONSTRUCTED = 0x20, - APPLICATION = 0x40, - CONTEXT_SPECIFIC = 0x80, - PRIVATE = 0xc0 -}; - -inline void BERDecodeError() {throw BERDecodeErr();} - -// unsigned int DERLengthEncode(unsigned int length, byte *output=0); -CRYPTOPP_DLL unsigned int DERLengthEncode(BufferedTransformation &out, unsigned int length); -// returns false if indefinite length -CRYPTOPP_DLL bool BERLengthDecode(BufferedTransformation &in, unsigned int &length); - -CRYPTOPP_DLL void DEREncodeNull(BufferedTransformation &out); -CRYPTOPP_DLL void BERDecodeNull(BufferedTransformation &in); - -CRYPTOPP_DLL unsigned int DEREncodeOctetString(BufferedTransformation &out, const byte *str, unsigned int strLen); -CRYPTOPP_DLL unsigned int DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str); - -// BER decode from source and DER reencode into dest -CRYPTOPP_DLL void DERReencode(BufferedTransformation &source, BufferedTransformation &dest); - -//! Object Identifier -class CRYPTOPP_DLL OID -{ -public: - OID() {} - OID(unsigned long v) : m_values(1, v) {} - OID(BufferedTransformation &bt) {BERDecode(bt);} - - inline OID & operator+=(unsigned long rhs) {m_values.push_back(rhs); return *this;} - - void DEREncode(BufferedTransformation &bt) const; - void BERDecode(BufferedTransformation &bt); - - // throw BERDecodeErr() if decoded value doesn't equal this OID - void BERDecodeAndCheck(BufferedTransformation &bt) const; - - std::vector m_values; - -private: - static void EncodeValue(BufferedTransformation &bt, unsigned long v); - static unsigned int DecodeValue(BufferedTransformation &bt, unsigned long &v); -}; - -//! BER General Decoder -class CRYPTOPP_DLL BERGeneralDecoder : public Store -{ -public: - explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); - explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); - ~BERGeneralDecoder(); - - bool IsDefiniteLength() const {return m_definiteLength;} - unsigned int RemainingLength() const {assert(m_definiteLength); return m_length;} - bool EndReached() const; - byte PeekByte() const; - void CheckByte(byte b); - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - - // call this to denote end of sequence - void MessageEnd(); - -protected: - BufferedTransformation &m_inQueue; - bool m_finished, m_definiteLength; - unsigned int m_length; - -private: - void Init(byte asnTag); - void StoreInitialize(const NameValuePairs& /* parameters */) {assert(false);} - unsigned int ReduceLength(unsigned int delta); -}; - -//! DER General Encoder -class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue -{ -public: - explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); - explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); - ~DERGeneralEncoder(); - - // call this to denote end of sequence - void MessageEnd(); - -private: - BufferedTransformation &m_outQueue; - bool m_finished; - - byte m_asnTag; -}; - -//! BER Sequence Decoder -class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder -{ -public: - explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} - explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} -}; - -//! DER Sequence Encoder -class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder -{ -public: - explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} - explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} -}; - -//! key that can be ASN.1 encoded -/** derived class should override either BERDecodeKey or BERDecodeKey2 */ -class CRYPTOPP_DLL ASN1Key : public ASN1CryptoMaterial -{ -public: - virtual OID GetAlgorithmID() const =0; - virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) - {BERDecodeNull(bt); return false;} - virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const - {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 - //! decode subjectPublicKey part of subjectPublicKeyInfo, or privateKey part of privateKeyInfo, without the BIT STRING or OCTET STRING header - virtual void BERDecodeKey(BufferedTransformation& /* bt */) {assert(false);} - virtual void BERDecodeKey2(BufferedTransformation& bt, bool /* parametersPresent */, unsigned int /* size */) - {BERDecodeKey(bt);} - //! encode subjectPublicKey part of subjectPublicKeyInfo, or privateKey part of privateKeyInfo, without the BIT STRING or OCTET STRING header - virtual void DEREncodeKey(BufferedTransformation &bt) const =0; -}; - -//! encodes/decodes subjectPublicKeyInfo -class CRYPTOPP_DLL X509PublicKey : virtual public ASN1Key, public PublicKey -{ -public: - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; -}; - -//! encodes/decodes privateKeyInfo -class CRYPTOPP_DLL PKCS8PrivateKey : virtual public ASN1Key, public PrivateKey -{ -public: - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - //! decode optional attributes including context-specific tag - /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */ - virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt); - //! encode optional attributes including context-specific tag - virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const; - -private: - ByteQueue m_optionalAttributes; -}; - -// ******************************************************** - -//! DER Encode Unsigned -/*! for INTEGER, BOOLEAN, and ENUM */ -template -unsigned int DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) -{ - byte buf[sizeof(w)+1]; - unsigned int bc; - if (asnTag == BOOLEAN) - { - buf[sizeof(w)] = w ? 0xff : 0; - bc = 1; - } - else - { - buf[0] = 0; - for (unsigned int i=0; i> (sizeof(w)-1-i)*8); - bc = sizeof(w); - while (bc > 1 && buf[sizeof(w)+1-bc] == 0) - --bc; - if (buf[sizeof(w)+1-bc] & 0x80) - ++bc; - } - out.Put(asnTag); - unsigned int lengthBytes = DERLengthEncode(out, bc); - out.Put(buf+sizeof(w)+1-bc, bc); - return 1+lengthBytes+bc; -} - -//! BER Decode Unsigned -// VC60 workaround: std::numeric_limits::max conflicts with MFC max macro -// CW41 workaround: std::numeric_limits::max causes a template error -template -void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, - T minValue = 0, T maxValue = 0xffffffff) -{ - byte b; - if (!in.Get(b) || b != asnTag) - BERDecodeError(); - - unsigned int bc; - BERLengthDecode(in, bc); - - SecByteBlock buf(bc); - - if (bc != in.Get(buf, bc)) - BERDecodeError(); - - const byte *ptr = buf; - while (bc > sizeof(w) && *ptr == 0) - { - bc--; - ptr++; - } - if (bc > sizeof(w)) - BERDecodeError(); - - w = 0; - for (unsigned int i=0; i maxValue) - BERDecodeError(); -} - -inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return lhs.m_values == rhs.m_values;} -inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return lhs.m_values != rhs.m_values;} -inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} -inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs) - {return ::CryptoPP::OID(lhs)+=rhs;} - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_RSA_H -#define CRYPTOPP_RSA_H - -/** \file - This file contains classes that implement the RSA - ciphers and signature schemes as defined in PKCS #1 v2.0. -*/ - -//- #include "pkcspad.h" -//- #include "oaep.h" -//- #include "integer.h" -//- #include "asn.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL RSAFunction : public TrapdoorFunction, public X509PublicKey -{ - typedef RSAFunction ThisClass; - -public: - void Initialize(const Integer &n, const Integer &e) - {m_n = n; m_e = e;} - - // X509PublicKey - OID GetAlgorithmID() const; - void BERDecodeKey(BufferedTransformation &bt); - void DEREncodeKey(BufferedTransformation &bt) const; - - // CryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // TrapdoorFunction - Integer ApplyFunction(const Integer &x) const; - Integer PreimageBound() const {return m_n;} - Integer ImageBound() const {return m_n;} - - // non-derived - const Integer & GetModulus() const {return m_n;} - const Integer & GetPublicExponent() const {return m_e;} - - void SetModulus(const Integer &n) {m_n = n;} - void SetPublicExponent(const Integer &e) {m_e = e;} - -protected: - Integer m_n, m_e; -}; - -//! _ -class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey -{ - typedef InvertibleRSAFunction ThisClass; - -public: - void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17); - void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u) - {m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;} - //! factor n given private exponent - void Initialize(const Integer &n, const Integer &e, const Integer &d); - - // PKCS8PrivateKey - void BERDecode(BufferedTransformation &bt) - {PKCS8PrivateKey::BERDecode(bt);} - void DEREncode(BufferedTransformation &bt) const - {PKCS8PrivateKey::DEREncode(bt);} - void BERDecodeKey(BufferedTransformation &bt); - void DEREncodeKey(BufferedTransformation &bt) const; - - // TrapdoorFunctionInverse - Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; - - // GeneratableCryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - /*! parameters: (ModulusSize, PublicExponent (default 17)) */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // non-derived interface - const Integer& GetPrime1() const {return m_p;} - const Integer& GetPrime2() const {return m_q;} - const Integer& GetPrivateExponent() const {return m_d;} - const Integer& GetModPrime1PrivateExponent() const {return m_dp;} - const Integer& GetModPrime2PrivateExponent() const {return m_dq;} - const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} - - void SetPrime1(const Integer &p) {m_p = p;} - void SetPrime2(const Integer &q) {m_q = q;} - void SetPrivateExponent(const Integer &d) {m_d = d;} - void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;} - void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;} - void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} - -protected: - Integer m_d, m_p, m_q, m_dp, m_dq, m_u; -}; - -//! RSA -struct CRYPTOPP_DLL RSA -{ - static std::string StaticAlgorithmName() {return "RSA";} - typedef RSAFunction PublicKey; - typedef InvertibleRSAFunction PrivateKey; -}; - -//! RSA signature scheme with appendix -/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */ -template -struct RSASS : public TF_SS -{ -}; - -// The three RSA signature schemes defined in PKCS #1 v2.0 -typedef RSASS::Signer RSASSA_PKCS1v15_SHA_Signer; -typedef RSASS::Verifier RSASSA_PKCS1v15_SHA_Verifier; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_BASECODE_H -#define CRYPTOPP_BASECODE_H - -//- #include "filters.h" -//- #include "algparam.h" -//- #include "argnames.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! base n encoder, where n is a power of 2 -class CRYPTOPP_DLL BaseN_Encoder : public Unflushable -{ -public: - BaseN_Encoder(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet) - (Name::Log2Base(), log2base) - (Name::Pad(), padding != -1) - (Name::PaddingByte(), byte(padding))); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - -private: - const byte *m_alphabet; - int m_padding, m_bitsPerChar, m_outputBlockSize; - int m_bytePos, m_bitPos; - SecByteBlock m_outBuf; -}; - -//! base n decoder, where n is a power of 2 -class CRYPTOPP_DLL BaseN_Decoder : public Unflushable -{ -public: - BaseN_Decoder(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base)); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - - static void InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive); - -private: - const int *m_lookup; - int m_padding, m_bitsPerChar, m_outputBlockSize; - int m_bytePos, m_bitPos; - SecByteBlock m_outBuf; -}; - -//! filter that breaks input stream into groups of fixed size -class CRYPTOPP_DLL Grouper : public Bufferless -{ -public: - Grouper(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize) - (Name::Separator(), ConstByteArrayParameter(separator)) - (Name::Terminator(), ConstByteArrayParameter(terminator))); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking); - -private: - SecByteBlock m_separator, m_terminator; - unsigned int m_groupSize, m_counter; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_BASE64_H -#define CRYPTOPP_BASE64_H - -//- #include "basecode.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Base64 Encoder Class -class Base64Encoder : public SimpleProxyFilter -{ -public: - Base64Encoder(BufferedTransformation *attachment = NULL, bool insertLineBreaks = true, int maxLineLength = 72) - : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) - { - IsolatedInitialize(MakeParameters(Name::InsertLineBreaks(), insertLineBreaks)(Name::MaxLineLength(), maxLineLength)); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); -}; - -//! Base64 Decoder Class -class Base64Decoder : public BaseN_Decoder -{ -public: - Base64Decoder(BufferedTransformation *attachment = NULL) - : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {} - - void IsolatedInitialize(const NameValuePairs& /* parameters */) {} - -private: - static const int *GetDecodingLookupArray(); -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_FILES_H -#define CRYPTOPP_FILES_H - -//- #include "cryptlib.h" -//- #include "filters.h" -//- #include "argnames.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! file-based implementation of Store interface -class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable -{ -public: - class Err : public Exception - { - public: - Err(const std::string &s) : Exception(IO_ERROR, s) {} - }; - class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}}; - class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}}; - - FileStore() : m_stream(NULL) {} - FileStore(std::istream &in) - {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));} - FileStore(const char *filename) - {StoreInitialize(MakeParameters(Name::InputFileName(), filename));} - - std::istream* GetStream() {return m_stream;} - - unsigned long MaxRetrievable() const; - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; - unsigned long Skip(unsigned long skipMax=ULONG_MAX); - -private: - void StoreInitialize(const NameValuePairs ¶meters); - - member_ptr m_file; - std::istream *m_stream; - byte *m_space; - unsigned int m_len; - bool m_waiting; -}; - -//! file-based implementation of Source interface -class CRYPTOPP_DLL FileSource : public SourceTemplate -{ -public: - typedef FileStore::Err Err; - typedef FileStore::OpenErr OpenErr; - typedef FileStore::ReadErr ReadErr; - - FileSource(BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {} - FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} - FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));} - - std::istream* GetStream() {return m_store.GetStream();} -}; - -//! file-based implementation of Sink interface -class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable -{ -public: - class Err : public Exception - { - public: - Err(const std::string &s) : Exception(IO_ERROR, s) {} - }; - class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}}; - class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}}; - - FileSink() : m_stream(NULL) {} - FileSink(std::ostream &out) - {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));} - FileSink(const char *filename, bool binary=true) - {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)("OutputBinaryMode", binary));} - - std::ostream* GetStream() {return m_stream;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking); - bool IsolatedFlush(bool hardFlush, bool blocking); - -private: - member_ptr m_file; - std::ostream *m_stream; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_RANDPOOL_H -#define CRYPTOPP_RANDPOOL_H - -//- #include "cryptlib.h" -//- #include "filters.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Randomness Pool -/*! This class can be used to generate - pseudorandom bytes after seeding the pool with - the Put() methods */ -class CRYPTOPP_DLL RandomPool : public RandomNumberGenerator, - public Bufferless -{ -public: - //! poolSize must be greater than 16 - RandomPool(unsigned int poolSize=384); - - unsigned int Put2(const byte *begin, unsigned int, int messageEnd, bool blocking); - - bool AnyRetrievable() const {return true;} - unsigned long MaxRetrievable() const {return ULONG_MAX;} - - unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); - unsigned int CopyRangeTo2(BufferedTransformation& /* target */, unsigned long& /* begin */, unsigned long /* end */ = ULONG_MAX, const std::string& /* channel */ = NULL_CHANNEL, bool /* blocking */ = true) const - { - throw NotImplemented("RandomPool: CopyRangeTo2() is not supported by this store"); - } - - byte GenerateByte(); - void GenerateBlock(byte *output, unsigned int size); - - void IsolatedInitialize(const NameValuePairs& /* parameters */) {} - -protected: - void Stir(); - -private: - SecByteBlock pool, key; - unsigned int addPos, getPos; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -// seckey.h - written and placed in the public domain by Wei Dai - -// This file contains helper classes/functions for implementing secret key algorithms. - -#ifndef CRYPTOPP_SECKEY_H -#define CRYPTOPP_SECKEY_H - -//- #include "cryptlib.h" -//- #include "misc.h" -//- #include "simple.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! to be inherited by block ciphers with fixed block size -template -class FixedBlockSize -{ -public: - enum {BLOCKSIZE = N}; -}; - -// ************** key length *************** - -//! to be inherited by keyed algorithms with fixed key length -template -class FixedKeyLength -{ -public: - enum {KEYLENGTH=N, MIN_KEYLENGTH=N, MAX_KEYLENGTH=N, DEFAULT_KEYLENGTH=N}; - enum {IV_REQUIREMENT = IV_REQ}; - static unsigned int StaticGetValidKeyLength(unsigned int) {return KEYLENGTH;} -}; - -// ************** implementation helper for SimpledKeyed *************** - -template -static inline void CheckedSetKey(T *obj, Empty empty, const byte *key, unsigned int length, const NameValuePairs ¶m) -{ - obj->ThrowIfInvalidKeyLength(length); - obj->UncheckedSetKey(key, length); -} - -template -static inline void CheckedSetKey(T *obj, CipherDir dir, const byte *key, unsigned int length, const NameValuePairs& /* param */) -{ - obj->ThrowIfInvalidKeyLength(length); - obj->UncheckedSetKey(dir, key, length); -} - -//! _ -template -class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE -{ -public: - unsigned int MinKeyLength() const {return INFO::MIN_KEYLENGTH;} - unsigned int MaxKeyLength() const {return (unsigned int)INFO::MAX_KEYLENGTH;} - unsigned int DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;} - unsigned int GetValidKeyLength(unsigned int n) const {return INFO::StaticGetValidKeyLength(n);} - typename BASE::IV_Requirement IVRequirement() const {return (typename BASE::IV_Requirement)INFO::IV_REQUIREMENT;} - -protected: - void AssertValidKeyLength(unsigned int length) {assert(GetValidKeyLength(length) == length);} -}; - -template -class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl > > -{ -public: - unsigned int BlockSize() const {return this->BLOCKSIZE;} -}; - -//! _ -template -class BlockCipherFinal : public ClonableImpl, BASE> -{ -public: - BlockCipherFinal() {} - BlockCipherFinal(const byte *key) - {SetKey(key, this->DEFAULT_KEYLENGTH);} - BlockCipherFinal(const byte *key, unsigned int length) - {SetKey(key, length);} - BlockCipherFinal(const byte *key, unsigned int length, unsigned int rounds) - {this->SetKeyWithRounds(key, length, rounds);} - - bool IsForwardTransformation() const {return DIR == ENCRYPTION;} - - void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶m = g_nullNameValuePairs) - { - CheckedSetKey(this, DIR, key, length, param); - } -}; - -// ************** documentation *************** - -/*! \brief Each class derived from this one defines two types, Encryption and Decryption, - both of which implement the SymmetricCipher interface. Two types of classes derive - from this class: stream ciphers and block cipher modes. Stream ciphers can be used - alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation - for more for information about using cipher modes and block ciphers. */ -struct SymmetricCipherDocumentation -{ - //! implements the SymmetricCipher interface - typedef SymmetricCipher Encryption; - //! implements the SymmetricCipher interface - typedef SymmetricCipher Decryption; -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_OSRNG_H -#define CRYPTOPP_OSRNG_H - -//- #include "config.h" - -#ifdef OS_RNG_AVAILABLE - -//- #include "randpool.h" -//- #include "rng.h" -//- #include "des.h" -//- #include "fips140.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Exception class for Operating-System Random Number Generator. -class CRYPTOPP_DLL OS_RNG_Err : public Exception -{ -public: - OS_RNG_Err(const std::string &operation); -}; - -#ifdef NONBLOCKING_RNG_AVAILABLE - -#ifdef CRYPTOPP_WIN32_AVAILABLE -class CRYPTOPP_DLL MicrosoftCryptoProvider -{ -public: - MicrosoftCryptoProvider(); - ~MicrosoftCryptoProvider(); -#if defined(_WIN64) - typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include -#else - typedef unsigned long ProviderHandle; -#endif - ProviderHandle GetProviderHandle() const {return m_hProvider;} -private: - ProviderHandle m_hProvider; -}; - -#pragma comment(lib, "advapi32.lib") -#endif - -//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom -class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator -{ -public: - NonblockingRng(); - ~NonblockingRng(); - byte GenerateByte(); - void GenerateBlock(byte *output, unsigned int size); - -protected: -#ifdef CRYPTOPP_WIN32_AVAILABLE -# ifndef WORKAROUND_MS_BUG_Q258000 - MicrosoftCryptoProvider m_Provider; -# endif -#else - int m_fd; -#endif -}; - -#endif - -#ifdef BLOCKING_RNG_AVAILABLE - -//! encapsulate /dev/random -class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator -{ -public: - BlockingRng(); - ~BlockingRng(); - byte GenerateByte(); - void GenerateBlock(byte *output, unsigned int size); - -protected: - int m_fd; -}; - -#endif - -CRYPTOPP_DLL void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size); - -//! Automaticly Seeded Randomness Pool -/*! This class seeds itself using an operating system provided RNG. */ -class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool -{ -public: - //! blocking will be ignored if the preferred RNG isn't available - explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) - {Reseed(blocking, seedSize);} - void Reseed(bool blocking = false, unsigned int seedSize = 32); -}; - -NAMESPACE_END - -#endif - -#endif -//////////////////////////////////////////////////////////////////////////////// - - - -//////////////////////////////////////////////////////////////////////////////// -#ifndef CRYPTOPP_MD4_H -#define CRYPTOPP_MD4_H - -//- #include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! MD4 -/*! \warning MD4 is considered insecure, and should not be used - unless you absolutely need compatibility with a broken product. */ -class MD4 : public IteratedHashWithStaticTransform -{ -public: - static void InitState(HashWordType *state); - static void Transform(word32 *digest, const word32 *data); - static const char *StaticAlgorithmName() {return "MD4";} -}; - -NAMESPACE_END - -#endif -//////////////////////////////////////////////////////////////////////////////// - -#endif