Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound 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 
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         // If you need to generate MACs with XMACC (instead of just verifying them),
00018         // you must save the counter before destroying an XMACC object
00019         // and reinitialize it the next time you create an XMACC with the same key.
00020         // Start counter at 0 when using a key for the first time.
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);       // byteReverse for backwards compatibility
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();               // reinit for next use
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);       // byteReverse for backwards compatibility
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();               // reinit for next use
00126         return macValid;
00127 }
00128 
00129 NAMESPACE_END
00130 
00131 #endif

Generated at Mon Jan 15 01:16:38 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000