File indexing completed on 2025-01-18 09:55:03
0001
0002
0003
0004
0005
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
0018
0019
0020
0021
0022
0023
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
0037 std::string AlgorithmName() const {
0038 return StaticAlgorithmName();
0039 }
0040
0041
0042 size_t MaxDerivedKeyLength() const {
0043 return static_cast<size_t>(T::DIGESTSIZE) * 255;
0044 }
0045
0046
0047 size_t GetValidDerivedLength(size_t keylength) const;
0048
0049
0050 size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0051 const NameValuePairs& params) const;
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
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
0078 const Algorithm & GetAlgorithm() const {
0079 return *this;
0080 }
0081
0082
0083
0084
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
0135 if (salt == NULLPTR)
0136 {
0137 salt = GetNullVector();
0138 saltLen = T::DIGESTSIZE;
0139 }
0140
0141
0142 HMAC<T> hmac;
0143 SecByteBlock key(T::DIGESTSIZE), buffer(T::DIGESTSIZE);
0144
0145
0146 hmac.SetKey(salt, saltLen);
0147 hmac.CalculateDigest(key, secret, secretLen);
0148
0149
0150 hmac.SetKey(key.begin(), key.size());
0151 byte block = 0;
0152
0153
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