@@ -38,6 +38,49 @@ constexpr size_t PBKDF2_HASH_LENGTH= ED25519_KEY_LENGTH;
3838constexpr 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+
4184constexpr 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