10#include <botan/internal/hkdf.h>
12#include <botan/exceptn.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/loadstor.h>
15#include <botan/internal/stl_util.h>
20 return std::make_unique<HKDF>(m_prf->new_object());
24 return fmt(
"HKDF({})", m_prf->name());
27void HKDF::perform_kdf(std::span<uint8_t> key,
28 std::span<const uint8_t> secret,
29 std::span<const uint8_t> salt,
30 std::span<const uint8_t> label)
const {
35 extract.derive_key(prk, secret, salt, {});
36 expand.derive_key(key, prk, {}, label);
40 return std::make_unique<HKDF_Extract>(m_prf->new_object());
44 return fmt(
"HKDF-Extract({})", m_prf->name());
47void HKDF_Extract::perform_kdf(std::span<uint8_t> key,
48 std::span<const uint8_t> secret,
49 std::span<const uint8_t> salt,
50 std::span<const uint8_t> label)
const {
51 const size_t prf_output_len = m_prf->output_length();
52 BOTAN_ARG_CHECK(key.size() <= prf_output_len,
"HKDF-Extract maximum output length exceeeded");
53 BOTAN_ARG_CHECK(label.empty(),
"HKDF-Extract does not support a label input");
60 m_prf->set_key(std::vector<uint8_t>(prf_output_len));
65 m_prf->update(secret);
67 if(key.size() == prf_output_len) {
70 const auto prk = m_prf->final();
71 copy_mem(key, std::span{prk}.first(key.size()));
76 return std::make_unique<HKDF_Expand>(m_prf->new_object());
80 return fmt(
"HKDF-Expand({})", m_prf->name());
83void HKDF_Expand::perform_kdf(std::span<uint8_t> key,
84 std::span<const uint8_t> secret,
85 std::span<const uint8_t> salt,
86 std::span<const uint8_t> label)
const {
87 const auto prf_output_length = m_prf->output_length();
88 BOTAN_ARG_CHECK(key.size() <= prf_output_length * 255,
"HKDF-Expand maximum output length exceeeded");
95 std::span<uint8_t> h = {};
98 m_prf->set_key(secret);
99 for(uint8_t counter = 1; !k.full(); ++counter) {
101 m_prf->update(label);
103 m_prf->update(counter);
107 if(k.remaining_capacity() >= prf_output_length) {
108 h = k.next(prf_output_length);
111 const auto full_prf_output = m_prf->final();
113 k.append(std::span{full_prf_output}.first(k.remaining_capacity()));
119 std::span<const uint8_t> secret,
120 std::string_view label,
121 std::span<const uint8_t> hash_val,
123 BOTAN_ARG_CHECK(length <= 0xFFFF,
"HKDF-Expand-Label requested output too large");
124 BOTAN_ARG_CHECK(label.size() <= 0xFF,
"HKDF-Expand-Label label too long");
125 BOTAN_ARG_CHECK(hash_val.size() <= 0xFF,
"HKDF-Expand-Label hash too long");
130 store_be(
static_cast<uint8_t
>(label.size())),
132 store_be(
static_cast<uint8_t
>(hash_val.size())));
139 return hkdf.
derive_key(length, secret, hash_val, prefix);
#define BOTAN_ARG_CHECK(expr, msg)
std::string name() const override
std::unique_ptr< KDF > new_object() const override
std::string name() const override
std::unique_ptr< KDF > new_object() const override
T derive_key(size_t key_len, const uint8_t secret[], size_t secret_len, const uint8_t salt[], size_t salt_len, const uint8_t label[]=nullptr, size_t label_len=0) const
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
std::string fmt(std::string_view format, const T &... args)
secure_vector< uint8_t > hkdf_expand_label(std::string_view hash_fn, std::span< const uint8_t > secret, std::string_view label, std::span< const uint8_t > hash_val, size_t length)
constexpr auto concat(Rs &&... ranges)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr auto store_be(ParamTs &&... params)
const uint8_t * cast_char_ptr_to_uint8(const char *s)