Crypto++  6.1
Free C++ class library of cryptographic schemes
hkdf.h
Go to the documentation of this file.
1 // hkdf.h - written and placed in public domain by Jeffrey Walton.
2 
3 /// \file hkdf.h
4 /// \brief Classes for HKDF from RFC 5869
5 /// \since Crypto++ 5.6.3
6 
7 #ifndef CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
8 #define CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
9 
10 #include "cryptlib.h"
11 #include "hrtimer.h"
12 #include "secblock.h"
13 #include "hmac.h"
14 
15 NAMESPACE_BEGIN(CryptoPP)
16 
17 /// abstract base class for key derivation function
19 {
20 public:
21  /// maximum number of bytes which can be produced under a secuirty context
22  virtual size_t MaxDerivedKeyLength() const =0;
23  virtual bool Usesinfo() const =0;
24  /// derive a key from secret
25  virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte* info=NULLPTR, size_t infoLen=0) const =0;
26 
27  virtual ~KeyDerivationFunction() {}
28 };
29 
30 /// \brief Extract-and-Expand Key Derivation Function (HKDF)
31 /// \tparam T HashTransformation class
32 /// \sa <A HREF="http://eprint.iacr.org/2010/264">Cryptographic Extraction and Key Derivation: The HKDF Scheme</A>
33 /// and <A HREF="http://tools.ietf.org/html/rfc5869">HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</A>
34 /// \since Crypto++ 5.6.3
35 template <class T>
37 {
38 public:
39  CRYPTOPP_CONSTANT(DIGESTSIZE = T::DIGESTSIZE)
40  CRYPTOPP_CONSTANT(SALTSIZE = T::DIGESTSIZE)
41  static const char* StaticAlgorithmName () {
42  static const std::string name(std::string("HKDF(") + std::string(T::StaticAlgorithmName()) + std::string(")"));
43  return name.c_str();
44  }
45  size_t MaxDerivedKeyLength() const {return static_cast<size_t>(T::DIGESTSIZE) * 255;}
46  bool Usesinfo() const {return true;}
47  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;
48 
49 protected:
50  // If salt is missing (NULLPTR), then use the NULL vector. Missing is different than EMPTY (0 length). The length
51  // of s_NullVector used depends on the Hash function. SHA-256 will use 32 bytes of s_NullVector.
52  typedef byte NullVectorType[SALTSIZE];
53  static const NullVectorType& GetNullVector() {
54  static const NullVectorType s_NullVector = {0};
55  return s_NullVector;
56  }
57 };
58 
59 template <class T>
60 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
61 {
62  static const size_t DIGEST_SIZE = static_cast<size_t>(T::DIGESTSIZE);
63  const unsigned int req = static_cast<unsigned int>(derivedLen);
64 
65  CRYPTOPP_ASSERT(secret && secretLen);
66  CRYPTOPP_ASSERT(derived && derivedLen);
67  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
68 
69  if (derivedLen > MaxDerivedKeyLength())
70  throw InvalidArgument("HKDF: derivedLen must be less than or equal to MaxDerivedKeyLength");
71 
72  HMAC<T> hmac;
74 
75  // Extract
76  const byte* key = (salt ? salt : GetNullVector());
77  const size_t klen = (salt ? saltLen : DIGEST_SIZE);
78 
79  hmac.SetKey(key, klen);
80  hmac.CalculateDigest(prk, secret, secretLen);
81 
82  // Expand
83  hmac.SetKey(prk.data(), prk.size());
84  byte block = 0;
85 
86  while (derivedLen > 0)
87  {
88  if (block++) {hmac.Update(buffer, buffer.size());}
89  if (info && infoLen) {hmac.Update(info, infoLen);}
90  hmac.CalculateDigest(buffer, &block, 1);
91 
92 #if CRYPTOPP_MSC_VERSION
93  const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
94  memcpy_s(derived, segmentLen, buffer, segmentLen);
95 #else
96  const size_t segmentLen = STDMIN(derivedLen, DIGEST_SIZE);
97  std::memcpy(derived, buffer, segmentLen);
98 #endif
99 
100  derived += segmentLen;
101  derivedLen -= segmentLen;
102  }
103 
104  return req;
105 }
106 
107 NAMESPACE_END
108 
109 #endif // CRYPTOPP_HASH_KEY_DERIVATION_FUNCTION_H
An invalid argument was detected.
Definition: cryptlib.h:199
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
derive a key from secret
Definition: hkdf.h:60
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
Definition: cryptlib.cpp:64
Extract-and-Expand Key Derivation Function (HKDF)
Definition: hkdf.h:36
Abstract base classes that provide a uniform interface to this library.
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:383
size_t MaxDerivedKeyLength() const
maximum number of bytes which can be produced under a secuirty context
Definition: hkdf.h:45
Classes and functions for secure memory allocations.
Classes for HMAC message authentication codes.
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:553
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: hmac.cpp:60
Fixed size stack-based SecBlock.
Definition: secblock.h:841
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:507
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
Updates the hash with additional input and computes the hash of the current message.
Definition: cryptlib.h:1141
HMAC.
Definition: hmac.h:50
Crypto++ library namespace.
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:561
abstract base class for key derivation function
Definition: hkdf.h:18