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 <string>
12 #include <memory>
13 #include <vector>
14 #include <chrono>
15 
16 namespace Botan {
17 
18 /**
19 * Base class for password based key derivation functions.
20 *
21 * Converts a password into a key using a salt and iterated hashing to
22 * make brute force attacks harder.
23 */
24 class BOTAN_PUBLIC_API(2,8) PasswordHash
25    {
26    public:
27       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       */
memory_param()40       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       */
parallelism()50       virtual size_t parallelism() const { return 0; }
51 
52       /**
53       * Returns an estimate of the total memory usage 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       */
total_memory_usage()59       virtual size_t total_memory_usage() const { return 0; }
60 
61       /**
62       * Derive a key from a password
63       *
64       * @param out buffer to store the derived key, must be of out_len bytes
65       * @param out_len the desired length of the key to produce
66       * @param password the password to derive the key from
67       * @param password_len the length of password in bytes
68       * @param salt a randomly chosen salt
69       * @param salt_len length of salt in bytes
70       *
71       * This function is const, but is not thread safe. Different threads should
72       * either use unique objects, or serialize all access.
73       */
74       virtual void derive_key(uint8_t out[], size_t out_len,
75                               const char* password, size_t password_len,
76                               const uint8_t salt[], size_t salt_len) const = 0;
77    };
78 
79 class BOTAN_PUBLIC_API(2,8) PasswordHashFamily
80    {
81    public:
82       /**
83       * Create an instance based on a name
84       * If provider is empty then best available is chosen.
85       * @param algo_spec algorithm name
86       * @param provider provider implementation to choose
87       * @return a null pointer if the algo/provider combination cannot be found
88       */
89       static std::unique_ptr<PasswordHashFamily> create(const std::string& algo_spec,
90                                                         const std::string& provider = "");
91 
92       /**
93       * Create an instance based on a name, or throw if the
94       * algo/provider combination cannot be found. If provider is
95       * empty then best available is chosen.
96       */
97       static std::unique_ptr<PasswordHashFamily>
98          create_or_throw(const std::string& algo_spec,
99                          const std::string& provider = "");
100 
101       /**
102       * @return list of available providers for this algorithm, empty if not available
103       */
104       static std::vector<std::string> providers(const std::string& algo_spec);
105 
106       virtual ~PasswordHashFamily() = default;
107 
108       /**
109       * @return name of this PasswordHash
110       */
111       virtual std::string name() const = 0;
112 
113       /**
114       * Return a new parameter set tuned for this machine
115       * @param output_length how long the output length will be
116       * @param msec the desired execution time in milliseconds
117       *
118       * @param max_memory_usage_mb some password hash functions can use a tunable
119       * amount of memory, in this case max_memory_usage limits the amount of RAM
120       * the returned parameters will require, in mebibytes (2**20 bytes). It may
121       * require some small amount above the request. Set to zero to place no
122       * limit at all.
123       */
124       virtual std::unique_ptr<PasswordHash> tune(size_t output_length,
125                                                  std::chrono::milliseconds msec,
126                                                  size_t max_memory_usage_mb = 0) const = 0;
127 
128       /**
129       * Return some default parameter set for this PBKDF that should be good
130       * enough for most users. The value returned may change over time as
131       * processing power and attacks improve.
132       */
133       virtual std::unique_ptr<PasswordHash> default_params() const = 0;
134 
135       /**
136       * Return a parameter chosen based on a rough approximation with the
137       * specified iteration count. The exact value this returns for a particular
138       * algorithm may change from over time. Think of it as an alternative to
139       * tune, where time is expressed in terms of PBKDF2 iterations rather than
140       * milliseconds.
141       */
142       virtual std::unique_ptr<PasswordHash> from_iterations(size_t iterations) const = 0;
143 
144       /**
145       * Create a password hash using some scheme specific format.
146       * Eg PBKDF2 and PGP-S2K set iterations in i1
147       * Scrypt uses N,r,p in i{1-3}
148       * Bcrypt-PBKDF just has iterations
149       * Argon2{i,d,id} would use iterations, memory, parallelism for i{1-3},
150       * and Argon2 type is part of the family.
151       *
152       * Values not needed should be set to 0
153       */
154       virtual std::unique_ptr<PasswordHash> from_params(
155          size_t i1,
156          size_t i2 = 0,
157          size_t i3 = 0) const = 0;
158    };
159 
160 }
161 
162 #endif
163