Botan  2.15.0
Crypto and TLS for C++11
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 #include <botan/mac.h>
10 #include <botan/hash.h>
11 #include <botan/scan_name.h>
12 #include <botan/exceptn.h>
13 
14 #if defined(BOTAN_HAS_HKDF)
15 #include <botan/hkdf.h>
16 #endif
17 
18 #if defined(BOTAN_HAS_KDF1)
19 #include <botan/kdf1.h>
20 #endif
21 
22 #if defined(BOTAN_HAS_KDF2)
23 #include <botan/kdf2.h>
24 #endif
25 
26 #if defined(BOTAN_HAS_KDF1_18033)
27 #include <botan/kdf1_iso18033.h>
28 #endif
29 
30 #if defined(BOTAN_HAS_TLS_V10_PRF) || defined(BOTAN_HAS_TLS_V12_PRF)
31 #include <botan/prf_tls.h>
32 #endif
33 
34 #if defined(BOTAN_HAS_X942_PRF)
35 #include <botan/prf_x942.h>
36 #endif
37 
38 #if defined(BOTAN_HAS_SP800_108)
39 #include <botan/sp800_108.h>
40 #endif
41 
42 #if defined(BOTAN_HAS_SP800_56A)
43 #include <botan/sp800_56a.h>
44 #endif
45 
46 #if defined(BOTAN_HAS_SP800_56C)
47 #include <botan/sp800_56c.h>
48 #endif
49 
50 namespace Botan {
51 
52 namespace {
53 
54 template<typename KDF_Type>
55 std::unique_ptr<KDF>
56 kdf_create_mac_or_hash(const std::string& nm)
57  {
58  if(auto mac = MessageAuthenticationCode::create(nm))
59  return std::unique_ptr<KDF>(new KDF_Type(mac.release()));
60 
61  if(auto mac = MessageAuthenticationCode::create("HMAC(" + nm + ")"))
62  return std::unique_ptr<KDF>(new KDF_Type(mac.release()));
63 
64  return nullptr;
65  }
66 
67 }
68 
69 std::unique_ptr<KDF> KDF::create(const std::string& algo_spec,
70  const std::string& provider)
71  {
72  const SCAN_Name req(algo_spec);
73 
74 #if defined(BOTAN_HAS_HKDF)
75  if(req.algo_name() == "HKDF" && req.arg_count() == 1)
76  {
77  if(provider.empty() || provider == "base")
78  {
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  {
85  if(provider.empty() || provider == "base")
86  {
87  return kdf_create_mac_or_hash<HKDF_Extract>(req.arg(0));
88  }
89  }
90 
91  if(req.algo_name() == "HKDF-Expand" && req.arg_count() == 1)
92  {
93  if(provider.empty() || provider == "base")
94  {
95  return kdf_create_mac_or_hash<HKDF_Expand>(req.arg(0));
96  }
97  }
98 #endif
99 
100 #if defined(BOTAN_HAS_KDF2)
101  if(req.algo_name() == "KDF2" && req.arg_count() == 1)
102  {
103  if(provider.empty() || provider == "base")
104  {
105  if(auto hash = HashFunction::create(req.arg(0)))
106  return std::unique_ptr<KDF>(new KDF2(hash.release()));
107  }
108  }
109 #endif
110 
111 #if defined(BOTAN_HAS_KDF1_18033)
112  if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1)
113  {
114  if(provider.empty() || provider == "base")
115  {
116  if(auto hash = HashFunction::create(req.arg(0)))
117  return std::unique_ptr<KDF>(new KDF1_18033(hash.release()));
118  }
119  }
120 #endif
121 
122 #if defined(BOTAN_HAS_KDF1)
123  if(req.algo_name() == "KDF1" && req.arg_count() == 1)
124  {
125  if(provider.empty() || provider == "base")
126  {
127  if(auto hash = HashFunction::create(req.arg(0)))
128  return std::unique_ptr<KDF>(new KDF1(hash.release()));
129  }
130  }
131 #endif
132 
133 #if defined(BOTAN_HAS_TLS_V10_PRF)
134  if(req.algo_name() == "TLS-PRF" && req.arg_count() == 0)
135  {
136  if(provider.empty() || provider == "base")
137  {
138  auto hmac_md5 = MessageAuthenticationCode::create("HMAC(MD5)");
139  auto hmac_sha1 = MessageAuthenticationCode::create("HMAC(SHA-1)");
140 
141  if(hmac_md5 && hmac_sha1)
142  return std::unique_ptr<KDF>(new TLS_PRF(std::move(hmac_md5), std::move(hmac_sha1)));
143  }
144  }
145 #endif
146 
147 #if defined(BOTAN_HAS_TLS_V12_PRF)
148  if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1)
149  {
150  if(provider.empty() || provider == "base")
151  {
152  return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0));
153  }
154  }
155 #endif
156 
157 #if defined(BOTAN_HAS_X942_PRF)
158  if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1)
159  {
160  if(provider.empty() || provider == "base")
161  {
162  return std::unique_ptr<KDF>(new X942_PRF(req.arg(0)));
163  }
164  }
165 #endif
166 
167 #if defined(BOTAN_HAS_SP800_108)
168  if(req.algo_name() == "SP800-108-Counter" && req.arg_count() == 1)
169  {
170  if(provider.empty() || provider == "base")
171  {
172  return kdf_create_mac_or_hash<SP800_108_Counter>(req.arg(0));
173  }
174  }
175 
176  if(req.algo_name() == "SP800-108-Feedback" && req.arg_count() == 1)
177  {
178  if(provider.empty() || provider == "base")
179  {
180  return kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0));
181  }
182  }
183 
184  if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count() == 1)
185  {
186  if(provider.empty() || provider == "base")
187  {
188  return kdf_create_mac_or_hash<SP800_108_Pipeline>(req.arg(0));
189  }
190  }
191 #endif
192 
193 #if defined(BOTAN_HAS_SP800_56A)
194  if(req.algo_name() == "SP800-56A" && req.arg_count() == 1)
195  {
196  if(auto hash = HashFunction::create(req.arg(0)))
197  return std::unique_ptr<KDF>(new SP800_56A_Hash(hash.release()));
198  if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
199  return std::unique_ptr<KDF>(new SP800_56A_HMAC(mac.release()));
200  }
201 #endif
202 
203 #if defined(BOTAN_HAS_SP800_56C)
204  if(req.algo_name() == "SP800-56C" && req.arg_count() == 1)
205  {
206  std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0)));
207  if(exp)
208  {
209  if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
210  return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release()));
211 
212  if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
213  return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release()));
214  }
215  }
216 #endif
217 
218  BOTAN_UNUSED(req);
219  BOTAN_UNUSED(provider);
220 
221  return nullptr;
222  }
223 
224 //static
225 std::unique_ptr<KDF>
226 KDF::create_or_throw(const std::string& algo,
227  const std::string& provider)
228  {
229  if(auto kdf = KDF::create(algo, provider))
230  {
231  return kdf;
232  }
233  throw Lookup_Error("KDF", algo, provider);
234  }
235 
236 std::vector<std::string> KDF::providers(const std::string& algo_spec)
237  {
238  return probe_providers_of<KDF>(algo_spec, { "base" });
239  }
240 
241 KDF* get_kdf(const std::string& algo_spec)
242  {
243  SCAN_Name request(algo_spec);
244 
245  if(request.algo_name() == "Raw")
246  return nullptr; // No KDF
247 
248  //return KDF::create_or_throw(algo_spec).release();
249  auto kdf = KDF::create(algo_spec);
250  if(!kdf)
251  throw Algorithm_Not_Found(algo_spec);
252  return kdf.release();
253  }
254 
255 }
size_t arg_count() const
Definition: scan_name.h:56
static std::unique_ptr< MessageAuthenticationCode > create(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:46
static std::vector< std::string > providers(const std::string &algo_spec)
Definition: kdf.cpp:236
std::string arg(size_t i) const
Definition: scan_name.cpp:124
KDF * get_kdf(const std::string &algo_spec)
Definition: kdf.cpp:241
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:106
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:142
const std::string & algo_name() const
Definition: scan_name.h:51
Definition: kdf.h:20
static std::unique_ptr< KDF > create(const std::string &algo_spec, const std::string &provider="")
Definition: kdf.cpp:69
virtual size_t 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 =0
static std::unique_ptr< KDF > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: kdf.cpp:226
MechanismType hash