00001 #ifndef CRYPTOPP_DMAC_H
00002 #define CRYPTOPP_DMAC_H
00003
00004 #include "cbcmac.h"
00005
00006 NAMESPACE_BEGIN(CryptoPP)
00007
00009
00012 template <class T> class DMAC : public MessageAuthenticationCode, SameKeyLengthAs<T>
00013 {
00014 public:
00015 enum {DIGESTSIZE=T::BLOCKSIZE};
00016
00017 #ifdef __MWERKS__ // CW50 workaround: can't use DEFAULT_KEYLENGTH here
00018 DMAC(const byte *key, unsigned int keylength = T::DEFAULT_KEYLENGTH);
00019 #else
00020 DMAC(const byte *key, unsigned int keylength = DEFAULT_KEYLENGTH);
00021 #endif
00022
00023 void Update(const byte *input, unsigned int length);
00024 void Final(byte *mac);
00025 unsigned int DigestSize() const {return DIGESTSIZE;}
00026
00027 private:
00028 byte *GenerateSubKeys(const byte *key, unsigned int keylength);
00029
00030 unsigned int subkeylength;
00031 SecByteBlock subkeys;
00032 CBC_MAC<T> mac1;
00033 T f2;
00034 unsigned int counter;
00035 };
00036
00037 template <class T>
00038 DMAC<T>::DMAC(const byte *key, unsigned int keylength)
00039 : subkeylength(T::KeyLength(T::BLOCKSIZE))
00040 , subkeys(2*STDMAX((unsigned int)T::BLOCKSIZE, subkeylength))
00041 , mac1(GenerateSubKeys(key, keylength), subkeylength)
00042 , f2(subkeys+subkeys.size/2, subkeylength)
00043 , counter(0)
00044 {
00045 subkeys.Resize(0);
00046 }
00047
00048 template <class T>
00049 void DMAC<T>::Update(const byte *input, unsigned int length)
00050 {
00051 mac1.Update(input, length);
00052 counter = (counter + length) % T::BLOCKSIZE;
00053 }
00054
00055 template <class T>
00056 void DMAC<T>::Final(byte *mac)
00057 {
00058 byte pad[T::BLOCKSIZE];
00059 byte padByte = byte(T::BLOCKSIZE-counter);
00060 memset(pad, padByte, padByte);
00061 mac1.Update(pad, padByte);
00062 mac1.Final(mac);
00063 f2.ProcessBlock(mac);
00064 }
00065
00066 template <class T>
00067 byte *DMAC<T>::GenerateSubKeys(const byte *key, unsigned int keylength)
00068 {
00069 T cipher(key, keylength);
00070 memset(subkeys, 0, subkeys.size);
00071 cipher.ProcessBlock(subkeys);
00072 subkeys[subkeys.size/2 + T::BLOCKSIZE - 1] = 1;
00073 cipher.ProcessBlock(subkeys+subkeys.size/2);
00074 return subkeys;
00075 }
00076
00077 NAMESPACE_END
00078
00079 #endif