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

Generated on Fri Aug 27 15:51:15 2004 for Crypto++ by doxygen 1.3.8