| Botan 3.10.0 Crypto and TLS for C& |
hkdf.cpp Go to the documentation of this file.
1/* 2* HKDF 3* (C) 2013,2015,2017 Jack Lloyd 4* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity 5* (C) 2024 René Meusel, Rohde & Schwarz Cybersecurity 6* 7* Botan is released under the Simplified BSD License (see license.txt) 8*/ 9 10#include <botan/internal/hkdf.h> 11 12#include <botan/internal/fmt.h> 13#include <botan/internal/loadstor.h> 14#include <botan/internal/mem_utils.h> 15#include <botan/internal/stl_util.h> 16 17namespace Botan {
18 19std::unique_ptr<KDF> HKDF::new_object()
const {
20 return std::make_unique<HKDF>(m_prf->new_object());
21}
22 23std::string HKDF::name()
const {
24 return fmt(
"HKDF({})", m_prf->name());
25}
26 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 {
31 HKDF_Extract extract(m_prf->new_object());
32 HKDF_Expand expand(m_prf->new_object());
33 secure_vector<uint8_t> prk(m_prf->output_length());
34 35 extract.derive_key(prk, secret, salt, {});
36 expand.derive_key(key, prk, {}, label);
37}
38 39std::unique_ptr<KDF> HKDF_Extract::new_object()
const {
40 return std::make_unique<HKDF_Extract>(m_prf->new_object());
41}
42 43std::string HKDF_Extract::name()
const {
44 return fmt(
"HKDF-Extract({})", m_prf->name());
45}
46 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 exceeded");
53 BOTAN_ARG_CHECK(label.empty(),
"HKDF-Extract does not support a label input");
54 55 if(key.empty()) {
56 return;
57 }
58 59 if(salt.empty()) {
60 m_prf->set_key(std::vector<uint8_t>(prf_output_len));
61 }
else {
62 m_prf->set_key(salt);
63 }
64 65 m_prf->update(secret);
66 67 if(key.size() == prf_output_len) {
68 m_prf->final(key);
69 }
else {
70 const auto prk = m_prf->final();
71 copy_mem(key, std::span{prk}.first(key.size()));
72 }
73}
74 75std::unique_ptr<KDF> HKDF_Expand::new_object()
const {
76 return std::make_unique<HKDF_Expand>(m_prf->new_object());
77}
78 79std::string HKDF_Expand::name()
const {
80 return fmt(
"HKDF-Expand({})", m_prf->name());
81}
82 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 exceeded");
89 90 if(key.empty()) {
91 return;
92 }
93 94 // Keep a reference to the previous PRF output (empty by default). 95 std::span<uint8_t> h = {};
96 97 BufferStuffer k(key);
98 m_prf->set_key(secret);
99 for(uint8_t counter = 1; !k.full(); ++counter) {
100 m_prf->update(h);
101 m_prf->update(label);
102 m_prf->update(salt);
103 m_prf->update(counter);
104 105 // Write straight into the output buffer, except if the PRF output needs 106 // a truncation in the final iteration. 107 if(k.remaining_capacity() >= prf_output_length) {
108 h = k.next(prf_output_length);
109 m_prf->final(h);
110 }
else {
111 const auto full_prf_output = m_prf->final();
112 h = {};
// this is the final iteration! 113 k.append(std::span{full_prf_output}.first(k.remaining_capacity()));
114 }
115 }
116}
117 118secure_vector<uint8_t> hkdf_expand_label(std::string_view hash_fn,
119 std::span<const uint8_t> secret,
120 std::string_view label,
121 std::span<const uint8_t> hash_val,
122 size_t length) {
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");
126 127 HKDF_Expand hkdf(MessageAuthenticationCode::create_or_throw(fmt(
"HMAC({})", hash_fn)));
128 129 const auto prefix = concat<std::vector<uint8_t>>(store_be(
static_cast<uint16_t
>(length)),
130 store_be(
static_cast<uint8_t
>(label.size())),
131 as_span_of_bytes(label),
132 store_be(
static_cast<uint8_t
>(hash_val.size())));
133 134 /* 135 * We do something a little dirty here to avoid copying the hash_val, 136 * making use of the fact that Botan's KDF interface supports label+salt, 137 * and knowing that our HKDF hashes first param label then param salt. 138 */ 139 return hkdf.derive_key(length, secret, hash_val, prefix);
140}
141 142}
// namespace Botan BOTAN_ARG_CHECK#define BOTAN_ARG_CHECK(expr, msg)Definition assert.h:33 Botan::HKDF_ExpandDefinition hkdf.h:68 Botan::HKDF_Expand::namestd::string name() const overrideDefinition hkdf.cpp:79 Botan::HKDF_Expand::new_objectstd::unique_ptr< KDF > new_object() const overrideDefinition hkdf.cpp:75 Botan::HKDF_ExtractDefinition hkdf.h:44 Botan::HKDF_Extract::new_objectstd::unique_ptr< KDF > new_object() const overrideDefinition hkdf.cpp:39 Botan::HKDF_Extract::namestd::string name() const overrideDefinition hkdf.cpp:43 Botan::HKDF::namestd::string name() const overrideDefinition hkdf.cpp:23 Botan::HKDF::new_objectstd::unique_ptr< KDF > new_object() const overrideDefinition hkdf.cpp:19 Botan::KDF::derive_keyT 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) constDefinition kdf.h:91 Botan::MessageAuthenticationCode::create_or_throwstatic std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")Definition mac.cpp:147 BotanDefinition alg_id.cpp:13 Botan::as_span_of_bytesstd::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)Definition mem_utils.h:28 Botan::copy_memconstexpr void copy_mem(T *out, const T *in, size_t n)Definition mem_ops.h:145 Botan::fmtstd::string fmt(std::string_view format, const T &... args)Definition fmt.h:53 Botan::hkdf_expand_labelsecure_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)Definition hkdf.cpp:118 Botan::concatconstexpr auto concat(Rs &&... ranges)Definition stl_util.h:254 Botan::secure_vectorstd::vector< T, secure_allocator< T > > secure_vectorDefinition secmem.h:69 Botan::store_beconstexpr auto store_be(ParamTs &&... params)Definition loadstor.h:745 Generated by

1.15.0