00001
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};};
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 ¶ms);
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;}
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))};
00055 FixedSizeSecBlock<HashWordType, BUFFER_SIZE> m_buffer;
00056 word32 m_counter, m_index;
00057 };
00058
00059
00060
00061
00062
00063
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 ¶ms)
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());
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();
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());
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();
00167
return macValid;
00168 }
00169
00170 NAMESPACE_END
00171
00172
#endif