00001
00002
00003 #ifndef CRYPTOPP_XORMAC_H
00004 #define CRYPTOPP_XORMAC_H
00005
00006 #include "iterhash.h"
00007
00008 NAMESPACE_BEGIN(CryptoPP)
00009
00011 template <class T> class XMACC : public IteratedHash<typename T::HashWordType, T::HIGHFIRST, T::BLOCKSIZE>, public MessageAuthenticationCode
00012 {
00013 public:
00014 enum {KEYLENGTH=T::DIGESTSIZE-4, DIGESTSIZE = 4+T::DIGESTSIZE};
00015 typedef typename T::HashWordType HashWordType;
00016
00017
00018
00019
00020
00021
00022 XMACC(const byte *userKey, word32 counter=0xffffffff);
00023
00024 word32 CurrentCounter() const {return counter;}
00025
00026 void Final(byte *mac);
00027 bool Verify(const byte *mac);
00028 unsigned int DigestSize() const {return DIGESTSIZE;}
00029
00030 private:
00031 void Init();
00032 static void WriteWord32(byte *output, word32 value);
00033 static void XorDigest(HashWordType *digest, const HashWordType *buffer);
00034 void vTransform(const HashWordType *data);
00035
00036 SecByteBlock key;
00037 SecBlock<HashWordType> buffer;
00038 word32 counter, index;
00039 };
00040
00041 template <class T> XMACC<T>::XMACC(const byte *userKey, word32 counter)
00042 : IteratedHash<HashWordType, T::HIGHFIRST, T::BLOCKSIZE>(T::DIGESTSIZE)
00043 , key(KEYLENGTH)
00044 , buffer(T::DIGESTSIZE/sizeof(HashWordType))
00045 , counter(counter)
00046 {
00047 memcpy(key, userKey, KEYLENGTH);
00048 Init();
00049 }
00050
00051 template <class T> void XMACC<T>::Init()
00052 {
00053 index = 0x80000000;
00054 memset(digest, 0, T::DIGESTSIZE);
00055 }
00056
00057 template <class T> inline void XMACC<T>::WriteWord32(byte *output, word32 value)
00058 {
00059 output[0] = byte(value >> 24);
00060 output[1] = byte(value >> 16);
00061 output[2] = byte(value >> 8);
00062 output[3] = byte(value);
00063 }
00064
00065 template <class T> inline void XMACC<T>::XorDigest(HashWordType *digest, const HashWordType *buffer)
00066 {
00067 for (unsigned i=0; i<(T::DIGESTSIZE/sizeof(HashWordType)); i++)
00068 digest[i] ^= buffer[i];
00069 }
00070
00071 template <class T> void XMACC<T>::vTransform(const HashWordType *input)
00072 {
00073 memcpy(buffer, key, KEYLENGTH);
00074 WriteWord32((byte *)buffer.ptr+KEYLENGTH, ++index);
00075 T::CorrectEndianess(buffer, buffer, T::DIGESTSIZE);
00076 T::Transform(buffer, input);
00077 XorDigest(digest, buffer);
00078 }
00079
00080 template <class T> void XMACC<T>::Final(byte *mac)
00081 {
00082 assert(counter != 0xffffffff);
00083
00084 PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType));
00085 CorrectEndianess(data, data, BLOCKSIZE - 2*sizeof(HashWordType));
00086 data[data.size-2] = byteReverse(countHi);
00087 data[data.size-1] = byteReverse(countLo);
00088 vTransform(data);
00089
00090 memcpy(buffer, key, KEYLENGTH);
00091 WriteWord32((byte *)buffer.ptr+KEYLENGTH, 0);
00092 memset(data, 0, BLOCKSIZE-4);
00093 WriteWord32((byte *)data.ptr+BLOCKSIZE-4, ++counter);
00094 T::CorrectEndianess(buffer, buffer, T::DIGESTSIZE);
00095 T::CorrectEndianess(data, data, BLOCKSIZE);
00096 T::Transform(buffer, data);
00097 XorDigest(digest, buffer);
00098
00099 WriteWord32(mac, counter);
00100 T::CorrectEndianess(digest, digest, T::DIGESTSIZE);
00101 memcpy(mac+4, digest, T::DIGESTSIZE);
00102
00103 Reinit();
00104 }
00105
00106 template <class T> bool XMACC<T>::Verify(const byte *mac)
00107 {
00108 PadLastBlock(BLOCKSIZE - 2*sizeof(HashWordType));
00109 CorrectEndianess(data, data, BLOCKSIZE - 2*sizeof(HashWordType));
00110 data[data.size-2] = byteReverse(countHi);
00111 data[data.size-1] = byteReverse(countLo);
00112 vTransform(data);
00113
00114 memcpy(buffer, key, KEYLENGTH);
00115 WriteWord32((byte *)buffer.ptr+KEYLENGTH, 0);
00116 memset(data, 0, BLOCKSIZE-4);
00117 memcpy((byte *)data.ptr+BLOCKSIZE-4, mac, 4);
00118 T::CorrectEndianess(buffer, buffer, T::DIGESTSIZE);
00119 T::CorrectEndianess(data, data, BLOCKSIZE);
00120 T::Transform(buffer, data);
00121 XorDigest(digest, buffer);
00122
00123 T::CorrectEndianess(digest, digest, T::DIGESTSIZE);
00124 bool macValid = (memcmp(mac+4, digest, T::DIGESTSIZE) == 0);
00125 Reinit();
00126 return macValid;
00127 }
00128
00129 NAMESPACE_END
00130
00131 #endif