Crypto++  7.0
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_HKDF_H
8 #define CRYPTOPP_HKDF_H
9 
10 #include "cryptlib.h"
11 #include "secblock.h"
12 #include "hmac.h"
13 
14 NAMESPACE_BEGIN(CryptoPP)
15 
16 /// \brief Extract-and-Expand Key Derivation Function (HKDF)
17 /// \tparam T HashTransformation class
18 /// \sa <A HREF="http://eprint.iacr.org/2010/264">Cryptographic Extraction and Key
19 /// Derivation: The HKDF Scheme</A> and
20 /// <A HREF="http://tools.ietf.org/html/rfc5869">HMAC-based Extract-and-Expand Key
21 /// Derivation Function (HKDF)</A>
22 /// \since Crypto++ 5.6.3
23 template <class T>
25 {
26 public:
27  virtual ~HKDF() {}
28 
29  static std::string StaticAlgorithmName () {
30  const std::string name(std::string("HKDF(") +
31  std::string(T::StaticAlgorithmName()) + std::string(")"));
32  return name;
33  }
34 
35  // KeyDerivationFunction interface
36  std::string AlgorithmName() const {
37  return StaticAlgorithmName();
38  }
39 
40  // KeyDerivationFunction interface
41  size_t MaxDerivedLength() const {
42  return static_cast<size_t>(T::DIGESTSIZE) * 255;
43  }
44 
45  // KeyDerivationFunction interface
46  size_t GetValidDerivedLength(size_t keylength) const;
47 
48  // KeyDerivationFunction interface
49  size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
50  const NameValuePairs& params) const;
51 
52  /// \brief Derive a key from a seed
53  /// \param derived the derived output buffer
54  /// \param derivedLen the size of the derived buffer, in bytes
55  /// \param secret the seed input buffer
56  /// \param secretLen the size of the secret buffer, in bytes
57  /// \param salt the salt input buffer
58  /// \param saltLen the size of the salt buffer, in bytes
59  /// \param info the additional input buffer
60  /// \param infoLen the size of the info buffer, in bytes
61  /// \returns the number of iterations performed
62  /// \throws InvalidDerivedLength if <tt>derivedLen</tt> is invalid for the scheme
63  /// \details DeriveKey() provides a standard interface to derive a key from
64  /// a seed and other parameters. Each class that derives from KeyDerivationFunction
65  /// provides an overload that accepts most parameters used by the derivation function.
66  /// \details <tt>salt</tt> and <tt>info</tt> can be <tt>nullptr</tt> with 0 length.
67  /// HKDF is unusual in that a non-NULL salt with length 0 is different than a
68  /// NULL <tt>salt</tt>. A NULL <tt>salt</tt> causes HKDF to use a string of 0's
69  /// of length <tt>T::DIGESTSIZE</tt> for the <tt>salt</tt>.
70  /// \details HKDF always returns 1 because it only performs 1 iteration. Other
71  /// derivation functions, like PBKDF's, will return more interesting values.
72  size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
73  const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const;
74 
75 protected:
76  // KeyDerivationFunction interface
77  const Algorithm & GetAlgorithm() const {
78  return *this;
79  }
80 
81  // If salt is absent (NULL), then use the NULL vector. Missing is different than
82  // EMPTY (Non-NULL, 0 length). The length of s_NullVector used depends on the Hash
83  // function. SHA-256 will use 32 bytes of s_NullVector.
84  typedef byte NullVectorType[T::DIGESTSIZE];
85  static const NullVectorType& GetNullVector() {
86  static const NullVectorType s_NullVector = {0};
87  return s_NullVector;
88  }
89 };
90 
91 template <class T>
92 size_t HKDF<T>::GetValidDerivedLength(size_t keylength) const
93 {
94  if (keylength > MaxDerivedLength())
95  return MaxDerivedLength();
96  return keylength;
97 }
98 
99 template <class T>
100 size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen,
101  const byte *secret, size_t secretLen, const NameValuePairs& params) const
102 {
103  CRYPTOPP_ASSERT(secret && secretLen);
104  CRYPTOPP_ASSERT(derived && derivedLen);
105  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedLength());
106 
108  SecByteBlock salt, info;
109 
110  if (params.GetValue("Salt", p))
111  salt.Assign(p.begin(), p.size());
112  else
113  salt.Assign(GetNullVector(), T::DIGESTSIZE);
114 
115  if (params.GetValue("Info", p))
116  info.Assign(p.begin(), p.size());
117  else
118  info.Assign(GetNullVector(), 0);
119 
120  return DeriveKey(derived, derivedLen, secret, secretLen, salt.begin(), salt.size(), info.begin(), info.size());
121 }
122 
123 template <class T>
124 size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
125  const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const
126 {
127  CRYPTOPP_ASSERT(secret && secretLen);
128  CRYPTOPP_ASSERT(derived && derivedLen);
129  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedLength());
130 
131  ThrowIfInvalidDerivedLength(derivedLen);
132 
133  // HKDF business logic. NULL is different than empty.
134  if (salt == NULLPTR)
135  {
136  salt = GetNullVector();
137  saltLen = T::DIGESTSIZE;
138  }
139 
140  // key is PRK from the RFC, salt is IKM from the RFC
141  HMAC<T> hmac;
142  SecByteBlock key(T::DIGESTSIZE), buffer(T::DIGESTSIZE);
143 
144  // Extract
145  hmac.SetKey(salt, saltLen);
146  hmac.CalculateDigest(key, secret, secretLen);
147 
148  // Key
149  hmac.SetKey(key.begin(), key.size());
150  byte block = 0;
151 
152  // Expand
153  while (derivedLen > 0)
154  {
155  if (block++) {hmac.Update(buffer, buffer.size());}
156  if (infoLen) {hmac.Update(info, infoLen);}
157  hmac.CalculateDigest(buffer, &block, 1);
158 
159 #if CRYPTOPP_MSC_VERSION
160  const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
161  const size_t segmentLen = STDMIN(derivedLen, digestSize);
162  memcpy_s(derived, segmentLen, buffer, segmentLen);
163 #else
164  const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
165  const size_t segmentLen = STDMIN(derivedLen, digestSize);
166  std::memcpy(derived, buffer, segmentLen);
167 #endif
168 
169  derived += segmentLen;
170  derivedLen -= segmentLen;
171  }
172 
173  return 1;
174 }
175 
176 NAMESPACE_END
177 
178 #endif // CRYPTOPP_HKDF_H
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:20
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
size_t size() const
Length of the memory block.
Definition: algparam.h:84
size_t MaxDerivedLength() const
Determine maximum number of bytes.
Definition: hkdf.h:41
Extract-and-Expand Key Derivation Function (HKDF)
Definition: hkdf.h:24
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 DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs &params) const
Derive a key from a seed.
Definition: hkdf.h:100
SecBlock<byte> typedef.
Definition: secblock.h:822
Classes and functions for secure memory allocations.
Classes for HMAC message authentication codes.
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:80
size_t GetValidDerivedLength(size_t keylength) const
Returns a valid key length for the derivation function.
Definition: hkdf.h:92
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:605
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: hmac.cpp:60
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
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:536
Interface for all crypto algorithms.
Definition: cryptlib.h:573
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:1139
HMAC.
Definition: hmac.h:50
Crypto++ library namespace.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:347
std::string AlgorithmName() const
Provides the name of this algorithm.
Definition: hkdf.h:36
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:561
Interface for key derivation functions.
Definition: cryptlib.h:1416
Interface for retrieving values given their names.
Definition: cryptlib.h:290