Coverage Report

Created: 2026-09-28 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/kdf/kdf.cpp
Line
Count
Source
1
/*
2
* KDF Retrieval
3
* (C) 1999-2007 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/kdf.h>
9
10
#include <botan/assert.h>
11
#include <botan/exceptn.h>
12
#include <botan/hash.h>
13
#include <botan/mac.h>
14
#include <botan/internal/fmt.h>
15
#include <botan/internal/mem_utils.h>
16
#include <botan/internal/scan_name.h>
17
18
#if defined(BOTAN_HAS_HKDF)
19
   #include <botan/internal/hkdf.h>
20
#endif
21
22
#if defined(BOTAN_HAS_KDF1)
23
   #include <botan/internal/kdf1.h>
24
#endif
25
26
#if defined(BOTAN_HAS_KDF2)
27
   #include <botan/internal/kdf2.h>
28
#endif
29
30
#if defined(BOTAN_HAS_KDF1_18033)
31
   #include <botan/internal/kdf1_iso18033.h>
32
#endif
33
34
#if defined(BOTAN_HAS_TLS_V12_PRF)
35
   #include <botan/internal/prf_tls.h>
36
#endif
37
38
#if defined(BOTAN_HAS_X942_PRF)
39
   #include <botan/internal/prf_x942.h>
40
#endif
41
42
#if defined(BOTAN_HAS_SP800_108)
43
   #include <botan/internal/sp800_108.h>
44
#endif
45
46
#if defined(BOTAN_HAS_SP800_56A)
47
   #include <botan/internal/sp800_56c_one_step.h>
48
#endif
49
50
#if defined(BOTAN_HAS_SP800_56C)
51
   #include <botan/internal/sp800_56c_two_step.h>
52
#endif
53
54
namespace Botan {
55
56
namespace {
57
58
template <typename KDF_Type, typename... ParamTs>
59
0
std::unique_ptr<KDF> kdf_create_mac_or_hash(std::string_view nm, ParamTs&&... params) {
60
0
   if(auto mac = MessageAuthenticationCode::create(fmt("HMAC({})", nm))) {
61
0
      return std::make_unique<KDF_Type>(std::move(mac), std::forward<ParamTs>(params)...);
62
0
   }
63
64
0
   if(auto mac = MessageAuthenticationCode::create(nm)) {
65
0
      return std::make_unique<KDF_Type>(std::move(mac), std::forward<ParamTs>(params)...);
66
0
   }
67
68
0
   return nullptr;
69
0
}
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::HKDF>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::HKDF_Extract>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::HKDF_Expand>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::TLS_12_PRF>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::SP800_108_Counter, unsigned long, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&&, unsigned long&&)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::SP800_108_Feedback, unsigned long, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&&, unsigned long&&)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::SP800_108_Pipeline, unsigned long, unsigned long>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long&&, unsigned long&&)
Unexecuted instantiation: kdf.cpp:std::__1::unique_ptr<Botan::KDF, std::__1::default_delete<Botan::KDF> > Botan::(anonymous namespace)::kdf_create_mac_or_hash<Botan::SP800_108_Feedback, int, int>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, int&&, int&&)
70
71
}  // namespace
72
73
0
std::unique_ptr<KDF> KDF::create(std::string_view algo_spec, std::string_view provider) {
74
0
   const SCAN_Name req(algo_spec);
75
76
0
#if defined(BOTAN_HAS_HKDF)
77
0
   if(req.algo_name() == "HKDF" && req.arg_count() == 1) {
78
0
      if(provider.empty() || provider == "base") {
79
0
         return kdf_create_mac_or_hash<HKDF>(req.arg(0));
80
0
      }
81
0
   }
82
83
0
   if(req.algo_name() == "HKDF-Extract" && req.arg_count() == 1) {
84
0
      if(provider.empty() || provider == "base") {
85
0
         return kdf_create_mac_or_hash<HKDF_Extract>(req.arg(0));
86
0
      }
87
0
   }
88
89
0
   if(req.algo_name() == "HKDF-Expand" && req.arg_count() == 1) {
90
0
      if(provider.empty() || provider == "base") {
91
0
         return kdf_create_mac_or_hash<HKDF_Expand>(req.arg(0));
92
0
      }
93
0
   }
94
0
#endif
95
96
0
#if defined(BOTAN_HAS_KDF2)
97
0
   if(req.algo_name() == "KDF2" && req.arg_count() == 1) {
98
0
      if(provider.empty() || provider == "base") {
99
0
         if(auto hash = HashFunction::create(req.arg(0))) {
100
0
            return std::make_unique<KDF2>(std::move(hash));
101
0
         }
102
0
      }
103
0
   }
104
0
#endif
105
106
0
#if defined(BOTAN_HAS_KDF1_18033)
107
0
   if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1) {
108
0
      if(provider.empty() || provider == "base") {
109
0
         if(auto hash = HashFunction::create(req.arg(0))) {
110
0
            return std::make_unique<KDF1_18033>(std::move(hash));
111
0
         }
112
0
      }
113
0
   }
114
0
#endif
115
116
0
#if defined(BOTAN_HAS_KDF1)
117
0
   if(req.algo_name() == "KDF1" && req.arg_count() == 1) {
118
0
      if(provider.empty() || provider == "base") {
119
0
         if(auto hash = HashFunction::create(req.arg(0))) {
120
0
            return std::make_unique<KDF1>(std::move(hash));
121
0
         }
122
0
      }
123
0
   }
124
0
#endif
125
126
0
#if defined(BOTAN_HAS_TLS_V12_PRF)
127
0
   if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1) {
128
0
      if(provider.empty() || provider == "base") {
129
0
         return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0));
130
0
      }
131
0
   }
132
0
#endif
133
134
0
#if defined(BOTAN_HAS_X942_PRF)
135
0
   if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1) {
136
0
      if(provider.empty() || provider == "base") {
137
0
         return std::make_unique<X942_PRF>(req.arg(0));
138
0
      }
139
0
   }
140
0
#endif
141
142
0
#if defined(BOTAN_HAS_SP800_108)
143
0
   if(req.algo_name() == "SP800-108-Counter" && req.arg_count_between(1, 3)) {
144
0
      if(provider.empty() || provider == "base") {
145
0
         return kdf_create_mac_or_hash<SP800_108_Counter>(
146
0
            req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
147
0
      }
148
0
   }
149
150
0
   if(req.algo_name() == "SP800-108-Feedback" && req.arg_count_between(1, 3)) {
151
0
      if(provider.empty() || provider == "base") {
152
0
         return kdf_create_mac_or_hash<SP800_108_Feedback>(
153
0
            req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
154
0
      }
155
0
   }
156
157
0
   if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count_between(1, 3)) {
158
0
      if(provider.empty() || provider == "base") {
159
0
         return kdf_create_mac_or_hash<SP800_108_Pipeline>(
160
0
            req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
161
0
      }
162
0
   }
163
0
#endif
164
165
0
#if defined(BOTAN_HAS_SP800_56A)
166
0
   if(req.algo_name() == "SP800-56A" && req.arg_count() == 1) {
167
0
      if(auto hash = HashFunction::create(req.arg(0))) {
168
0
         return std::make_unique<SP800_56C_One_Step_Hash>(std::move(hash));
169
0
      }
170
0
      if(req.arg(0) == "KMAC-128") {
171
0
         return std::make_unique<SP800_56C_One_Step_KMAC128>();
172
0
      }
173
0
      if(req.arg(0) == "KMAC-256") {
174
0
         return std::make_unique<SP800_56C_One_Step_KMAC256>();
175
0
      }
176
0
      if(auto mac = MessageAuthenticationCode::create(req.arg(0))) {
177
0
         return std::make_unique<SP800_56C_One_Step_HMAC>(std::move(mac));
178
0
      }
179
0
   }
180
0
#endif
181
182
0
#if defined(BOTAN_HAS_SP800_56C)
183
0
   if(req.algo_name() == "SP800-56C" && req.arg_count() == 1) {
184
0
      std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0), 32, 32));
185
0
      if(exp) {
186
0
         if(auto mac = MessageAuthenticationCode::create(req.arg(0))) {
187
0
            return std::make_unique<SP800_56C_Two_Step>(std::move(mac), std::move(exp));
188
0
         }
189
190
0
         if(auto mac = MessageAuthenticationCode::create(fmt("HMAC({})", req.arg(0)))) {
191
0
            return std::make_unique<SP800_56C_Two_Step>(std::move(mac), std::move(exp));
192
0
         }
193
0
      }
194
0
   }
195
0
#endif
196
197
0
   BOTAN_UNUSED(req);
198
0
   BOTAN_UNUSED(provider);
199
200
0
   return nullptr;
201
0
}
202
203
//static
204
0
std::unique_ptr<KDF> KDF::create_or_throw(std::string_view algo, std::string_view provider) {
205
0
   if(auto kdf = KDF::create(algo, provider)) {
206
0
      return kdf;
207
0
   }
208
0
   throw Lookup_Error("KDF", algo, provider);
209
0
}
210
211
0
std::vector<std::string> KDF::providers(std::string_view algo_spec) {
212
0
   return probe_providers_of<KDF>(algo_spec);
213
0
}
214
215
//static
216
0
std::span<const uint8_t> KDF::_as_span(std::string_view s) {
217
0
   return as_span_of_bytes(s);
218
0
}
219
220
}  // namespace Botan