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