From a9bdfccbc63708749b3b60fbb98719605401cc8b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 12 Mar 2025 10:46:09 +1100 Subject: [PATCH] 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 iterations. --- include/mysql/plugin_audit.h.pp | 10 ++++ include/mysql/plugin_auth.h.pp | 10 ++++ include/mysql/plugin_data_type.h.pp | 10 ++++ include/mysql/plugin_encryption.h.pp | 10 ++++ include/mysql/plugin_ftparser.h.pp | 10 ++++ include/mysql/plugin_function.h.pp | 10 ++++ include/mysql/plugin_password_validation.h.pp | 10 ++++ include/mysql/service_my_crypt.h | 14 +++++ include/service_versions.h | 2 +- .../t/filekeys-data-sha1-pbkdf2.enc | 1 + .../suite/encryption/t/filekeys-data-sha1.enc | Bin 0 -> 416 bytes .../t/filekeys-data-sha224-pbkdf2.enc | Bin 0 -> 416 bytes .../encryption/t/filekeys-data-sha224.enc | Bin 0 -> 416 bytes .../t/filekeys-data-sha256-pbkdf2.enc | Bin 0 -> 416 bytes .../encryption/t/filekeys-data-sha256.enc | Bin 0 -> 416 bytes .../t/filekeys-data-sha384-pbkdf2.enc | 3 + .../encryption/t/filekeys-data-sha384.enc | Bin 0 -> 416 bytes .../t/filekeys-data-sha512-pbkdf2.enc | Bin 0 -> 416 bytes .../encryption/t/filekeys-data-sha512.enc | Bin 0 -> 416 bytes .../t/filekeys_encfile.combinations | 52 ++++++++++++++++++ .../suite/encryption/t/filekeys_encfile.opt | 2 - .../suite/encryption/t/filekeys_encfile.test | 33 +++++++++++ mysys_ssl/my_crypt.cc | 37 +++++++++++++ .../file_key_management_plugin.cc | 47 +++++++++++++++- plugin/file_key_management/parser.cc | 52 +----------------- plugin/file_key_management/parser.h | 10 ++-- sql/sql_plugin_services.inl | 3 +- 27 files changed, 268 insertions(+), 58 deletions(-) create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha1-pbkdf2.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha1.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha224-pbkdf2.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha224.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha256-pbkdf2.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha256.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha384-pbkdf2.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha384.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha512-pbkdf2.enc create mode 100644 mysql-test/suite/encryption/t/filekeys-data-sha512.enc create mode 100644 mysql-test/suite/encryption/t/filekeys_encfile.combinations delete mode 100644 mysql-test/suite/encryption/t/filekeys_encfile.opt diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 2ba67eb40cf..fca41a85db0 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 43201f954c2..4e9bfcfd103 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp index 94ce7bfff7b..35641802e03 100644 --- a/include/mysql/plugin_data_type.h.pp +++ b/include/mysql/plugin_data_type.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index f26a02def18..e8b7f7b3e60 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 7c3e476849a..4de3fc3a9e6 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp index 42970389951..63c63cefa10 100644 --- a/include/mysql/plugin_function.h.pp +++ b/include/mysql/plugin_function.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index 3d92c127b87..6cc728a8529 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -169,6 +169,8 @@ extern "C" { enum my_aes_mode { MY_AES_ECB, MY_AES_CBC }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -182,6 +184,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); } *my_crypt_service; int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -193,6 +199,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); } 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 @@ -57,6 +57,9 @@ enum my_aes_mode { #endif }; +enum my_digest { MY_DIGEST_SHA1, MY_DIGEST_SHA224, MY_DIGEST_SHA256, + MY_DIGEST_SHA384, MY_DIGEST_SHA512 }; + extern struct my_crypt_service_st { int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags, const unsigned char* key, unsigned int klen, @@ -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); } *my_crypt_service; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -95,6 +102,9 @@ extern struct my_crypt_service_st { #define my_random_bytes(A,B)\ my_crypt_service->my_random_bytes(A,B) +#define my_bytes_to_key(A, B, C, D, E, F, G) \ +my_crypt_service->my_bytes_to_key(A,B,C,D,E,F,G) + #else int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, @@ -108,6 +118,10 @@ int my_aes_crypt(enum my_aes_mode mode, int flags, const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen); 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); 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); #endif diff --git a/include/service_versions.h b/include/service_versions.h index ea74ac01bb9..40e668ea843 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -27,7 +27,7 @@ #define VERSION_encryption 0x0300 #define VERSION_encryption_scheme 0x0100 #define VERSION_logger 0x0200 -#define VERSION_my_crypt 0x0100 +#define VERSION_my_crypt 0x0101 #define VERSION_my_md5 0x0100 #define VERSION_my_print_error 0x0200 #define VERSION_my_sha1 0x0101 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha1-pbkdf2.enc b/mysql-test/suite/encryption/t/filekeys-data-sha1-pbkdf2.enc new file mode 100644 index 00000000000..fee415deeff --- /dev/null +++ b/mysql-test/suite/encryption/t/filekeys-data-sha1-pbkdf2.enc @@ -0,0 +1 @@ +Salted__pΞU*y|ρ3HZ t#rҾb=V9,377ʼ)F"}S*Z8 ƄdśfX&wNlވ3{.IBouae4RQ-aK`${O#U zUB3G)VKI=(pcUbT0*R5LHU(qUdELU7ZsJ*5hBQ5OTX#)^cuUm`v>y!|H_6CpPbVLo zeZo_1Pn6WXcZp=^)xy{A(w@NNj$e^pL*CdkzQ{UWXSSXabx{?#VDh9b4v2OLN>TW0 zxf}da&K0^^0=31RKP)+;M;*+Wdaoc5X0`x;t=)GL%q8*Rn(%274gw~~d{@_WQXQg& zy_Bo@!LNBd;h6798kO*MqX)gu&4TN>6;jB?Be!ZSh?O23*~6#9?*lrHD2C+ZVWhaW z-n#l`JTG0n7=k-3<~_AT8)9a?{l)Bna#D11@oD!hByP>SNV~}kgzm$m5kJwH KnMh9+u7xh|EX;HO literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha224-pbkdf2.enc b/mysql-test/suite/encryption/t/filekeys-data-sha224-pbkdf2.enc new file mode 100644 index 0000000000000000000000000000000000000000..6a68a288943d5b4704314d2f79874301c2bd4e7f GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5xw!?r5c2mIqm?yvrGvMnXz4RzKzYoPHv=Hwco<~nA z{b`lMcaSsGG2vSMM(IvXQyi@gyt(yFl)qW#k9xv3qs5dE_tTOPp_~lW4@8W)2KoRE zli$;nAp>L(xKKr-{A^MvkDNc`5nMC9${7WqWa6lZa(Ny3`kBdxn#)7uG7nRXOn2P0QJEK{)6& zi%w8Q0AP?ZbR|zH80FQlA$G{!<9EoCa>J6)@@ZguPn)?6m$vV83j;uys;S$#S1D9N z+b!zZ92T*6-B1^o1jPQqx(f1guHgrUn^yMmErZHhU#)2~XMy1@V}!dglGPfw3|-W0 z#1b0KW2mZGkWZ!dPa%#QazqG`<~>4@-QjkYcr>EM;OQB%Xlvx+#n2ij7Xsb2 KpIC&uSrbOWbk55F literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha224.enc b/mysql-test/suite/encryption/t/filekeys-data-sha224.enc new file mode 100644 index 0000000000000000000000000000000000000000..4ba1fc1b38376105091f17846261f2fa07141bd1 GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5y~(<6KH{6KP9CWk91L;hr=0lS1OB7$Rqe<$^<|FY4I8C%EM zL6*P;RD_Bd)sX%u%to=0-37g=0p9s%%jMGyaVV6ITnxb*R*exmNp>JB>}}U5gOEOJzf4FO4Trcn$BdS0<@irGrX-@*V2*cdp4!j2DVN!`YsM$FrC*FHThLjwRrG_ z;YVoHR`YOi9rNqiEpL@17&oTMWd$3aG)CP#Oqc>_eEoR&UP`yALB59)dq|&PbA6mP z{num*Q&~ZRs_GTj7O{=I^=Jt;*ZV#&b4DW2!+19ubuersyb0;8^IGLU$&QIY0LDiW KJfbIFN>J^~fzMF@ literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha256-pbkdf2.enc b/mysql-test/suite/encryption/t/filekeys-data-sha256-pbkdf2.enc new file mode 100644 index 0000000000000000000000000000000000000000..8dfb26541e7ac27148d362f7052a9a85d8c69eb4 GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5zWBp-VfTuPPWCRD#Dy>D~@`FetcZ|(iz66E-czj%QLj3|*y zmoR|PMkY)l6)+cPWptEl!*Lz3-yj8Ts8qQ7S@?ZsXFU@M3V%hioqsc1;y&cUx zw53a&+yR9yY&0f{Duz-iVR6H((_|Ld1Tn=Ssq^2t?N)aF`!+Tu^ KKP_G~ZVDlIbHio; literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha256.enc b/mysql-test/suite/encryption/t/filekeys-data-sha256.enc new file mode 100644 index 0000000000000000000000000000000000000000..6daf285af8163d5a479706992a11c34e9c03cde5 GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5xK(3Z{>{71WAS26YiA>7@rE6apsgOpmLnJ*k@GBwlfxY|QX zpsYsxUCq^ghOK?{eZys; zufaioF=)a4TVr1jp~WV9gNLnY=C8Qn0D1`a?)|T{12i6s@ Kmbh>4U8rbOYSE4W literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha384-pbkdf2.enc b/mysql-test/suite/encryption/t/filekeys-data-sha384-pbkdf2.enc new file mode 100644 index 00000000000..2e9f65cbd2d --- /dev/null +++ b/mysql-test/suite/encryption/t/filekeys-data-sha384-pbkdf2.enc @@ -0,0 +1,3 @@ +Salted__rjQ̪@}ou1큾V߲Xqh@oPh/ݱÇDb}VNT{ 35enҏ>:M +\ZI-& u:?/3clM:Ŷpk.xz"G4K6Gِ[aU uXvJx ;4s99.yqxl$46&͐Uh 0z*+a1# !.5]/="okgP2< +ZC&3_9E\[H4=;[:×UbaE|-M"=-}凛#,~#g:ؠV15w^ulyANWCwS0UP0[F51F \ No newline at end of file diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha384.enc b/mysql-test/suite/encryption/t/filekeys-data-sha384.enc new file mode 100644 index 0000000000000000000000000000000000000000..c588121b62a9c1623b1a57b770fdd165bba23335 GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5w}OBZf7O5B497 z>+{dn5_PaIP57X&E(7@duB4=d@EgGzJY5#GWy3Br`xzYGh5B40)CWEeuNqPT5K!43 z3aZ<%CqnF%KxZN|`ghJ<1pBeHJ!~@`AQmF6R9XYw>&b&N4s)1=YE^niZHP$KtJY6c?X~I*;OYR21`|^Ary}f KK4)vSFS+0Xpu%(j literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys-data-sha512-pbkdf2.enc b/mysql-test/suite/encryption/t/filekeys-data-sha512-pbkdf2.enc new file mode 100644 index 0000000000000000000000000000000000000000..9e7582b12e9b835ba905246392ae1141338baaaa GIT binary patch literal 416 zcmV;R0bl-8VQh3|WM5z9#oVyHmf8$l6U7FxRMTYPj5#|Ik))1<3i_%J0zg?7*cCv^+GdFnX4qa5;uZRq5l$3H$UvkxNUbGp(Qfl)&9&ui-{UqRR z_SBj^Z|u4%(ozU#o$~wMG&!tge~GZQKL~5c75@@<+W(Zqhnn2b$-l^7>K_}q1=e{0rbk@J9HD`AD7 z^E4y)dg9jW$<*#u+^W;}!Yq24bl#kExDK6f(=*RYAU*|>G~E-~*gzm3f^MOJBBNpHt1EHZ zv1FJ8Ik^;`%#G)Z3W|+I(I7=vUwMx4QIEpa_r~07Zj1&T#f(f-%U-uK$w?#RXP8LU z#u)M5&IX(^LI}=LrwNxql$)}UZ&H?M1bjN>>Fn6q4hq;nJAK2fh|<+jccOfj9jxTyXMOF)yBW zebAlG$wpz0F5eyYt0>*u(R$49`Nss_b+p@E%FEOm6op)X9E<|{3Vhf-i6~f{FC8_= KLIdFL1PLcj>(Y?` literal 0 HcmV?d00001 diff --git a/mysql-test/suite/encryption/t/filekeys_encfile.combinations b/mysql-test/suite/encryption/t/filekeys_encfile.combinations new file mode 100644 index 00000000000..652ef183e42 --- /dev/null +++ b/mysql-test/suite/encryption/t/filekeys_encfile.combinations @@ -0,0 +1,52 @@ +[sha1] +--loose-file-key-management-filekey=secret +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha1.enc + +[sha224] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha224 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha224.enc + +[sha256] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha256 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha256.enc + +[sha384] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha384 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha384.enc + +[sha512] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha512 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha512.enc + +[sha1_pbkdf2] +--loose-file-key-management-filekey=secret +--loose-file-key-management-use-pbkdf2=10000 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha1-pbkdf2.enc + +[sha224_pbkdf2] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha224 +--loose-file-key-management-use-pbkdf2=1000 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha224-pbkdf2.enc + +[sha256_pbkdf2] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha256 +--loose-file-key-management-use-pbkdf2=100000 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha256-pbkdf2.enc + +[sha384_pbkdf2] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha384 +--loose-file-key-management-use-pbkdf2=12345 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha384-pbkdf2.enc + +[sha512_pbkdf2] +--loose-file-key-management-filekey=secret +--loose-file-key-management-digest=sha512 +--loose-file-key-management-use-pbkdf2=10000 +--loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data-sha512-pbkdf2.enc diff --git a/mysql-test/suite/encryption/t/filekeys_encfile.opt b/mysql-test/suite/encryption/t/filekeys_encfile.opt deleted file mode 100644 index 651cc0f4cbe..00000000000 --- a/mysql-test/suite/encryption/t/filekeys_encfile.opt +++ /dev/null @@ -1,2 +0,0 @@ ---loose-file-key-management-filekey=secret ---loose-file-key-management-filename=$MTR_SUITE_DIR/t/filekeys-data.enc diff --git a/mysql-test/suite/encryption/t/filekeys_encfile.test b/mysql-test/suite/encryption/t/filekeys_encfile.test index a0611a38ec4..66a79b09ad0 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; +# exec openssl enc -aes-256-cbc -md sha224 -iter 1000 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha224-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha256 -iter 100000 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha256-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha384 -iter 12345 -pass pass:secret -in $plain_keyfile -out $enc_keyfile_prefix-sha384-pbkdf2.enc; +# exec openssl enc -aes-256-cbc -md sha512 -iter 10000 -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..a70ce4efef6 100644 --- a/mysys_ssl/my_crypt.cc +++ b/mysys_ssl/my_crypt.cc @@ -31,6 +31,8 @@ #include #define CTX_ALIGN 16 +#define KEY_LENGTH 32 +#define IV_LENGTH 16 class MyCTX { @@ -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, get_digest(digest), + 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..1ceac9d1875 100644 --- a/plugin/file_key_management/file_key_management_plugin.cc +++ b/plugin/file_key_management/file_key_management_plugin.cc @@ -22,6 +22,8 @@ static char* filename; static char* filekey; static unsigned long encryption_algorithm; +static unsigned long digest; +static uint use_pbkdf2; static const char *encryption_algorithm_names[]= { @@ -32,8 +34,20 @@ static const char *encryption_algorithm_names[]= 0 }; +static const char *digest_names[]= +{ + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + 0 +}; + static TYPELIB encryption_algorithm_typelib=CREATE_TYPELIB_FOR(encryption_algorithm_names); +static TYPELIB digest_typelib=CREATE_TYPELIB_FOR(digest_names); + static MYSQL_SYSVAR_STR(filename, filename, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Path and name of the key file", @@ -54,10 +68,24 @@ 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 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, + "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, 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 }; @@ -127,6 +155,23 @@ static inline enum my_aes_mode mode(int flags) return MY_AES_CBC; } +static inline enum my_digest get_digest() +{ + switch (digest) + { + case 0: return MY_DIGEST_SHA1; + case 1: return MY_DIGEST_SHA224; + case 2: return MY_DIGEST_SHA256; + case 3: return MY_DIGEST_SHA384; + case 4: return MY_DIGEST_SHA512; + default: + { + assert(0); + return MY_DIGEST_SHA1; + } + } +} + static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen, const unsigned char* iv, unsigned int ivlen, int flags, unsigned int key_id, unsigned int key_version) @@ -170,7 +215,7 @@ struct st_mariadb_encryption file_key_management_plugin= { static int file_key_management_plugin_init(void *p) { - Parser parser(filename, filekey); + Parser parser(filename, filekey, get_digest(), use_pbkdf2); return parser.parse(&keys); } diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc index 65ff5a14705..e8aecd3500b 100644 --- a/plugin/file_key_management/parser.cc +++ b/plugin/file_key_management/parser.cc @@ -88,54 +88,6 @@ openssl enc -aes-256-cbc -md sha1 -k "secret" -in keys.txt -out keys.enc #define OpenSSL_key_len 32 #define OpenSSL_iv_len 16 -/** - Calculate key and iv from a given salt and secret as in the - openssl command-line tool - - @param salt [in] the given salt as extracted from the encrypted file - @param secret [in] the given secret as String, provided by the user - @param key [out] 32 Bytes of key are written to this pointer - @param iv [out] 16 Bytes of iv are written to this pointer -*/ - -void Parser::bytes_to_key(const unsigned char *salt, const char *input, - unsigned char *key, unsigned char *iv) -{ - unsigned char digest[MY_SHA1_HASH_SIZE]; - int key_left = OpenSSL_key_len; - int iv_left = OpenSSL_iv_len; - const size_t ilen= strlen(input); - const size_t slen= OpenSSL_salt_len; // either this or explicit (size_t) casts below - - my_sha1_multi(digest, input, ilen, salt, slen, NullS); - - while (iv_left) - { - int left= MY_SHA1_HASH_SIZE; - if (key_left) - { - int store = MY_MIN(key_left, MY_SHA1_HASH_SIZE); - memcpy(&key[OpenSSL_key_len - key_left], digest, store); - - key_left -= store; - left -= store; - } - - if (iv_left && left) - { - int store= MY_MIN(iv_left, left); - memcpy(&iv[OpenSSL_iv_len - iv_left], &digest[MY_SHA1_HASH_SIZE - left], store); - - iv_left -= store; - } - - if (iv_left) - my_sha1_multi(digest, digest, MY_SHA1_HASH_SIZE, - input, ilen, salt, slen, NullS); - } -} - - bool Parser::parse(std::map *keys) { const char *secret= filekey; @@ -374,7 +326,9 @@ char* Parser::read_and_decrypt_file(const char *secret) my_error(EE_OUTOFMEMORY, ME_ERROR_LOG | ME_FATAL, file_size); goto err2; } - bytes_to_key(buffer + OpenSSL_prefix_len, secret, key, iv); + my_bytes_to_key(buffer + OpenSSL_prefix_len, + (const unsigned char *) secret, (uint) strlen(secret), + key, iv, digest, use_pbkdf2); uint32 d_size; if (my_aes_crypt(MY_AES_CBC, ENCRYPTION_FLAG_DECRYPT, buffer + OpenSSL_prefix_len + OpenSSL_salt_len, diff --git a/plugin/file_key_management/parser.h b/plugin/file_key_management/parser.h index e2fda758bf9..8af2b5b035e 100644 --- a/plugin/file_key_management/parser.h +++ b/plugin/file_key_management/parser.h @@ -35,13 +35,13 @@ class Parser { const char *filename; const char *filekey; + const enum my_digest digest; + const uint use_pbkdf2; unsigned int line_number; unsigned int from_hex(char c) { return c <= '9' ? c - '0' : tolower(c) - 'a' + 10; } - void bytes_to_key(const unsigned char *salt, const char *secret, - unsigned char *key, unsigned char *iv); bool read_filekey(const char *filekey, char *secret); bool parse_file(std::map *keys, const char *secret); void report_error(const char *reason, size_t position); @@ -49,7 +49,9 @@ class Parser char* read_and_decrypt_file(const char *secret); public: - Parser(const char* fn, const char *fk) : - filename(fn), filekey(fk), line_number(0) { } + Parser(const char* fn, const char *fk, enum my_digest digest, + uint use_pbkdf2) : + filename(fn), filekey(fk), digest(digest), use_pbkdf2(use_pbkdf2), + line_number(0) { } bool parse(std::map *keys); }; diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 2114f3560a7..5d314dcfce8 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -210,7 +210,8 @@ static struct my_crypt_service_st crypt_handler= my_aes_crypt, my_aes_get_size, my_aes_ctx_size, - my_random_bytes + my_random_bytes, + my_bytes_to_key, }; static struct my_print_error_service_st my_print_error_handler=