From 2330107ca886512c2f03696ce086f94beb39d70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Feb 2015 13:26:57 +0200 Subject: [PATCH 1/2] MDEV-7572: InnoDB: Assertion failure in log_init_crypt_key if file_key_management_plugin is used Fixed error handling and added disabling InnoDB redo log encryption if encryption key management plugin is not there. --- include/my_aes.h | 4 +- .../mysql/plugin_encryption_key_management.h | 2 +- ...nodb-page_encryption_log_encryption.result | 239 ++++++++++++++++++ .../innodb-page_encryption_log_encryption.opt | 2 + ...innodb-page_encryption_log_encryption.test | 152 +++++++++++ sql/encryption_keys.cc | 6 +- storage/innobase/log/log0crypt.cc | 44 +++- storage/xtradb/log/log0crypt.cc | 43 +++- 8 files changed, 467 insertions(+), 25 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-page_encryption_log_encryption.result create mode 100644 mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.opt create mode 100644 mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test diff --git a/include/my_aes.h b/include/my_aes.h index db50d35efd5df..057fa1e98602b 100644 --- a/include/my_aes.h +++ b/include/my_aes.h @@ -33,8 +33,8 @@ typedef int Crypt_result; #define AES_KEY_CREATION_FAILED -10 #define CRYPT_KEY_OK 0 -#define CRYPT_BUFFER_TO_SMALL -11; -#define CRYPT_KEY_UNKNOWN -48; +#define CRYPT_BUFFER_TO_SMALL -11 +#define CRYPT_KEY_UNKNOWN -48 /* The max block sizes of all supported algorithms */ #define MY_AES_BLOCK_SIZE 16 diff --git a/include/mysql/plugin_encryption_key_management.h b/include/mysql/plugin_encryption_key_management.h index 1ba4659196f07..af7730e5ee744 100644 --- a/include/mysql/plugin_encryption_key_management.h +++ b/include/mysql/plugin_encryption_key_management.h @@ -29,7 +29,7 @@ #define MariaDB_ENCRYPTION_KEY_MANAGEMENT_INTERFACE_VERSION 0x0100 -#define BAD_ENCRYPTION_KEY_VERSION (~0U) +#define BAD_ENCRYPTION_KEY_VERSION (UINT_MAX32) /** Encryption key management plugin descriptor diff --git a/mysql-test/suite/innodb/r/innodb-page_encryption_log_encryption.result b/mysql-test/suite/innodb/r/innodb-page_encryption_log_encryption.result new file mode 100644 index 0000000000000..62f07778d5ac3 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-page_encryption_log_encryption.result @@ -0,0 +1,239 @@ +call mtr.add_suppression("KeyID 0 not found or with error. Check the key and the log file*"); +call mtr.add_suppression("Disabling redo log encryption"); +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; +create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact page_encryption=1 page_encryption_key=1; +create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed page_encryption=1 page_encryption_key=2; +create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic page_encryption=1 page_encryption_key=3; +create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant page_encryption=1 page_encryption_key=4; +show create table innodb_compact; +Table Create Table +innodb_compact CREATE TABLE `innodb_compact` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT `page_encryption`=1 `page_encryption_key`=1 +show create table innodb_compressed; +Table Create Table +innodb_compressed CREATE TABLE `innodb_compressed` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED `page_encryption`=1 `page_encryption_key`=2 +show create table innodb_dynamic; +Table Create Table +innodb_dynamic CREATE TABLE `innodb_dynamic` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC `page_encryption`=1 `page_encryption_key`=3 +show create table innodb_redundant; +Table Create Table +innodb_redundant CREATE TABLE `innodb_redundant` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT `page_encryption`=1 `page_encryption_key`=4 +create procedure innodb_insert_proc (repeat_count int) +begin +declare current_num int; +set current_num = 0; +while current_num < repeat_count do +insert into innodb_normal values(current_num, substring(MD5(RAND()), -64)); +set current_num = current_num + 1; +end while; +end// +commit; +set autocommit=0; +call innodb_insert_proc(2000); +commit; +set autocommit=1; +insert into innodb_compact select * from innodb_normal; +insert into innodb_compressed select * from innodb_normal; +insert into innodb_dynamic select * from innodb_normal; +insert into innodb_redundant select * from innodb_normal; +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compressed where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_dynamic where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_redundant where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +variable_value >= 0 +1 +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +variable_value >= 0 +1 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; +variable_value = 0 +1 +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compressed where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_dynamic where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_redundant where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +variable_value >= 0 +1 +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +variable_value >= 0 +1 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; +variable_value = 0 +1 +alter table innodb_compact engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_compact; +Table Create Table +innodb_compact CREATE TABLE `innodb_compact` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +alter table innodb_compressed engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_compressed; +Table Create Table +innodb_compressed CREATE TABLE `innodb_compressed` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +alter table innodb_dynamic engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_dynamic; +Table Create Table +innodb_dynamic CREATE TABLE `innodb_dynamic` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +alter table innodb_redundant engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_redundant; +Table Create Table +innodb_redundant CREATE TABLE `innodb_redundant` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +show create table innodb_compact; +Table Create Table +innodb_compact CREATE TABLE `innodb_compact` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +show create table innodb_compressed; +Table Create Table +innodb_compressed CREATE TABLE `innodb_compressed` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +show create table innodb_dynamic; +Table Create Table +innodb_dynamic CREATE TABLE `innodb_dynamic` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +show create table innodb_redundant; +Table Create Table +innodb_redundant CREATE TABLE `innodb_redundant` ( + `c1` bigint(20) NOT NULL, + `b` char(200) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compressed where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_dynamic where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_redundant where c1 < 1500000; +count(*) +2000 +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +count(*) +2000 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +variable_value = 0 +1 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +variable_value = 0 +1 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; +variable_value = 0 +1 +drop procedure innodb_insert_proc; +drop table innodb_normal; +drop table innodb_compact; +drop table innodb_compressed; +drop table innodb_dynamic; +drop table innodb_redundant; diff --git a/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.opt b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.opt new file mode 100644 index 0000000000000..7cda4be1fff80 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.opt @@ -0,0 +1,2 @@ +--encryption-algorithm=aes_ctr +--innodb-encrypt-log diff --git a/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test new file mode 100644 index 0000000000000..c2f67dbe5b5e5 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test @@ -0,0 +1,152 @@ +-- source include/have_innodb.inc +-- source include/have_file_key_management_plugin.inc + +--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 + +call mtr.add_suppression("KeyID 0 not found or with error. Check the key and the log file*"); +call mtr.add_suppression("Disabling redo log encryption"); + +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; + +create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; +create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact page_encryption=1 page_encryption_key=1; +create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed page_encryption=1 page_encryption_key=2; +create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic page_encryption=1 page_encryption_key=3; +create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant page_encryption=1 page_encryption_key=4; + +show create table innodb_compact; +show create table innodb_compressed; +show create table innodb_dynamic; +show create table innodb_redundant; + +delimiter //; +create procedure innodb_insert_proc (repeat_count int) +begin + declare current_num int; + set current_num = 0; + while current_num < repeat_count do + insert into innodb_normal values(current_num, substring(MD5(RAND()), -64)); + set current_num = current_num + 1; + end while; +end// +delimiter ;// +commit; + +set autocommit=0; +call innodb_insert_proc(2000); +commit; +set autocommit=1; + +insert into innodb_compact select * from innodb_normal; +insert into innodb_compressed select * from innodb_normal; +insert into innodb_dynamic select * from innodb_normal; +insert into innodb_redundant select * from innodb_normal; + +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +select count(*) from innodb_compressed where c1 < 1500000; +select count(*) from innodb_dynamic where c1 < 1500000; +select count(*) from innodb_redundant where c1 < 1500000; +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; + +# Note there that these variables are updated only when real I/O is done, thus they are not reliable +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; + +--source include/restart_mysqld.inc + +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; + +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +select count(*) from innodb_compressed where c1 < 1500000; +select count(*) from innodb_dynamic where c1 < 1500000; +select count(*) from innodb_redundant where c1 < 1500000; +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; + +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +SELECT variable_value >= 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; + +alter table innodb_compact engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_compact; +alter table innodb_compressed engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_compressed; +alter table innodb_dynamic engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_dynamic; +alter table innodb_redundant engine=innodb page_encryption=DEFAULT page_encryption_key=DEFAULT; +show create table innodb_redundant; + +--source include/restart_mysqld.inc + +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; + +show create table innodb_compact; +show create table innodb_compressed; +show create table innodb_dynamic; +show create table innodb_redundant; + +update innodb_normal set c1 = c1 +1; +update innodb_compact set c1 = c1 + 1; +update innodb_compressed set c1 = c1 + 1; +update innodb_dynamic set c1 = c1 + 1; +update innodb_redundant set c1 = c1 + 1; +select count(*) from innodb_compact where c1 < 1500000; +select count(*) from innodb_compressed where c1 < 1500000; +select count(*) from innodb_dynamic where c1 < 1500000; +select count(*) from innodb_redundant where c1 < 1500000; +select count(*) from innodb_compact t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_dynamic t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_compressed t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; +select count(*) from innodb_redundant t1, innodb_normal t2 where +t1.c1 = t2.c1 and t1.b = t2.b; + +# After alter+restart these should be 0 +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encrypted'; +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decrypted'; +SELECT variable_value = 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_encryption_error'; + +drop procedure innodb_insert_proc; +drop table innodb_normal; +drop table innodb_compact; +drop table innodb_compressed; +drop table innodb_dynamic; +drop table innodb_redundant; + +# reset system +--disable_query_log +EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; +EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; +--enable_query_log diff --git a/sql/encryption_keys.cc b/sql/encryption_keys.cc index 835ecd470cfb9..07a5d346a05e3 100644 --- a/sql/encryption_keys.cc +++ b/sql/encryption_keys.cc @@ -13,7 +13,7 @@ uint opt_debug_encryption_key_version = 0; static plugin_ref encryption_key_manager= 0; static struct st_mariadb_encryption_key_management *handle; -uint get_latest_encryption_key_version() +unsigned int get_latest_encryption_key_version() { #ifndef DBUG_OFF if (debug_use_static_encryption_keys) @@ -31,7 +31,7 @@ uint get_latest_encryption_key_version() return BAD_ENCRYPTION_KEY_VERSION; } -uint has_encryption_key(uint version) +unsigned int has_encryption_key(uint version) { if (encryption_key_manager) return handle->has_key_version(version); @@ -39,7 +39,7 @@ uint has_encryption_key(uint version) return 0; } -uint get_encryption_key_size(uint version) +unsigned int get_encryption_key_size(uint version) { if (encryption_key_manager) return handle->get_key_size(version); diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index 17e1404777e2a..3d4be2e7792bb 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -7,11 +7,13 @@ Created 11/25/2013 Minli Zhu #include "m_string.h" #include "log0crypt.h" #include - +#include #include "log0log.h" #include "srv0start.h" // for srv_start_lsn #include "log0recv.h" // for recv_sys +#include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION + /* If true, enable redo log encryption. */ UNIV_INTERN my_bool srv_encrypt_log = FALSE; /* @@ -50,7 +52,7 @@ log_init_crypt_msg_and_nonce(void) if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK) { fprintf(stderr, - "\nInnodb redo log crypto: generate " + "\nInnoDB redo log crypto: generate " "%u-byte random number as crypto msg failed.\n", PURPOSE_BYTE_LEN); abort(); @@ -59,7 +61,7 @@ log_init_crypt_msg_and_nonce(void) if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) { fprintf(stderr, - "\nInnodb redo log crypto: generate " + "\nInnoDB redo log crypto: generate " "%u-byte random number as AES_CTR nonce failed.\n", MY_AES_BLOCK_SIZE); abort(); @@ -78,7 +80,7 @@ log_init_crypt_key( { if (crypt_ver == UNENCRYPTED_KEY_VER) { - fprintf(stderr, "\nInnodb redo log crypto: unencrypted key ver.\n\n"); + fprintf(stderr, "\nInnoDB redo log crypto: unencrypted key ver.\n\n"); memset(key, 0, MY_AES_BLOCK_SIZE); return; } @@ -86,7 +88,7 @@ log_init_crypt_key( if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) { fprintf(stderr, - "\nInnodb redo log crypto: msg type mismatched. " + "\nInnoDB redo log crypto: msg type mismatched. " "Expected: %x; Actual: %x\n", redo_log_purpose_byte, crypt_msg[PURPOSE_BYTE_OFFSET]); abort(); @@ -96,7 +98,7 @@ log_init_crypt_key( if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE)) { fprintf(stderr, - "\nInnodb redo log crypto: getting mysqld crypto key " + "\nInnoDB redo log crypto: getting mysqld crypto key " "from key version failed.\n"); abort(); } @@ -112,7 +114,7 @@ log_init_crypt_key( if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) { fprintf(stderr, - "\nInnodb redo log crypto: getting redo log crypto key " + "\nInnoDB redo log crypto: getting redo log crypto key " "failed.\n"); abort(); } @@ -233,13 +235,35 @@ log_crypt_set_ver_and_key( uint& key_ver, /*!< out: latest key version */ byte* crypt_key) /*!< out: crypto key */ { - if (!srv_encrypt_log || - (key_ver = get_latest_encryption_key_version()) == UNENCRYPTED_KEY_VER) - { + bool encrypted; + + if (srv_encrypt_log) { + unsigned int vkey; + vkey = get_latest_encryption_key_version(); + encrypted = true; + + if (vkey == UNENCRYPTED_KEY_VER || + vkey == BAD_ENCRYPTION_KEY_VERSION || + vkey == (unsigned int)CRYPT_KEY_UNKNOWN) { + encrypted = false; + + fprintf(stderr, "\nInnoDB redo log crypto: Can't initialize to key version %du\n", + key_ver); + fprintf(stderr, "InnoDB: [Warning] Disabling redo log encryption\n"); + srv_encrypt_log = FALSE; + } else { + key_ver = vkey; + } + } else { + encrypted = false; + } + + if (!encrypted) { key_ver = UNENCRYPTED_KEY_VER; memset(crypt_key, 0, MY_AES_BLOCK_SIZE); return; } + log_init_crypt_key(redo_log_crypt_msg, key_ver, crypt_key); } diff --git a/storage/xtradb/log/log0crypt.cc b/storage/xtradb/log/log0crypt.cc index 17e1404777e2a..be2f77ebc7214 100644 --- a/storage/xtradb/log/log0crypt.cc +++ b/storage/xtradb/log/log0crypt.cc @@ -7,11 +7,14 @@ Created 11/25/2013 Minli Zhu #include "m_string.h" #include "log0crypt.h" #include +#include #include "log0log.h" #include "srv0start.h" // for srv_start_lsn #include "log0recv.h" // for recv_sys +#include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION + /* If true, enable redo log encryption. */ UNIV_INTERN my_bool srv_encrypt_log = FALSE; /* @@ -50,7 +53,7 @@ log_init_crypt_msg_and_nonce(void) if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK) { fprintf(stderr, - "\nInnodb redo log crypto: generate " + "\nInnoDB redo log crypto: generate " "%u-byte random number as crypto msg failed.\n", PURPOSE_BYTE_LEN); abort(); @@ -59,7 +62,7 @@ log_init_crypt_msg_and_nonce(void) if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) { fprintf(stderr, - "\nInnodb redo log crypto: generate " + "\nInnoDB redo log crypto: generate " "%u-byte random number as AES_CTR nonce failed.\n", MY_AES_BLOCK_SIZE); abort(); @@ -78,7 +81,7 @@ log_init_crypt_key( { if (crypt_ver == UNENCRYPTED_KEY_VER) { - fprintf(stderr, "\nInnodb redo log crypto: unencrypted key ver.\n\n"); + fprintf(stderr, "\nInnoDB redo log crypto: unencrypted key ver.\n\n"); memset(key, 0, MY_AES_BLOCK_SIZE); return; } @@ -86,7 +89,7 @@ log_init_crypt_key( if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) { fprintf(stderr, - "\nInnodb redo log crypto: msg type mismatched. " + "\nInnoDB redo log crypto: msg type mismatched. " "Expected: %x; Actual: %x\n", redo_log_purpose_byte, crypt_msg[PURPOSE_BYTE_OFFSET]); abort(); @@ -96,7 +99,7 @@ log_init_crypt_key( if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE)) { fprintf(stderr, - "\nInnodb redo log crypto: getting mysqld crypto key " + "\nInnoDB redo log crypto: getting mysqld crypto key " "from key version failed.\n"); abort(); } @@ -112,7 +115,7 @@ log_init_crypt_key( if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) { fprintf(stderr, - "\nInnodb redo log crypto: getting redo log crypto key " + "\nInnoDB redo log crypto: getting redo log crypto key " "failed.\n"); abort(); } @@ -233,13 +236,35 @@ log_crypt_set_ver_and_key( uint& key_ver, /*!< out: latest key version */ byte* crypt_key) /*!< out: crypto key */ { - if (!srv_encrypt_log || - (key_ver = get_latest_encryption_key_version()) == UNENCRYPTED_KEY_VER) - { + bool encrypted; + + if (srv_encrypt_log) { + unsigned int vkey; + vkey = get_latest_encryption_key_version(); + encrypted = true; + + if (vkey == UNENCRYPTED_KEY_VER || + vkey == BAD_ENCRYPTION_KEY_VERSION || + vkey == (unsigned int)CRYPT_KEY_UNKNOWN) { + encrypted = false; + + fprintf(stderr, "\nInnoDB redo log crypto: Can't initialize to key version %du\n", + key_ver); + fprintf(stderr, "InnoDB: [Warning] Disabling redo log encryption\n"); + srv_encrypt_log = FALSE; + } else { + key_ver = vkey; + } + } else { + encrypted = false; + } + + if (!encrypted) { key_ver = UNENCRYPTED_KEY_VER; memset(crypt_key, 0, MY_AES_BLOCK_SIZE); return; } + log_init_crypt_key(redo_log_crypt_msg, key_ver, crypt_key); } From f37b857f803fcc0ae8c3e66a57849df76ffdacee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 26 Feb 2015 17:19:51 +0200 Subject: [PATCH 2/2] Fix test case. --- .../suite/innodb/t/innodb-page_encryption_log_encryption.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test index c2f67dbe5b5e5..80e3447870ea9 100644 --- a/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test +++ b/mysql-test/suite/innodb/t/innodb-page_encryption_log_encryption.test @@ -8,6 +8,8 @@ let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; call mtr.add_suppression("KeyID 0 not found or with error. Check the key and the log file*"); call mtr.add_suppression("Disabling redo log encryption"); +call mtr.add_suppression("InnoDB: [Warning] Disabling redo log encryption"); +call mtr.add_suppression("InnoDB:*"); SET GLOBAL innodb_file_format = `Barracuda`; SET GLOBAL innodb_file_per_table = ON;