summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-06-27 16:23:03 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-06-28 19:07:59 +0530
commit723a4b1d78274b10222b03088ff75884b78c2ced (patch)
tree21c6e7815728426948ce43815cdd8f3b3ee8d8ac
parente4a0dbfb4aa77a9d41039f5cd7144d98a6b9baed (diff)
downloadmariadb-git-723a4b1d78274b10222b03088ff75884b78c2ced.tar.gz
MDEV-17228 Encrypted temporary tables are not encrypted
- Introduce a new variable called innodb_encrypt_temporary_tables which is a boolean variable. It decides whether to encrypt the temporary tablespace. - Encrypts the temporary tablespace based on full checksum format. - Introduced a new counter to track encrypted and decrypted temporary tablespace pages. - Warnings issued if temporary table creation has conflict value with innodb_encrypt_temporary_tables - Added a new test case which reads and writes the pages from/to temporary tablespace.
-rw-r--r--mysql-test/suite/encryption/r/debug_key_management.result1
-rw-r--r--mysql-test/suite/encryption/r/innodb_encrypt_log.result2
-rw-r--r--mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result19
-rw-r--r--mysql-test/suite/encryption/r/innodb_encryption.result2
-rw-r--r--mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.opt2
-rw-r--r--mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test23
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result14
-rw-r--r--storage/innobase/buf/buf0buf.cc149
-rw-r--r--storage/innobase/buf/buf0dblwr.cc14
-rw-r--r--storage/innobase/handler/ha_innodb.cc28
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc19
-rw-r--r--storage/innobase/include/buf0buf.h6
-rw-r--r--storage/innobase/include/log0crypt.h8
-rw-r--r--storage/innobase/include/srv0srv.h15
-rw-r--r--storage/innobase/log/log0crypt.cc20
-rw-r--r--storage/innobase/row/row0log.cc9
-rw-r--r--storage/innobase/row/row0merge.cc4
-rw-r--r--storage/innobase/srv/srv0srv.cc9
-rw-r--r--storage/innobase/srv/srv0start.cc8
19 files changed, 280 insertions, 72 deletions
diff --git a/mysql-test/suite/encryption/r/debug_key_management.result b/mysql-test/suite/encryption/r/debug_key_management.result
index 02e05b4d221..75e2629c1d6 100644
--- a/mysql-test/suite/encryption/r/debug_key_management.result
+++ b/mysql-test/suite/encryption/r/debug_key_management.result
@@ -3,6 +3,7 @@ show variables like 'innodb_encrypt%';
Variable_name Value
innodb_encrypt_log ON
innodb_encrypt_tables ON
+innodb_encrypt_temporary_tables OFF
innodb_encryption_rotate_key_age 2
innodb_encryption_rotation_iops 100
innodb_encryption_threads 4
diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_log.result b/mysql-test/suite/encryption/r/innodb_encrypt_log.result
index 0663890c685..b999e8cb34a 100644
--- a/mysql-test/suite/encryption/r/innodb_encrypt_log.result
+++ b/mysql-test/suite/encryption/r/innodb_encrypt_log.result
@@ -22,6 +22,8 @@ key (col_int_key),
key (col_char_key)
) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
CREATE TEMPORARY TABLE t LIKE t0;
+Warnings:
+Warning 1478 Ignoring encryption parameter during temporary table creation.
INSERT INTO t VALUES
(NULL,1,1,'private','secret'),(NULL,2,2,'sacred','success'),
(NULL,3,3,'story','secure'),(NULL,4,4,'security','sacrament');
diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result
new file mode 100644
index 00000000000..9a291ae1354
--- /dev/null
+++ b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result
@@ -0,0 +1,19 @@
+SELECT variable_value into @old_encrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted';
+SELECT variable_value into @old_decrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted';
+CREATE TEMPORARY TABLE t1(f1 CHAR(200), f2 CHAR(200)) ENGINE=InnoDB;
+INSERT INTO t1 (f1,f2) SELECT '', '' FROM seq_1_to_8192;
+CREATE TEMPORARY TABLE t2(f1 CHAR(100), f2 CHAR(200), f3 CHAR(200))ENGINE=InnoDB;
+INSERT INTO t2 (f1,f2,f3) SELECT '', '', '' FROM seq_1_to_8192;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+8192
+SELECT variable_value > @old_encrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted';
+variable_value > @old_encrypted
+1
+SELECT variable_value > @old_decrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted';
+variable_value > @old_decrypted
+1
diff --git a/mysql-test/suite/encryption/r/innodb_encryption.result b/mysql-test/suite/encryption/r/innodb_encryption.result
index 7b7601a289c..75614c6b88c 100644
--- a/mysql-test/suite/encryption/r/innodb_encryption.result
+++ b/mysql-test/suite/encryption/r/innodb_encryption.result
@@ -3,6 +3,7 @@ SHOW VARIABLES LIKE 'innodb_encrypt%';
Variable_name Value
innodb_encrypt_log ON
innodb_encrypt_tables ON
+innodb_encrypt_temporary_tables OFF
innodb_encryption_rotate_key_age 15
innodb_encryption_rotation_iops 100
innodb_encryption_threads 4
@@ -57,6 +58,7 @@ SHOW VARIABLES LIKE 'innodb_encrypt%';
Variable_name Value
innodb_encrypt_log ON
innodb_encrypt_tables OFF
+innodb_encrypt_temporary_tables OFF
innodb_encryption_rotate_key_age 15
innodb_encryption_rotation_iops 100
innodb_encryption_threads 0
diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.opt b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.opt
new file mode 100644
index 00000000000..70797302d01
--- /dev/null
+++ b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.opt
@@ -0,0 +1,2 @@
+--innodb_buffer_pool_size=5M
+--innodb_encrypt_temporary_tables=1
diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test
new file mode 100644
index 00000000000..6c16afa28f4
--- /dev/null
+++ b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test
@@ -0,0 +1,23 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+--source include/have_file_key_management_plugin.inc
+
+SELECT variable_value into @old_encrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted';
+
+SELECT variable_value into @old_decrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted';
+
+CREATE TEMPORARY TABLE t1(f1 CHAR(200), f2 CHAR(200)) ENGINE=InnoDB;
+INSERT INTO t1 (f1,f2) SELECT '', '' FROM seq_1_to_8192;
+
+CREATE TEMPORARY TABLE t2(f1 CHAR(100), f2 CHAR(200), f3 CHAR(200))ENGINE=InnoDB;
+INSERT INTO t2 (f1,f2,f3) SELECT '', '', '' FROM seq_1_to_8192;
+
+SELECT COUNT(*) FROM t1;
+SELECT variable_value > @old_encrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted';
+
+SELECT variable_value > @old_decrypted FROM information_schema.global_status
+WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted';
+--source include/restart_mysqld.inc
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index e9fc3693889..fd1dfc56621 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -1028,6 +1028,20 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON,FORCE
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
+VARIABLE_NAME INNODB_ENCRYPT_TEMPORARY_TABLES
+SESSION_VALUE NULL
+GLOBAL_VALUE OFF
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE OFF
+VARIABLE_SCOPE GLOBAL
+VARIABLE_TYPE BOOLEAN
+VARIABLE_COMMENT Enrypt the temporary table data.
+NUMERIC_MIN_VALUE NULL
+NUMERIC_MAX_VALUE NULL
+NUMERIC_BLOCK_SIZE NULL
+ENUM_VALUE_LIST OFF,ON
+READ_ONLY YES
+COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_FAKE_CHANGES
SESSION_VALUE OFF
GLOBAL_VALUE OFF
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 644d033e1b7..1840066707f 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -60,6 +60,7 @@ Created 11/5/1995 Heikki Tuuri
#include "dict0dict.h"
#include "log0recv.h"
#include "srv0mon.h"
+#include "log0crypt.h"
#endif /* !UNIV_INNOCHECKSUM */
#include "page0zip.h"
#include "sync0sync.h"
@@ -476,6 +477,45 @@ buf_pool_register_chunk(
chunk->blocks->frame, chunk));
}
+/** Decrypt a page for temporary tablespace.
+@param[in,out] tmp_frame Temporary buffer
+@param[in] src_frame Page to decrypt
+@return true if temporary tablespace decrypted, false if not */
+static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame)
+{
+ if (buf_page_is_zeroes(src_frame, srv_page_size)) {
+ return true;
+ }
+
+ /* read space & lsn */
+ uint header_len = FIL_PAGE_DATA;
+
+ /* Copy FIL page header, it is not encrypted */
+ memcpy(tmp_frame, src_frame, header_len);
+
+ /* Calculate the offset where decryption starts */
+ const byte* src = src_frame + header_len;
+ byte* dst = tmp_frame + header_len;
+ uint srclen = uint(srv_page_size)
+ - header_len - FIL_PAGE_DATA_END;
+ ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
+
+ if (!log_tmp_block_decrypt(src, srclen, dst,
+ (offset * srv_page_size))) {
+ return false;
+ }
+
+ memcpy(tmp_frame + srv_page_size - FIL_PAGE_DATA_END,
+ src_frame + srv_page_size - FIL_PAGE_DATA_END,
+ FIL_PAGE_DATA_END);
+
+ memcpy(src_frame, tmp_frame, srv_page_size);
+ srv_stats.pages_decrypted.inc();
+ srv_stats.n_temp_blocks_decrypted.inc();
+
+ return true; /* page was decrypted */
+}
+
/** Decrypt a page.
@param[in,out] bpage Page control block
@param[in,out] space tablespace
@@ -495,6 +535,22 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
return (true);
}
+ if (space->purpose == FIL_TYPE_TEMPORARY
+ && innodb_encrypt_temporary_tables) {
+ buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool);
+ buf_tmp_reserve_crypt_buf(slot);
+
+ if (!buf_tmp_page_decrypt(slot->crypt_buf, dst_frame)) {
+ slot->release();
+ ib::error() << "Encrypted page " << bpage->id
+ << " in file " << space->chain.start->name;
+ return false;
+ }
+
+ slot->release();
+ return true;
+ }
+
/* Page is encrypted if encryption information is found from
tablespace and page contains used key_version. This is true
also for pages first compressed and then encrypted. */
@@ -923,6 +979,22 @@ static uint32_t buf_page_check_crc32(const byte* page, uint32_t checksum)
# define buf_page_check_crc32(page, checksum) buf_calc_page_crc32(page)
#endif /* INNODB_BUG_ENDIAN_CRC32 */
+/** Check if a page is all zeroes.
+@param[in] read_buf database page
+@param[in] page_size page frame size
+@return whether the page is all zeroes */
+bool buf_page_is_zeroes(const void* read_buf, size_t page_size)
+{
+ const ulint* b = reinterpret_cast<const ulint*>(read_buf);
+ const ulint* const e = b + page_size / sizeof *b;
+ do {
+ if (*b++) {
+ return false;
+ }
+ } while (b != e);
+ return true;
+}
+
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
@@ -7281,6 +7353,44 @@ operator<<(
return(out);
}
+/** Encrypt a buffer of temporary tablespace
+@param[in] offset Page offset
+@param[in] src_frame Page to encrypt
+@param[in,out] dst_frame Output buffer
+@return encrypted buffer or NULL */
+static byte* buf_tmp_page_encrypt(
+ ulint offset,
+ byte* src_frame,
+ byte* dst_frame)
+{
+ uint header_len = FIL_PAGE_DATA;
+ /* FIL page header is not encrypted */
+ memcpy(dst_frame, src_frame, header_len);
+
+ /* Calculate the start offset in a page */
+ uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END;
+ uint srclen = srv_page_size - unencrypted_bytes;
+ const byte* src = src_frame + header_len;
+ byte* dst = dst_frame + header_len;
+
+ if (!log_tmp_block_encrypt(src, srclen, dst, (offset * srv_page_size),
+ true)) {
+ return NULL;
+ }
+
+ memcpy(dst_frame + srv_page_size - FIL_PAGE_DATA_END,
+ src_frame + srv_page_size - FIL_PAGE_DATA_END,
+ FIL_PAGE_DATA_END);
+
+ /* Handle post encryption checksum */
+ mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
+ buf_calc_page_crc32(dst_frame));
+
+ srv_stats.pages_encrypted.inc();
+ srv_stats.n_temp_blocks_encrypted.inc();
+ return dst_frame;
+}
+
/** Encryption and page_compression hook that is called just before
a page is written to disk.
@param[in,out] space tablespace
@@ -7314,13 +7424,21 @@ buf_page_encrypt_before_write(
fil_space_crypt_t* crypt_data = space->crypt_data;
- const bool encrypted = crypt_data
- && !crypt_data->not_encrypted()
- && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
- && (!crypt_data->is_default_encryption()
- || srv_encrypt_tables);
+ bool encrypted, page_compressed;
+
+ if (space->purpose == FIL_TYPE_TEMPORARY) {
+ ut_ad(!crypt_data);
+ encrypted = innodb_encrypt_temporary_tables;
+ page_compressed = false;
+ } else {
+ encrypted = crypt_data
+ && !crypt_data->not_encrypted()
+ && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
+ && (!crypt_data->is_default_encryption()
+ || srv_encrypt_tables);
- bool page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
+ page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
+ }
if (!encrypted && !page_compressed) {
/* No need to encrypt or page compress the page.
@@ -7341,18 +7459,25 @@ buf_page_encrypt_before_write(
if (!page_compressed) {
not_compressed:
- /* Encrypt page content */
- byte* tmp = fil_space_encrypt(space,
- bpage->id.page_no(),
- bpage->newest_modification,
- src_frame,
- dst_frame);
+ byte* tmp;
+ if (space->purpose == FIL_TYPE_TEMPORARY) {
+ /* Encrypt temporary tablespace page content */
+ tmp = buf_tmp_page_encrypt(bpage->id.page_no(),
+ src_frame, dst_frame);
+ } else {
+ /* Encrypt page content */
+ tmp = fil_space_encrypt(
+ space, bpage->id.page_no(),
+ bpage->newest_modification,
+ src_frame, dst_frame);
+ }
bpage->real_size = UNIV_PAGE_SIZE;
slot->out_buf = dst_frame = tmp;
ut_d(fil_page_type_validate(tmp));
} else {
+ ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
/* First we compress the page content */
buf_tmp_reserve_compression_buf(slot);
byte* tmp = slot->comp_buf;
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 64d34ad7d59..8410a753699 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -338,20 +338,6 @@ too_small:
goto start_again;
}
-/** Check if a page is all zeroes.
-@param[in] read_buf database page
-@param[in] page_size page frame size
-@return whether the page is all zeroes */
-static bool buf_page_is_zeroes(const byte* read_buf, size_t page_size)
-{
- for (ulint i = 0; i < page_size; i++) {
- if (read_buf[i] != 0) {
- return false;
- }
- }
- return true;
-}
-
/**
At database startup initializes the doublewrite buffer memory structure if
we already have a doublewrite buffer created in the data files. If we are
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c5ee609da20..50429890669 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1194,6 +1194,12 @@ static SHOW_VAR innodb_status_variables[]= {
{"encryption_n_rowlog_blocks_decrypted",
(char*)&export_vars.innodb_n_rowlog_blocks_decrypted,
SHOW_LONGLONG},
+ {"encryption_n_temp_blocks_encrypted",
+ (char*)&export_vars.innodb_n_temp_blocks_encrypted,
+ SHOW_LONGLONG},
+ {"encryption_n_temp_blocks_decrypted",
+ (char*)&export_vars.innodb_n_temp_blocks_decrypted,
+ SHOW_LONGLONG},
/* scrubing */
{"scrub_background_page_reorganizations",
@@ -3931,7 +3937,8 @@ innobase_init(
}
#endif
- if ((srv_encrypt_tables || srv_encrypt_log)
+ if ((srv_encrypt_tables || srv_encrypt_log
+ || innodb_encrypt_temporary_tables)
&& !encryption_key_id_exists(FIL_DEFAULT_ENCRYPTION_KEY)) {
sql_print_error("InnoDB: cannot enable encryption, "
"encryption plugin is not available");
@@ -11270,7 +11277,18 @@ err_col:
Given that temp table lifetime is limited to connection/server lifetime
on re-start we don't need to restore temp-table and so no entry is
needed in SYSTEM tables. */
- if (dict_table_is_temporary(table)) {
+ if (table->is_temporary()) {
+
+ if ((options->encryption == 1
+ && !innodb_encrypt_temporary_tables)
+ || (options->encryption == 2
+ && innodb_encrypt_temporary_tables)) {
+ push_warning_printf(m_thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_ILLEGAL_HA_CREATE_OPTION,
+ "Ignoring encryption parameter during "
+ "temporary table creation.");
+ }
+
/* Get a new table ID */
dict_table_assign_new_id(table, m_trx);
table->space = SRV_TMP_SPACE_ID;
@@ -20993,6 +21011,11 @@ static MYSQL_SYSVAR_BOOL(instrument_semaphores, innodb_instrument_semaphores,
"DEPRECATED. This setting has no effect.",
NULL, innodb_instrument_semaphores_update, FALSE);
+static MYSQL_SYSVAR_BOOL(encrypt_temporary_tables, innodb_encrypt_temporary_tables,
+ PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
+ "Enrypt the temporary table data.",
+ NULL, NULL, false);
+
#include "ha_xtradb.h"
static struct st_mysql_sys_var* innobase_system_variables[]= {
@@ -21207,6 +21230,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(instrument_semaphores),
MYSQL_SYSVAR(buf_dump_status_frequency),
MYSQL_SYSVAR(background_thread),
+ MYSQL_SYSVAR(encrypt_temporary_tables),
/* XtraDB compatibility system variables */
#define HA_XTRADB_SYSVARS
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index f9897423c80..29a7e8908a3 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -4832,20 +4832,6 @@ ibuf_print(
mutex_exit(&ibuf_mutex);
}
-/** Check if a page is all zeroes.
-@param[in] read_buf database page
-@param[in] size page size
-@return whether the page is all zeroes */
-static bool buf_page_is_zeroes(const byte* read_buf, const page_size_t& size)
-{
- for (ulint i = 0; i < size.physical(); i++) {
- if (read_buf[i] != 0) {
- return false;
- }
- }
- return true;
-}
-
/******************************************************************//**
Checks the insert buffer bitmaps on IMPORT TABLESPACE.
@return DB_SUCCESS or error code */
@@ -4916,7 +4902,7 @@ ibuf_check_bitmap_on_import(
bitmap_page = ibuf_bitmap_get_map_page(
page_id_t(space_id, page_no), page_size, &mtr);
- if (buf_page_is_zeroes(bitmap_page, page_size)) {
+ if (buf_page_is_zeroes(bitmap_page, page_size.physical())) {
/* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be
all-zero pages. */
@@ -4929,7 +4915,8 @@ ibuf_check_bitmap_on_import(
page_size,
RW_S_LATCH, &mtr);
page_t* page = buf_block_get_frame(block);
- ut_ad(buf_page_is_zeroes(page, page_size));
+ ut_ad(buf_page_is_zeroes(
+ page, page_size.physical()));
}
#endif /* UNIV_DEBUG */
ibuf_exit(&mtr);
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index e75a1d9ec44..6bfeeb83018 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -646,6 +646,12 @@ buf_block_unfix(buf_block_t* block);
# endif /* UNIV_DEBUG */
#endif /* !UNIV_INNOCHECKSUM */
+/** Check if a page is all zeroes.
+@param[in] read_buf database page
+@param[in] page_size page frame size
+@return whether the page is all zeroes */
+bool buf_page_is_zeroes(const void* read_buf, size_t page_size);
+
/** Checks if the page is in crc32 checksum format.
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
diff --git a/storage/innobase/include/log0crypt.h b/storage/innobase/include/log0crypt.h
index 19c1493924d..7a14b022e66 100644
--- a/storage/innobase/include/log0crypt.h
+++ b/storage/innobase/include/log0crypt.h
@@ -87,7 +87,6 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt = false);
@param[in] size size of the block
@param[out] dst destination block
@param[in] offs offset to block
-@param[in] space_id tablespace id
@param[in] encrypt true=encrypt; false=decrypt
@return whether the operation succeeded */
UNIV_INTERN
@@ -97,7 +96,6 @@ log_tmp_block_encrypt(
ulint size,
byte* dst,
uint64_t offs,
- ulint space_id,
bool encrypt = true)
MY_ATTRIBUTE((warn_unused_result, nonnull));
@@ -106,7 +104,6 @@ log_tmp_block_encrypt(
@param[in] size size of the block
@param[out] dst destination block
@param[in] offs offset to block
-@param[in] space_id tablespace id
@return whether the operation succeeded */
inline
bool
@@ -114,10 +111,9 @@ log_tmp_block_decrypt(
const byte* src,
ulint size,
byte* dst,
- uint64_t offs,
- ulint space_id)
+ uint64_t offs)
{
- return(log_tmp_block_encrypt(src, size, dst, offs, space_id, false));
+ return(log_tmp_block_encrypt(src, size, dst, offs, false));
}
/** @return whether temporary files are encrypted */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 426f79d090b..9242d9af523 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -187,6 +187,12 @@ struct srv_stats_t
/** Number of spaces in keyrotation list */
ulint_ctr_64_t key_rotation_list_length;
+
+ /** Number of temporary tablespace blocks encrypted */
+ ulint_ctr_64_t n_temp_blocks_encrypted;
+
+ /** Number of temporary tablespace blocks decrypted */
+ ulint_ctr_64_t n_temp_blocks_decrypted;
};
extern const char* srv_main_thread_op_info;
@@ -499,6 +505,9 @@ extern ulong srv_max_purge_lag;
extern ulong srv_max_purge_lag_delay;
extern ulong srv_replication_delay;
+
+extern my_bool innodb_encrypt_temporary_tables;
+
/*-------------------------------------------*/
/** Modes of operation */
@@ -1066,6 +1075,12 @@ struct export_var_t{
/*!< Number of row log blocks decrypted */
ib_int64_t innodb_n_rowlog_blocks_decrypted;
+ /* Number of temporary tablespace pages encrypted */
+ ib_int64_t innodb_n_temp_blocks_encrypted;
+
+ /* Number of temporary tablespace pages decrypted */
+ ib_int64_t innodb_n_temp_blocks_decrypted;
+
ulint innodb_sec_rec_cluster_reads; /*!< srv_sec_rec_cluster_reads */
ulint innodb_sec_rec_cluster_reads_avoided;/*!< srv_sec_rec_cluster_reads_avoided */
diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc
index 352fe104181..f1297921839 100644
--- a/storage/innobase/log/log0crypt.cc
+++ b/storage/innobase/log/log0crypt.cc
@@ -60,6 +60,9 @@ struct crypt_info_t {
/** The crypt info */
static crypt_info_t info;
+/** Initialization vector used for temporary files/tablespace */
+static byte tmp_iv[MY_AES_BLOCK_SIZE];
+
/** Crypt info when upgrading from 10.1 */
static crypt_info_t infos[5 * 2];
/** First unused slot in infos[] */
@@ -195,9 +198,6 @@ UNIV_INTERN
bool
log_crypt_init()
{
- ut_ad(log_mutex_own());
- ut_ad(log_sys->is_encrypted());
-
info.key_version = encryption_key_get_latest_version(
LOG_DEFAULT_ENCRYPTION_KEY);
@@ -207,7 +207,8 @@ log_crypt_init()
return false;
}
- if (my_random_bytes(info.crypt_msg.bytes, sizeof info.crypt_msg)
+ if (my_random_bytes(tmp_iv, MY_AES_BLOCK_SIZE) != MY_AES_OK
+ || my_random_bytes(info.crypt_msg.bytes, sizeof info.crypt_msg)
!= MY_AES_OK
|| my_random_bytes(info.crypt_nonce.bytes, sizeof info.crypt_nonce)
!= MY_AES_OK) {
@@ -372,7 +373,6 @@ log_crypt_read_checkpoint_buf(const byte* buf)
@param[in] size size of the block
@param[out] dst destination block
@param[in] offs offset to block
-@param[in] space_id tablespace id
@param[in] encrypt true=encrypt; false=decrypt
@return whether the operation succeeded */
UNIV_INTERN
@@ -382,19 +382,17 @@ log_tmp_block_encrypt(
ulint size,
byte* dst,
uint64_t offs,
- ulint space_id,
bool encrypt)
{
uint dst_len;
- uint64_t aes_ctr_iv[MY_AES_BLOCK_SIZE / sizeof(uint64_t)];
- bzero(aes_ctr_iv, sizeof aes_ctr_iv);
- aes_ctr_iv[0] = space_id;
- aes_ctr_iv[1] = offs;
+ uint64_t iv[MY_AES_BLOCK_SIZE / sizeof(uint64_t)];
+ iv[0] = offs;
+ memcpy(iv + 1, tmp_iv, sizeof iv - sizeof *iv);
int rc = encryption_crypt(
src, size, dst, &dst_len,
const_cast<byte*>(info.crypt_key.bytes), sizeof info.crypt_key,
- reinterpret_cast<byte*>(aes_ctr_iv), sizeof aes_ctr_iv,
+ reinterpret_cast<byte*>(iv), sizeof iv,
encrypt
? ENCRYPTION_FLAG_ENCRYPT|ENCRYPTION_FLAG_NOPAD
: ENCRYPTION_FLAG_DECRYPT|ENCRYPTION_FLAG_NOPAD,
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 012cf8b2963..3924a07fb0f 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -385,8 +385,7 @@ row_log_online_op(
if (log_tmp_is_encrypted()) {
if (!log_tmp_block_encrypt(
buf, srv_sort_buf_size,
- log->crypt_tail, byte_offset,
- index->table->space)) {
+ log->crypt_tail, byte_offset)) {
log->error = DB_DECRYPTION_FAILED;
goto write_failed;
}
@@ -2670,8 +2669,7 @@ all_done:
if (log_tmp_is_encrypted()) {
if (!log_tmp_block_decrypt(
buf, srv_sort_buf_size,
- index->online_log->crypt_head,
- ofs, index->table->space)) {
+ index->online_log->crypt_head, ofs)) {
error = DB_DECRYPTION_FAILED;
goto func_exit;
}
@@ -3541,8 +3539,7 @@ all_done:
if (log_tmp_is_encrypted()) {
if (!log_tmp_block_decrypt(
buf, srv_sort_buf_size,
- index->online_log->crypt_head,
- ofs, index->table->space)) {
+ index->online_log->crypt_head, ofs)) {
error = DB_DECRYPTION_FAILED;
goto func_exit;
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 3f8bcb0a430..d485debfe72 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1094,7 +1094,7 @@ row_merge_read(
/* If encryption is enabled decrypt buffer */
if (success && log_tmp_is_encrypted()) {
if (!log_tmp_block_decrypt(buf, srv_sort_buf_size,
- crypt_buf, ofs, space)) {
+ crypt_buf, ofs)) {
return (FALSE);
}
@@ -1143,7 +1143,7 @@ row_merge_write(
if (!log_tmp_block_encrypt(static_cast<const byte*>(buf),
buf_len,
static_cast<byte*>(crypt_buf),
- ofs, space)) {
+ ofs)) {
return false;
}
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index a6ada6067fd..22a0c023c6d 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -450,6 +450,9 @@ my_bool srv_print_innodb_lock_monitor;
PRIMARY KEY */
my_bool srv_force_primary_key;
+/** Key version to encrypt the temporary tablespace */
+my_bool innodb_encrypt_temporary_tables;
+
/* Array of English strings describing the current state of an
i/o handler thread */
@@ -1646,6 +1649,12 @@ srv_export_innodb_status(void)
export_vars.innodb_n_rowlog_blocks_encrypted = srv_stats.n_rowlog_blocks_encrypted;
export_vars.innodb_n_rowlog_blocks_decrypted = srv_stats.n_rowlog_blocks_decrypted;
+ export_vars.innodb_n_temp_blocks_encrypted =
+ srv_stats.n_temp_blocks_encrypted;
+
+ export_vars.innodb_n_temp_blocks_decrypted =
+ srv_stats.n_temp_blocks_decrypted;
+
export_vars.innodb_defragment_compression_failures =
btr_defragment_compression_failures;
export_vars.innodb_defragment_failures = btr_defragment_failures;
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 281b7e5c583..99a8f41698e 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -491,9 +491,6 @@ create_log_files(
/* Create a log checkpoint. */
log_mutex_enter();
- if (log_sys->is_encrypted() && !log_crypt_init()) {
- return(DB_ERROR);
- }
ut_d(recv_no_log_write = false);
log_sys->lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
@@ -1923,6 +1920,11 @@ innobase_start_or_create_for_mysql()
srv_log_file_size_requested = srv_log_file_size;
+ if ((srv_encrypt_log || innodb_encrypt_temporary_tables)
+ && !log_crypt_init()) {
+ return srv_init_abort(DB_ERROR);
+ }
+
if (create_new_db) {
buf_flush_sync_all_buf_pools();