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