MySQL 8.3.0
Source Code Documentation
kdf_pbkdf2.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2018, 2023, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24#ifndef MYSQLROUTER_KDF_PBKDF2_INCLUDED
25#define MYSQLROUTER_KDF_PBKDF2_INCLUDED
26
27#include <cstdint>
28#include <stdexcept>
29#include <string>
30#include <vector>
31
32#include "mcf_error.h"
34
35/**
36 * Key Derivation Function for PBKDF2.
37 *
38 * See: RFC 2898
39 *
40 * while PBKDF2 support several hash-functions, only the most commonly used,
41 * secure variants are exposed:
42 *
43 * - SHA256
44 * - SHA512
45 *
46 * while the insecure ones are not offered:
47 *
48 * - SHA1
49 *
50 * Other HMACs of (https://tools.ietf.org/html/rfc8018#appendix-B.1.2)
51 * may be added:
52 *
53 * - SHA224
54 * - SHA384
55 * - SHA512-224
56 * - SHA512-256
57 */
59 public:
60 enum class Type { Sha_256, Sha_512 };
61 static std::vector<uint8_t> salt();
62 static std::vector<uint8_t> derive(Type type, unsigned long rounds,
63 const std::vector<uint8_t> &salt,
64 const std::string &key);
65};
66
67/**
68 * map the MCF name to internal types.
69 *
70 * MCF-name are taking from passlib:
71 *
72 * https://passlib.readthedocs.io/en/stable/modular_crypt_format.html#application-defined-hashes
73 */
75 public:
77 static constexpr char kTypeSha256[] = "pbkdf2-sha256";
78 static constexpr char kTypeSha512[] = "pbkdf2-sha512";
79
80 static std::pair<bool, std::string> name(Type type) noexcept {
81 switch (type) {
82 case Type::Sha_256:
83 return std::make_pair(true, kTypeSha256);
84 case Type::Sha_512:
85 return std::make_pair(true, kTypeSha512);
86 }
87
88 return std::make_pair(false, std::string{});
89 }
90
91 static std::pair<bool, Type> type(const std::string &name) noexcept {
92 if (name == kTypeSha256) {
93 return std::make_pair(true, Type::Sha_256);
94 } else if (name == kTypeSha512) {
95 return std::make_pair(true, Type::Sha_512);
96 }
97
98 return std::make_pair(false, Type{});
99 }
100
101 static bool supports_name(const std::string &name) noexcept {
102 if (name == kTypeSha256) {
103 return true;
104 } else if (name == kTypeSha512) {
105 return true;
106 }
107
108 return false;
109 }
110};
111
112/**
113 * MCF reader/writer for PBKDF2.
114 */
116 public:
120
121 /**
122 * rounds if no rounds was specified in from_mcf().
123 */
124 static constexpr unsigned long kDefaultRounds = 1000;
125 /**
126 * minimum rounds.
127 */
128 static constexpr unsigned long kMinRounds = 1;
129 /**
130 * maximum rounds.
131 */
132 static constexpr unsigned long kMaxRounds = 999999999;
133 /**
134 * maximum length of the salt.
135 *
136 * only the first kMaxSaltLength bytes of the salt will be used.
137 */
138 static constexpr size_t kMaxSaltLength = 16;
139
140 Pbkdf2McfAdaptor(Type type, unsigned long rounds,
141 const std::vector<uint8_t> &salt,
142 const std::vector<uint8_t> &checksum)
143 : type_{type}, rounds_{rounds}, salt_{salt}, checksum_{checksum} {
144 // limit salt
145 if (salt_.size() > kMaxSaltLength) {
146 salt_.resize(kMaxSaltLength);
147 }
148
149 // limit rounds to allow range
150 if (rounds_ < kMinRounds) rounds_ = kMinRounds;
151 if (rounds_ > kMaxRounds) rounds_ = kMaxRounds;
152 }
153
154 /**
155 * name of the digest according to MCF.
156 *
157 * - pbkdf2_sha256 for SHA256
158 * - pbkdf2_sha512 for SHA512
159 */
160 std::string mcf_id() const {
161 auto r = mcf_type::name(digest());
162 if (r.first) return r.second;
163
164 throw std::invalid_argument("failed to map digest to a name");
165 }
166
167 /**
168 * checksum.
169 *
170 * RFC4648 base64 encoded
171 */
172 std::vector<uint8_t> checksum() const { return checksum_; }
173
174 /**
175 * salt.
176 *
177 * @pre must be [a-z0-9]*
178 */
179 std::vector<uint8_t> salt() const { return salt_; }
180
181 /**
182 *
183 */
184 Type digest() const { return type_; }
185
186 /**
187 * rounds.
188 *
189 * rounds the hash will be applied on itself.
190 */
191 unsigned long rounds() const { return rounds_; }
192
193 /**
194 * build PBKDF2 from a MCF notation.
195 *
196 * - ${prefix}${rounds}${salt}${checksum}
197 * - ${prefix}${rounds}${salt}
198 *
199 * prefix
200 * : pbkdf2_sha256|pbkdf2_sha512
201 *
202 * rounds
203 * : [1-9][0-9]*
204 *
205 * salt
206 * : [^$]*
207 *
208 * checksum
209 * : [./a-zA-Z0-0]*
210 */
211 static Pbkdf2McfAdaptor from_mcf(const std::string &data);
212
213 /**
214 * encode to MCF.
215 *
216 * MCF (Modular Crypt Format)
217 */
218 std::string to_mcf() const;
219
220 /**
221 * Base64 encode.
222 *
223 * Variant of RFC... with a different alphabet
224 *
225 * - no whitespace
226 * - no padding
227 * - . and / as altchars instead of + and /
228 */
229 static std::vector<uint8_t> base64_decode(const std::string &binary);
230
231 /**
232 * Base64 decode.
233 *
234 * Variant of RFC... with a different alphabet
235 */
236 static std::string base64_encode(const std::vector<uint8_t> &encoded);
237
238 /**
239 * derive a checksum from a key.
240 *
241 * updates checksum
242 */
243 void derive(const std::string &key) {
244 checksum_ = kdf_type::derive(type_, rounds(), salt(), key);
245 }
246
247 static bool supports_mcf_id(const std::string mcf_id) {
248 return mcf_type::supports_name(mcf_id);
249 }
250
251 static std::error_code validate(const std::string &mcf_line,
252 const std::string &password) {
253 try {
254 auto mcf = from_mcf(mcf_line);
255 if (kdf_type::derive(mcf.digest(), mcf.rounds(), mcf.salt(), password) ==
256 mcf.checksum()) {
257 return {};
258 } else {
260 }
261 } catch (const std::exception &) {
262 // whatever the exception was, make it a parse-error
264 }
265 }
266
267 private:
269 unsigned long rounds_;
270 std::vector<uint8_t> salt_;
271 std::vector<uint8_t> checksum_;
272};
273
274#endif
MCF reader/writer for PBKDF2.
Definition: kdf_pbkdf2.h:115
std::vector< uint8_t > checksum() const
checksum.
Definition: kdf_pbkdf2.h:172
void derive(const std::string &key)
derive a checksum from a key.
Definition: kdf_pbkdf2.h:243
unsigned long rounds_
Definition: kdf_pbkdf2.h:269
static std::error_code validate(const std::string &mcf_line, const std::string &password)
Definition: kdf_pbkdf2.h:251
std::vector< uint8_t > salt() const
salt.
Definition: kdf_pbkdf2.h:179
std::vector< uint8_t > salt_
Definition: kdf_pbkdf2.h:270
unsigned long rounds() const
rounds.
Definition: kdf_pbkdf2.h:191
std::vector< uint8_t > checksum_
Definition: kdf_pbkdf2.h:271
std::string mcf_id() const
name of the digest according to MCF.
Definition: kdf_pbkdf2.h:160
static bool supports_mcf_id(const std::string mcf_id)
Definition: kdf_pbkdf2.h:247
Type digest() const
Definition: kdf_pbkdf2.h:184
Type type_
Definition: kdf_pbkdf2.h:268
Pbkdf2McfAdaptor(Type type, unsigned long rounds, const std::vector< uint8_t > &salt, const std::vector< uint8_t > &checksum)
Definition: kdf_pbkdf2.h:140
map the MCF name to internal types.
Definition: kdf_pbkdf2.h:74
static bool supports_name(const std::string &name) noexcept
Definition: kdf_pbkdf2.h:101
static constexpr char kTypeSha256[]
Definition: kdf_pbkdf2.h:77
static std::pair< bool, std::string > name(Type type) noexcept
Definition: kdf_pbkdf2.h:80
static std::pair< bool, Type > type(const std::string &name) noexcept
Definition: kdf_pbkdf2.h:91
static constexpr char kTypeSha512[]
Definition: kdf_pbkdf2.h:78
Key Derivation Function for PBKDF2.
Definition: kdf_pbkdf2.h:58
Type
Definition: kdf_pbkdf2.h:60
#define HTTP_AUTH_BACKEND_LIB_EXPORT
Definition: http_auth_backend_lib_export.h:15
static int64 base64_decode(const char *src_base, size_t len, void *dst, const char **end_ptr, int flags)
Decode a base64 string The base64-encoded data in the range ['src','*end_ptr') will be decoded and st...
Definition: base64.h:303
static int base64_encode(const void *src, size_t src_len, char *dst)
Definition: base64.h:242
@ kPasswordNotMatched
static char * password
Definition: mysql_secure_installation.cc:57
constexpr value_type binary
Definition: classic_protocol_constants.h:274
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:78
Type
Definition: resource_group_basic_types.h:32
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:85
required string key
Definition: replication_asynchronous_connection_failover.proto:59
required string type
Definition: replication_group_member_actions.proto:33
case opt name
Definition: sslopt-case.h:32