diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-11-12 12:05:42 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-11-14 10:19:10 +0200 |
commit | 2eba5d6eabdd3f82bcc9859bb9333e1909ec0852 (patch) | |
tree | 3d8d8be35cc31520b438ae29b04b64c3b1198ed8 | |
parent | 59c82dde09984d10f16417c9c82cd759f81d770c (diff) | |
download | mariadb-git-bb-10.1-MDEV-17229.tar.gz |
MDEV-17229: Encryption threads ignore innodb_default_encryption_key_idbb-10.1-MDEV-17229
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
in the 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_default_encryption_key_id=999 not available in the 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 in the encryption plugin. This can be seen on server error log e.g.
[ERROR] innodb_default_encryption_key_id=999 is unavailable in the 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 engine=innodb;
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=1;
CREATE TABLE t1 (a int) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=10;
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) engine=innodb 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) engine=innodb 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) engine=innodb;
will use currently set global encryption key_id when encryption threads
does key rotation from unencrypted to encrypted state.
Changes
innodb-checksum-algorithm
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.
fil_crypt_start_encrypting_space()
Use global default encryption key_id when creating encryption meta data.
innodb_default_encryption_key_id_validate()
New function to validate that used key_id is found from encryption plugin.
innodb_default_encryption_key_id()
New accessessor function for default encryption key_id.
innobase_init()
Do not allow server startup using encryption key_id that is not found
from encryption plugin.
-rw-r--r-- | mysql-test/suite/encryption/r/innodb-encryption-alter.result | 35 | ||||
-rw-r--r-- | mysql-test/suite/encryption/r/innodb_encryption_default_key.result | 54 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-encryption-alter.test | 12 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-redo-badkey.opt | 2 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-redo-badkey.test | 2 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-redo-nokeys.opt | 2 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-redo-nokeys.test | 2 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb_encryption_default_key.opt | 2 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb_encryption_default_key.test | 79 | ||||
-rw-r--r-- | storage/innobase/fil/fil0crypt.cc | 5 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 70 | ||||
-rw-r--r-- | storage/innobase/include/ha_prototypes.h | 3 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0crypt.cc | 5 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 70 | ||||
-rw-r--r-- | storage/xtradb/include/ha_prototypes.h | 3 |
15 files changed, 308 insertions, 38 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-encryption-alter.result b/mysql-test/suite/encryption/r/innodb-encryption-alter.result index 5245d1da7d0..e1ff9eacfbe 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-alter.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-alter.result @@ -4,23 +4,28 @@ SET GLOBAL innodb_encrypt_tables = ON; 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; Warnings: -Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 4 when encryption is disabled +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; @@ -39,16 +44,14 @@ t1 CREATE TABLE `t1` ( `c` varchar(256) DEFAULT NULL, PRIMARY KEY (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTION_KEY_ID`=4 +set innodb_default_encryption_key_id = 1; 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; Level Code Message Warning 140 InnoDB: ENCRYPTION_KEY_ID 99 not available Error 1478 Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' -set innodb_default_encryption_key_id = 1; drop table t1,t2; SET GLOBAL innodb_encrypt_tables=OFF; CREATE TABLE t1 (a int not null primary key) engine=innodb; 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..6ad1f621cb7 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb_encryption_default_key.result @@ -0,0 +1,54 @@ +call mtr.add_suppression("innodb_default_encryption_key_id=999 is unavailable in the 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 = -1; +ERROR 42000: Variable 'innodb_default_encryption_key_id' can't be set to the value of '-1' +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'innodb_default_encryption_key_id' can't be set to the value of '-1' +SET GLOBAL innodb_default_encryption_key_id = 4294967296; +ERROR 42000: Variable 'innodb_default_encryption_key_id' can't be set to the value of '4294967296' +SHOW WARNINGS; +Level Code Message +Error 1231 Variable 'innodb_default_encryption_key_id' can't be set to the value of '4294967296' +SET GLOBAL innodb_default_encryption_key_id = 'k'; +ERROR 42000: Incorrect argument type to variable 'innodb_default_encryption_key_id' +SHOW WARNINGS; +Level Code Message +Error 1232 Incorrect argument type to variable 'innodb_default_encryption_key_id' +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_default_encryption_key_id=999 not available in the 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-encryption-alter.test b/mysql-test/suite/encryption/t/innodb-encryption-alter.test index 9465226dd96..fdd2dd86805 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-alter.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-alter.test @@ -19,25 +19,25 @@ 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; DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; SHOW CREATE TABLE t1; +set innodb_default_encryption_key_id = 1; CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=1; --error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ENCRYPTION_KEY_ID=99; SHOW WARNINGS; -set innodb_default_encryption_key_id = 1; - --disable_warnings --disable_query_log 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..0f077707f98 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encryption_default_key.test @@ -0,0 +1,79 @@ +-- source include/have_innodb.inc +-- source include/have_file_key_management_plugin.inc +-- source include/not_embedded.inc + +call mtr.add_suppression("innodb_default_encryption_key_id=999 is unavailable in the 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; + +# +# Test limits +# +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL innodb_default_encryption_key_id = -1; +SHOW WARNINGS; +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL innodb_default_encryption_key_id = 4294967296; +SHOW WARNINGS; +--error ER_WRONG_TYPE_FOR_VAR +SET GLOBAL innodb_default_encryption_key_id = 'k'; +SHOW WARNINGS; + +# 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..3e66bfee884 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, + innodb_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 a0e6a385b37..d0ef42f7d82 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -685,11 +685,64 @@ 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; + } + + if (key_id_buf < 1 || key_id_buf > UINT_MAX32) { + /* Out of range */ + 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_default_encryption_key_id=%u not available in the 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); +/** @return innodb_default_encryption_key_id */ +UNIV_INTERN uint innodb_default_encryption_key_id() +{ + 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 +3481,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 +3646,14 @@ 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_default_encryption_key_id=%u is " + "unavailable in the encryption plugin", key_id); + goto error; + } + os_innodb_umask = (ulint) my_umask; /* First calculate the default path for innodb_data_home_dir etc., @@ -11937,12 +11999,12 @@ 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 != THDVAR(thd, default_encryption_key_id)) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, - "InnoDB: Ignored ENCRYPTION_KEY_ID %u when encryption is disabled", + "InnoDB: Ignored ENCRYPTION_KEY_ID=%u when encryption is disabled", (uint)options->encryption_key_id ); options->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index be423c8bd01..84d5652ce64 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -348,6 +348,9 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** @return innodb_default_encryption_key_id */ +UNIV_INTERN uint innodb_default_encryption_key_id(); + /** 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..3e66bfee884 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, + innodb_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 d01977f072b..c9da3e19623 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -686,11 +686,64 @@ 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; + } + + if (key_id_buf < 1 || key_id_buf > UINT_MAX32) { + /* Out of range */ + 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_default_encryption_key_id=%u not available in the 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); +/** @return innodb_default_encryption_key_id */ +UNIV_INTERN uint innodb_default_encryption_key_id() +{ + 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 +3892,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 +4096,14 @@ 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_default_encryption_key_id=%u is " + "unavailable in the encryption plugin", key_id); + goto error; + } + os_innodb_umask = (ulint) my_umask; /* First calculate the default path for innodb_data_home_dir etc., @@ -12504,12 +12566,12 @@ 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 != THDVAR(thd, default_encryption_key_id)) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, - "InnoDB: Ignored ENCRYPTION_KEY_ID %u when encryption is disabled", + "InnoDB: Ignored ENCRYPTION_KEY_ID=%u when encryption is disabled", (uint)options->encryption_key_id ); options->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 3f3c4f28ced..60b36440a8b 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -366,6 +366,9 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** @return innodb_default_encryption_key_id */ +UNIV_INTERN uint innodb_default_encryption_key_id(); + /** Get status of innodb_tmpdir. @param[in] thd thread handle, or NULL to query the global innodb_tmpdir. |