Botan  2.8.0
Crypto and TLS for C++11
pbkdf.cpp
Go to the documentation of this file.
1 /*
2 * PBKDF
3 * (C) 2012 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/pbkdf.h>
9 #include <botan/exceptn.h>
10 #include <botan/scan_name.h>
11 
12 #if defined(BOTAN_HAS_PBKDF1)
13 #include <botan/pbkdf1.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_PBKDF2)
17 #include <botan/pbkdf2.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_PGP_S2K)
21 #include <botan/pgp_s2k.h>
22 #endif
23 
24 namespace Botan {
25 
26 std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec,
27  const std::string& provider)
28  {
29  const SCAN_Name req(algo_spec);
30 
31 #if defined(BOTAN_HAS_PBKDF2)
32  if(req.algo_name() == "PBKDF2")
33  {
34  // TODO OpenSSL
35 
36  if(provider.empty() || provider == "base")
37  {
38  if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
39  return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
40 
41  if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
42  return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
43  }
44 
45  return nullptr;
46  }
47 #endif
48 
49 #if defined(BOTAN_HAS_PBKDF1)
50  if(req.algo_name() == "PBKDF1" && req.arg_count() == 1)
51  {
52  if(auto hash = HashFunction::create(req.arg(0)))
53  return std::unique_ptr<PBKDF>(new PKCS5_PBKDF1(hash.release()));
54 
55  }
56 #endif
57 
58 #if defined(BOTAN_HAS_PGP_S2K)
59  if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
60  {
61  if(auto hash = HashFunction::create(req.arg(0)))
62  return std::unique_ptr<PBKDF>(new OpenPGP_S2K(hash.release()));
63  }
64 #endif
65 
66  BOTAN_UNUSED(req);
67  BOTAN_UNUSED(provider);
68 
69  return nullptr;
70  }
71 
72 //static
73 std::unique_ptr<PBKDF>
74 PBKDF::create_or_throw(const std::string& algo,
75  const std::string& provider)
76  {
77  if(auto pbkdf = PBKDF::create(algo, provider))
78  {
79  return pbkdf;
80  }
81  throw Lookup_Error("PBKDF", algo, provider);
82  }
83 
84 std::vector<std::string> PBKDF::providers(const std::string& algo_spec)
85  {
86  return probe_providers_of<PBKDF>(algo_spec, { "base", "openssl" });
87  }
88 
89 void PBKDF::pbkdf_timed(uint8_t out[], size_t out_len,
90  const std::string& passphrase,
91  const uint8_t salt[], size_t salt_len,
92  std::chrono::milliseconds msec,
93  size_t& iterations) const
94  {
95  iterations = pbkdf(out, out_len, passphrase, salt, salt_len, 0, msec);
96  }
97 
98 void PBKDF::pbkdf_iterations(uint8_t out[], size_t out_len,
99  const std::string& passphrase,
100  const uint8_t salt[], size_t salt_len,
101  size_t iterations) const
102  {
103  if(iterations == 0)
104  throw Invalid_Argument(name() + ": Invalid iteration count");
105 
106  const size_t iterations_run = pbkdf(out, out_len, passphrase,
107  salt, salt_len, iterations,
108  std::chrono::milliseconds(0));
109  BOTAN_ASSERT_EQUAL(iterations, iterations_run, "Expected PBKDF iterations");
110  }
111 
113  const std::string& passphrase,
114  const uint8_t salt[], size_t salt_len,
115  size_t iterations) const
116  {
117  secure_vector<uint8_t> out(out_len);
118  pbkdf_iterations(out.data(), out_len, passphrase, salt, salt_len, iterations);
119  return out;
120  }
121 
123  const std::string& passphrase,
124  const uint8_t salt[], size_t salt_len,
125  std::chrono::milliseconds msec,
126  size_t& iterations) const
127  {
128  secure_vector<uint8_t> out(out_len);
129  pbkdf_timed(out.data(), out_len, passphrase, salt, salt_len, msec, iterations);
130  return out;
131  }
132 
133 }
static std::unique_ptr< PBKDF > create(const std::string &algo_spec, const std::string &provider="")
Definition: pbkdf.cpp:26
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:46
static std::vector< std::string > providers(const std::string &algo_spec)
Definition: pbkdf.cpp:84
void pbkdf_iterations(uint8_t out[], size_t out_len, const std::string &passphrase, const uint8_t salt[], size_t salt_len, size_t iterations) const
Definition: pbkdf.cpp:98
virtual std::string name() const =0
std::string arg(size_t i) const
Definition: scan_name.cpp:122
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:81
virtual size_t pbkdf(uint8_t out[], size_t out_len, const std::string &passphrase, const uint8_t salt[], size_t salt_len, size_t iterations, std::chrono::milliseconds msec) const =0
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:110
size_t salt_len
Definition: x509_obj.cpp:26
Definition: alg_id.cpp:13
static std::unique_ptr< PBKDF > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: pbkdf.cpp:74
#define BOTAN_UNUSED(...)
Definition: assert.h:142
const std::string & algo_name() const
Definition: scan_name.h:44
void pbkdf_timed(uint8_t out[], size_t out_len, const std::string &passphrase, const uint8_t salt[], size_t salt_len, std::chrono::milliseconds msec, size_t &iterations) const
Definition: pbkdf.cpp:89
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
MechanismType hash