• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 12805544433

16 Jan 2025 09:08AM UTC coverage: 90.876% (-0.4%) from 91.245%
12805544433

Pull #4540

github

web-flow
Merge cc1ceff51 into 9b798efbb
Pull Request #4540: PKCS #11 Version 3.2 Support

93425 of 102805 relevant lines covered (90.88%)

11409241.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.31
/src/lib/kdf/hkdf/hkdf.cpp
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/exceptn.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/loadstor.h>
15
#include <botan/internal/stl_util.h>
16

17
namespace Botan {
18

19
std::unique_ptr<KDF> HKDF::new_object() const {
13✔
20
   return std::make_unique<HKDF>(m_prf->new_object());
26✔
21
}
22

23
std::string HKDF::name() const {
39✔
24
   return fmt("HKDF({})", m_prf->name());
39✔
25
}
26

27
void HKDF::perform_kdf(std::span<uint8_t> key,
13✔
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());
13✔
32
   HKDF_Expand expand(m_prf->new_object());
13✔
33
   secure_vector<uint8_t> prk(m_prf->output_length());
13✔
34

35
   extract.derive_key(prk, secret, salt, {});
13✔
36
   expand.derive_key(key, prk, {}, label);
26✔
37
}
39✔
38

39
std::unique_ptr<KDF> HKDF_Extract::new_object() const {
12✔
40
   return std::make_unique<HKDF_Extract>(m_prf->new_object());
24✔
41
}
42

43
std::string HKDF_Extract::name() const {
36✔
44
   return fmt("HKDF-Extract({})", m_prf->name());
36✔
45
}
46

47
void HKDF_Extract::perform_kdf(std::span<uint8_t> key,
2,969✔
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();
2,969✔
52
   BOTAN_ARG_CHECK(key.size() <= prf_output_len, "HKDF-Extract maximum output length exceeeded");
2,969✔
53
   BOTAN_ARG_CHECK(label.empty(), "HKDF-Extract does not support a label input");
2,969✔
54

55
   if(key.empty()) {
2,969✔
56
      return;
57
   }
58

59
   if(salt.empty()) {
2,969✔
60
      m_prf->set_key(std::vector<uint8_t>(prf_output_len));
24✔
61
   } else {
62
      m_prf->set_key(salt);
2,957✔
63
   }
64

65
   m_prf->update(secret);
2,969✔
66

67
   if(key.size() == prf_output_len) {
2,969✔
68
      m_prf->final(key);
2,969✔
69
   } else {
70
      const auto prk = m_prf->final();
×
71
      copy_mem(key, std::span{prk}.first(key.size()));
×
72
   }
×
73
}
×
74

75
std::unique_ptr<KDF> HKDF_Expand::new_object() const {
12✔
76
   return std::make_unique<HKDF_Expand>(m_prf->new_object());
24✔
77
}
78

79
std::string HKDF_Expand::name() const {
36✔
80
   return fmt("HKDF-Expand({})", m_prf->name());
36✔
81
}
82

83
void HKDF_Expand::perform_kdf(std::span<uint8_t> key,
14,881✔
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();
14,881✔
88
   BOTAN_ARG_CHECK(key.size() <= prf_output_length * 255, "HKDF-Expand maximum output length exceeeded");
14,881✔
89

90
   if(key.empty()) {
14,881✔
91
      return;
×
92
   }
93

94
   // Keep a reference to the previous PRF output (empty by default).
95
   std::span<uint8_t> h = {};
14,881✔
96

97
   BufferStuffer k(key);
14,881✔
98
   m_prf->set_key(secret);
14,881✔
99
   for(uint8_t counter = 1; !k.full(); ++counter) {
30,139✔
100
      m_prf->update(h);
15,258✔
101
      m_prf->update(label);
15,258✔
102
      m_prf->update(salt);
15,258✔
103
      m_prf->update(counter);
15,258✔
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) {
15,258✔
108
         h = k.next(prf_output_length);
11,853✔
109
         m_prf->final(h);
11,853✔
110
      } else {
111
         const auto full_prf_output = m_prf->final();
3,405✔
112
         h = {};  // this is the final iteration!
3,405✔
113
         k.append(std::span{full_prf_output}.first(k.remaining_capacity()));
3,405✔
114
      }
3,405✔
115
   }
116
}
117

118
secure_vector<uint8_t> hkdf_expand_label(std::string_view hash_fn,
4✔
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");
4✔
124
   BOTAN_ARG_CHECK(label.size() <= 0xFF, "HKDF-Expand-Label label too long");
4✔
125
   BOTAN_ARG_CHECK(hash_val.size() <= 0xFF, "HKDF-Expand-Label hash too long");
4✔
126

127
   HKDF_Expand hkdf(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash_fn)));
4✔
128

129
   const auto prefix = concat<std::vector<uint8_t>>(store_be(static_cast<uint16_t>(length)),
8✔
130
                                                    store_be(static_cast<uint8_t>(label.size())),
8✔
131
                                                    std::span{cast_char_ptr_to_uint8(label.data()), label.size()},
4✔
132
                                                    store_be(static_cast<uint8_t>(hash_val.size())));
8✔
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);
4✔
140
}
8✔
141

142
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc