Re: 0cc1c382dfc: MDEV-34712 Add support to sha2 and pbkdf2 key derivation in file_key_management

Hi, Yuchen, On Mar 10, Yuchen Pei wrote:
revision-id: 0cc1c382dfc (mariadb-11.8.1-9-g0cc1c382dfc) parent(s): 3a81664cb80 author: Yuchen Pei committer: Yuchen Pei timestamp: 2025-03-05 13:33:53 +1100 message:
MDEV-34712 Add support to sha2 and pbkdf2 key derivation in file_key_management
Add two new variables:
file_key_management_digest={sha1|sha224|sha256|sha384|sha512}
This specify the digest function to use in key derivation of the key used for decryption of the keyfile
file_key_management_use_pbkdf2=N
This specify whether pbkdf2 is used in the key derivation, and if so (N != 0), how many thousands iterations.
diff --git a/include/mysql/service_my_crypt.h b/include/mysql/service_my_crypt.h index 1a4ebcfd067..3a58d0828fc 100644 --- a/include/mysql/service_my_crypt.h +++ b/include/mysql/service_my_crypt.h @@ -70,6 +73,10 @@ extern struct my_crypt_service_st { unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length); unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode); int (*my_random_bytes)(unsigned char* buf, int num); + void (*my_bytes_to_key)(const unsigned char *salt, const unsigned char *input, + unsigned int input_len, unsigned char *key, + unsigned char *iv, enum my_digest digest, + unsigned int use_pbkdf2);
backward compatible API change - you need to increment the service version
} *my_crypt_service;
#ifdef MYSQL_DYNAMIC_PLUGIN diff --git a/mysql-test/suite/encryption/t/filekeys_encfile.test b/mysql-test/suite/encryption/t/filekeys_encfile.test index a0611a38ec4..89e13834a79 100644 --- a/mysql-test/suite/encryption/t/filekeys_encfile.test +++ b/mysql-test/suite/encryption/t/filekeys_encfile.test @@ -1 +1,34 @@ +# # The encrypted key files were generated using the following: + +# let $plain_keyfile=$MYSQL_TMP_DIR/keys.txt; +# let $enc_keyfile_prefix=$MTR_SUITE_DIR/t/filekeys-data; + +# write_file $plain_keyfile; +# # +# # this is a comment +# # +# 1;770A8A65DA156D24EE2A093277530142 +# 2;4D92199549E0F2EF009B4160F3582E5528A11A45017F3EF8 +# # another comment +# 33;B374A26A71490437AA024E4FADD5B497FDFF1A8EA6FF12F6FB65AF2720B59CCF +# 4;18420B5CBA31CCDFFE9716E91EB61374D05914F3ADE23E03 --> ignored + +# 5;966050D7777350B6FD5CCB3E5F648DA45C63BEFB6DEDDFA13443F156B7D35C84 +# 6;B5EA210C8C09EF20DB95EC584714A89F # and yet another + +# EOF + +# exec openssl enc -aes-256-cbc -md sha1 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha1.enc; +# exec openssl enc -aes-256-cbc -md sha224 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha224.enc; +# exec openssl enc -aes-256-cbc -md sha256 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha256.enc; +# exec openssl enc -aes-256-cbc -md sha384 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha384.enc; +# exec openssl enc -aes-256-cbc -md sha512 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha512.enc; +# exec openssl enc -aes-256-cbc -md sha1 -pbkdf2 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha1-pbkdf2.enc;
better say -iter 1000 instead of -pbkdf2 (to match plugin parameters) And change some tests to use a non-default value, please
+# exec openssl enc -aes-256-cbc -md sha224 -pbkdf2 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha224-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha256 -pbkdf2 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha256-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha384 -pbkdf2 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha384-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha512 -pbkdf2 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha512-pbkdf2.enc; + +# echo Done; + source filekeys_goodtest.inc; diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc index 346eff51b1b..ef74121d530 100644 --- a/mysys_ssl/my_crypt.cc +++ b/mysys_ssl/my_crypt.cc @@ -382,4 +384,39 @@ int my_random_bytes(uchar *buf, int num) return MY_AES_OK; }
+static inline const EVP_MD *get_digest(enum my_digest digest) +{ + switch (digest) + { + case MY_DIGEST_SHA1: return EVP_sha1(); + case MY_DIGEST_SHA224: return EVP_sha224(); + case MY_DIGEST_SHA256: return EVP_sha256(); + case MY_DIGEST_SHA384: return EVP_sha384(); + case MY_DIGEST_SHA512: return EVP_sha512(); + default: + { + assert(0); + return NULL; + } + } +} + +void my_bytes_to_key(const unsigned char *salt, const unsigned char *input, + uint input_len, unsigned char *key, unsigned char *iv, + enum my_digest digest, uint use_pbkdf2) +{ + if (use_pbkdf2 == 0) + EVP_BytesToKey(EVP_aes_256_cbc(), get_digest(digest), salt, + input, input_len, 1, key, iv); + else + { + uchar keyiv[KEY_LENGTH + IV_LENGTH]; + PKCS5_PBKDF2_HMAC((const char*) input, input_len, salt, 8, + use_pbkdf2 * 1000, get_digest(digest),
I suggest not to do *1000. It doesn't help with anything and introduces a limitation that we don't need. Perhaps somebody has a policy of using 2^N iterations in PBKDF2? Also, `openssl enc -iter` doesn't do *1000
+ KEY_LENGTH + IV_LENGTH, keyiv); + memcpy(key, keyiv, KEY_LENGTH); + memcpy(iv, keyiv + KEY_LENGTH, IV_LENGTH); + } +} + } diff --git a/plugin/file_key_management/file_key_management_plugin.cc b/plugin/file_key_management/file_key_management_plugin.cc index 8702785a1fd..f37cfe05960 100644 --- a/plugin/file_key_management/file_key_management_plugin.cc +++ b/plugin/file_key_management/file_key_management_plugin.cc @@ -54,10 +68,22 @@ static MYSQL_SYSVAR_ENUM(encryption_algorithm, encryption_algorithm, "Encryption algorithm to use" recommendation, NULL, NULL, 0, &encryption_algorithm_typelib);
+static MYSQL_SYSVAR_ENUM(digest, digest, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Digest to use",
"Digest algorithm used for decrypting the key file. The value of the openssl enc -md option"
+ NULL, NULL, 0, &digest_typelib); + +static MYSQL_SYSVAR_UINT(use_pbkdf2, use_pbkdf2, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Use pbkdf2",
"Number of PBKDF2 iteration used for decrypting the key file. Use 0 to disable PBKDF2, otherwise it's a value of the openssl enc -iter option"
+ NULL, NULL, 0, 0, UINT_MAX / 1000, 0); + static struct st_mysql_sys_var* settings[] = { MYSQL_SYSVAR(filename), MYSQL_SYSVAR(filekey), MYSQL_SYSVAR(encryption_algorithm), + MYSQL_SYSVAR(digest), + MYSQL_SYSVAR(use_pbkdf2), NULL };
Regards, Sergei Chief Architect, MariaDB Server and security@mariadb.org
participants (1)
-
Sergei Golubchik