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