From f424a18112032cf61d2871a6b91a5af607c171ae Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Fri, 20 Jul 2012 16:21:49 +0000 Subject: CryptoPP: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1083 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CryptoPP/crypto/src/xormac.h | 179 +++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 plugins/CryptoPP/crypto/src/xormac.h (limited to 'plugins/CryptoPP/crypto/src/xormac.h') diff --git a/plugins/CryptoPP/crypto/src/xormac.h b/plugins/CryptoPP/crypto/src/xormac.h new file mode 100644 index 0000000000..977b2cd6f7 --- /dev/null +++ b/plugins/CryptoPP/crypto/src/xormac.h @@ -0,0 +1,179 @@ +// xormac.h - written and placed in the public domain by Wei Dai + +#ifndef CRYPTOPP_XORMAC_H +#define CRYPTOPP_XORMAC_H + +#include "seckey.h" +#include "iterhash.h" +#include "argnames.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +template struct DigestSizeSubtract4Workaround // VC60 workaround +{ + CRYPTOPP_CONSTANT(RESULT = T::DIGESTSIZE-4) +}; + +template +class CRYPTOPP_NO_VTABLE XMACC_Base : public FixedKeyLength::RESULT, SimpleKeyingInterface::INTERNALLY_GENERATED_IV>, + public IteratedHash +{ +public: + static std::string StaticAlgorithmName() {return std::string("XMAC(") + T::StaticAlgorithmName() + ")";} + CRYPTOPP_CONSTANT(DIGESTSIZE = 4+T::DIGESTSIZE) + typedef typename T::HashWordType HashWordType; + + XMACC_Base() {SetStateSize(T::DIGESTSIZE);} + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void Resynchronize(const byte *IV) + { + GetWord(false, BIG_ENDIAN_ORDER, m_counter, IV); + this->Restart(); + } + unsigned int IVSize() const + {return 4;} + void GetNextIV(byte *IV) + { + if (m_counter == 0xffffffff) + throw NotImplemented("XMACC: must have a valid counter to get next IV"); + PutWord(false, BIG_ENDIAN_ORDER, IV, m_counter+1); + } + + word32 CurrentCounter() const {return m_counter;} + + void TruncatedFinal(byte *mac, size_t size); + bool TruncatedVerify(const byte *mac, size_t length); + unsigned int DigestSize() const {return DIGESTSIZE;} // need to override this + +private: + void Init(); + static void WriteWord32(byte *output, word32 value); + static void XorDigest(HashWordType *digest, const HashWordType *buffer); + void HashEndianCorrectedBlock(const HashWordType *data); + + FixedSizeSecBlock::RESULT> m_key; + CRYPTOPP_CONSTANT(BUFFER_SIZE = (T::DIGESTSIZE / sizeof(HashWordType))) // VC60 workaround +#ifdef __BORLANDC__ + FixedSizeSecBlock m_buffer; +#else + FixedSizeSecBlock m_buffer; +#endif + word32 m_counter, m_index; +}; + +//! XMAC +/*! If you need to generate MACs with XMACC (instead of just verifying them), + you must save the counter before destroying an XMACC object + and reinitialize it the next time you create an XMACC with the same key. + Start counter at 0 when using a key for the first time. */ +template +class XMACC : public ClonableImpl, MessageAuthenticationCodeImpl > > +{ +public: + XMACC() {} + XMACC(const byte *key, word32 counter = 0xffffffff) + {this->SetKey(key, this->KEYLENGTH, MakeParameters(Name::XMACC_Counter(), counter));} +}; + +template void XMACC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + this->AssertValidKeyLength(length); + m_counter = 0xffffffff; + const byte *iv = NULL; + if (params.GetValue(Name::IV(), iv)) + GetWord(false, BIG_ENDIAN_ORDER, m_counter, iv); + else + params.GetValue(Name::XMACC_Counter(), m_counter); + memcpy_s(m_key, m_key.SizeInBytes(), key, this->KEYLENGTH); + Init(); +} + +template void XMACC_Base::Init() +{ + m_index = 0x80000000; + memset(this->m_digest, 0, T::DIGESTSIZE); +} + +template inline void XMACC_Base::WriteWord32(byte *output, word32 value) +{ + output[0] = byte(value >> 24); + output[1] = byte(value >> 16); + output[2] = byte(value >> 8); + output[3] = byte(value); +} + +template inline void XMACC_Base::XorDigest(HashWordType *digest, const HashWordType *buffer) +{ + for (unsigned i=0; i<(T::DIGESTSIZE/sizeof(HashWordType)); i++) + digest[i] ^= buffer[i]; +} + +template void XMACC_Base::HashEndianCorrectedBlock(const HashWordType *input) +{ + memcpy_s(m_buffer, m_buffer.SizeInBytes(), m_key, this->KEYLENGTH); + WriteWord32((byte *)m_buffer.begin()+this->KEYLENGTH, ++m_index); + T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); + T::Transform(m_buffer, input); + XorDigest(this->m_digest, m_buffer); +} + +template void XMACC_Base::TruncatedFinal(byte *mac, size_t size) +{ + this->ThrowIfInvalidTruncatedSize(size); + if (size < 4) + throw InvalidArgument("XMACC: truncating the MAC to less than 4 bytes will cause it to be unverifiable"); + if (m_counter == 0xffffffff) + throw InvalidArgument("XMACC: the counter must be initialized to a valid value for MAC generation"); + + 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] = ByteReverse(this->GetBitCountHi()); // ByteReverse for backwards compatibility + this->m_data[this->m_data.size()-1] = ByteReverse(this->GetBitCountLo()); + HashEndianCorrectedBlock(this->m_data); + + memcpy_s(m_buffer, m_buffer.SizeInBytes(), m_key, this->KEYLENGTH); + WriteWord32((byte *)m_buffer.begin()+this->KEYLENGTH, 0); + memset(this->m_data, 0, this->BLOCKSIZE-4); + WriteWord32((byte *)this->m_data.begin()+this->BLOCKSIZE-4, ++m_counter); + T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); + T::CorrectEndianess(this->m_data, this->m_data, this->BLOCKSIZE); + T::Transform(m_buffer, this->m_data); + XorDigest(this->m_digest, m_buffer); + + WriteWord32(mac, m_counter); + T::CorrectEndianess(this->m_digest, this->m_digest, T::DIGESTSIZE); + memcpy_s(mac+4, size-4, this->m_digest, size-4); + + this->Restart(); // reinit for next use +} + +template bool XMACC_Base::TruncatedVerify(const byte *mac, size_t size) +{ + assert(4 <= size && size <= DIGESTSIZE); + + 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] = ByteReverse(this->GetBitCountHi()); // ByteReverse for backwards compatibility + this->m_data[this->m_data.size()-1] = ByteReverse(this->GetBitCountLo()); + HashEndianCorrectedBlock(this->m_data); + + memcpy_s(m_buffer, m_buffer.SizeInBytes(), m_key, this->KEYLENGTH); + WriteWord32((byte *)m_buffer.begin()+this->KEYLENGTH, 0); + memset(this->m_data, 0, this->BLOCKSIZE-4); + memcpy_s((byte *)this->m_data.begin()+this->BLOCKSIZE-4, 4, mac, 4); + T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); + T::CorrectEndianess(this->m_data, this->m_data, this->BLOCKSIZE); + T::Transform(m_buffer, this->m_data); + XorDigest(this->m_digest, m_buffer); + + T::CorrectEndianess(this->m_digest, this->m_digest, T::DIGESTSIZE); + bool macValid = (memcmp(mac+4, this->m_digest, size-4) == 0); + this->Restart(); // reinit for next use + return macValid; +} + +NAMESPACE_END + +#endif -- cgit v1.2.3