Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:03

0001 // hkdf.h - written and placed in public domain by Jeffrey Walton.

0002 
0003 /// \file hkdf.h

0004 /// \brief Classes for HKDF from RFC 5869

0005 /// \since Crypto++ 5.6.3

0006 
0007 #ifndef CRYPTOPP_HKDF_H
0008 #define CRYPTOPP_HKDF_H
0009 
0010 #include "cryptlib.h"
0011 #include "secblock.h"
0012 #include "algparam.h"
0013 #include "hmac.h"
0014 
0015 NAMESPACE_BEGIN(CryptoPP)
0016 
0017 /// \brief Extract-and-Expand Key Derivation Function (HKDF)

0018 /// \tparam T HashTransformation class

0019 /// \sa <A HREF="http://eprint.iacr.org/2010/264">Cryptographic Extraction and Key

0020 ///   Derivation: The HKDF Scheme</A> and

0021 ///   <A HREF="http://tools.ietf.org/html/rfc5869">HMAC-based Extract-and-Expand Key

0022 ///   Derivation Function (HKDF)</A>

0023 /// \since Crypto++ 5.6.3

0024 template <class T>
0025 class HKDF : public KeyDerivationFunction
0026 {
0027 public:
0028     virtual ~HKDF() {}
0029 
0030     static std::string StaticAlgorithmName () {
0031         const std::string name(std::string("HKDF(") +
0032             std::string(T::StaticAlgorithmName()) + std::string(")"));
0033         return name;
0034     }
0035 
0036     // KeyDerivationFunction interface

0037     std::string AlgorithmName() const {
0038         return StaticAlgorithmName();
0039     }
0040 
0041     // KeyDerivationFunction interface

0042     size_t MaxDerivedKeyLength() const {
0043         return static_cast<size_t>(T::DIGESTSIZE) * 255;
0044     }
0045 
0046     // KeyDerivationFunction interface

0047     size_t GetValidDerivedLength(size_t keylength) const;
0048 
0049     // KeyDerivationFunction interface

0050     size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0051         const NameValuePairs& params) const;
0052 
0053     /// \brief Derive a key from a seed

0054     /// \param derived the derived output buffer

0055     /// \param derivedLen the size of the derived buffer, in bytes

0056     /// \param secret the seed input buffer

0057     /// \param secretLen the size of the secret buffer, in bytes

0058     /// \param salt the salt input buffer

0059     /// \param saltLen the size of the salt buffer, in bytes

0060     /// \param info the additional input buffer

0061     /// \param infoLen the size of the info buffer, in bytes

0062     /// \return the number of iterations performed

0063     /// \throw InvalidDerivedKeyLength if <tt>derivedLen</tt> is invalid for the scheme

0064     /// \details DeriveKey() provides a standard interface to derive a key from

0065     ///   a seed and other parameters. Each class that derives from KeyDerivationFunction

0066     ///   provides an overload that accepts most parameters used by the derivation function.

0067     /// \details <tt>salt</tt> and <tt>info</tt> can be <tt>nullptr</tt> with 0 length.

0068     ///   HKDF is unusual in that a non-NULL salt with length 0 is different than a

0069     ///   NULL <tt>salt</tt>. A NULL <tt>salt</tt> causes HKDF to use a string of 0's

0070     ///   of length <tt>T::DIGESTSIZE</tt> for the <tt>salt</tt>.

0071     /// \details HKDF always returns 1 because it only performs 1 iteration. Other

0072     ///   derivation functions, like PBKDF's, will return more interesting values.

0073     size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0074         const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const;
0075 
0076 protected:
0077     // KeyDerivationFunction interface

0078     const Algorithm & GetAlgorithm() const {
0079         return *this;
0080     }
0081 
0082     // If salt is absent (NULL), then use the NULL vector. Missing is different than

0083     // EMPTY (Non-NULL, 0 length). The length of s_NullVector used depends on the Hash

0084     // function. SHA-256 will use 32 bytes of s_NullVector.

0085     typedef byte NullVectorType[T::DIGESTSIZE];
0086     static const NullVectorType& GetNullVector() {
0087         static const NullVectorType s_NullVector = {0};
0088         return s_NullVector;
0089     }
0090 };
0091 
0092 template <class T>
0093 size_t HKDF<T>::GetValidDerivedLength(size_t keylength) const
0094 {
0095     if (keylength > MaxDerivedKeyLength())
0096         return MaxDerivedKeyLength();
0097     return keylength;
0098 }
0099 
0100 template <class T>
0101 size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen,
0102     const byte *secret, size_t secretLen, const NameValuePairs& params) const
0103 {
0104     CRYPTOPP_ASSERT(secret && secretLen);
0105     CRYPTOPP_ASSERT(derived && derivedLen);
0106     CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0107 
0108     ConstByteArrayParameter p;
0109     SecByteBlock salt, info;
0110 
0111     if (params.GetValue("Salt", p))
0112         salt.Assign(p.begin(), p.size());
0113     else
0114         salt.Assign(GetNullVector(), T::DIGESTSIZE);
0115 
0116     if (params.GetValue("Info", p))
0117         info.Assign(p.begin(), p.size());
0118     else
0119         info.Assign(GetNullVector(), 0);
0120 
0121     return DeriveKey(derived, derivedLen, secret, secretLen, salt.begin(), salt.size(), info.begin(), info.size());
0122 }
0123 
0124 template <class T>
0125 size_t HKDF<T>::DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0126     const byte *salt, size_t saltLen, const byte* info, size_t infoLen) const
0127 {
0128     CRYPTOPP_ASSERT(secret && secretLen);
0129     CRYPTOPP_ASSERT(derived && derivedLen);
0130     CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0131 
0132     ThrowIfInvalidDerivedKeyLength(derivedLen);
0133 
0134     // HKDF business logic. NULL is different than empty.

0135     if (salt == NULLPTR)
0136     {
0137         salt = GetNullVector();
0138         saltLen = T::DIGESTSIZE;
0139     }
0140 
0141     // key is PRK from the RFC, salt is IKM from the RFC

0142     HMAC<T> hmac;
0143     SecByteBlock key(T::DIGESTSIZE), buffer(T::DIGESTSIZE);
0144 
0145     // Extract

0146     hmac.SetKey(salt, saltLen);
0147     hmac.CalculateDigest(key, secret, secretLen);
0148 
0149     // Key

0150     hmac.SetKey(key.begin(), key.size());
0151     byte block = 0;
0152 
0153     // Expand

0154     while (derivedLen > 0)
0155     {
0156         if (block++) {hmac.Update(buffer, buffer.size());}
0157         if (infoLen) {hmac.Update(info, infoLen);}
0158         hmac.CalculateDigest(buffer, &block, 1);
0159 
0160 #if CRYPTOPP_MSC_VERSION
0161         const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
0162         const size_t segmentLen = STDMIN(derivedLen, digestSize);
0163         memcpy_s(derived, segmentLen, buffer, segmentLen);
0164 #else
0165         const size_t digestSize = static_cast<size_t>(T::DIGESTSIZE);
0166         const size_t segmentLen = STDMIN(derivedLen, digestSize);
0167         std::memcpy(derived, buffer, segmentLen);
0168 #endif
0169 
0170         derived += segmentLen;
0171         derivedLen -= segmentLen;
0172     }
0173 
0174     return 1;
0175 }
0176 
0177 NAMESPACE_END
0178 
0179 #endif // CRYPTOPP_HKDF_H