00001 #ifndef CRYPTOPP_CBCMAC_H
00002 #define CRYPTOPP_CBCMAC_H
00003
00004 #include "cryptlib.h"
00005 #include "misc.h"
00006
00007 NAMESPACE_BEGIN(CryptoPP)
00008
00010
00014 template <class T> class CBC_MAC : public MessageAuthenticationCode, public SameKeyLengthAs<T>
00015 {
00016 public:
00017 enum {DIGESTSIZE=T::BLOCKSIZE};
00018
00019 #ifdef __MWERKS__ // CW50 workaround: can't use DEFAULT_KEYLENGTH here
00020 CBC_MAC(const byte *key, unsigned int keylength = T::DEFAULT_KEYLENGTH);
00021 #else
00022 CBC_MAC(const byte *key, unsigned int keylength = DEFAULT_KEYLENGTH);
00023 #endif
00024
00025 void Update(const byte *input, unsigned int length);
00026 void Final(byte *mac);
00027 unsigned int DigestSize() const {return DIGESTSIZE;}
00028
00029 private:
00030 void ProcessBuf();
00031 T cipher;
00032 SecByteBlock reg;
00033 unsigned int counter;
00034 };
00035
00036 template <class T>
00037 CBC_MAC<T>::CBC_MAC(const byte *key, unsigned int keylength)
00038 : cipher(key, keylength)
00039 , reg(T::BLOCKSIZE)
00040 , counter(0)
00041 {
00042 memset(reg, 0, T::BLOCKSIZE);
00043 }
00044
00045 template <class T>
00046 void CBC_MAC<T>::Update(const byte *input, unsigned int length)
00047 {
00048 while (counter && length)
00049 {
00050 reg[counter++] ^= *input++;
00051 if (counter == T::BLOCKSIZE)
00052 ProcessBuf();
00053 length--;
00054 }
00055
00056 while (length >= T::BLOCKSIZE)
00057 {
00058 xorbuf(reg, input, T::BLOCKSIZE);
00059 ProcessBuf();
00060 input += T::BLOCKSIZE;
00061 length -= T::BLOCKSIZE;
00062 }
00063
00064 while (length--)
00065 {
00066 reg[counter++] ^= *input++;
00067 if (counter == T::BLOCKSIZE)
00068 ProcessBuf();
00069 }
00070 }
00071
00072 template <class T>
00073 void CBC_MAC<T>::Final(byte *mac)
00074 {
00075 if (counter)
00076 ProcessBuf();
00077 memcpy(mac, reg, T::BLOCKSIZE);
00078 }
00079
00080 template <class T>
00081 void CBC_MAC<T>::ProcessBuf()
00082 {
00083 cipher.ProcessBlock(reg);
00084 counter = 0;
00085 }
00086
00087 NAMESPACE_END
00088
00089 #endif