revision-id: 9c46adbb7e093029c56dddd5dbbef407db4e8160 (mariadb-10.1.37-7-g9c46adbb7e0) parent(s): ef40018535b71f0a4387fa6c1cc22e9991dfc0db author: Jan Lindström committer: Jan Lindström timestamp: 2018-11-12 12:05:42 +0200 message: MDEV-17229: Encryption threads ignore innodb_default_encryption_key_id Background MariaDB identifies encryption keys using a positive 32-bit integer. This makes it easier to identify the key you want to use for particular tables, through the ENCRYPTION_KEY_ID table option. You can set the default key using the innodb_default_encryption_key_id system variable. If no value is set system default (1) is used. Syntax SET [GLOBAL|SESSION] innodb-default-encryption-key-id=<key_id>; Used default encryption key_id can't be set to value that does not exists on encryption plugin. e.g. SET GLOBAL innodb_default_encryption_key_id = 999; ERROR 42000: Variable 'innodb_default_encryption_key_id' can't be set to the value of '999' SHOW WARNINGS; Level Code Message Warning 1210 InnoDB: innodb_default_encryption_key_id=999 not available in encryption plugin Error 1231 Variable 'innodb_default_encryption_key_id' can't be set to the value of '999' If variable is set on configuration file (my.cnf or similar) server will refuse to start if used key_id is not found from encryption plugin. This can be seen on server error log e.g. [ERROR] InnoDB: cannot use encryption as default encryption key_id 999 not found from encryption plugin. [ERROR] Plugin 'InnoDB' init function returned error. [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. If user creates a table that is not encrypted e.g: create table t1(a int) encrypted=no; and default encryption key_id is not same as system default (1), a warning is issued and system default is used. SET GLOBAL innodb-default-encryption-key-id=10; CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO; Warnings: Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 10 when encryption is disabled Currently set default encryption key_id does not effect tables that are created using specific encryption key_id e.g. create table t1(a int) encrypted=yes encryption_key_id=4; Instead specified key_id (in above case 4) is used. Tables using encryption but no specific encryption key_id e.g. create table t1(a int) encrypted=yes; will use currently set default encryption key_id for that session or if no key_id defined the set global encryption key_id or system default. Tables using default table options e.g create table t1(a int); will use currently set global encryption key_id when encryption threads does key rotation from unencrypted to encrypted state. Changes innodb-checksum-algorithm innodb-compressed-blob innodb-encryption-alter innodb-redo-badkey innodb-redo-nokeys These test require small changes as now we do not allow default key_id that is not found from encryption plugin and tables using no encryption produce warning when nondefault encryption key_id is used. fil0fil.cc::fil_crypt_start_encrypting_space() Use global default encryption key_id when creating encryption meta data. ha_innodb.cc::innodb_default_encryption_key_id_validate() New function to validate that used key_id is found from encryption plugin. ha_innodb.cc::thd_default_encryption_key_id() New accessessor function for default encryption key_id. ha_innodb.cc::innobase_init() Do not allow server startup using encryption key_id that is not found from encryption plugin. --- .../encryption/r/innodb-checksum-algorithm.result | 2 +- .../encryption/r/innodb-compressed-blob.result | 2 + .../encryption/r/innodb-encryption-alter.result | 31 +++++----- .../r/innodb_encryption_default_key.result | 39 +++++++++++++ .../encryption/t/innodb-checksum-algorithm.test | 6 +- .../encryption/t/innodb-encryption-alter.test | 9 +-- .../suite/encryption/t/innodb-redo-badkey.opt | 2 +- .../suite/encryption/t/innodb-redo-badkey.test | 2 +- .../suite/encryption/t/innodb-redo-nokeys.opt | 2 +- .../suite/encryption/t/innodb-redo-nokeys.test | 2 +- .../encryption/t/innodb_encryption_default_key.opt | 2 + .../t/innodb_encryption_default_key.test | 66 +++++++++++++++++++++ storage/innobase/fil/fil0crypt.cc | 5 +- storage/innobase/handler/ha_innodb.cc | 67 +++++++++++++++++++++- storage/innobase/include/ha_prototypes.h | 5 ++ storage/xtradb/fil/fil0crypt.cc | 5 +- storage/xtradb/handler/ha_innodb.cc | 67 +++++++++++++++++++++- storage/xtradb/include/ha_prototypes.h | 5 ++ 18 files changed, 285 insertions(+), 34 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result b/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result index a853f3869a9..b3deac98e3c 100644 --- a/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result +++ b/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result @@ -10,7 +10,7 @@ SET GLOBAL innodb_encrypt_tables = ON; SET GLOBAL innodb_encryption_threads = 4; call mtr.add_suppression("InnoDB: innodb_checksum_algorithm is set to \"strict_(crc32|none|innodb)\" but the page \\[page id: space=[0-9]+, page number=[0-9]+\\] contains a valid checksum \"(innodb|none|crc32)\""); SET GLOBAL innodb_checksum_algorithm = innodb; -SET GLOBAL innodb_default_encryption_key_id=4; +SET GLOBAL innodb_default_encryption_key_id=1; SET GLOBAL innodb_checksum_algorithm=crc32; create table tce_crc32(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=yes; diff --git a/mysql-test/suite/encryption/r/innodb-compressed-blob.result b/mysql-test/suite/encryption/r/innodb-compressed-blob.result index ce73b80820f..a6f4856fdbb 100644 --- a/mysql-test/suite/encryption/r/innodb-compressed-blob.result +++ b/mysql-test/suite/encryption/r/innodb-compressed-blob.result @@ -7,6 +7,8 @@ set GLOBAL innodb_default_encryption_key_id=4; create table t1(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed; create table t2(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed encrypted=yes; create table t3(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed encrypted=no; +Warnings: +Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 4 when encryption is disabled insert into t1 values (1, repeat('secret',6000)); insert into t2 values (1, repeat('secret',6000)); insert into t3 values (1, repeat('secret',6000)); diff --git a/mysql-test/suite/encryption/r/innodb-encryption-alter.result b/mysql-test/suite/encryption/r/innodb-encryption-alter.result index 5245d1da7d0..381f14c9e9e 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-alter.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-alter.result @@ -7,20 +7,25 @@ Warnings: Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 4 when encryption is disabled DROP TABLE t1; set innodb_default_encryption_key_id = 99; +ERROR 42000: Variable 'innodb_default_encryption_key_id' can't be set to the value of '99' CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 140 InnoDB: ENCRYPTION_KEY_ID 99 not available -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `c` varchar(256) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 140 InnoDB: ENCRYPTION_KEY_ID 99 not available -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `c` varchar(256) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTED`=YES +DROP TABLE t1; set innodb_default_encryption_key_id = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES; SHOW CREATE TABLE t1; @@ -40,8 +45,6 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTION_KEY_ID`=4 CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=1; -Warnings: -Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 1 when encryption is disabled ALTER TABLE t1 ENCRYPTION_KEY_ID=99; ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' SHOW WARNINGS; diff --git a/mysql-test/suite/encryption/r/innodb_encryption_default_key.result b/mysql-test/suite/encryption/r/innodb_encryption_default_key.result new file mode 100644 index 00000000000..13754df0d8b --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb_encryption_default_key.result @@ -0,0 +1,39 @@ +call mtr.add_suppression("InnoDB: cannot use encryption as default encryption key_id 999 not found from encryption plugin."); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +create table t1 (a int not null primary key) engine=InnoDB; +create table t2 (a int not null primary key) encrypted=yes engine=InnoDB; +SET GLOBAL innodb_default_encryption_key_id = 999; +ERROR 42000: Variable 'innodb_default_encryption_key_id' can't be set to the value of '999' +SHOW WARNINGS; +Level Code Message +Warning 1210 InnoDB: innodb_default_encryption_key_id=999 not available in encryption plugin +Error 1231 Variable 'innodb_default_encryption_key_id' can't be set to the value of '999' +SET GLOBAL innodb_default_encryption_key_id = 4; +SET GLOBAL innodb_encryption_threads = 4; +SET GLOBAL innodb_encrypt_tables = ON; +SET SESSION innodb_default_encryption_key_id = 2; +create table t3 (a int not null primary key) engine=InnoDB; +create table t4 (a int not null primary key) encrypted=yes engine=InnoDB; +SET SESSION innodb_default_encryption_key_id = 10; +create table t5 (a int not null primary key) engine=InnoDB; +create table t6 (a int not null primary key) encrypted=yes engine=InnoDB; +SELECT NAME,CURRENT_KEY_ID,MIN_KEY_VERSION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 ORDER BY NAME; +NAME CURRENT_KEY_ID MIN_KEY_VERSION +SELECT NAME,CURRENT_KEY_ID,MIN_KEY_VERSION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 ORDER BY NAME; +NAME CURRENT_KEY_ID MIN_KEY_VERSION +./ibdata1 4 1 +mysql/innodb_index_stats 4 1 +mysql/innodb_table_stats 4 1 +test/t1 4 1 +test/t2 1 1 +test/t3 2 1 +test/t4 2 1 +test/t5 10 1 +test/t6 10 1 +# Success! +DROP TABLE t1, t2, t3, t4, t5, t6; +# Restart mysqld --innodb_default_encryption_key_id=999 +# Restart mysqld --innodb_default_encryption_key_id=1 diff --git a/mysql-test/suite/encryption/t/innodb-checksum-algorithm.test b/mysql-test/suite/encryption/t/innodb-checksum-algorithm.test index d0caed05006..21ff07b5837 100644 --- a/mysql-test/suite/encryption/t/innodb-checksum-algorithm.test +++ b/mysql-test/suite/encryption/t/innodb-checksum-algorithm.test @@ -16,7 +16,11 @@ SET GLOBAL innodb_encryption_threads = 4; call mtr.add_suppression("InnoDB: innodb_checksum_algorithm is set to \"strict_(crc32|none|innodb)\" but the page \\[page id: space=[0-9]+, page number=[0-9]+\\] contains a valid checksum \"(innodb|none|crc32)\""); SET GLOBAL innodb_checksum_algorithm = innodb; -SET GLOBAL innodb_default_encryption_key_id=4; +# +# Need to use default encryption key_id as below creating tables +# with encrypted=no where nondefault key_id is not allowed. +# +SET GLOBAL innodb_default_encryption_key_id=1; let MYSQLD_DATADIR =`SELECT @@datadir`; diff --git a/mysql-test/suite/encryption/t/innodb-encryption-alter.test b/mysql-test/suite/encryption/t/innodb-encryption-alter.test index 9465226dd96..d79bdecfc1a 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-alter.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-alter.test @@ -19,13 +19,14 @@ SET GLOBAL innodb_encryption_threads = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=4; DROP TABLE t1; +--error ER_WRONG_VALUE_FOR_VAR set innodb_default_encryption_key_id = 99; ---error 1005 CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; -SHOW WARNINGS; ---error 1005 +SHOW CREATE TABLE t1; +DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES; -SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; set innodb_default_encryption_key_id = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=YES; SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.opt b/mysql-test/suite/encryption/t/innodb-redo-badkey.opt index 343128e8803..2b07bbb4b73 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.opt +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.opt @@ -1,5 +1,5 @@ --innodb-change-buffering=all ---innodb-encrypt-tables=on +--innodb-encrypt-tables=off --innodb-tablespaces-encryption --innodb-encryption-threads=2 --innodb-default-encryption-key-id=4 diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test index 69de4f0f921..75e765ca941 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test @@ -16,7 +16,7 @@ call mtr.add_suppression("InnoDB: Plugin initialization aborted "); call mtr.add_suppression("InnoDB: ############### CORRUPT LOG RECORD FOUND ##################"); --echo # Restart mysqld --file-key-management-filename=keys2.txt --- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt +-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt --innodb-default-encryption-key-id=20 --innodb-encrypt-tables=ON -- source include/restart_mysqld.inc --echo # Wait max 10 min for key encryption threads to encrypt all spaces diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.opt b/mysql-test/suite/encryption/t/innodb-redo-nokeys.opt index 21afc19fc5d..b72e464c480 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-nokeys.opt +++ b/mysql-test/suite/encryption/t/innodb-redo-nokeys.opt @@ -1,3 +1,3 @@ --innodb-change-buffering=none --innodb-encrypt-tables=on ---innodb-default-encryption-key-id=20 +--innodb-default-encryption-key-id=1 diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test index 68d831fcd17..5882b9de5c5 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test +++ b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test @@ -12,7 +12,7 @@ call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE faile call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[1234]\\.ibd' cannot be decrypted\\."); --echo # Restart mysqld --file-key-management-filename=keys2.txt --- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt +-- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt --innodb-default-encryption-key-id=20 -- source include/restart_mysqld.inc --disable_warnings diff --git a/mysql-test/suite/encryption/t/innodb_encryption_default_key.opt b/mysql-test/suite/encryption/t/innodb_encryption_default_key.opt new file mode 100644 index 00000000000..5a60c7ba21c --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encryption_default_key.opt @@ -0,0 +1,2 @@ +--innodb-tablespaces-encryption +--innodb-encrypt-tables=OFF diff --git a/mysql-test/suite/encryption/t/innodb_encryption_default_key.test b/mysql-test/suite/encryption/t/innodb_encryption_default_key.test new file mode 100644 index 00000000000..61a9f973d20 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encryption_default_key.test @@ -0,0 +1,66 @@ +-- source include/have_innodb.inc +-- source include/have_file_key_management_plugin.inc +-- source include/not_embedded.inc + +call mtr.add_suppression("InnoDB: cannot use encryption as default encryption key_id 999 not found from encryption plugin."); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); + +--disable_query_log +let $innodb_file_format_orig = `SELECT @@innodb_file_format`; +let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; +--enable_query_log + +--disable_warnings +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +--enable_warnings + +create table t1 (a int not null primary key) engine=InnoDB; +create table t2 (a int not null primary key) encrypted=yes engine=InnoDB; + +# Do not allow setting default key to key_id that is not found +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL innodb_default_encryption_key_id = 999; +SHOW WARNINGS; + +SET GLOBAL innodb_default_encryption_key_id = 4; +SET GLOBAL innodb_encryption_threads = 4; +SET GLOBAL innodb_encrypt_tables = ON; + +--connect (con11,localhost,root,,test) +SET SESSION innodb_default_encryption_key_id = 2; +create table t3 (a int not null primary key) engine=InnoDB; +create table t4 (a int not null primary key) encrypted=yes engine=InnoDB; +--disconnect con11 + +--connect (con12,localhost,root,,test) +SET SESSION innodb_default_encryption_key_id = 10; +create table t5 (a int not null primary key) engine=InnoDB; +create table t6 (a int not null primary key) encrypted=yes engine=InnoDB; +--disconnect con12 + +--connection default +--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'` +--let $wait_condition=SELECT COUNT(*) = $tables_count + 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND ROTATING_OR_FLUSHING = 0; +--source include/wait_condition.inc + +SELECT NAME,CURRENT_KEY_ID,MIN_KEY_VERSION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 ORDER BY NAME; +SELECT NAME,CURRENT_KEY_ID,MIN_KEY_VERSION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 ORDER BY NAME; + +--echo # Success! + +DROP TABLE t1, t2, t3, t4, t5, t6; + +# +# Try to restart server with key_id that is not found from encryption plugin +# +--echo # Restart mysqld --innodb_default_encryption_key_id=999 +-- let $restart_parameters=--innodb_default_encryption_key_id=999 +--error 1 +-- source include/restart_mysqld.inc + +--echo # Restart mysqld --innodb_default_encryption_key_id=1 +-- let $restart_parameters=--innodb_default_encryption_key_id=1 +--error 1 +-- source include/restart_mysqld.inc diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 7859fe67d40..c618a520b40 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1063,8 +1063,9 @@ fil_crypt_start_encrypting_space( * risk of finding encrypted pages without having * crypt data in page 0 */ - /* 1 - create crypt data */ - crypt_data = fil_space_create_crypt_data(FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); + /* 1 - create crypt data using default encryption key_id */ + crypt_data = fil_space_create_crypt_data(FIL_ENCRYPTION_DEFAULT, + thd_default_encryption_key_id()); if (crypt_data == NULL) { mutex_exit(&fil_crypt_threads_mutex); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b3a830e47c3..0d9beb452d9 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -685,11 +685,61 @@ static int mysql_tmpfile_path(const char *path, const char *prefix) static void innodb_remember_check_sysvar_funcs(); mysql_var_check_func check_sysvar_enum; +/** Validate passed-in "value" is a valid encryption key_id +found from encryption plugin. +This function is registered as a callback with MySQL. +@param[in,out] thd thread handle +@param[in] var pointer to system variable +@param[out] save immediate result for validate +@param[in] value incoming string +@return 0 for valid key_id */ +static +int +innodb_default_encryption_key_id_validate( + THD* thd, + struct st_mysql_sys_var* var, + void* save, + struct st_mysql_value* value) +{ + long long key_id_buf; + uint key_id; + + if (value->val_int(value, &key_id_buf)) { + /* The value is NULL. That is invalid. */ + return(1); + } + + *reinterpret_cast<uint*>(save) = key_id = static_cast<uint>(key_id_buf); + + /* Default encryption key_id must be found from encryption + plugin keys. */ + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: innodb_default_encryption_key_id=%u not available in encryption plugin", + key_id); + return (1); + } + + return(0); +} + static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, "Default encryption key id used for table encryption.", - NULL, NULL, + innodb_default_encryption_key_id_validate, + NULL, FIL_DEFAULT_ENCRYPTION_KEY, 1, UINT_MAX32, 0); +/** Get global default encryption key_id +@return key_id */ +UNIV_INTERN +uint thd_default_encryption_key_id(void) +{ + return(THDVAR(NULL, default_encryption_key_id)); +} + /** Structure for CREATE TABLE options (table options). It needs to be called ha_table_option_struct. @@ -3428,6 +3478,7 @@ innobase_init( char *default_path; uint format_id; ulong num_pll_degree; + uint key_id = FIL_DEFAULT_ENCRYPTION_KEY; DBUG_ENTER("innobase_init"); handlerton *innobase_hton= (handlerton*) p; @@ -3592,6 +3643,16 @@ innobase_init( goto error; } + key_id = THDVAR(NULL, default_encryption_key_id); + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + sql_print_error("InnoDB: cannot use encryption as " + " default encryption key_id %u" + " not found from encryption plugin.", + key_id); + goto error; + } + os_innodb_umask = (ulint) my_umask; /* First calculate the default path for innodb_data_home_dir etc., @@ -11947,8 +12008,8 @@ ha_innobase::check_table_options( } /* Ignore nondefault key_id if encryption is set off */ - if (encrypt == FIL_ENCRYPTION_OFF && - options->encryption_key_id != THDVAR(thd, default_encryption_key_id)) { + if (encrypt == FIL_ENCRYPTION_OFF + && options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index be423c8bd01..06610dcc94b 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -348,6 +348,11 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** Get global default encryption key_id +@return key_id */ +UNIV_INTERN +uint thd_default_encryption_key_id(void); + /** Get status of innodb_tmpdir. @param[in] thd thread handle, or NULL to query the global innodb_tmpdir. diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 7859fe67d40..c618a520b40 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -1063,8 +1063,9 @@ fil_crypt_start_encrypting_space( * risk of finding encrypted pages without having * crypt data in page 0 */ - /* 1 - create crypt data */ - crypt_data = fil_space_create_crypt_data(FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); + /* 1 - create crypt data using default encryption key_id */ + crypt_data = fil_space_create_crypt_data(FIL_ENCRYPTION_DEFAULT, + thd_default_encryption_key_id()); if (crypt_data == NULL) { mutex_exit(&fil_crypt_threads_mutex); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 05066512db9..704e3478195 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -686,11 +686,61 @@ ib_cb_t innodb_api_cb[] = { static void innodb_remember_check_sysvar_funcs(); mysql_var_check_func check_sysvar_enum; +/** Validate passed-in "value" is a valid encryption key_id +found from encryption plugin. +This function is registered as a callback with MySQL. +@param[in,out] thd thread handle +@param[in] var pointer to system variable +@param[out] save immediate result for validate +@param[in] value incoming string +@return 0 for valid key_id */ +static +int +innodb_default_encryption_key_id_validate( + THD* thd, + struct st_mysql_sys_var* var, + void* save, + struct st_mysql_value* value) +{ + long long key_id_buf; + uint key_id; + + if (value->val_int(value, &key_id_buf)) { + /* The value is NULL. That is invalid. */ + return(1); + } + + *reinterpret_cast<uint*>(save) = key_id = static_cast<uint>(key_id_buf); + + /* Default encryption key_id must be found from encryption + plugin keys. */ + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: innodb_default_encryption_key_id=%u not available in encryption plugin", + key_id); + return (1); + } + + return(0); +} + static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, "Default encryption key id used for table encryption.", - NULL, NULL, + innodb_default_encryption_key_id_validate, + NULL, FIL_DEFAULT_ENCRYPTION_KEY, 1, UINT_MAX32, 0); +/** Get global default encryption key_id +@return key_id */ +UNIV_INTERN +uint thd_default_encryption_key_id(void) +{ + return(THDVAR(NULL, default_encryption_key_id)); +} + /** Structure for CREATE TABLE options (table options). It needs to be called ha_table_option_struct. @@ -3839,6 +3889,7 @@ innobase_init( char *default_path; uint format_id; ulong num_pll_degree; + uint key_id = FIL_DEFAULT_ENCRYPTION_KEY; DBUG_ENTER("innobase_init"); handlerton *innobase_hton= (handlerton*) p; @@ -4042,6 +4093,16 @@ innobase_init( goto error; } + key_id = THDVAR(NULL, default_encryption_key_id); + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + sql_print_error("InnoDB: cannot use encryption as " + " default encryption key_id %u" + " not found from encryption plugin.", + key_id); + goto error; + } + os_innodb_umask = (ulint) my_umask; /* First calculate the default path for innodb_data_home_dir etc., @@ -12514,8 +12575,8 @@ ha_innobase::check_table_options( } /* Ignore nondefault key_id if encryption is set off */ - if (encrypt == FIL_ENCRYPTION_OFF && - options->encryption_key_id != THDVAR(thd, default_encryption_key_id)) { + if (encrypt == FIL_ENCRYPTION_OFF + && options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 3f3c4f28ced..ef91484817a 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -366,6 +366,11 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** Get global default encryption key_id +@return key_id */ +UNIV_INTERN +uint thd_default_encryption_key_id(void); + /** Get status of innodb_tmpdir. @param[in] thd thread handle, or NULL to query the global innodb_tmpdir.