Skip to content

Commit 910d32e

Browse files
committed
MDEV-35254 Make iterations count configurable in PARSEC plugin
This patch adds a global plugin variable parsec_iterations to define define the number of iterations to be used when generating the key corresponding to the password. It has a default value, lower and upper bounds.
1 parent 5ed3668 commit 910d32e

1 file changed

Lines changed: 49 additions & 3 deletions

File tree

plugin/auth_parsec/server_parsec.cc

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,49 @@ constexpr size_t PBKDF2_HASH_LENGTH= ED25519_KEY_LENGTH;
3838
constexpr size_t CLIENT_RESPONSE_LENGTH= CHALLENGE_SCRAMBLE_LENGTH
3939
+ ED25519_SIG_LENGTH;
4040

41+
constexpr unsigned int PARSEC_ITERATIONS_DEFAULT= 1u << 18;
42+
constexpr unsigned int PARSEC_ITERATIONS_MIN= 1u << 10;
43+
constexpr unsigned int PARSEC_ITERATIONS_MAX= 1u << 19;
44+
constexpr unsigned int PARSEC_ITERATIONS_STEP= 1u;
45+
static unsigned int iterations;
46+
47+
static inline unsigned int round_to_power_of_two(const unsigned int x) {
48+
unsigned int p = 1;
49+
while (p < x)
50+
p <<= 1;
51+
return p;
52+
}
53+
54+
55+
static inline unsigned int log_2_of_power_of_2(const unsigned int x) {
56+
// function will not work correctly for non power of 2 unsigned integers
57+
unsigned int p = 0;
58+
while ((1u << p) != x)
59+
p++;
60+
return p;
61+
}
62+
63+
static void update_parsec_iterations(MYSQL_THD thd,
64+
struct st_mysql_sys_var *var __attribute__((unused)),
65+
void *var_ptr __attribute__((unused)), const void *save)
66+
{
67+
unsigned int iterations_user_input= *(unsigned int *) save;
68+
iterations= round_to_power_of_two(iterations_user_input);
69+
if (iterations != iterations_user_input)
70+
my_printf_error(0, "parsec: parsec_iterations rounded up to %d (next supported value)",
71+
ME_WARNING, iterations);
72+
}
73+
74+
static MYSQL_SYSVAR_UINT(parsec_iterations, iterations, PLUGIN_VAR_OPCMDARG,
75+
"Number of iterations to be used when generating the key corresponding to the password",
76+
NULL, update_parsec_iterations, PARSEC_ITERATIONS_DEFAULT, PARSEC_ITERATIONS_MIN,
77+
PARSEC_ITERATIONS_MAX, PARSEC_ITERATIONS_STEP);
78+
79+
static struct st_mysql_sys_var* system_vars[] = {
80+
MYSQL_SYSVAR(parsec_iterations),
81+
NULL
82+
};
83+
4184
constexpr size_t base64_length(size_t input_length)
4285
{
4386
return ((input_length + 2) / 3) * 4; // with padding
@@ -176,7 +219,8 @@ int hash_password(const char *password, size_t password_length,
176219

177220
Passwd_in_memory memory;
178221
memory.algorithm= 'P';
179-
memory.iterations= 0;
222+
constexpr unsigned int ITER_BASE_VAL= 10u;
223+
memory.iterations= '0' + (log_2_of_power_of_2(iterations) - ITER_BASE_VAL);
180224
my_random_bytes(memory.salt, sizeof(memory.salt));
181225

182226
uchar derived_key[PBKDF2_HASH_LENGTH];
@@ -204,10 +248,12 @@ int digest_to_binary(const char *hash, size_t hash_length,
204248
{
205249
auto stored= (Passwd_as_stored*)hash;
206250
auto memory= (Passwd_in_memory*)out;
251+
const uchar ITER_MAX_VAL= '0' +
252+
log_2_of_power_of_2(PARSEC_ITERATIONS_MAX) - 10;
207253

208254
if (hash_length != sizeof (*stored) || *out_length < sizeof(*memory) ||
209255
stored->algorithm != 'P' ||
210-
stored->iterations < '0' || stored->iterations > '3' ||
256+
stored->iterations < '0' || stored->iterations > ITER_MAX_VAL ||
211257
stored->colon != ':' || stored->colon2 != ':')
212258
{
213259
my_printf_error(ER_PASSWD_LENGTH, "Wrong ext-salt format", 0);
@@ -313,7 +359,7 @@ maria_declare_plugin(auth_parsec)
313359
NULL,
314360
0x0100,
315361
NULL,
316-
NULL,
362+
system_vars,
317363
"1.0",
318364
MariaDB_PLUGIN_MATURITY_GAMMA
319365
}

0 commit comments

Comments
 (0)