mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -3,6 +3,7 @@ show variables like 'innodb_encrypt%';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
innodb_encrypt_log ON
|
innodb_encrypt_log ON
|
||||||
innodb_encrypt_tables ON
|
innodb_encrypt_tables ON
|
||||||
|
innodb_encrypt_temporary_tables OFF
|
||||||
innodb_encryption_rotate_key_age 2
|
innodb_encryption_rotate_key_age 2
|
||||||
innodb_encryption_rotation_iops 100
|
innodb_encryption_rotation_iops 100
|
||||||
innodb_encryption_threads 4
|
innodb_encryption_threads 4
|
||||||
|
@ -22,6 +22,8 @@ key (col_int_key),
|
|||||||
key (col_char_key)
|
key (col_char_key)
|
||||||
) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
|
) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1;
|
||||||
CREATE TEMPORARY TABLE t LIKE t0;
|
CREATE TEMPORARY TABLE t LIKE t0;
|
||||||
|
Warnings:
|
||||||
|
Warning 1478 Ignoring encryption parameter during temporary table creation.
|
||||||
INSERT INTO t VALUES
|
INSERT INTO t VALUES
|
||||||
(NULL,1,1,'private','secret'),(NULL,2,2,'sacred','success'),
|
(NULL,1,1,'private','secret'),(NULL,2,2,'sacred','success'),
|
||||||
(NULL,3,3,'story','secure'),(NULL,4,4,'security','sacrament');
|
(NULL,3,3,'story','secure'),(NULL,4,4,'security','sacrament');
|
||||||
|
@ -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
|
@ -3,6 +3,7 @@ SHOW VARIABLES LIKE 'innodb_encrypt%';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
innodb_encrypt_log ON
|
innodb_encrypt_log ON
|
||||||
innodb_encrypt_tables ON
|
innodb_encrypt_tables ON
|
||||||
|
innodb_encrypt_temporary_tables OFF
|
||||||
innodb_encryption_rotate_key_age 15
|
innodb_encryption_rotate_key_age 15
|
||||||
innodb_encryption_rotation_iops 100
|
innodb_encryption_rotation_iops 100
|
||||||
innodb_encryption_threads 4
|
innodb_encryption_threads 4
|
||||||
@ -57,6 +58,7 @@ SHOW VARIABLES LIKE 'innodb_encrypt%';
|
|||||||
Variable_name Value
|
Variable_name Value
|
||||||
innodb_encrypt_log ON
|
innodb_encrypt_log ON
|
||||||
innodb_encrypt_tables OFF
|
innodb_encrypt_tables OFF
|
||||||
|
innodb_encrypt_temporary_tables OFF
|
||||||
innodb_encryption_rotate_key_age 15
|
innodb_encryption_rotate_key_age 15
|
||||||
innodb_encryption_rotation_iops 100
|
innodb_encryption_rotation_iops 100
|
||||||
innodb_encryption_threads 0
|
innodb_encryption_threads 0
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
--innodb_buffer_pool_size=5M
|
||||||
|
--innodb_encrypt_temporary_tables=1
|
@ -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
|
@ -1028,6 +1028,20 @@ NUMERIC_BLOCK_SIZE NULL
|
|||||||
ENUM_VALUE_LIST OFF,ON,FORCE
|
ENUM_VALUE_LIST OFF,ON,FORCE
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
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
|
VARIABLE_NAME INNODB_FAKE_CHANGES
|
||||||
SESSION_VALUE OFF
|
SESSION_VALUE OFF
|
||||||
GLOBAL_VALUE OFF
|
GLOBAL_VALUE OFF
|
||||||
|
@ -60,6 +60,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||||||
#include "dict0dict.h"
|
#include "dict0dict.h"
|
||||||
#include "log0recv.h"
|
#include "log0recv.h"
|
||||||
#include "srv0mon.h"
|
#include "srv0mon.h"
|
||||||
|
#include "log0crypt.h"
|
||||||
#endif /* !UNIV_INNOCHECKSUM */
|
#endif /* !UNIV_INNOCHECKSUM */
|
||||||
#include "page0zip.h"
|
#include "page0zip.h"
|
||||||
#include "sync0sync.h"
|
#include "sync0sync.h"
|
||||||
@ -476,6 +477,45 @@ buf_pool_register_chunk(
|
|||||||
chunk->blocks->frame, 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.
|
/** Decrypt a page.
|
||||||
@param[in,out] bpage Page control block
|
@param[in,out] bpage Page control block
|
||||||
@param[in,out] space tablespace
|
@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);
|
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
|
/* Page is encrypted if encryption information is found from
|
||||||
tablespace and page contains used key_version. This is true
|
tablespace and page contains used key_version. This is true
|
||||||
also for pages first compressed and then encrypted. */
|
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)
|
# define buf_page_check_crc32(page, checksum) buf_calc_page_crc32(page)
|
||||||
#endif /* INNODB_BUG_ENDIAN_CRC32 */
|
#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.
|
/** Check if a page is corrupt.
|
||||||
@param[in] check_lsn whether the LSN should be checked
|
@param[in] check_lsn whether the LSN should be checked
|
||||||
@param[in] read_buf database page
|
@param[in] read_buf database page
|
||||||
@ -7281,6 +7353,44 @@ operator<<(
|
|||||||
return(out);
|
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
|
/** Encryption and page_compression hook that is called just before
|
||||||
a page is written to disk.
|
a page is written to disk.
|
||||||
@param[in,out] space tablespace
|
@param[in,out] space tablespace
|
||||||
@ -7314,13 +7424,21 @@ buf_page_encrypt_before_write(
|
|||||||
|
|
||||||
fil_space_crypt_t* crypt_data = space->crypt_data;
|
fil_space_crypt_t* crypt_data = space->crypt_data;
|
||||||
|
|
||||||
const bool encrypted = crypt_data
|
bool encrypted, page_compressed;
|
||||||
&& !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);
|
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);
|
||||||
|
|
||||||
|
page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
|
||||||
|
}
|
||||||
|
|
||||||
if (!encrypted && !page_compressed) {
|
if (!encrypted && !page_compressed) {
|
||||||
/* No need to encrypt or page compress the page.
|
/* No need to encrypt or page compress the page.
|
||||||
@ -7341,18 +7459,25 @@ buf_page_encrypt_before_write(
|
|||||||
|
|
||||||
if (!page_compressed) {
|
if (!page_compressed) {
|
||||||
not_compressed:
|
not_compressed:
|
||||||
/* Encrypt page content */
|
byte* tmp;
|
||||||
byte* tmp = fil_space_encrypt(space,
|
if (space->purpose == FIL_TYPE_TEMPORARY) {
|
||||||
bpage->id.page_no(),
|
/* Encrypt temporary tablespace page content */
|
||||||
bpage->newest_modification,
|
tmp = buf_tmp_page_encrypt(bpage->id.page_no(),
|
||||||
src_frame,
|
src_frame, dst_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;
|
bpage->real_size = UNIV_PAGE_SIZE;
|
||||||
slot->out_buf = dst_frame = tmp;
|
slot->out_buf = dst_frame = tmp;
|
||||||
|
|
||||||
ut_d(fil_page_type_validate(tmp));
|
ut_d(fil_page_type_validate(tmp));
|
||||||
} else {
|
} else {
|
||||||
|
ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
|
||||||
/* First we compress the page content */
|
/* First we compress the page content */
|
||||||
buf_tmp_reserve_compression_buf(slot);
|
buf_tmp_reserve_compression_buf(slot);
|
||||||
byte* tmp = slot->comp_buf;
|
byte* tmp = slot->comp_buf;
|
||||||
|
@ -338,20 +338,6 @@ too_small:
|
|||||||
goto start_again;
|
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
|
At database startup initializes the doublewrite buffer memory structure if
|
||||||
we already have a doublewrite buffer created in the data files. If we are
|
we already have a doublewrite buffer created in the data files. If we are
|
||||||
|
@ -1194,6 +1194,12 @@ static SHOW_VAR innodb_status_variables[]= {
|
|||||||
{"encryption_n_rowlog_blocks_decrypted",
|
{"encryption_n_rowlog_blocks_decrypted",
|
||||||
(char*)&export_vars.innodb_n_rowlog_blocks_decrypted,
|
(char*)&export_vars.innodb_n_rowlog_blocks_decrypted,
|
||||||
SHOW_LONGLONG},
|
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 */
|
/* scrubing */
|
||||||
{"scrub_background_page_reorganizations",
|
{"scrub_background_page_reorganizations",
|
||||||
@ -3931,7 +3937,8 @@ innobase_init(
|
|||||||
}
|
}
|
||||||
#endif
|
#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)) {
|
&& !encryption_key_id_exists(FIL_DEFAULT_ENCRYPTION_KEY)) {
|
||||||
sql_print_error("InnoDB: cannot enable encryption, "
|
sql_print_error("InnoDB: cannot enable encryption, "
|
||||||
"encryption plugin is not available");
|
"encryption plugin is not available");
|
||||||
@ -11270,7 +11277,18 @@ err_col:
|
|||||||
Given that temp table lifetime is limited to connection/server lifetime
|
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
|
on re-start we don't need to restore temp-table and so no entry is
|
||||||
needed in SYSTEM tables. */
|
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 */
|
/* Get a new table ID */
|
||||||
dict_table_assign_new_id(table, m_trx);
|
dict_table_assign_new_id(table, m_trx);
|
||||||
table->space = SRV_TMP_SPACE_ID;
|
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.",
|
"DEPRECATED. This setting has no effect.",
|
||||||
NULL, innodb_instrument_semaphores_update, FALSE);
|
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"
|
#include "ha_xtradb.h"
|
||||||
|
|
||||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
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(instrument_semaphores),
|
||||||
MYSQL_SYSVAR(buf_dump_status_frequency),
|
MYSQL_SYSVAR(buf_dump_status_frequency),
|
||||||
MYSQL_SYSVAR(background_thread),
|
MYSQL_SYSVAR(background_thread),
|
||||||
|
MYSQL_SYSVAR(encrypt_temporary_tables),
|
||||||
|
|
||||||
/* XtraDB compatibility system variables */
|
/* XtraDB compatibility system variables */
|
||||||
#define HA_XTRADB_SYSVARS
|
#define HA_XTRADB_SYSVARS
|
||||||
|
@ -4832,20 +4832,6 @@ ibuf_print(
|
|||||||
mutex_exit(&ibuf_mutex);
|
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.
|
Checks the insert buffer bitmaps on IMPORT TABLESPACE.
|
||||||
@return DB_SUCCESS or error code */
|
@return DB_SUCCESS or error code */
|
||||||
@ -4916,7 +4902,7 @@ ibuf_check_bitmap_on_import(
|
|||||||
bitmap_page = ibuf_bitmap_get_map_page(
|
bitmap_page = ibuf_bitmap_get_map_page(
|
||||||
page_id_t(space_id, page_no), page_size, &mtr);
|
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
|
/* This means we got all-zero page instead of
|
||||||
ibuf bitmap page. The subsequent page should be
|
ibuf bitmap page. The subsequent page should be
|
||||||
all-zero pages. */
|
all-zero pages. */
|
||||||
@ -4929,7 +4915,8 @@ ibuf_check_bitmap_on_import(
|
|||||||
page_size,
|
page_size,
|
||||||
RW_S_LATCH, &mtr);
|
RW_S_LATCH, &mtr);
|
||||||
page_t* page = buf_block_get_frame(block);
|
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 */
|
#endif /* UNIV_DEBUG */
|
||||||
ibuf_exit(&mtr);
|
ibuf_exit(&mtr);
|
||||||
|
@ -646,6 +646,12 @@ buf_block_unfix(buf_block_t* block);
|
|||||||
# endif /* UNIV_DEBUG */
|
# endif /* UNIV_DEBUG */
|
||||||
#endif /* !UNIV_INNOCHECKSUM */
|
#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.
|
/** Checks if the page is in crc32 checksum format.
|
||||||
@param[in] read_buf database page
|
@param[in] read_buf database page
|
||||||
@param[in] checksum_field1 new checksum field
|
@param[in] checksum_field1 new checksum field
|
||||||
|
@ -87,7 +87,6 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt = false);
|
|||||||
@param[in] size size of the block
|
@param[in] size size of the block
|
||||||
@param[out] dst destination block
|
@param[out] dst destination block
|
||||||
@param[in] offs offset to block
|
@param[in] offs offset to block
|
||||||
@param[in] space_id tablespace id
|
|
||||||
@param[in] encrypt true=encrypt; false=decrypt
|
@param[in] encrypt true=encrypt; false=decrypt
|
||||||
@return whether the operation succeeded */
|
@return whether the operation succeeded */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
@ -97,7 +96,6 @@ log_tmp_block_encrypt(
|
|||||||
ulint size,
|
ulint size,
|
||||||
byte* dst,
|
byte* dst,
|
||||||
uint64_t offs,
|
uint64_t offs,
|
||||||
ulint space_id,
|
|
||||||
bool encrypt = true)
|
bool encrypt = true)
|
||||||
MY_ATTRIBUTE((warn_unused_result, nonnull));
|
MY_ATTRIBUTE((warn_unused_result, nonnull));
|
||||||
|
|
||||||
@ -106,7 +104,6 @@ log_tmp_block_encrypt(
|
|||||||
@param[in] size size of the block
|
@param[in] size size of the block
|
||||||
@param[out] dst destination block
|
@param[out] dst destination block
|
||||||
@param[in] offs offset to block
|
@param[in] offs offset to block
|
||||||
@param[in] space_id tablespace id
|
|
||||||
@return whether the operation succeeded */
|
@return whether the operation succeeded */
|
||||||
inline
|
inline
|
||||||
bool
|
bool
|
||||||
@ -114,10 +111,9 @@ log_tmp_block_decrypt(
|
|||||||
const byte* src,
|
const byte* src,
|
||||||
ulint size,
|
ulint size,
|
||||||
byte* dst,
|
byte* dst,
|
||||||
uint64_t offs,
|
uint64_t offs)
|
||||||
ulint space_id)
|
|
||||||
{
|
{
|
||||||
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 */
|
/** @return whether temporary files are encrypted */
|
||||||
|
@ -187,6 +187,12 @@ struct srv_stats_t
|
|||||||
|
|
||||||
/** Number of spaces in keyrotation list */
|
/** Number of spaces in keyrotation list */
|
||||||
ulint_ctr_64_t key_rotation_list_length;
|
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;
|
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_max_purge_lag_delay;
|
||||||
|
|
||||||
extern ulong srv_replication_delay;
|
extern ulong srv_replication_delay;
|
||||||
|
|
||||||
|
extern my_bool innodb_encrypt_temporary_tables;
|
||||||
|
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
|
|
||||||
/** Modes of operation */
|
/** Modes of operation */
|
||||||
@ -1066,6 +1075,12 @@ struct export_var_t{
|
|||||||
/*!< Number of row log blocks decrypted */
|
/*!< Number of row log blocks decrypted */
|
||||||
ib_int64_t innodb_n_rowlog_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; /*!< srv_sec_rec_cluster_reads */
|
||||||
ulint innodb_sec_rec_cluster_reads_avoided;/*!< srv_sec_rec_cluster_reads_avoided */
|
ulint innodb_sec_rec_cluster_reads_avoided;/*!< srv_sec_rec_cluster_reads_avoided */
|
||||||
|
|
||||||
|
@ -60,6 +60,9 @@ struct crypt_info_t {
|
|||||||
/** The crypt info */
|
/** The crypt info */
|
||||||
static crypt_info_t 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 */
|
/** Crypt info when upgrading from 10.1 */
|
||||||
static crypt_info_t infos[5 * 2];
|
static crypt_info_t infos[5 * 2];
|
||||||
/** First unused slot in infos[] */
|
/** First unused slot in infos[] */
|
||||||
@ -195,9 +198,6 @@ UNIV_INTERN
|
|||||||
bool
|
bool
|
||||||
log_crypt_init()
|
log_crypt_init()
|
||||||
{
|
{
|
||||||
ut_ad(log_mutex_own());
|
|
||||||
ut_ad(log_sys->is_encrypted());
|
|
||||||
|
|
||||||
info.key_version = encryption_key_get_latest_version(
|
info.key_version = encryption_key_get_latest_version(
|
||||||
LOG_DEFAULT_ENCRYPTION_KEY);
|
LOG_DEFAULT_ENCRYPTION_KEY);
|
||||||
|
|
||||||
@ -207,7 +207,8 @@ log_crypt_init()
|
|||||||
return false;
|
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_AES_OK
|
||||||
|| my_random_bytes(info.crypt_nonce.bytes, sizeof info.crypt_nonce)
|
|| my_random_bytes(info.crypt_nonce.bytes, sizeof info.crypt_nonce)
|
||||||
!= MY_AES_OK) {
|
!= MY_AES_OK) {
|
||||||
@ -372,7 +373,6 @@ log_crypt_read_checkpoint_buf(const byte* buf)
|
|||||||
@param[in] size size of the block
|
@param[in] size size of the block
|
||||||
@param[out] dst destination block
|
@param[out] dst destination block
|
||||||
@param[in] offs offset to block
|
@param[in] offs offset to block
|
||||||
@param[in] space_id tablespace id
|
|
||||||
@param[in] encrypt true=encrypt; false=decrypt
|
@param[in] encrypt true=encrypt; false=decrypt
|
||||||
@return whether the operation succeeded */
|
@return whether the operation succeeded */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
@ -382,19 +382,17 @@ log_tmp_block_encrypt(
|
|||||||
ulint size,
|
ulint size,
|
||||||
byte* dst,
|
byte* dst,
|
||||||
uint64_t offs,
|
uint64_t offs,
|
||||||
ulint space_id,
|
|
||||||
bool encrypt)
|
bool encrypt)
|
||||||
{
|
{
|
||||||
uint dst_len;
|
uint dst_len;
|
||||||
uint64_t aes_ctr_iv[MY_AES_BLOCK_SIZE / sizeof(uint64_t)];
|
uint64_t iv[MY_AES_BLOCK_SIZE / sizeof(uint64_t)];
|
||||||
bzero(aes_ctr_iv, sizeof aes_ctr_iv);
|
iv[0] = offs;
|
||||||
aes_ctr_iv[0] = space_id;
|
memcpy(iv + 1, tmp_iv, sizeof iv - sizeof *iv);
|
||||||
aes_ctr_iv[1] = offs;
|
|
||||||
|
|
||||||
int rc = encryption_crypt(
|
int rc = encryption_crypt(
|
||||||
src, size, dst, &dst_len,
|
src, size, dst, &dst_len,
|
||||||
const_cast<byte*>(info.crypt_key.bytes), sizeof info.crypt_key,
|
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
|
encrypt
|
||||||
? ENCRYPTION_FLAG_ENCRYPT|ENCRYPTION_FLAG_NOPAD
|
? ENCRYPTION_FLAG_ENCRYPT|ENCRYPTION_FLAG_NOPAD
|
||||||
: ENCRYPTION_FLAG_DECRYPT|ENCRYPTION_FLAG_NOPAD,
|
: ENCRYPTION_FLAG_DECRYPT|ENCRYPTION_FLAG_NOPAD,
|
||||||
|
@ -385,8 +385,7 @@ row_log_online_op(
|
|||||||
if (log_tmp_is_encrypted()) {
|
if (log_tmp_is_encrypted()) {
|
||||||
if (!log_tmp_block_encrypt(
|
if (!log_tmp_block_encrypt(
|
||||||
buf, srv_sort_buf_size,
|
buf, srv_sort_buf_size,
|
||||||
log->crypt_tail, byte_offset,
|
log->crypt_tail, byte_offset)) {
|
||||||
index->table->space)) {
|
|
||||||
log->error = DB_DECRYPTION_FAILED;
|
log->error = DB_DECRYPTION_FAILED;
|
||||||
goto write_failed;
|
goto write_failed;
|
||||||
}
|
}
|
||||||
@ -2670,8 +2669,7 @@ all_done:
|
|||||||
if (log_tmp_is_encrypted()) {
|
if (log_tmp_is_encrypted()) {
|
||||||
if (!log_tmp_block_decrypt(
|
if (!log_tmp_block_decrypt(
|
||||||
buf, srv_sort_buf_size,
|
buf, srv_sort_buf_size,
|
||||||
index->online_log->crypt_head,
|
index->online_log->crypt_head, ofs)) {
|
||||||
ofs, index->table->space)) {
|
|
||||||
error = DB_DECRYPTION_FAILED;
|
error = DB_DECRYPTION_FAILED;
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
@ -3541,8 +3539,7 @@ all_done:
|
|||||||
if (log_tmp_is_encrypted()) {
|
if (log_tmp_is_encrypted()) {
|
||||||
if (!log_tmp_block_decrypt(
|
if (!log_tmp_block_decrypt(
|
||||||
buf, srv_sort_buf_size,
|
buf, srv_sort_buf_size,
|
||||||
index->online_log->crypt_head,
|
index->online_log->crypt_head, ofs)) {
|
||||||
ofs, index->table->space)) {
|
|
||||||
error = DB_DECRYPTION_FAILED;
|
error = DB_DECRYPTION_FAILED;
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
@ -1094,7 +1094,7 @@ row_merge_read(
|
|||||||
/* If encryption is enabled decrypt buffer */
|
/* If encryption is enabled decrypt buffer */
|
||||||
if (success && log_tmp_is_encrypted()) {
|
if (success && log_tmp_is_encrypted()) {
|
||||||
if (!log_tmp_block_decrypt(buf, srv_sort_buf_size,
|
if (!log_tmp_block_decrypt(buf, srv_sort_buf_size,
|
||||||
crypt_buf, ofs, space)) {
|
crypt_buf, ofs)) {
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,7 +1143,7 @@ row_merge_write(
|
|||||||
if (!log_tmp_block_encrypt(static_cast<const byte*>(buf),
|
if (!log_tmp_block_encrypt(static_cast<const byte*>(buf),
|
||||||
buf_len,
|
buf_len,
|
||||||
static_cast<byte*>(crypt_buf),
|
static_cast<byte*>(crypt_buf),
|
||||||
ofs, space)) {
|
ofs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,6 +450,9 @@ my_bool srv_print_innodb_lock_monitor;
|
|||||||
PRIMARY KEY */
|
PRIMARY KEY */
|
||||||
my_bool srv_force_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
|
/* Array of English strings describing the current state of an
|
||||||
i/o handler thread */
|
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_encrypted = srv_stats.n_rowlog_blocks_encrypted;
|
||||||
export_vars.innodb_n_rowlog_blocks_decrypted = srv_stats.n_rowlog_blocks_decrypted;
|
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 =
|
export_vars.innodb_defragment_compression_failures =
|
||||||
btr_defragment_compression_failures;
|
btr_defragment_compression_failures;
|
||||||
export_vars.innodb_defragment_failures = btr_defragment_failures;
|
export_vars.innodb_defragment_failures = btr_defragment_failures;
|
||||||
|
@ -491,9 +491,6 @@ create_log_files(
|
|||||||
|
|
||||||
/* Create a log checkpoint. */
|
/* Create a log checkpoint. */
|
||||||
log_mutex_enter();
|
log_mutex_enter();
|
||||||
if (log_sys->is_encrypted() && !log_crypt_init()) {
|
|
||||||
return(DB_ERROR);
|
|
||||||
}
|
|
||||||
ut_d(recv_no_log_write = false);
|
ut_d(recv_no_log_write = false);
|
||||||
log_sys->lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE);
|
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;
|
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) {
|
if (create_new_db) {
|
||||||
|
|
||||||
buf_flush_sync_all_buf_pools();
|
buf_flush_sync_all_buf_pools();
|
||||||
|
Reference in New Issue
Block a user