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