Coverage Report

Created: 2025-04-11 06:34

/src/botan/build/include/public/botan/pwdhash.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2018 Ribose Inc
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef BOTAN_PWDHASH_H_
8
#define BOTAN_PWDHASH_H_
9
10
#include <botan/types.h>
11
#include <chrono>
12
#include <memory>
13
#include <span>
14
#include <string>
15
#include <vector>
16
17
namespace Botan {
18
19
/**
20
* Base class for password based key derivation functions.
21
*
22
* Converts a password into a key using a salt and iterated hashing to
23
* make brute force attacks harder.
24
*/
25
class BOTAN_PUBLIC_API(2, 8) PasswordHash {
26
   public:
27
0
      virtual ~PasswordHash() = default;
28
29
      virtual std::string to_string() const = 0;
30
31
      /**
32
      * Most password hashes have some notion of iterations.
33
      */
34
      virtual size_t iterations() const = 0;
35
36
      /**
37
      * Some password hashing algorithms have a parameter which controls how
38
      * much memory is used. If not supported by some algorithm, returns 0.
39
      */
40
0
      virtual size_t memory_param() const { return 0; }
41
42
      /**
43
      * Some password hashing algorithms have a parallelism parameter.
44
      * If the algorithm does not support this notion, then the
45
      * function returns zero. This allows distinguishing between a
46
      * password hash which just does not support parallel operation,
47
      * vs one that does support parallel operation but which has been
48
      * configured to use a single lane.
49
      */
50
0
      virtual size_t parallelism() const { return 0; }
51
52
      /**
53
      * Returns an estimate of the total number of bytes required to perform this
54
      * key derivation.
55
      *
56
      * If this algorithm uses a small and constant amount of memory, with no
57
      * effort made towards being memory hard, this function returns 0.
58
      */
59
0
      virtual size_t total_memory_usage() const { return 0; }
60
61
      /**
62
      * @returns true if this password hash supports supplying a key
63
      */
64
0
      virtual bool supports_keyed_operation() const { return false; }
65
66
      /**
67
      * @returns true if this password hash supports supplying associated data
68
      */
69
0
      virtual bool supports_associated_data() const { return false; }
70
71
      /**
72
      * Hash a password into a bitstring
73
      *
74
      * Derive a key from the specified @p password and  @p salt, placing it into
75
      * @p out.
76
      *
77
      * @param out a span where the derived key will be placed
78
      * @param password the password to derive the key from
79
      * @param salt a randomly chosen salt
80
      *
81
      * This function is const, but is not thread safe. Different threads should
82
      * either use unique objects, or serialize all access.
83
      */
84
0
      void hash(std::span<uint8_t> out, std::string_view password, std::span<const uint8_t> salt) const {
85
0
         this->derive_key(out.data(), out.size(), password.data(), password.size(), salt.data(), salt.size());
86
0
      }
87
88
      /**
89
      * Hash a password into a bitstring
90
      *
91
      * Derive a key from the specified @p password, @p salt, @p
92
      * associated_data, and secret @p key, placing it into @p out. The
93
      * @p associated_data and @p key are both allowed to be empty. Currently
94
      * non-empty AD/key is only supported with Argon2.
95
      *
96
      * @param out a span where the derived key will be placed
97
      * @param password the password to derive the key from
98
      * @param salt a randomly chosen salt
99
      * @param associated_data some additional data
100
      * @param key a secret key
101
      *
102
      * This function is const, but is not thread safe. Different threads should
103
      * either use unique objects, or serialize all access.
104
      */
105
      void hash(std::span<uint8_t> out,
106
                std::string_view password,
107
                std::span<const uint8_t> salt,
108
                std::span<const uint8_t> associated_data,
109
0
                std::span<const uint8_t> key) const {
110
0
         this->derive_key(out.data(),
111
0
                          out.size(),
112
0
                          password.data(),
113
0
                          password.size(),
114
0
                          salt.data(),
115
0
                          salt.size(),
116
0
                          associated_data.data(),
117
0
                          associated_data.size(),
118
0
                          key.data(),
119
0
                          key.size());
120
0
      }
121
122
      /**
123
      * Derive a key from a password
124
      *
125
      * @param out buffer to store the derived key, must be of out_len bytes
126
      * @param out_len the desired length of the key to produce
127
      * @param password the password to derive the key from
128
      * @param password_len the length of password in bytes
129
      * @param salt a randomly chosen salt
130
      * @param salt_len length of salt in bytes
131
      *
132
      * This function is const, but is not thread safe. Different threads should
133
      * either use unique objects, or serialize all access.
134
      */
135
      virtual void derive_key(uint8_t out[],
136
                              size_t out_len,
137
                              const char* password,
138
                              size_t password_len,
139
                              const uint8_t salt[],
140
                              size_t salt_len) const = 0;
141
142
      /**
143
      * Derive a key from a password plus additional data and/or a secret key
144
      *
145
      * Currently this is only supported for Argon2. Using a non-empty AD or key
146
      * with other algorithms will cause a Not_Implemented exception.
147
      *
148
      * @param out buffer to store the derived key, must be of out_len bytes
149
      * @param out_len the desired length of the key to produce
150
      * @param password the password to derive the key from
151
      * @param password_len the length of password in bytes
152
      * @param salt a randomly chosen salt
153
      * @param salt_len length of salt in bytes
154
      * @param ad some additional data
155
      * @param ad_len length of ad in bytes
156
      * @param key a secret key
157
      * @param key_len length of key in bytes
158
      *
159
      * This function is const, but is not thread safe. Different threads should
160
      * either use unique objects, or serialize all access.
161
      */
162
      virtual void derive_key(uint8_t out[],
163
                              size_t out_len,
164
                              const char* password,
165
                              size_t password_len,
166
                              const uint8_t salt[],
167
                              size_t salt_len,
168
                              const uint8_t ad[],
169
                              size_t ad_len,
170
                              const uint8_t key[],
171
                              size_t key_len) const;
172
};
173
174
class BOTAN_PUBLIC_API(2, 8) PasswordHashFamily {
175
   public:
176
      /**
177
      * Create an instance based on a name
178
      * If provider is empty then best available is chosen.
179
      * @param algo_spec algorithm name
180
      * @param provider provider implementation to choose
181
      * @return a null pointer if the algo/provider combination cannot be found
182
      */
183
      static std::unique_ptr<PasswordHashFamily> create(std::string_view algo_spec, std::string_view provider = "");
184
185
      /**
186
      * Create an instance based on a name, or throw if the
187
      * algo/provider combination cannot be found. If provider is
188
      * empty then best available is chosen.
189
      */
190
      static std::unique_ptr<PasswordHashFamily> create_or_throw(std::string_view algo_spec,
191
                                                                 std::string_view provider = "");
192
193
      /**
194
      * @return list of available providers for this algorithm, empty if not available
195
      */
196
      static std::vector<std::string> providers(std::string_view algo_spec);
197
198
0
      virtual ~PasswordHashFamily() = default;
199
200
      /**
201
      * @return name of this PasswordHash
202
      */
203
      virtual std::string name() const = 0;
204
205
      /**
206
      * Return a new parameter set tuned for this machine
207
      *
208
      * Return a password hash instance tuned to run for approximately @p msec
209
      * milliseconds when producing an output of length @p output_length.
210
      * (Accuracy may vary, use the command line utility ``botan pbkdf_tune`` to
211
      * check.)
212
      *
213
      * The parameters will be selected to use at most @p max_memory_usage_mb
214
      * megabytes of memory, or if left as zero any size is allowed.
215
      *
216
      * This function works by runing a short tuning loop to estimate the
217
      * performance of the algorithm, then scaling the parameters appropriately
218
      * to hit the target size. The length of time the tuning loop runs can be
219
      * controlled using the @p tuning_msec parameter.
220
      *
221
      * @param output_length how long the output length will be
222
      * @param msec the desired execution time in milliseconds
223
      *
224
      * @param max_memory_usage_mb some password hash functions can use a
225
      * tunable amount of memory, in this case max_memory_usage limits the
226
      * amount of RAM the returned parameters will require, in mebibytes (2**20
227
      * bytes). It may require some small amount above the request. Set to zero
228
      * to place no limit at all.
229
      * @param tuning_msec how long to run the tuning loop
230
      */
231
      virtual std::unique_ptr<PasswordHash> tune(
232
         size_t output_length,
233
         std::chrono::milliseconds msec,
234
         size_t max_memory_usage_mb = 0,
235
         std::chrono::milliseconds tuning_msec = std::chrono::milliseconds(10)) const = 0;
236
237
      /**
238
      * Return some default parameter set for this PBKDF that should be good
239
      * enough for most users. The value returned may change over time as
240
      * processing power and attacks improve.
241
      */
242
      virtual std::unique_ptr<PasswordHash> default_params() const = 0;
243
244
      /**
245
      * Return a parameter chosen based on a rough approximation with the
246
      * specified iteration count. The exact value this returns for a particular
247
      * algorithm may change from over time. Think of it as an alternative to
248
      * tune, where time is expressed in terms of PBKDF2 iterations rather than
249
      * milliseconds.
250
      */
251
      virtual std::unique_ptr<PasswordHash> from_iterations(size_t iterations) const = 0;
252
253
      /**
254
      * Create a password hash using some scheme specific format. Parameters are as follows:
255
      * - For PBKDF2, PGP-S2K, and Bcrypt-PBKDF, i1 is iterations
256
      * - Scrypt uses N, r, p for i{1-3}
257
      * - Argon2 family uses memory (in KB), iterations, and parallelism for i{1-3}
258
      *
259
      * All unneeded parameters should be set to 0 or left blank.
260
      */
261
      virtual std::unique_ptr<PasswordHash> from_params(size_t i1, size_t i2 = 0, size_t i3 = 0) const = 0;
262
};
263
264
}  // namespace Botan
265
266
#endif