hkdf.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // hkdf.h - written and placed in public domain by Jeffrey Walton.
  2. /// \file hkdf.h
  3. /// \brief Classes for HKDF from RFC 5869
  4. /// \since Crypto++ 5.6.3
  5. #ifndef CRYPTOPP_HKDF_H
  6. #define CRYPTOPP_HKDF_H
  7. #include "cryptlib.h"
  8. #include "secblock.h"
  9. #include "algparam.h"
  10. #include "hmac.h"
  11. NAMESPACE_BEGIN(CryptoPP)
  12. /// \brief Extract-and-Expand Key Derivation Function (HKDF)
  13. /// \tparam T HashTransformation class
  14. /// \sa <A HREF="http://eprint.iacr.org/2010/264">Cryptographic Extraction and Key
  15. /// Derivation: The HKDF Scheme</A> and
  16. /// <A HREF="http://tools.ietf.org/html/rfc5869">HMAC-based Extract-and-Expand Key
  17. /// Derivation Function (HKDF)</A>
  18. /// \since Crypto++ 5.6.3
  19. template <class T>
  20. class HKDF : public KeyDerivationFunction
  21. {
  22. public:
  23. virtual ~HKDF() {}
  24. static std::string StaticAlgorithmName () {
  25. const std::string name(std::string("HKDF(") +
  26. std::string(T::StaticAlgorithmName()) + std::string(")"));
  27. return name;
  28. }
  29. // KeyDerivationFunction interface
  30. std::string AlgorithmName() const {
  31. return StaticAlgorithmName();
  32. }
  33. // KeyDerivationFunction interface
  34. size_t MaxDerivedKeyLength() const {
  35. return static_cast<size_t>(T::DIGESTSIZE) * 255;
  36. }
  37. // KeyDerivationFunction interface
  38. size_t GetValidDerivedLength(size_t keylength) const;
  39. // KeyDerivationFunction interface
  40. size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
  41. const NameValuePairs& params) const;
  42. /// \brief Derive a key from a seed
  43. /// \param derived the derived output buffer
  44. /// \param derivedLen the size of the derived buffer, in bytes
  45. /// \param secret the seed input buffer
  46. /// \param secretLen the size of the secret buffer, in bytes
  47. /// \param salt the salt input buffer
  48. /// \param saltLen the size of the salt buffer, in bytes
  49. /// \param info the additional input buffer
  50. /// \param infoLen the size of the info buffer, in bytes
  51. /// \return the number of iterations performed
  52. /// \throw InvalidDerivedKeyLength if <tt>derivedLen</tt> is invalid for the scheme
  53. /// \details DeriveKey() provides a standard interface to derive a key from
  54. /// a seed and other parameters. Each class that derives from KeyDerivationFunction
  55. /// provides an overload that accepts most parameters used by the derivation function.
  56. /// \details <tt>salt</tt> and <tt>info</tt> can be <tt>nullptr</tt> with 0 length.
  57. /// HKDF is unusual in that a non-NULL salt with length 0 is different than a
  58. /// NULL <tt>salt</tt>. A NULL <tt>salt</tt> causes HKDF to use a string of 0's
  59. /// of length <tt>T::DIGESTSIZE</tt> for the <tt>salt</tt>.
  60. /// \details HKDF always returns 1 because it only performs 1 iteration. Other
  61. /// derivation functions, like PBKDF's, will return more interesting values.
  62. size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
  63. const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const;
  64. protected:
  65. // KeyDerivationFunction interface
  66. const Algorithm & GetAlgorithm() const {
  67. return *this;
  68. }
  69. // If salt is absent (NULL), then use the NULL vector. Missing is different than
  70. // EMPTY (Non-NULL, 0 length). The length of s_NullVector used depends on the Hash
  71. // function. SHA-256 will use 32 bytes of s_NullVector.
  72. typedef byte NullVectorType[T::DIGESTSIZE];
  73. static const NullVectorType& GetNullVector() {
  74. static const NullVectorType s_NullVector = {0};
  75. return s_NullVector;
  76. }
  77. };
  78. template <class T>
  79. size_t HKDF<T>::GetValidDerivedLength(size_t keylength) const
  80. {
  81. if (keylength > MaxDerivedKeyLength())
  82. return MaxDerivedKeyLength();
  83. return keylength;
  84. }
  85. template <class T>
  86. size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen,
  87. const byte *secret, size_t secretLen, const NameValuePairs& params) const
  88. {
  89. CRYPTOPP_ASSERT(secret && secretLen);
  90. CRYPTOPP_ASSERT(derived && derivedLen);
  91. CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
  92. ConstByteArrayParameter p;
  93. SecByteBlock salt, info;
  94. if (params.GetValue("Salt", p))
  95. salt.Assign(p.begin(), p.size());
  96. else
  97. salt.Assign(GetNullVector(), T::DIGESTSIZE);
  98. if (params.GetValue("Info", p))
  99. info.Assign(p.begin(), p.size());
  100. else
  101. info.Assign(GetNullVector(), 0);
  102. return DeriveKey(derived, derivedLen, secret, secretLen, salt.begin(), salt.size(), info.begin(), info.size());
  103. }
  104. template <class T>
  105. size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
  106. const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const
  107. {
  108. CRYPTOPP_ASSERT(secret && secretLen);
  109. CRYPTOPP_ASSERT(derived && derivedLen);
  110. CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
  111. ThrowIfInvalidDerivedKeyLength(derivedLen);
  112. // HKDF business logic. NULL is different than empty.
  113. if (salt == NULLPTR)
  114. {
  115. salt = GetNullVector();
  116. saltLen = T::DIGESTSIZE;
  117. }
  118. // key is PRK from the RFC, salt is IKM from the RFC
  119. HMAC<T> hmac;
  120. SecByteBlock key(T::DIGESTSIZE), buffer(T::DIGESTSIZE);
  121. // Extract
  122. hmac.SetKey(salt, saltLen);
  123. hmac.CalculateDigest(key, secret, secretLen);
  124. // Key
  125. hmac.SetKey(key.begin(), key.size());
  126. byte block = 0;
  127. // Expand
  128. while (derivedLen > 0)
  129. {
  130. if (block++) {hmac.Update(buffer, buffer.size());}
  131. if (infoLen) {hmac.Update(info, infoLen);}
  132. hmac.CalculateDigest(buffer, &block, 1);
  133. #if CRYPTOPP_MSC_VERSION
  134. const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
  135. const size_t segmentLen = STDMIN(derivedLen, digestSize);
  136. memcpy_s(derived, segmentLen, buffer, segmentLen);
  137. #else
  138. const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
  139. const size_t segmentLen = STDMIN(derivedLen, digestSize);
  140. std::memcpy(derived, buffer, segmentLen);
  141. #endif
  142. derived += segmentLen;
  143. derivedLen -= segmentLen;
  144. }
  145. return 1;
  146. }
  147. NAMESPACE_END
  148. #endif // CRYPTOPP_HKDF_H