1 // mdc.h - originally written and placed in the public domain by Wei Dai
2 
3 /// \file mdc.h
4 /// \brief Classes for the MDC message digest
5 
6 #ifndef CRYPTOPP_MDC_H
7 #define CRYPTOPP_MDC_H
8 
9 #include "seckey.h"
10 #include "secblock.h"
11 #include "misc.h"
12 
13 // GCC cast warning
14 #define HashWordPtr(x) ((HashWordType*)(void*)(x))
15 #define ConstHashWordPtr(x) ((const HashWordType*)(const void*)(x))
16 
17 NAMESPACE_BEGIN(CryptoPP)
18 
19 /// \tparam B BlockCipher derived class
20 /// \brief MDC_Info cipher information
21 template <class B>
22 struct MDC_Info : public FixedBlockSize<B::DIGESTSIZE>, public FixedKeyLength<B::BLOCKSIZE>
23 {
StaticAlgorithmNameMDC_Info24 	static std::string StaticAlgorithmName() {return std::string("MDC/")+B::StaticAlgorithmName();}
25 };
26 
27 /// \brief MDC cipher
28 /// \tparam H HashTransformation derived class
29 /// \details MDC() is a construction by Peter Gutmann to turn an iterated hash function into a PRF
30 /// \sa <a href="http://www.cryptopp.com/wiki/MDC">MDC</a>
31 template <class H>
32 class MDC : public MDC_Info<H>
33 {
34 	/// \brief MDC cipher encryption operation
35 	class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl<MDC_Info<H> >
36 	{
37 		typedef typename H::HashWordType HashWordType;
38 
39 	public:
UncheckedSetKey(const byte * userKey,unsigned int length,const NameValuePairs & params)40 		void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
41 		{
42 			CRYPTOPP_UNUSED(params);
43 			this->AssertValidKeyLength(length);
44 			ConditionalByteReverse(BIG_ENDIAN_ORDER, Key(), ConstHashWordPtr(userKey), this->KEYLENGTH);
45 		}
46 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock)47 		void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
48 		{
49 			ConditionalByteReverse(BIG_ENDIAN_ORDER, Buffer(), ConstHashWordPtr(inBlock), this->BLOCKSIZE);
50 			H::Transform(Buffer(), Key());
51 
52 			if (xorBlock)
53 			{
54 				ConditionalByteReverse(BIG_ENDIAN_ORDER, Buffer(), Buffer(), this->BLOCKSIZE);
55 				xorbuf(outBlock, xorBlock, m_buffer, this->BLOCKSIZE);
56 			}
57 			else
58 			{
59 				ConditionalByteReverse(BIG_ENDIAN_ORDER, HashWordPtr(outBlock), Buffer(), this->BLOCKSIZE);
60 			}
61 		}
62 
IsPermutation()63 		bool IsPermutation() const {return false;}
64 
OptimalDataAlignment()65 		unsigned int OptimalDataAlignment() const {return sizeof(HashWordType);}
66 
67 	private:
Key()68 		HashWordType *Key() {return HashWordPtr(m_key.data());}
Key()69 		const HashWordType *Key() const {return ConstHashWordPtr(m_key.data());}
Buffer()70 		HashWordType *Buffer() const {return HashWordPtr(m_buffer.data());}
71 
72 		// VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup
73 		FixedSizeSecBlock<byte, MDC_Info<H>::KEYLENGTH, AllocatorWithCleanup<byte> > m_key;
74 		mutable FixedSizeSecBlock<byte, MDC_Info<H>::BLOCKSIZE, AllocatorWithCleanup<byte> > m_buffer;
75 	};
76 
77 public:
78 	// use BlockCipher interface
79 	typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
80 };
81 
82 NAMESPACE_END
83 
84 #endif
85