00001
00002
00003
#ifndef CRYPTOPP_HMAC_H
00004
#define CRYPTOPP_HMAC_H
00005
00006
#include "seckey.h"
00007
#include "secblock.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011 template <class T>
00012 class HMAC_Base : public
VariableKeyLength<16, 0, UINT_MAX>, public
MessageAuthenticationCode
00013 {
00014
public:
00015
static std::string StaticAlgorithmName() {
return std::string(
"HMAC(") + T::StaticAlgorithmName() +
")";}
00016
00017
00018
enum {DIGESTSIZE=T::DIGESTSIZE, BLOCKSIZE=T::BLOCKSIZE};
00019
00020 HMAC_Base() : m_innerHashKeyed(false) {}
00021
void UncheckedSetKey(
const byte *userKey,
unsigned int keylength);
00022
00023
void Restart();
00024
void Update(
const byte *input,
unsigned int length);
00025
void TruncatedFinal(byte *mac,
unsigned int size);
00026
unsigned int DigestSize()
const {
return DIGESTSIZE;}
00027
00028
private:
00029
void KeyInnerHash();
00030
00031
enum {IPAD=0x36, OPAD=0x5c};
00032
00033 FixedSizeSecBlock<byte, BLOCKSIZE> k_ipad, k_opad;
00034 FixedSizeSecBlock<byte, DIGESTSIZE> m_innerHash;
00035 T m_hash;
00036
bool m_innerHashKeyed;
00037 };
00038
00039
00040
00041
template <
class T>
00042 class HMAC :
public MessageAuthenticationCodeTemplate<HMAC_Base<T> >
00043 {
00044
public:
00045
HMAC() {}
00046
HMAC(
const byte *key,
unsigned int length=HMAC_Base<T>::DEFAULT_KEYLENGTH)
00047 {SetKey(key, length);}
00048 };
00049
00050
template <
class T>
00051
void HMAC_Base<T>::UncheckedSetKey(
const byte *userKey,
unsigned int keylength)
00052 {
00053 AssertValidKeyLength(keylength);
00054
00055
Restart();
00056
00057
if (keylength <= T::BLOCKSIZE)
00058 memcpy(k_ipad, userKey, keylength);
00059
else
00060 {
00061 m_hash.CalculateDigest(k_ipad, userKey, keylength);
00062 keylength = T::DIGESTSIZE;
00063 }
00064
00065 assert(keylength <= T::BLOCKSIZE);
00066 memset(k_ipad+keylength, 0, T::BLOCKSIZE-keylength);
00067
00068
for (
unsigned int i=0; i<T::BLOCKSIZE; i++)
00069 {
00070 k_opad[i] = k_ipad[i] ^ OPAD;
00071 k_ipad[i] ^= IPAD;
00072 }
00073 }
00074
00075
template <
class T>
00076
void HMAC_Base<T>::KeyInnerHash()
00077 {
00078 assert(!m_innerHashKeyed);
00079 m_hash.Update(k_ipad, T::BLOCKSIZE);
00080 m_innerHashKeyed =
true;
00081 }
00082
00083
template <
class T>
00084
void HMAC_Base<T>::Restart()
00085 {
00086
if (m_innerHashKeyed)
00087 {
00088 m_hash.Restart();
00089 m_innerHashKeyed =
false;
00090 }
00091 }
00092
00093
template <
class T>
00094
void HMAC_Base<T>::Update(
const byte *input,
unsigned int length)
00095 {
00096
if (!m_innerHashKeyed)
00097 KeyInnerHash();
00098 m_hash.Update(input, length);
00099 }
00100
00101
template <
class T>
00102
void HMAC_Base<T>::TruncatedFinal(byte *mac,
unsigned int size)
00103 {
00104 ThrowIfInvalidTruncatedSize(size);
00105
00106
if (!m_innerHashKeyed)
00107 KeyInnerHash();
00108 m_hash.Final(m_innerHash);
00109
00110 m_hash.Update(k_opad, T::BLOCKSIZE);
00111 m_hash.Update(m_innerHash, DIGESTSIZE);
00112 m_hash.TruncatedFinal(mac, size);
00113
00114 m_innerHashKeyed =
false;
00115 }
00116
00117 NAMESPACE_END
00118
00119
#endif