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