Botan 3.9.0
Crypto and TLS for C&
kdf.cpp
Go to the documentation of this file.
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
54namespace Botan {
55
56namespace {
57
58template <typename KDF_Type, typename... ParamTs>
59std::unique_ptr<KDF> kdf_create_mac_or_hash(std::string_view nm, ParamTs&&... params) {
60 if(auto mac = MessageAuthenticationCode::create(fmt("HMAC({})", nm))) {
61 return std::make_unique<KDF_Type>(std::move(mac), std::forward<ParamTs>(params)...);
62 }
63
64 if(auto mac = MessageAuthenticationCode::create(nm)) {
65 return std::make_unique<KDF_Type>(std::move(mac), std::forward<ParamTs>(params)...);
66 }
67
68 return nullptr;
69}
70
71} // namespace
72
73std::unique_ptr<KDF> KDF::create(std::string_view algo_spec, std::string_view provider) {
74 const SCAN_Name req(algo_spec);
75
76#if defined(BOTAN_HAS_HKDF)
77 if(req.algo_name() == "HKDF" && req.arg_count() == 1) {
78 if(provider.empty() || provider == "base") {
79 return kdf_create_mac_or_hash<HKDF>(req.arg(0));
80 }
81 }
82
83 if(req.algo_name() == "HKDF-Extract" && req.arg_count() == 1) {
84 if(provider.empty() || provider == "base") {
85 return kdf_create_mac_or_hash<HKDF_Extract>(req.arg(0));
86 }
87 }
88
89 if(req.algo_name() == "HKDF-Expand" && req.arg_count() == 1) {
90 if(provider.empty() || provider == "base") {
91 return kdf_create_mac_or_hash<HKDF_Expand>(req.arg(0));
92 }
93 }
94#endif
95
96#if defined(BOTAN_HAS_KDF2)
97 if(req.algo_name() == "KDF2" && req.arg_count() == 1) {
98 if(provider.empty() || provider == "base") {
99 if(auto hash = HashFunction::create(req.arg(0))) {
100 return std::make_unique<KDF2>(std::move(hash));
101 }
102 }
103 }
104#endif
105
106#if defined(BOTAN_HAS_KDF1_18033)
107 if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1) {
108 if(provider.empty() || provider == "base") {
109 if(auto hash = HashFunction::create(req.arg(0))) {
110 return std::make_unique<KDF1_18033>(std::move(hash));
111 }
112 }
113 }
114#endif
115
116#if defined(BOTAN_HAS_KDF1)
117 if(req.algo_name() == "KDF1" && req.arg_count() == 1) {
118 if(provider.empty() || provider == "base") {
119 if(auto hash = HashFunction::create(req.arg(0))) {
120 return std::make_unique<KDF1>(std::move(hash));
121 }
122 }
123 }
124#endif
125
126#if defined(BOTAN_HAS_TLS_V12_PRF)
127 if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1) {
128 if(provider.empty() || provider == "base") {
129 return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0));
130 }
131 }
132#endif
133
134#if defined(BOTAN_HAS_X942_PRF)
135 if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1) {
136 if(provider.empty() || provider == "base") {
137 return std::make_unique<X942_PRF>(req.arg(0));
138 }
139 }
140#endif
141
142#if defined(BOTAN_HAS_SP800_108)
143 if(req.algo_name() == "SP800-108-Counter" && req.arg_count_between(1, 3)) {
144 if(provider.empty() || provider == "base") {
145 return kdf_create_mac_or_hash<SP800_108_Counter>(
146 req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
147 }
148 }
149
150 if(req.algo_name() == "SP800-108-Feedback" && req.arg_count_between(1, 3)) {
151 if(provider.empty() || provider == "base") {
152 return kdf_create_mac_or_hash<SP800_108_Feedback>(
153 req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
154 }
155 }
156
157 if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count_between(1, 3)) {
158 if(provider.empty() || provider == "base") {
159 return kdf_create_mac_or_hash<SP800_108_Pipeline>(
160 req.arg(0), req.arg_as_integer(1, 32), req.arg_as_integer(2, 32));
161 }
162 }
163#endif
164
165#if defined(BOTAN_HAS_SP800_56A)
166 if(req.algo_name() == "SP800-56A" && req.arg_count() == 1) {
167 if(auto hash = HashFunction::create(req.arg(0))) {
168 return std::make_unique<SP800_56C_One_Step_Hash>(std::move(hash));
169 }
170 if(req.arg(0) == "KMAC-128") {
171 return std::make_unique<SP800_56C_One_Step_KMAC128>();
172 }
173 if(req.arg(0) == "KMAC-256") {
174 return std::make_unique<SP800_56C_One_Step_KMAC256>();
175 }
176 if(auto mac = MessageAuthenticationCode::create(req.arg(0))) {
177 return std::make_unique<SP800_56C_One_Step_HMAC>(std::move(mac));
178 }
179 }
180#endif
181
182#if defined(BOTAN_HAS_SP800_56C)
183 if(req.algo_name() == "SP800-56C" && req.arg_count() == 1) {
184 std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0), 32, 32));
185 if(exp) {
186 if(auto mac = MessageAuthenticationCode::create(req.arg(0))) {
187 return std::make_unique<SP800_56C_Two_Step>(std::move(mac), std::move(exp));
188 }
189
190 if(auto mac = MessageAuthenticationCode::create(fmt("HMAC({})", req.arg(0)))) {
191 return std::make_unique<SP800_56C_Two_Step>(std::move(mac), std::move(exp));
192 }
193 }
194 }
195#endif
196
197 BOTAN_UNUSED(req);
198 BOTAN_UNUSED(provider);
199
200 return nullptr;
201}
202
203//static
204std::unique_ptr<KDF> KDF::create_or_throw(std::string_view algo, std::string_view provider) {
205 if(auto kdf = KDF::create(algo, provider)) {
206 return kdf;
207 }
208 throw Lookup_Error("KDF", algo, provider);
209}
210
211std::vector<std::string> KDF::providers(std::string_view algo_spec) {
212 return probe_providers_of<KDF>(algo_spec);
213}
214
215//static
216std::span<const uint8_t> KDF::_as_span(std::string_view s) {
217 return as_span_of_bytes(s);
218}
219
220} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:107
static std::unique_ptr< KDF > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition kdf.cpp:204
static std::vector< std::string > providers(std::string_view algo_spec)
Definition kdf.cpp:211
static std::unique_ptr< KDF > create(std::string_view algo_spec, std::string_view provider="")
Definition kdf.cpp:73
void kdf(uint8_t 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[], size_t label_len) const
Definition kdf.h:67
static std::unique_ptr< MessageAuthenticationCode > create(std::string_view algo_spec, std::string_view provider="")
Definition mac.cpp:51
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:49
const std::string & algo_name() const
Definition scan_name.h:44
size_t arg_as_integer(size_t i, size_t def_value) const
bool arg_count_between(size_t lower, size_t upper) const
Definition scan_name.h:56
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:28
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< std::string > probe_providers_of(std::string_view algo_spec, const std::vector< std::string > &possible={"base"})
Definition scan_name.h:105