Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

xormac.h

00001 // xormac.h - written and placed in the public domain by Wei Dai 00002 00003 #ifndef CRYPTOPP_XORMAC_H 00004 #define CRYPTOPP_XORMAC_H 00005 00006 #include "iterhash.h" 00007 #include "argnames.h" 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 template <class T> struct DigestSizeSubtract4Workaround {enum {RESULT = T::DIGESTSIZE-4};}; // VC60 workaround 00012 00013 template <class T> 00014 class XMACC_Base : public FixedKeyLength<DigestSizeSubtract4Workaround<T>::RESULT, SimpleKeyingInterface::INTERNALLY_GENERATED_IV>, 00015 public IteratedHash<typename T::HashWordType, typename T::ByteOrderClass, T::BLOCKSIZE, MessageAuthenticationCode> 00016 { 00017 public: 00018 static std::string StaticAlgorithmName() {return std::string("XMAC(") + T::StaticAlgorithmName() + ")";} 00019 enum {DIGESTSIZE = 4+T::DIGESTSIZE}; 00020 typedef typename T::HashWordType HashWordType; 00021 00022 XMACC_Base() : IteratedHash<HashWordType, CPP_TYPENAME T::ByteOrderClass, T::BLOCKSIZE, MessageAuthenticationCode>(T::DIGESTSIZE) {} 00023 00024 void CheckedSetKey(void *, Empty empty, const byte *key, unsigned int length, const NameValuePairs &params); 00025 void Resynchronize(const byte *IV) 00026 { 00027 GetWord(false, BIG_ENDIAN_ORDER, m_counter, IV); 00028 Restart(); 00029 } 00030 unsigned int IVSize() const 00031 {return 4;} 00032 void GetNextIV(byte *IV) 00033 { 00034 if (m_counter == 0xffffffff) 00035 throw NotImplemented("XMACC: must have a valid counter to get next IV"); 00036 PutWord(false, BIG_ENDIAN_ORDER, IV, m_counter+1); 00037 } 00038 00039 word32 CurrentCounter() const {return m_counter;} 00040 00041 void TruncatedFinal(byte *mac, unsigned int size); 00042 bool TruncatedVerify(const byte *mac, unsigned int length); 00043 unsigned int DigestSize() const {return DIGESTSIZE;} // need to override this 00044 00045 private: 00046 void Init(); 00047 static void WriteWord32(byte *output, word32 value); 00048 static void XorDigest(HashWordType *digest, const HashWordType *buffer); 00049 void vTransform(const HashWordType *data); 00050 00051 FixedSizeSecBlock<byte, DigestSizeSubtract4Workaround<T>::RESULT> m_key; 00052 enum {BUFFER_SIZE = ((T::DIGESTSIZE) / sizeof(HashWordType))}; // VC60 workaround 00053 FixedSizeSecBlock<HashWordType, BUFFER_SIZE> m_buffer; 00054 word32 m_counter, m_index; 00055 }; 00056 00057 //! <a href="http://www.weidai.com/scan-mirror/mac.html#XMAC">XMAC</a> 00058 /*! If you need to generate MACs with XMACC (instead of just verifying them), 00059 you must save the counter before destroying an XMACC object 00060 and reinitialize it the next time you create an XMACC with the same key. 00061 Start counter at 0 when using a key for the first time. */ 00062 template <class T> 00063 class XMACC : public MessageAuthenticationCodeTemplate<XMACC_Base<T> > 00064 { 00065 public: 00066 XMACC() {} 00067 XMACC(const byte *key, word32 counter = 0xffffffff) 00068 {SetKey(key, KEYLENGTH, MakeParameters(Name::XMACC_Counter(), counter));} 00069 }; 00070 00071 template <class T> void XMACC_Base<T>::CheckedSetKey(void *, Empty empty, const byte *key, unsigned int length, const NameValuePairs &params) 00072 { 00073 ThrowIfInvalidKeyLength(length); 00074 m_counter = 0xffffffff; 00075 const byte *iv = NULL; 00076 if (params.GetValue(Name::IV(), iv)) 00077 GetWord(false, BIG_ENDIAN_ORDER, m_counter, iv); 00078 else 00079 params.GetValue(Name::XMACC_Counter(), m_counter); 00080 memcpy(m_key, key, KEYLENGTH); 00081 Init(); 00082 } 00083 00084 template <class T> void XMACC_Base<T>::Init() 00085 { 00086 m_index = 0x80000000; 00087 memset(m_digest, 0, T::DIGESTSIZE); 00088 } 00089 00090 template <class T> inline void XMACC_Base<T>::WriteWord32(byte *output, word32 value) 00091 { 00092 output[0] = byte(value >> 24); 00093 output[1] = byte(value >> 16); 00094 output[2] = byte(value >> 8); 00095 output[3] = byte(value); 00096 } 00097 00098 template <class T> inline void XMACC_Base<T>::XorDigest(HashWordType *digest, const HashWordType *buffer) 00099 { 00100 for (unsigned i=0; i<(T::DIGESTSIZE/sizeof(HashWordType)); i++) 00101 digest[i] ^= buffer[i]; 00102 } 00103 00104 template <class T> void XMACC_Base<T>::vTransform(const HashWordType *input) 00105 { 00106 memcpy(m_buffer, m_key, KEYLENGTH); 00107 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, ++m_index); 00108 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); 00109 T::Transform(m_buffer, input); 00110 XorDigest(m_digest, m_buffer); 00111 } 00112 00113 template <class T> void XMACC_Base<T>::TruncatedFinal(byte *mac, unsigned int size) 00114 { 00115 ThrowIfInvalidTruncatedSize(size); 00116 if (size < 4) 00117 throw InvalidArgument("XMACC: truncating the MAC to less than 4 bytes will cause it to be unverifiable"); 00118 if (m_counter == 0xffffffff) 00119 throw InvalidArgument("XMACC: the counter must be initialized to a valid value for MAC generation"); 00120 00121 PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType)); 00122 CorrectEndianess(m_data, m_data, BLOCKSIZE - 2*sizeof(HashWordType)); 00123 m_data[m_data.size()-2] = ByteReverse(GetBitCountHi()); // byteReverse for backwards compatibility 00124 m_data[m_data.size()-1] = ByteReverse(GetBitCountLo()); 00125 vTransform(m_data); 00126 00127 memcpy(m_buffer, m_key, KEYLENGTH); 00128 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, 0); 00129 memset(m_data, 0, BLOCKSIZE-4); 00130 WriteWord32((byte *)m_data.begin()+BLOCKSIZE-4, ++m_counter); 00131 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); 00132 T::CorrectEndianess(m_data, m_data, BLOCKSIZE); 00133 T::Transform(m_buffer, m_data); 00134 XorDigest(m_digest, m_buffer); 00135 00136 WriteWord32(mac, m_counter); 00137 T::CorrectEndianess(m_digest, m_digest, T::DIGESTSIZE); 00138 memcpy(mac+4, m_digest, size-4); 00139 00140 Restart(); // reinit for next use 00141 } 00142 00143 template <class T> bool XMACC_Base<T>::TruncatedVerify(const byte *mac, unsigned int size) 00144 { 00145 assert(4 <= size && size <= DIGESTSIZE); 00146 00147 PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType)); 00148 CorrectEndianess(m_data, m_data, BLOCKSIZE - 2*sizeof(HashWordType)); 00149 m_data[m_data.size()-2] = ByteReverse(GetBitCountHi()); // byteReverse for backwards compatibility 00150 m_data[m_data.size()-1] = ByteReverse(GetBitCountLo()); 00151 vTransform(m_data); 00152 00153 memcpy(m_buffer, m_key, KEYLENGTH); 00154 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, 0); 00155 memset(m_data, 0, BLOCKSIZE-4); 00156 memcpy((byte *)m_data.begin()+BLOCKSIZE-4, mac, 4); 00157 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE); 00158 T::CorrectEndianess(m_data, m_data, BLOCKSIZE); 00159 T::Transform(m_buffer, m_data); 00160 XorDigest(m_digest, m_buffer); 00161 00162 T::CorrectEndianess(m_digest, m_digest, T::DIGESTSIZE); 00163 bool macValid = (memcmp(mac+4, m_digest, size-4) == 0); 00164 Restart(); // reinit for next use 00165 return macValid; 00166 } 00167 00168 NAMESPACE_END 00169 00170 #endif

Generated on Wed Jul 28 08:07:09 2004 for Crypto++ by doxygen 1.3.7