00001
00002
00003
#ifndef CRYPTOPP_XORMAC_H
00004
#define CRYPTOPP_XORMAC_H
00005
00006
#include "iterhash.h"
00007
#include "argnames.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011 template <class T> struct DigestSizeSubtract4Workaround {
enum {RESULT = T::DIGESTSIZE-4};};
00012
00013
template <
class T>
00014
class XMACC_Base :
public FixedKeyLength<DigestSizeSubtract4Workaround<T>::RESULT, SimpleKeyingInterface::INTERNALLY_GENERATED_IV>,
00015
public IteratedHash<typename T::HashWordType, typename T::ByteOrderClass, T::BLOCKSIZE, MessageAuthenticationCode>
00016 {
00017
public:
00018
static std::string StaticAlgorithmName() {
return std::string(
"XMAC(") + T::StaticAlgorithmName() +
")";}
00019
enum {DIGESTSIZE = 4+T::DIGESTSIZE};
00020
typedef typename T::HashWordType HashWordType;
00021
00022 XMACC_Base() :
IteratedHash<HashWordType, CPP_TYPENAME T::ByteOrderClass, T::BLOCKSIZE,
MessageAuthenticationCode>(T::DIGESTSIZE) {}
00023
00024
void CheckedSetKey(
void *, Empty empty,
const byte *key,
unsigned int length,
const NameValuePairs ¶ms);
00025
void Resynchronize(
const byte *IV)
00026 {
00027 GetWord(
false, BIG_ENDIAN_ORDER, m_counter, IV);
00028 Restart();
00029 }
00030
unsigned int IVSize()
const
00031
{
return 4;}
00032
void GetNextIV(byte *IV)
00033 {
00034
if (m_counter == 0xffffffff)
00035
throw NotImplemented(
"XMACC: must have a valid counter to get next IV");
00036 PutWord(
false, BIG_ENDIAN_ORDER, IV, m_counter+1);
00037 }
00038
00039 word32 CurrentCounter()
const {
return m_counter;}
00040
00041
void TruncatedFinal(byte *mac,
unsigned int size);
00042
bool TruncatedVerify(
const byte *mac,
unsigned int length);
00043
unsigned int DigestSize()
const {
return DIGESTSIZE;}
00044
00045
private:
00046
void Init();
00047
static void WriteWord32(byte *output, word32 value);
00048
static void XorDigest(HashWordType *digest,
const HashWordType *buffer);
00049
void vTransform(
const HashWordType *data);
00050
00051 FixedSizeSecBlock<byte, DigestSizeSubtract4Workaround<T>::RESULT> m_key;
00052
enum {BUFFER_SIZE = ((T::DIGESTSIZE) /
sizeof(HashWordType))};
00053 FixedSizeSecBlock<HashWordType, BUFFER_SIZE> m_buffer;
00054 word32 m_counter, m_index;
00055 };
00056
00057
00058
00059
00060
00061
00062
template <
class T>
00063 class XMACC :
public MessageAuthenticationCodeTemplate<XMACC_Base<T> >
00064 {
00065
public:
00066
XMACC() {}
00067
XMACC(
const byte *key, word32 counter = 0xffffffff)
00068 {SetKey(key, KEYLENGTH, MakeParameters(Name::XMACC_Counter(), counter));}
00069 };
00070
00071
template <
class T>
void XMACC_Base<T>::CheckedSetKey(
void *, Empty empty,
const byte *key,
unsigned int length,
const NameValuePairs ¶ms)
00072 {
00073 ThrowIfInvalidKeyLength(length);
00074 m_counter = 0xffffffff;
00075
const byte *iv = NULL;
00076
if (params.
GetValue(Name::IV(), iv))
00077 GetWord(
false, BIG_ENDIAN_ORDER, m_counter, iv);
00078
else
00079 params.
GetValue(Name::XMACC_Counter(), m_counter);
00080 memcpy(m_key, key, KEYLENGTH);
00081 Init();
00082 }
00083
00084
template <
class T>
void XMACC_Base<T>::Init()
00085 {
00086 m_index = 0x80000000;
00087 memset(m_digest, 0, T::DIGESTSIZE);
00088 }
00089
00090
template <
class T>
inline void XMACC_Base<T>::WriteWord32(byte *output, word32 value)
00091 {
00092 output[0] = byte(value >> 24);
00093 output[1] = byte(value >> 16);
00094 output[2] = byte(value >> 8);
00095 output[3] = byte(value);
00096 }
00097
00098
template <
class T>
inline void XMACC_Base<T>::XorDigest(HashWordType *digest,
const HashWordType *buffer)
00099 {
00100
for (
unsigned i=0; i<(T::DIGESTSIZE/
sizeof(HashWordType)); i++)
00101 digest[i] ^= buffer[i];
00102 }
00103
00104
template <
class T>
void XMACC_Base<T>::vTransform(
const HashWordType *input)
00105 {
00106 memcpy(m_buffer, m_key, KEYLENGTH);
00107 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, ++m_index);
00108 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE);
00109 T::Transform(m_buffer, input);
00110 XorDigest(m_digest, m_buffer);
00111 }
00112
00113
template <
class T>
void XMACC_Base<T>::TruncatedFinal(byte *mac,
unsigned int size)
00114 {
00115 ThrowIfInvalidTruncatedSize(size);
00116
if (size < 4)
00117
throw InvalidArgument(
"XMACC: truncating the MAC to less than 4 bytes will cause it to be unverifiable");
00118
if (m_counter == 0xffffffff)
00119
throw InvalidArgument(
"XMACC: the counter must be initialized to a valid value for MAC generation");
00120
00121 PadLastBlock(BLOCKSIZE - 2*
sizeof(HashWordType));
00122 CorrectEndianess(m_data, m_data, BLOCKSIZE - 2*
sizeof(HashWordType));
00123 m_data[m_data.size()-2] = ByteReverse(GetBitCountHi());
00124 m_data[m_data.size()-1] = ByteReverse(GetBitCountLo());
00125 vTransform(m_data);
00126
00127 memcpy(m_buffer, m_key, KEYLENGTH);
00128 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, 0);
00129 memset(m_data, 0, BLOCKSIZE-4);
00130 WriteWord32((byte *)m_data.begin()+BLOCKSIZE-4, ++m_counter);
00131 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE);
00132 T::CorrectEndianess(m_data, m_data, BLOCKSIZE);
00133 T::Transform(m_buffer, m_data);
00134 XorDigest(m_digest, m_buffer);
00135
00136 WriteWord32(mac, m_counter);
00137 T::CorrectEndianess(m_digest, m_digest, T::DIGESTSIZE);
00138 memcpy(mac+4, m_digest, size-4);
00139
00140
Restart();
00141 }
00142
00143
template <
class T>
bool XMACC_Base<T>::TruncatedVerify(
const byte *mac,
unsigned int size)
00144 {
00145 assert(4 <= size && size <= DIGESTSIZE);
00146
00147 PadLastBlock(BLOCKSIZE - 2*
sizeof(HashWordType));
00148 CorrectEndianess(m_data, m_data, BLOCKSIZE - 2*
sizeof(HashWordType));
00149 m_data[m_data.size()-2] = ByteReverse(GetBitCountHi());
00150 m_data[m_data.size()-1] = ByteReverse(GetBitCountLo());
00151 vTransform(m_data);
00152
00153 memcpy(m_buffer, m_key, KEYLENGTH);
00154 WriteWord32((byte *)m_buffer.begin()+KEYLENGTH, 0);
00155 memset(m_data, 0, BLOCKSIZE-4);
00156 memcpy((byte *)m_data.begin()+BLOCKSIZE-4, mac, 4);
00157 T::CorrectEndianess(m_buffer, m_buffer, T::DIGESTSIZE);
00158 T::CorrectEndianess(m_data, m_data, BLOCKSIZE);
00159 T::Transform(m_buffer, m_data);
00160 XorDigest(m_digest, m_buffer);
00161
00162 T::CorrectEndianess(m_digest, m_digest, T::DIGESTSIZE);
00163
bool macValid = (memcmp(mac+4, m_digest, size-4) == 0);
00164
Restart();
00165
return macValid;
00166 }
00167
00168 NAMESPACE_END
00169
00170
#endif