00001
00002
00003 #ifndef CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
00004 #define CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
00005
00006 #include "cryptlib.h"
00007 #include "hrtimer.h"
00008 #include "secblock.h"
00009 #include "hmac.h"
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013
00014 class KeyDerivationFunction
00015 {
00016 public:
00017
00018 virtual size_t MaxDerivedKeyLength() const =0;
00019 virtual bool Usesinfo() const =0;
00020
00021 virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info=NULL, size_t infoLen=0) const =0;
00022
00023 virtual ~KeyDerivationFunction() {}
00024 };
00025
00026
00027
00028 template <class T>
00029 class HKDF : public KeyDerivationFunction
00030 {
00031 public:
00032 static const char* StaticAlgorithmName () {
00033 static const std::string name(std::string("HKDF(") + std::string(T::StaticAlgorithmName()) + std::string(")"));
00034 return name.c_str();
00035 }
00036 size_t MaxDerivedKeyLength() const {return static_cast<size_t>(T::DIGESTSIZE) * 255;}
00037 bool Usesinfo() const {return true;}
00038 unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const;
00039
00040 protected:
00041
00042
00043 typedef byte NullVectorType[T::DIGESTSIZE];
00044 static const NullVectorType& GetNullVector() {
00045 static const NullVectorType s_NullVector = {0};
00046 return s_NullVector;
00047 }
00048 };
00049
00050 template <class T>
00051 unsigned int HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const
00052 {
00053 static const size_t DIGEST_SIZE = static_cast<size_t>(T::DIGESTSIZE);
00054 const unsigned int req = static_cast<unsigned int>(derivedLen);
00055
00056 assert(secret && secretLen);
00057 assert(derived && derivedLen);
00058 assert(derivedLen <= MaxDerivedKeyLength());
00059
00060 if (derivedLen > MaxDerivedKeyLength())
00061 throw InvalidArgument("HKDF: derivedLen must be less than or equal to MaxDerivedKeyLength");
00062
00063 HMAC<T> hmac;
00064 FixedSizeSecBlock<byte, DIGEST_SIZE> prk, buffer;
00065
00066
00067 const byte* key = (salt ? salt : GetNullVector());
00068 const size_t klen = (salt ? saltLen : DIGEST_SIZE);
00069
00070 hmac.SetKey(key, klen);
00071 hmac.CalculateDigest(prk, secret, secretLen);
00072
00073
00074 hmac.SetKey(prk.data(), prk.size());
00075 byte block = 0;
00076
00077 while (derivedLen > 0)
00078 {
00079 if (block++) {hmac.Update(buffer, buffer.size());}
00080 if (info && infoLen) {hmac.Update(info, infoLen);}
00081 hmac.CalculateDigest(buffer, &block, 1);
00082
00083 #if CRYPTOPP_MSC_VERSION
00084 const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
00085 memcpy_s(derived, segmentLen, buffer, segmentLen);
00086 #else
00087 const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
00088 std::memcpy(derived, buffer, segmentLen);
00089 #endif
00090
00091 derived += segmentLen;
00092 derivedLen -= segmentLen;
00093 }
00094
00095 return req;
00096 }
00097
00098 NAMESPACE_END
00099
00100 #endif // CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H