Commit 71ec0463 authored by Jan Lindström's avatar Jan Lindström Committed by Sergei Golubchik

Encryption cleanup

Step 3:

-- Make encrytion_algorithm changeable by SUPER
-- Remove AES_ECB method from encryption_algorithms
-- Support AES method change by storing used method on InnoDB/XtraDB objects
-- Store used AES method to crypt_data as different crypt types
-- Store used AES method to redo/undo logs and checkpoint
-- Store used AES method on every encrypted page after key_version
-- Add test
parent 0ba9fa35
...@@ -115,8 +115,8 @@ extern MYSQL_PLUGIN_IMPORT my_aes_decrypt_dynamic_type my_aes_decrypt_dynamic; ...@@ -115,8 +115,8 @@ extern MYSQL_PLUGIN_IMPORT my_aes_decrypt_dynamic_type my_aes_decrypt_dynamic;
enum enum_my_aes_encryption_algorithm enum enum_my_aes_encryption_algorithm
{ {
MY_AES_ALGORITHM_NONE, MY_AES_ALGORITHM_ECB, MY_AES_ALGORITHM_CBC, MY_AES_ALGORITHM_NONE, MY_AES_ALGORITHM_CTR,
MY_AES_ALGORITHM_CTR MY_AES_ALGORITHM_CBC, MY_AES_ALGORITHM_ECB
}; };
my_aes_decrypt_dynamic_type get_aes_decrypt_func(enum enum_my_aes_encryption_algorithm method); my_aes_decrypt_dynamic_type get_aes_decrypt_func(enum enum_my_aes_encryption_algorithm method);
......
[cbc] [cbc]
encryption-algorithm=aes_cbc encryption-algorithm=aes_cbc
[ecb]
encryption-algorithm=aes_ecb
[ctr] [ctr]
encryption-algorithm=aes_ctr encryption-algorithm=aes_ctr
...@@ -167,8 +167,8 @@ The following options may be given as the first argument: ...@@ -167,8 +167,8 @@ The following options may be given as the first argument:
execution) execution)
--encryption-algorithm=name --encryption-algorithm=name
Which encryption algorithm to use for table encryption. Which encryption algorithm to use for table encryption.
aes_cbc is the recommended one.. One of: none, aes_ecb, aes_cbc is the recommended one.. One of: none, aes_cbc,
aes_cbc, aes_ctr aes_ctr
--enforce-storage-engine=name --enforce-storage-engine=name
Force the use of a storage engine for new tables Force the use of a storage engine for new tables
--event-scheduler[=name] --event-scheduler[=name]
......
SET @start_global_value = @@global.innodb_encryption_threads;
SET GLOBAL innodb_file_format = `Barracuda`;
SET GLOBAL innodb_file_per_table = ON;
SHOW VARIABLES LIKE 'innodb_encrypt%';
Variable_name Value
innodb_encrypt_log ON
innodb_encrypt_tables OFF
innodb_encryption_rotate_key_age 15
innodb_encryption_rotation_iops 100
innodb_encryption_threads 0
DESCRIBE INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
Field Type Null Key Default Extra
SPACE int(11) unsigned NO 0
NAME varchar(655) YES NULL
ENCRYPTION_SCHEME int(11) unsigned NO 0
KEYSERVER_REQUESTS int(11) unsigned NO 0
MIN_KEY_VERSION int(11) unsigned NO 0
CURRENT_KEY_VERSION int(11) unsigned NO 0
KEY_ROTATION_PAGE_NUMBER bigint(21) unsigned YES NULL
KEY_ROTATION_MAX_PAGE_NUMBER bigint(21) unsigned YES NULL
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;
create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic;
create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed;
create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant;
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_dynamic select * from innodb_normal;
insert into innodb_compressed select * from innodb_normal;
insert into innodb_redundant select * from innodb_normal;
" Start encrypt tablespaces
SET GLOBAL innodb_encrypt_tables = on;
SET GLOBAL innodb_encryption_threads = 4;
# Wait max 5 min for key encryption threads to encrypt one space
# Success!
# Wait max 10 min for key encryption threads to encrypt all space
# Success!
# Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encrypt_tables = off;
set GLOBAL encryption_algorithm = aes_cbc;
# Wait max 10 min for key encryption threads to decrypt all space
# Success!
# Shutdown innodb_encryption_threads
SET GLOBAL innodb_encryption_threads=0;
# Turn on encryption
# since threads are off tables should remain unencrypted
SET GLOBAL innodb_encrypt_tables = on;
# Wait 15s to check that nothing gets encrypted
# Success!
# Startup innodb_encryption_threads
SET GLOBAL innodb_encryption_threads=4;
# Wait 1 min to check that it start encrypting again
# Success!
# Wait max 10 min for key encryption threads to decrypt all space
# Success!
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
SELECT variable_value > 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_compressed';
variable_value > 0
0
SELECT variable_value > 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decompressed';
variable_value > 0
0
drop procedure innodb_insert_proc;
drop table innodb_normal;
drop table innodb_compact;
drop table innodb_dynamic;
drop table innodb_compressed;
drop table innodb_redundant;
--aria-encrypt-tables=ON
--encrypt-tmp-disk-tables=ON
--innodb-encryption-rotate-key-age=15
--innodb-encryption-threads=0
--innodb-tablespaces-encryption
--innodb-encrypt-log=ON
#
#
#
-- source include/have_innodb.inc
-- source include/have_example_key_management_plugin.inc
# embedded does not support restart
-- source include/not_embedded.inc
--disable_query_log
let $orig_algorithm=`SELECT @@encryption_algorithm`;
let $innodb_file_format_orig = `SELECT @@innodb_file_format`;
let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`;
let $encrypt_tables_orig = `SELECT @@innodb_encrypt_tables`;
--enable_query_log
SET @start_global_value = @@global.innodb_encryption_threads;
SET GLOBAL innodb_file_format = `Barracuda`;
SET GLOBAL innodb_file_per_table = ON;
--disable_query_log
EVAL SET GLOBAL encryption_algorithm = $orig_algorithm;
--enable_query_log
SHOW VARIABLES LIKE 'innodb_encrypt%';
DESCRIBE INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
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;
create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic;
create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed;
create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=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_dynamic select * from innodb_normal;
insert into innodb_compressed select * from innodb_normal;
insert into innodb_redundant select * from innodb_normal;
--echo " Start encrypt tablespaces
SET GLOBAL innodb_encrypt_tables = on;
SET GLOBAL innodb_encryption_threads = 4;
--echo # Wait max 5 min for key encryption threads to encrypt one space
let $cnt=300;
while ($cnt)
{
let $success=`SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION > 0`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
SHOW STATUS LIKE 'innodb_encryption%';
-- die Timeout waiting for encryption threads
}
--echo # Success!
--echo # Wait max 10 min for key encryption threads to encrypt all space
let $cnt=600;
while ($cnt)
{
let $success=`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
SHOW STATUS LIKE 'innodb_encryption%';
-- die Timeout waiting for encryption threads
}
--echo # Success!
--echo # Now turn off encryption and wait for threads to decrypt everything
SET GLOBAL innodb_encrypt_tables = off;
set GLOBAL encryption_algorithm = aes_cbc;
--echo # Wait max 10 min for key encryption threads to decrypt all space
let $cnt=600;
while ($cnt)
{
let $success=`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
SHOW STATUS LIKE 'innodb_encryption%';
-- die Timeout waiting for encryption threads
}
--echo # Success!
--echo # Shutdown innodb_encryption_threads
SET GLOBAL innodb_encryption_threads=0;
--echo # Turn on encryption
--echo # since threads are off tables should remain unencrypted
SET GLOBAL innodb_encrypt_tables = on;
--echo # Wait 15s to check that nothing gets encrypted
let $cnt=15;
while ($cnt)
{
let $success=`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0`;
if ($success)
{
real_sleep 1;
dec $cnt;
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
-- die Failure, tablespace getting encrypted even if innodb_encryption_threads=0
}
}
--echo # Success!
--echo # Startup innodb_encryption_threads
SET GLOBAL innodb_encryption_threads=4;
--echo # Wait 1 min to check that it start encrypting again
let $cnt=60;
while ($cnt)
{
let $success=`SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 OR KEY_ROTATION_PAGE_NUMBER IS NOT NULL`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
SHOW STATUS LIKE 'innodb_encryption%';
-- die Timeout waiting for encryption threads
}
--echo # Success!
--echo # Wait max 10 min for key encryption threads to decrypt all space
let $cnt=600;
while ($cnt)
{
let $success=`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0`;
if ($success)
{
let $cnt=0;
}
if (!$success)
{
real_sleep 1;
dec $cnt;
}
}
if (!$success)
{
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION;
SHOW STATUS LIKE 'innodb_encryption%';
-- die Timeout waiting for encryption threads
}
--echo # Success!
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';
SELECT variable_value > 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_compressed';
SELECT variable_value > 0 FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_num_pages_page_decompressed';
drop procedure innodb_insert_proc;
drop table innodb_normal;
drop table innodb_compact;
drop table innodb_dynamic;
drop table innodb_compressed;
drop table innodb_redundant;
# reset system
--disable_query_log
EVAL SET GLOBAL innodb_encrypt_tables = $encrypt_tables_orig;
SET GLOBAL innodb_encryption_threads=@start_global_value;
EVAL SET GLOBAL encryption_algorithm = $orig_algorithm;
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
...@@ -3,5 +3,6 @@ select @@global.encryption_algorithm; ...@@ -3,5 +3,6 @@ select @@global.encryption_algorithm;
none none
select @@session.encryption_algorithm; select @@session.encryption_algorithm;
ERROR HY000: Variable 'encryption_algorithm' is a GLOBAL variable ERROR HY000: Variable 'encryption_algorithm' is a GLOBAL variable
set global encryption_algorithm="none"; set global encryption_algorithm = aes_cbc;
ERROR HY000: Variable 'encryption_algorithm' is a read only variable set global encryption_algorithm = aes_cbc;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
...@@ -706,8 +706,8 @@ VARIABLE_COMMENT Which encryption algorithm to use for table encryption. aes_cbc ...@@ -706,8 +706,8 @@ VARIABLE_COMMENT Which encryption algorithm to use for table encryption. aes_cbc
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST none,aes_ecb,aes_cbc,aes_ctr ENUM_VALUE_LIST none,aes_cbc,aes_ctr
READ_ONLY YES READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME ENCRYPT_TMP_DISK_TABLES VARIABLE_NAME ENCRYPT_TMP_DISK_TABLES
SESSION_VALUE NULL SESSION_VALUE NULL
......
# bool global # enum global
--disable_query_log
let $orig_algorithm=`SELECT @@encryption_algorithm`;
--enable_query_log
#
# exists as global only # exists as global only
# #
select @@global.encryption_algorithm; select @@global.encryption_algorithm;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR --error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.encryption_algorithm; select @@session.encryption_algorithm;
set global encryption_algorithm = aes_cbc;
# #
# show that it's not writable # Check changeable only by super
# #
--error 1238 --source include/add_anonymous_users.inc
set global encryption_algorithm="none";
connect (con1,localhost,user_1,,);
connection con1;
--error 1227
set global encryption_algorithm = aes_cbc;
connection default;
--source include/delete_anonymous_users.inc
# reset system
--disable_query_log
EVAL SET GLOBAL encryption_algorithm = $orig_algorithm;
--enable_query_log
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
#include "opt_range.h" #include "opt_range.h"
#include "rpl_parallel.h" #include "rpl_parallel.h"
#include "encryption_keys.h" #include "encryption_keys.h"
#include "my_aes.h"
/* /*
The rule for this file: everything should be 'static'. When a sys_var The rule for this file: everything should be 'static'. When a sys_var
variable or a function from this file is - in very rare cases - needed variable or a function from this file is - in very rare cases - needed
...@@ -5185,13 +5185,30 @@ static Sys_var_mybool Sys_encrypt_tmp_disk_tables( ...@@ -5185,13 +5185,30 @@ static Sys_var_mybool Sys_encrypt_tmp_disk_tables(
GLOBAL_VAR(encrypt_tmp_disk_tables), GLOBAL_VAR(encrypt_tmp_disk_tables),
CMD_LINE(OPT_ARG), DEFAULT(FALSE)); CMD_LINE(OPT_ARG), DEFAULT(FALSE));
static bool fix_encryption_algorithm(sys_var *self, THD *thd,
enum_var_type type)
{
if (my_aes_init_dynamic_encrypt((enum_my_aes_encryption_algorithm)
encryption_algorithm))
{
fprintf(stderr, "Can't initialize encryption algorithm to \"%s\".\nCheck that the program is linked with the right library (openssl?)\n",
encryption_algorithm_names[encryption_algorithm]);
return true;
}
return false;
}
const char *encryption_algorithm_names[]= const char *encryption_algorithm_names[]=
{ "none", "aes_ecb", "aes_cbc", "aes_ctr", 0 }; { "none", "aes_cbc", "aes_ctr", 0 };
static Sys_var_enum Sys_encryption_algorithm( static Sys_var_enum Sys_encryption_algorithm(
"encryption_algorithm", "encryption_algorithm",
"Which encryption algorithm to use for table encryption. aes_cbc is the recommended one.", "Which encryption algorithm to use for table encryption. aes_cbc is the recommended one.",
READ_ONLY GLOBAL_VAR(encryption_algorithm),CMD_LINE(REQUIRED_ARG), GLOBAL_VAR(encryption_algorithm),CMD_LINE(REQUIRED_ARG),
encryption_algorithm_names, DEFAULT(0)); encryption_algorithm_names, DEFAULT(0),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0), ON_UPDATE(fix_encryption_algorithm));
static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var) static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var)
{ {
......
...@@ -2454,6 +2454,19 @@ buf_block_align_instance( ...@@ -2454,6 +2454,19 @@ buf_block_align_instance(
== 0xffffffff); == 0xffffffff);
break; break;
case BUF_BLOCK_FILE_PAGE: case BUF_BLOCK_FILE_PAGE:
if (block->page.space
!= page_get_space_id(page_align(ptr))) {
fprintf(stderr, "Block space id %du page space id %lu page type %s\n",
block->page.space, page_get_space_id(page_align(ptr)),
fil_get_page_type_name(mach_read_from_4(ptr + FIL_PAGE_TYPE)));
}
if (block->page.offset
!= page_get_page_no(page_align(ptr))) {
fprintf(stderr, "Block offset %du page offset %lu page type %s\n",
block->page.offset, page_get_page_no(page_align(ptr)),
fil_get_page_type_name(mach_read_from_4(ptr + FIL_PAGE_TYPE)));
}
ut_ad(block->page.space ut_ad(block->page.space
== page_get_space_id(page_align(ptr))); == page_get_space_id(page_align(ptr)));
ut_ad(block->page.offset ut_ad(block->page.offset
......
...@@ -23,8 +23,6 @@ Created Jonas Oreland Google ...@@ -23,8 +23,6 @@ Created Jonas Oreland Google
Modified Jan Lindström jan.lindstrom@mariadb.com Modified Jan Lindström jan.lindstrom@mariadb.com
*******************************************************/ *******************************************************/
#include "fil0fil.h"
#include "fil0crypt.h"
#include "srv0srv.h" #include "srv0srv.h"
#include "srv0start.h" #include "srv0start.h"
#include "mach0data.h" #include "mach0data.h"
...@@ -37,6 +35,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com ...@@ -37,6 +35,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "fsp0fsp.h" #include "fsp0fsp.h"
#include "fil0pagecompress.h" #include "fil0pagecompress.h"
#include "ha_prototypes.h" // IB_LOG_ #include "ha_prototypes.h" // IB_LOG_
#include "fil0fil.h"
#include "fil0crypt.h"
#include <my_crypt.h> #include <my_crypt.h>
...@@ -119,34 +119,6 @@ static const unsigned char CRYPT_MAGIC[MAGIC_SZ] = { ...@@ -119,34 +119,6 @@ static const unsigned char CRYPT_MAGIC[MAGIC_SZ] = {
static const unsigned char EMPTY_PATTERN[MAGIC_SZ] = { static const unsigned char EMPTY_PATTERN[MAGIC_SZ] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
/******************************************************************
Map used AES method to crypt scheme
@return used AES crypt scheme */
UNIV_INTERN
uint
fil_crypt_get_aes_method(
/*=====================*/
uint aes_method)
{
switch (aes_method) {
case MY_AES_ALGORITHM_NONE:
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
break;
case MY_AES_ALGORITHM_CTR:
return (uint) CRYPT_SCHEME_1_CTR;
break;
case MY_AES_ALGORITHM_CBC:
return (uint) CRYPT_SCHEME_1_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", aes_method);
ut_error;
}
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
}
/********************************************************************* /*********************************************************************
Init space crypt */ Init space crypt */
UNIV_INTERN UNIV_INTERN
...@@ -659,29 +631,6 @@ fil_space_check_encryption_write( ...@@ -659,29 +631,6 @@ fil_space_check_encryption_write(
return true; return true;
} }
/******************************************************************
Map current aes method
@return AES method */
UNIV_INTERN
uint
fil_crypt_map_aes_method(
/*=====================*/
uint aes_method) /*!< in: AES method */
{
switch((fil_crypt_method_t)aes_method) {
case CRYPT_SCHEME_1_CTR:
return (uint)MY_AES_ALGORITHM_CTR;
break;
case CRYPT_SCHEME_1_CBC:
return (uint)MY_AES_ALGORITHM_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", (int)aes_method);
ut_error;
}
}
/****************************************************************** /******************************************************************
Encrypt a page */ Encrypt a page */
UNIV_INTERN UNIV_INTERN
......
...@@ -6858,7 +6858,7 @@ Get crypt data for a tablespace */ ...@@ -6858,7 +6858,7 @@ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
fil_space_crypt_t* fil_space_crypt_t*
fil_space_get_crypt_data( fil_space_get_crypt_data(
/*==================*/ /*=====================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
...@@ -6879,12 +6879,29 @@ fil_space_get_crypt_data( ...@@ -6879,12 +6879,29 @@ fil_space_get_crypt_data(
return(crypt_data); return(crypt_data);
} }
/******************************************************************
Get crypt data for a tablespace */
UNIV_INTERN
fil_space_crypt_t*
fil_space_crypt_data(
/*=================*/
fil_space_t* space) /*!< in: filespace */
{
fil_space_crypt_t* crypt_data = NULL;
if (space != NULL) {
crypt_data = space->crypt_data;
}
return(crypt_data);
}
/****************************************************************** /******************************************************************
Get crypt data for a tablespace */ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
void void
fil_space_set_crypt_data( fil_space_set_crypt_data(
/*==================*/ /*=====================*/
ulint id, /*!< in: space id */ ulint id, /*!< in: space id */
fil_space_crypt_t* crypt_data) /*!< in: crypt data */ fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{ {
......
...@@ -87,6 +87,7 @@ static ulint srv_data_read, srv_data_written; ...@@ -87,6 +87,7 @@ static ulint srv_data_read, srv_data_written;
For page compressed pages compress the page before actual write For page compressed pages compress the page before actual write
operation. operation.
@return compressed page to be written*/ @return compressed page to be written*/
UNIV_INTERN
byte* byte*
fil_compress_page( fil_compress_page(
/*==============*/ /*==============*/
...@@ -379,6 +380,7 @@ fil_compress_page( ...@@ -379,6 +380,7 @@ fil_compress_page(
/****************************************************************//** /****************************************************************//**
For page compressed pages decompress the page after actual read For page compressed pages decompress the page after actual read
operation. */ operation. */
UNIV_INTERN
void void
fil_decompress_page( fil_decompress_page(
/*================*/ /*================*/
......
...@@ -67,3 +67,54 @@ fil_page_encryption_status( ...@@ -67,3 +67,54 @@ fil_page_encryption_status(
} }
return 0; return 0;
} }
/******************************************************************
Map used AES method to crypt scheme
@return used AES crypt scheme */
UNIV_INLINE
uint
fil_crypt_get_aes_method(
/*=====================*/
uint aes_method)
{
switch (aes_method) {
case MY_AES_ALGORITHM_NONE:
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
break;
case MY_AES_ALGORITHM_CTR:
return (uint) CRYPT_SCHEME_1_CTR;
break;
case MY_AES_ALGORITHM_CBC:
return (uint) CRYPT_SCHEME_1_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", aes_method);
ut_error;
}
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
}
/******************************************************************
Map current aes method
@return AES method */
UNIV_INLINE
uint
fil_crypt_map_aes_method(
/*=====================*/
uint aes_method) /*!< in: AES method */
{
switch((fil_crypt_method_t)aes_method) {
case CRYPT_SCHEME_1_CTR:
return (uint)MY_AES_ALGORITHM_CTR;
break;
case CRYPT_SCHEME_1_CBC:
return (uint)MY_AES_ALGORITHM_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", (int)aes_method);
ut_error;
}
}
...@@ -34,6 +34,7 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ...@@ -34,6 +34,7 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
Returns the page compression level flag of the space, or 0 if the space Returns the page compression level flag of the space, or 0 if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return page compression level if page compressed, ULINT_UNDEFINED if space not found */ @return page compression level if page compressed, ULINT_UNDEFINED if space not found */
UNIV_INTERN
ulint ulint
fil_space_get_page_compression_level( fil_space_get_page_compression_level(
/*=================================*/ /*=================================*/
...@@ -42,6 +43,7 @@ fil_space_get_page_compression_level( ...@@ -42,6 +43,7 @@ fil_space_get_page_compression_level(
Returns the page compression flag of the space, or false if the space Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */ @return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool ibool
fil_space_is_page_compressed( fil_space_is_page_compressed(
/*=========================*/ /*=========================*/
...@@ -50,6 +52,7 @@ fil_space_is_page_compressed( ...@@ -50,6 +52,7 @@ fil_space_is_page_compressed(
Returns the page compression flag of the space, or false if the space Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */ @return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool ibool
fil_space_get_page_compressed( fil_space_get_page_compressed(
/*=========================*/ /*=========================*/
...@@ -58,6 +61,7 @@ fil_space_get_page_compressed( ...@@ -58,6 +61,7 @@ fil_space_get_page_compressed(
Returns the atomic writes flag of the space, or false if the space Returns the atomic writes flag of the space, or false if the space
is not using atomic writes. The tablespace must be cached in the memory cache. is not using atomic writes. The tablespace must be cached in the memory cache.
@return atomic write table option value */ @return atomic write table option value */
UNIV_INTERN
atomic_writes_t atomic_writes_t
fil_space_get_atomic_writes( fil_space_get_atomic_writes(
/*=========================*/ /*=========================*/
...@@ -65,6 +69,7 @@ fil_space_get_atomic_writes( ...@@ -65,6 +69,7 @@ fil_space_get_atomic_writes(
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is index page or not Find out wheather the page is index page or not
@return true if page type index page, false if not */ @return true if page type index page, false if not */
UNIV_INTERN
ibool ibool
fil_page_is_index_page( fil_page_is_index_page(
/*===================*/ /*===================*/
...@@ -74,6 +79,7 @@ fil_page_is_index_page( ...@@ -74,6 +79,7 @@ fil_page_is_index_page(
Get the name of the compression algorithm used for page Get the name of the compression algorithm used for page
compression. compression.
@return compression algorithm name or "UNKNOWN" if not known*/ @return compression algorithm name or "UNKNOWN" if not known*/
UNIV_INTERN
const char* const char*
fil_get_compression_alg_name( fil_get_compression_alg_name(
/*=========================*/ /*=========================*/
...@@ -83,6 +89,7 @@ fil_get_compression_alg_name( ...@@ -83,6 +89,7 @@ fil_get_compression_alg_name(
For page compressed pages compress the page before actual write For page compressed pages compress the page before actual write
operation. operation.
@return compressed page to be written*/ @return compressed page to be written*/
UNIV_INTERN
byte* byte*
fil_compress_page( fil_compress_page(
/*==============*/ /*==============*/
...@@ -102,6 +109,7 @@ fil_compress_page( ...@@ -102,6 +109,7 @@ fil_compress_page(
For page compressed pages decompress the page after actual read For page compressed pages decompress the page after actual read
operation. operation.
@return uncompressed page */ @return uncompressed page */
UNIV_INTERN
void void
fil_decompress_page( fil_decompress_page(
/*================*/ /*================*/
...@@ -115,6 +123,7 @@ fil_decompress_page( ...@@ -115,6 +123,7 @@ fil_decompress_page(
/****************************************************************//** /****************************************************************//**
Get space id from fil node Get space id from fil node
@return space id*/ @return space id*/
UNIV_INTERN
ulint ulint
fil_node_get_space_id( fil_node_get_space_id(
/*==================*/ /*==================*/
...@@ -123,13 +132,16 @@ fil_node_get_space_id( ...@@ -123,13 +132,16 @@ fil_node_get_space_id(
/****************************************************************//** /****************************************************************//**
Get block size from fil node Get block size from fil node
@return block size*/ @return block size*/
UNIV_INTERN
ulint ulint
fil_node_get_block_size( fil_node_get_block_size(
/*====================*/
fil_node_t* node); /*!< in: Node where to get block fil_node_t* node); /*!< in: Node where to get block
size */ size */
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is page compressed Find out wheather the page is page compressed
@return true if page is page compressed*/ @return true if page is page compressed */
UNIV_INTERN
ibool ibool
fil_page_is_compressed( fil_page_is_compressed(
/*===================*/ /*===================*/
...@@ -138,6 +150,7 @@ fil_page_is_compressed( ...@@ -138,6 +150,7 @@ fil_page_is_compressed(
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is page compressed with lzo method Find out wheather the page is page compressed with lzo method
@return true if page is page compressed with lzo method*/ @return true if page is page compressed with lzo method*/
UNIV_INTERN
ibool ibool
fil_page_is_lzo_compressed( fil_page_is_lzo_compressed(
/*=======================*/ /*=======================*/
......
...@@ -23,6 +23,8 @@ extern my_bool srv_encrypt_log; ...@@ -23,6 +23,8 @@ extern my_bool srv_encrypt_log;
extern byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE]; extern byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE];
/* IV to concatenate with counter used by AES_CTR for redo log crypto. */ /* IV to concatenate with counter used by AES_CTR for redo log crypto. */
extern byte aes_ctr_nonce[MY_AES_BLOCK_SIZE]; extern byte aes_ctr_nonce[MY_AES_BLOCK_SIZE];
/* AES method used for redo log encryption/decryption. */
extern byte redo_aes_method;
/*********************************************************************//** /*********************************************************************//**
Generate a 128-bit random message used to generate redo log crypto key. Generate a 128-bit random message used to generate redo log crypto key.
......
...@@ -678,7 +678,7 @@ extern log_t* log_sys; ...@@ -678,7 +678,7 @@ extern log_t* log_sys;
#define LOG_CHECKPOINT_OFFSET_HIGH32 (16 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CHECKPOINT_OFFSET_HIGH32 (16 + LOG_CHECKPOINT_ARRAY_END)
#define LOG_CRYPT_VER (20 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_VER (20 + LOG_CHECKPOINT_ARRAY_END)
/*!< 32-bit key version. Corresponding /*!< 32-bit key version. Corresponding
key has been used for log records with key has been used for log records with
lsn <= the checkpoint' lsn */ lsn <= the checkpoint' lsn */
#define LOG_CRYPT_MSG (24 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_MSG (24 + LOG_CHECKPOINT_ARRAY_END)
/*!< a 128-bit value used to /*!< a 128-bit value used to
...@@ -688,8 +688,10 @@ extern log_t* log_sys; ...@@ -688,8 +688,10 @@ extern log_t* log_sys;
15-byte random number.*/ 15-byte random number.*/
#define LOG_CRYPT_IV (40 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_IV (40 + LOG_CHECKPOINT_ARRAY_END)
/*!< a 128-bit random number used as /*!< a 128-bit random number used as
AES-CTR iv/nonce for redo log */ AES-* iv/nonce for redo log */
#define LOG_CHECKPOINT_SIZE (56 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_METHOD (56 + LOG_CHECKPOINT_ARRAY_END)
/*!< AES method used */
#define LOG_CHECKPOINT_SIZE (57 + LOG_CHECKPOINT_ARRAY_END)
/* Offsets of a log file header */ /* Offsets of a log file header */
#define LOG_GROUP_ID 0 /* log group number */ #define LOG_GROUP_ID 0 /* log group number */
......
...@@ -30,6 +30,9 @@ Modified Jan Lindström jan.lindstrom@mariadb.com ...@@ -30,6 +30,9 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "log0log.h" #include "log0log.h"
#include "srv0start.h" // for srv_start_lsn #include "srv0start.h" // for srv_start_lsn
#include "log0recv.h" // for recv_sys #include "log0recv.h" // for recv_sys
#include "ha_prototypes.h" // ib_logf
#include "fil0fil.h" // for page types
#include "fil0crypt.h" // for aes_method
#include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION #include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION
#include "ha_prototypes.h" // IB_LOG_ #include "ha_prototypes.h" // IB_LOG_
...@@ -43,15 +46,17 @@ UNIV_INTERN my_bool srv_encrypt_log = FALSE; ...@@ -43,15 +46,17 @@ UNIV_INTERN my_bool srv_encrypt_log = FALSE;
static const byte redo_log_purpose_byte = 0x02; static const byte redo_log_purpose_byte = 0x02;
/* Plain text used by AES_ECB to generate redo log crypt key. */ /* Plain text used by AES_ECB to generate redo log crypt key. */
byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE] = {0}; byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE] = {0};
/* IV to concatenate with counter used by AES_CTR for redo log /* IV to concatenate with counter used by AES for redo log
* encryption/decryption. */ * encryption/decryption. */
byte aes_ctr_nonce[MY_AES_BLOCK_SIZE] = {0}; byte aes_ctr_nonce[MY_AES_BLOCK_SIZE] = {0};
/* AES method used for redo log encryption/decryption. */
byte redo_aes_method = 0;
/*********************************************************************//** /*********************************************************************//**
Generate a 128-bit value used to generate crypt key for redo log. Generate a 128-bit value used to generate crypt key for redo log.
It is generated via the concatenation of 1 purpose byte (0x02) and 15-byte It is generated via the concatenation of 1 purpose byte (0x02) and 15-byte
random number. random number.
Init AES-CTR iv/nonce with random number. Init AES iv/nonce with random number.
It is called when: It is called when:
- redo logs do not exist when start up, or - redo logs do not exist when start up, or
- transition from without crypto. - transition from without crypto.
...@@ -69,8 +74,8 @@ log_init_crypt_msg_and_nonce(void) ...@@ -69,8 +74,8 @@ log_init_crypt_msg_and_nonce(void)
/*==============================*/ /*==============================*/
{ {
mach_write_to_1(redo_log_crypt_msg, redo_log_purpose_byte); mach_write_to_1(redo_log_crypt_msg, redo_log_purpose_byte);
if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK)
{ if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: generate " "Redo log crypto: generate "
"%u-byte random number as crypto msg failed.", "%u-byte random number as crypto msg failed.",
...@@ -78,14 +83,16 @@ log_init_crypt_msg_and_nonce(void) ...@@ -78,14 +83,16 @@ log_init_crypt_msg_and_nonce(void)
abort(); abort();
} }
if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: generate " "Redo log crypto: generate "
"%u-byte random number as AES_CTR nonce failed.", "%u-byte random number failed.",
MY_AES_BLOCK_SIZE); MY_AES_BLOCK_SIZE);
abort(); abort();
} }
/* Set up current AES method */
redo_aes_method = (byte)fil_crypt_get_aes_method(current_aes_dynamic_method);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -98,16 +105,14 @@ log_init_crypt_key( ...@@ -98,16 +105,14 @@ log_init_crypt_key(
const uint crypt_ver, /*< in: key version */ const uint crypt_ver, /*< in: key version */
byte* key) /*< out: crypt key*/ byte* key) /*< out: crypt key*/
{ {
if (crypt_ver == UNENCRYPTED_KEY_VER) if (crypt_ver == UNENCRYPTED_KEY_VER) {
{
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"Redo log crypto: unencrypted key ver."); "Redo log crypto: unencrypted key ver.");
memset(key, 0, MY_AES_BLOCK_SIZE); memset(key, 0, MY_AES_BLOCK_SIZE);
return; return;
} }
if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: msg type mismatched. " "Redo log crypto: msg type mismatched. "
"Expected: %x; Actual: %x.", "Expected: %x; Actual: %x.",
...@@ -116,8 +121,8 @@ log_init_crypt_key( ...@@ -116,8 +121,8 @@ log_init_crypt_key(
} }
byte mysqld_key[MY_AES_BLOCK_SIZE] = {0}; byte mysqld_key[MY_AES_BLOCK_SIZE] = {0};
if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE))
{ if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: getting mysqld crypto key " "Redo log crypto: getting mysqld crypto key "
"from key version failed."); "from key version failed.");
...@@ -125,15 +130,16 @@ log_init_crypt_key( ...@@ -125,15 +130,16 @@ log_init_crypt_key(
} }
uint32 dst_len; uint32 dst_len;
my_aes_encrypt_dynamic_type func= get_aes_encrypt_func(MY_AES_ALGORITHM_ECB); my_aes_encrypt_dynamic_type func= get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
int rc= (*func)(crypt_msg, MY_AES_BLOCK_SIZE, //src, srclen int rc= (*func)(crypt_msg, MY_AES_BLOCK_SIZE, //src, srclen
key, &dst_len, //dst, &dstlen key, &dst_len, //dst, &dstlen
(unsigned char*)&mysqld_key, sizeof(mysqld_key), (unsigned char*)&mysqld_key, sizeof(mysqld_key),
NULL, 0, NULL, 0,
1); 1);
if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: getting redo log crypto key " "Redo log crypto: getting redo log crypto key "
"failed."); "failed.");
...@@ -158,7 +164,7 @@ log_block_get_start_lsn( ...@@ -158,7 +164,7 @@ log_block_get_start_lsn(
} }
/*********************************************************************//** /*********************************************************************//**
Call AES CTR to encrypt/decrypt log blocks. */ Call AES to encrypt/decrypt log blocks. */
static static
Crypt_result Crypt_result
log_blocks_crypt( log_blocks_crypt(
...@@ -175,21 +181,22 @@ log_blocks_crypt( ...@@ -175,21 +181,22 @@ log_blocks_crypt(
ulint log_block_no, log_block_start_lsn; ulint log_block_no, log_block_start_lsn;
byte *key; byte *key;
ulint lsn; ulint lsn;
if (is_encrypt) uint aes_method = (uint)redo_aes_method;
{
if (is_encrypt) {
ut_a(log_sys && log_sys->redo_log_crypt_ver != UNENCRYPTED_KEY_VER); ut_a(log_sys && log_sys->redo_log_crypt_ver != UNENCRYPTED_KEY_VER);
key = (byte *)(log_sys->redo_log_crypt_key); key = (byte *)(log_sys->redo_log_crypt_key);
lsn = log_sys->lsn; lsn = log_sys->lsn;
} else { } else {
ut_a(recv_sys && recv_sys->recv_log_crypt_ver != UNENCRYPTED_KEY_VER); ut_a(recv_sys && recv_sys->recv_log_crypt_ver != UNENCRYPTED_KEY_VER);
key = (byte *)(recv_sys->recv_log_crypt_key); key = (byte *)(recv_sys->recv_log_crypt_key);
lsn = srv_start_lsn; lsn = srv_start_lsn;
} }
ut_a(size % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a(size % OS_FILE_LOG_BLOCK_SIZE == 0);
src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE; src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE;
for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE)
{ for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE) {
log_block_no = log_block_get_hdr_no(log_block); log_block_no = log_block_get_hdr_no(log_block);
log_block_start_lsn = log_block_get_start_lsn(lsn, log_block_no); log_block_start_lsn = log_block_get_start_lsn(lsn, log_block_no);
...@@ -205,11 +212,13 @@ log_blocks_crypt( ...@@ -205,11 +212,13 @@ log_blocks_crypt(
mach_write_to_4(aes_ctr_counter + 11, log_block_no); mach_write_to_4(aes_ctr_counter + 11, log_block_no);
bzero(aes_ctr_counter + 15, 1); bzero(aes_ctr_counter + 15, 1);
int rc = (* my_aes_encrypt_dynamic)(log_block + LOG_BLOCK_HDR_SIZE, src_len, my_aes_encrypt_dynamic_type func = get_aes_encrypt_func((enum_my_aes_encryption_algorithm)fil_crypt_map_aes_method(aes_method));
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
(unsigned char*)key, 16, int rc = (*func)(log_block + LOG_BLOCK_HDR_SIZE, src_len,
aes_ctr_counter, MY_AES_BLOCK_SIZE, dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
1); (unsigned char*)key, 16,
aes_ctr_counter, MY_AES_BLOCK_SIZE,
1);
ut_a(rc == AES_OK); ut_a(rc == AES_OK);
ut_a(dst_len == src_len); ut_a(dst_len == src_len);
...@@ -302,13 +311,17 @@ log_crypt_write_checkpoint_buf( ...@@ -302,13 +311,17 @@ log_crypt_write_checkpoint_buf(
{ {
ut_a(log_sys); ut_a(log_sys);
mach_write_to_4(buf + LOG_CRYPT_VER, log_sys->redo_log_crypt_ver); mach_write_to_4(buf + LOG_CRYPT_VER, log_sys->redo_log_crypt_ver);
if (!srv_encrypt_log || if (!srv_encrypt_log ||
log_sys->redo_log_crypt_ver == UNENCRYPTED_KEY_VER) { log_sys->redo_log_crypt_ver == UNENCRYPTED_KEY_VER) {
memset(buf + LOG_CRYPT_MSG, 0, MY_AES_BLOCK_SIZE); memset(buf + LOG_CRYPT_MSG, 0, MY_AES_BLOCK_SIZE);
memset(buf + LOG_CRYPT_IV, 0, MY_AES_BLOCK_SIZE); memset(buf + LOG_CRYPT_IV, 0, MY_AES_BLOCK_SIZE);
memset(buf + LOG_CRYPT_METHOD, 0, 1);
return; return;
} }
ut_a(redo_log_crypt_msg[PURPOSE_BYTE_OFFSET] == redo_log_purpose_byte); ut_a(redo_log_crypt_msg[PURPOSE_BYTE_OFFSET] == redo_log_purpose_byte);
memcpy(buf + LOG_CRYPT_MSG, redo_log_crypt_msg, MY_AES_BLOCK_SIZE); memcpy(buf + LOG_CRYPT_MSG, redo_log_crypt_msg, MY_AES_BLOCK_SIZE);
memcpy(buf + LOG_CRYPT_IV, aes_ctr_nonce, MY_AES_BLOCK_SIZE); memcpy(buf + LOG_CRYPT_IV, aes_ctr_nonce, MY_AES_BLOCK_SIZE);
mach_write_to_1(buf + LOG_CRYPT_METHOD, redo_aes_method);
} }
...@@ -3088,13 +3088,16 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3088,13 +3088,16 @@ recv_recovery_from_checkpoint_start_func(
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN); archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
recv_crypt_ver = mach_read_from_4(buf + LOG_CRYPT_VER); recv_crypt_ver = mach_read_from_4(buf + LOG_CRYPT_VER);
if (recv_crypt_ver == UNENCRYPTED_KEY_VER) if (recv_crypt_ver == UNENCRYPTED_KEY_VER)
{ {
log_init_crypt_msg_and_nonce(); log_init_crypt_msg_and_nonce();
} else { } else {
ut_memcpy(redo_log_crypt_msg, buf + LOG_CRYPT_MSG, MY_AES_BLOCK_SIZE); ut_memcpy(redo_log_crypt_msg, buf + LOG_CRYPT_MSG, MY_AES_BLOCK_SIZE);
ut_memcpy(aes_ctr_nonce, buf + LOG_CRYPT_IV, MY_AES_BLOCK_SIZE); ut_memcpy(aes_ctr_nonce, buf + LOG_CRYPT_IV, MY_AES_BLOCK_SIZE);
redo_aes_method = (byte)mach_read_from_1(buf + LOG_CRYPT_METHOD);
} }
/* Read the first log file header to print a note if this is /* Read the first log file header to print a note if this is
......
...@@ -2450,6 +2450,19 @@ buf_block_align_instance( ...@@ -2450,6 +2450,19 @@ buf_block_align_instance(
== 0xffffffff); == 0xffffffff);
break; break;
case BUF_BLOCK_FILE_PAGE: case BUF_BLOCK_FILE_PAGE:
if (block->page.space
!= page_get_space_id(page_align(ptr))) {
fprintf(stderr, "Block space id %du page space id %lu page type %s\n",
block->page.space, page_get_space_id(page_align(ptr)),
fil_get_page_type_name(mach_read_from_4(ptr + FIL_PAGE_TYPE)));
}
if (block->page.offset
!= page_get_page_no(page_align(ptr))) {
fprintf(stderr, "Block offset %du page offset %lu page type %s\n",
block->page.offset, page_get_page_no(page_align(ptr)),
fil_get_page_type_name(mach_read_from_4(ptr + FIL_PAGE_TYPE)));
}
ut_ad(block->page.space ut_ad(block->page.space
== page_get_space_id(page_align(ptr))); == page_get_space_id(page_align(ptr)));
ut_ad(block->page.offset ut_ad(block->page.offset
......
...@@ -119,33 +119,6 @@ static const unsigned char CRYPT_MAGIC[MAGIC_SZ] = { ...@@ -119,33 +119,6 @@ static const unsigned char CRYPT_MAGIC[MAGIC_SZ] = {
static const unsigned char EMPTY_PATTERN[MAGIC_SZ] = { static const unsigned char EMPTY_PATTERN[MAGIC_SZ] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
/******************************************************************
Map used AES method to crypt scheme
@return used AES crypt scheme */
UNIV_INTERN
uint
fil_crypt_get_aes_method(
/*=====================*/
uint aes_method)
{
switch (aes_method) {
case MY_AES_ALGORITHM_NONE:
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
break;
case MY_AES_ALGORITHM_CTR:
return (uint) CRYPT_SCHEME_1_CTR;
break;
case MY_AES_ALGORITHM_CBC:
return (uint) CRYPT_SCHEME_1_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", aes_method);
ut_error;
}
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
}
/********************************************************************* /*********************************************************************
Init space crypt */ Init space crypt */
...@@ -659,29 +632,6 @@ fil_space_check_encryption_write( ...@@ -659,29 +632,6 @@ fil_space_check_encryption_write(
return true; return true;
} }
/******************************************************************
Map current aes method
@return AES method */
UNIV_INTERN
uint
fil_crypt_map_aes_method(
/*=====================*/
uint aes_method) /*!< in: AES method */
{
switch((fil_crypt_method_t)aes_method) {
case CRYPT_SCHEME_1_CTR:
return (uint)MY_AES_ALGORITHM_CTR;
break;
case CRYPT_SCHEME_1_CBC:
return (uint)MY_AES_ALGORITHM_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", (int)aes_method);
ut_error;
}
}
/****************************************************************** /******************************************************************
Encrypt a page */ Encrypt a page */
UNIV_INTERN UNIV_INTERN
......
...@@ -6992,7 +6992,7 @@ Get crypt data for a tablespace */ ...@@ -6992,7 +6992,7 @@ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
fil_space_crypt_t* fil_space_crypt_t*
fil_space_get_crypt_data( fil_space_get_crypt_data(
/*==================*/ /*=====================*/
ulint id) /*!< in: space id */ ulint id) /*!< in: space id */
{ {
fil_space_t* space; fil_space_t* space;
...@@ -7013,12 +7013,29 @@ fil_space_get_crypt_data( ...@@ -7013,12 +7013,29 @@ fil_space_get_crypt_data(
return(crypt_data); return(crypt_data);
} }
/******************************************************************
Get crypt data for a tablespace */
UNIV_INTERN
fil_space_crypt_t*
fil_space_crypt_data(
/*=================*/
fil_space_t* space) /*!< in: filespace */
{
fil_space_crypt_t* crypt_data = NULL;
if (space != NULL) {
crypt_data = space->crypt_data;
}
return(crypt_data);
}
/****************************************************************** /******************************************************************
Get crypt data for a tablespace */ Get crypt data for a tablespace */
UNIV_INTERN UNIV_INTERN
void void
fil_space_set_crypt_data( fil_space_set_crypt_data(
/*==================*/ /*=====================*/
ulint id, /*!< in: space id */ ulint id, /*!< in: space id */
fil_space_crypt_t* crypt_data) /*!< in: crypt data */ fil_space_crypt_t* crypt_data) /*!< in: crypt data */
{ {
......
...@@ -87,6 +87,7 @@ static ulint srv_data_read, srv_data_written; ...@@ -87,6 +87,7 @@ static ulint srv_data_read, srv_data_written;
For page compressed pages compress the page before actual write For page compressed pages compress the page before actual write
operation. operation.
@return compressed page to be written*/ @return compressed page to be written*/
UNIV_INTERN
byte* byte*
fil_compress_page( fil_compress_page(
/*==============*/ /*==============*/
...@@ -373,6 +374,7 @@ fil_compress_page( ...@@ -373,6 +374,7 @@ fil_compress_page(
/****************************************************************//** /****************************************************************//**
For page compressed pages decompress the page after actual read For page compressed pages decompress the page after actual read
operation. */ operation. */
UNIV_INTERN
void void
fil_decompress_page( fil_decompress_page(
/*================*/ /*================*/
......
...@@ -67,3 +67,54 @@ fil_page_encryption_status( ...@@ -67,3 +67,54 @@ fil_page_encryption_status(
} }
return 0; return 0;
} }
/******************************************************************
Map used AES method to crypt scheme
@return used AES crypt scheme */
UNIV_INLINE
uint
fil_crypt_get_aes_method(
/*=====================*/
uint aes_method)
{
switch (aes_method) {
case MY_AES_ALGORITHM_NONE:
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
break;
case MY_AES_ALGORITHM_CTR:
return (uint) CRYPT_SCHEME_1_CTR;
break;
case MY_AES_ALGORITHM_CBC:
return (uint) CRYPT_SCHEME_1_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", aes_method);
ut_error;
}
return (uint) CRYPT_SCHEME_1_UNENCRYPTED;
}
/******************************************************************
Map current aes method
@return AES method */
UNIV_INLINE
uint
fil_crypt_map_aes_method(
/*=====================*/
uint aes_method) /*!< in: AES method */
{
switch((fil_crypt_method_t)aes_method) {
case CRYPT_SCHEME_1_CTR:
return (uint)MY_AES_ALGORITHM_CTR;
break;
case CRYPT_SCHEME_1_CBC:
return (uint)MY_AES_ALGORITHM_CBC;
break;
default:
ib_logf(IB_LOG_LEVEL_FATAL,
"Current AES method %d not supported.\n", (int)aes_method);
ut_error;
}
}
...@@ -34,6 +34,7 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ...@@ -34,6 +34,7 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
Returns the page compression level flag of the space, or 0 if the space Returns the page compression level flag of the space, or 0 if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return page compression level if page compressed, ULINT_UNDEFINED if space not found */ @return page compression level if page compressed, ULINT_UNDEFINED if space not found */
UNIV_INTERN
ulint ulint
fil_space_get_page_compression_level( fil_space_get_page_compression_level(
/*=================================*/ /*=================================*/
...@@ -42,6 +43,7 @@ fil_space_get_page_compression_level( ...@@ -42,6 +43,7 @@ fil_space_get_page_compression_level(
Returns the page compression flag of the space, or false if the space Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */ @return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool ibool
fil_space_is_page_compressed( fil_space_is_page_compressed(
/*=========================*/ /*=========================*/
...@@ -50,6 +52,7 @@ fil_space_is_page_compressed( ...@@ -50,6 +52,7 @@ fil_space_is_page_compressed(
Returns the page compression flag of the space, or false if the space Returns the page compression flag of the space, or false if the space
is not compressed. The tablespace must be cached in the memory cache. is not compressed. The tablespace must be cached in the memory cache.
@return true if page compressed, false if not or space not found */ @return true if page compressed, false if not or space not found */
UNIV_INTERN
ibool ibool
fil_space_get_page_compressed( fil_space_get_page_compressed(
/*=========================*/ /*=========================*/
...@@ -58,6 +61,7 @@ fil_space_get_page_compressed( ...@@ -58,6 +61,7 @@ fil_space_get_page_compressed(
Returns the atomic writes flag of the space, or false if the space Returns the atomic writes flag of the space, or false if the space
is not using atomic writes. The tablespace must be cached in the memory cache. is not using atomic writes. The tablespace must be cached in the memory cache.
@return atomic write table option value */ @return atomic write table option value */
UNIV_INTERN
atomic_writes_t atomic_writes_t
fil_space_get_atomic_writes( fil_space_get_atomic_writes(
/*=========================*/ /*=========================*/
...@@ -65,6 +69,7 @@ fil_space_get_atomic_writes( ...@@ -65,6 +69,7 @@ fil_space_get_atomic_writes(
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is index page or not Find out wheather the page is index page or not
@return true if page type index page, false if not */ @return true if page type index page, false if not */
UNIV_INTERN
ibool ibool
fil_page_is_index_page( fil_page_is_index_page(
/*===================*/ /*===================*/
...@@ -74,6 +79,7 @@ fil_page_is_index_page( ...@@ -74,6 +79,7 @@ fil_page_is_index_page(
Get the name of the compression algorithm used for page Get the name of the compression algorithm used for page
compression. compression.
@return compression algorithm name or "UNKNOWN" if not known*/ @return compression algorithm name or "UNKNOWN" if not known*/
UNIV_INTERN
const char* const char*
fil_get_compression_alg_name( fil_get_compression_alg_name(
/*=========================*/ /*=========================*/
...@@ -83,6 +89,7 @@ fil_get_compression_alg_name( ...@@ -83,6 +89,7 @@ fil_get_compression_alg_name(
For page compressed pages compress the page before actual write For page compressed pages compress the page before actual write
operation. operation.
@return compressed page to be written*/ @return compressed page to be written*/
UNIV_INTERN
byte* byte*
fil_compress_page( fil_compress_page(
/*==============*/ /*==============*/
...@@ -102,6 +109,7 @@ fil_compress_page( ...@@ -102,6 +109,7 @@ fil_compress_page(
For page compressed pages decompress the page after actual read For page compressed pages decompress the page after actual read
operation. operation.
@return uncompressed page */ @return uncompressed page */
UNIV_INTERN
void void
fil_decompress_page( fil_decompress_page(
/*================*/ /*================*/
...@@ -115,6 +123,7 @@ fil_decompress_page( ...@@ -115,6 +123,7 @@ fil_decompress_page(
/****************************************************************//** /****************************************************************//**
Get space id from fil node Get space id from fil node
@return space id*/ @return space id*/
UNIV_INTERN
ulint ulint
fil_node_get_space_id( fil_node_get_space_id(
/*==================*/ /*==================*/
...@@ -123,13 +132,16 @@ fil_node_get_space_id( ...@@ -123,13 +132,16 @@ fil_node_get_space_id(
/****************************************************************//** /****************************************************************//**
Get block size from fil node Get block size from fil node
@return block size*/ @return block size*/
UNIV_INTERN
ulint ulint
fil_node_get_block_size( fil_node_get_block_size(
/*====================*/
fil_node_t* node); /*!< in: Node where to get block fil_node_t* node); /*!< in: Node where to get block
size */ size */
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is page compressed Find out wheather the page is page compressed
@return true if page is page compressed*/ @return true if page is page compressed */
UNIV_INTERN
ibool ibool
fil_page_is_compressed( fil_page_is_compressed(
/*===================*/ /*===================*/
...@@ -138,6 +150,7 @@ fil_page_is_compressed( ...@@ -138,6 +150,7 @@ fil_page_is_compressed(
/*******************************************************************//** /*******************************************************************//**
Find out wheather the page is page compressed with lzo method Find out wheather the page is page compressed with lzo method
@return true if page is page compressed with lzo method*/ @return true if page is page compressed with lzo method*/
UNIV_INTERN
ibool ibool
fil_page_is_lzo_compressed( fil_page_is_lzo_compressed(
/*=======================*/ /*=======================*/
......
...@@ -23,6 +23,8 @@ extern my_bool srv_encrypt_log; ...@@ -23,6 +23,8 @@ extern my_bool srv_encrypt_log;
extern byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE]; extern byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE];
/* IV to concatenate with counter used by AES_CTR for redo log crypto. */ /* IV to concatenate with counter used by AES_CTR for redo log crypto. */
extern byte aes_ctr_nonce[MY_AES_BLOCK_SIZE]; extern byte aes_ctr_nonce[MY_AES_BLOCK_SIZE];
/* AES method used for redo log encryption/decryption. */
extern byte redo_aes_method;
/*********************************************************************//** /*********************************************************************//**
Generate a 128-bit random message used to generate redo log crypto key. Generate a 128-bit random message used to generate redo log crypto key.
......
...@@ -748,7 +748,7 @@ extern log_t* log_sys; ...@@ -748,7 +748,7 @@ extern log_t* log_sys;
#define LOG_CHECKPOINT_OFFSET_HIGH32 (16 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CHECKPOINT_OFFSET_HIGH32 (16 + LOG_CHECKPOINT_ARRAY_END)
#define LOG_CRYPT_VER (20 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_VER (20 + LOG_CHECKPOINT_ARRAY_END)
/*!< 32-bit key version. Corresponding /*!< 32-bit key version. Corresponding
key has been used for log records with key has been used for log records with
lsn <= the checkpoint' lsn */ lsn <= the checkpoint' lsn */
#define LOG_CRYPT_MSG (24 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_MSG (24 + LOG_CHECKPOINT_ARRAY_END)
/*!< a 128-bit value used to /*!< a 128-bit value used to
...@@ -758,8 +758,10 @@ extern log_t* log_sys; ...@@ -758,8 +758,10 @@ extern log_t* log_sys;
15-byte random number.*/ 15-byte random number.*/
#define LOG_CRYPT_IV (40 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_IV (40 + LOG_CHECKPOINT_ARRAY_END)
/*!< a 128-bit random number used as /*!< a 128-bit random number used as
AES-CTR iv/nonce for redo log */ AES-* iv/nonce for redo log */
#define LOG_CHECKPOINT_SIZE (56 + LOG_CHECKPOINT_ARRAY_END) #define LOG_CRYPT_METHOD (56 + LOG_CHECKPOINT_ARRAY_END)
/*!< AES method used */
#define LOG_CHECKPOINT_SIZE (57 + LOG_CHECKPOINT_ARRAY_END)
/* Offsets of a log file header */ /* Offsets of a log file header */
#define LOG_GROUP_ID 0 /* log group number */ #define LOG_GROUP_ID 0 /* log group number */
......
...@@ -31,6 +31,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com ...@@ -31,6 +31,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "log0log.h" #include "log0log.h"
#include "srv0start.h" // for srv_start_lsn #include "srv0start.h" // for srv_start_lsn
#include "log0recv.h" // for recv_sys #include "log0recv.h" // for recv_sys
#include "fil0fil.h" // for page types
#include "fil0crypt.h" // for aes_method
#include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION #include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION
#include "ha_prototypes.h" // IB_LOG_ #include "ha_prototypes.h" // IB_LOG_
...@@ -44,15 +46,17 @@ UNIV_INTERN my_bool srv_encrypt_log = FALSE; ...@@ -44,15 +46,17 @@ UNIV_INTERN my_bool srv_encrypt_log = FALSE;
static const byte redo_log_purpose_byte = 0x02; static const byte redo_log_purpose_byte = 0x02;
/* Plain text used by AES_ECB to generate redo log crypt key. */ /* Plain text used by AES_ECB to generate redo log crypt key. */
byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE] = {0}; byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE] = {0};
/* IV to concatenate with counter used by AES_CTR for redo log /* IV to concatenate with counter used by AES for redo log
* encryption/decryption. */ * encryption/decryption. */
byte aes_ctr_nonce[MY_AES_BLOCK_SIZE] = {0}; byte aes_ctr_nonce[MY_AES_BLOCK_SIZE] = {0};
/* AES method used for redo log encryption/decryption. */
byte redo_aes_method = 0;
/*********************************************************************//** /*********************************************************************//**
Generate a 128-bit value used to generate crypt key for redo log. Generate a 128-bit value used to generate crypt key for redo log.
It is generated via the concatenation of 1 purpose byte (0x02) and 15-byte It is generated via the concatenation of 1 purpose byte (0x02) and 15-byte
random number. random number.
Init AES-CTR iv/nonce with random number. Init AES iv/nonce with random number.
It is called when: It is called when:
- redo logs do not exist when start up, or - redo logs do not exist when start up, or
- transition from without crypto. - transition from without crypto.
...@@ -70,8 +74,8 @@ log_init_crypt_msg_and_nonce(void) ...@@ -70,8 +74,8 @@ log_init_crypt_msg_and_nonce(void)
/*==============================*/ /*==============================*/
{ {
mach_write_to_1(redo_log_crypt_msg, redo_log_purpose_byte); mach_write_to_1(redo_log_crypt_msg, redo_log_purpose_byte);
if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK)
{ if (my_random_bytes(redo_log_crypt_msg + 1, PURPOSE_BYTE_LEN) != AES_OK) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: generate " "Redo log crypto: generate "
"%u-byte random number as crypto msg failed.", "%u-byte random number as crypto msg failed.",
...@@ -79,14 +83,16 @@ log_init_crypt_msg_and_nonce(void) ...@@ -79,14 +83,16 @@ log_init_crypt_msg_and_nonce(void)
abort(); abort();
} }
if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) if (my_random_bytes(aes_ctr_nonce, MY_AES_BLOCK_SIZE) != AES_OK) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: generate " "Redo log crypto: generate "
"%u-byte random number as AES_CTR nonce failed.", "%u-byte random number failed.",
MY_AES_BLOCK_SIZE); MY_AES_BLOCK_SIZE);
abort(); abort();
} }
/* Set up current AES method */
redo_aes_method = (byte)fil_crypt_get_aes_method(current_aes_dynamic_method);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -99,16 +105,14 @@ log_init_crypt_key( ...@@ -99,16 +105,14 @@ log_init_crypt_key(
const uint crypt_ver, /*< in: key version */ const uint crypt_ver, /*< in: key version */
byte* key) /*< out: crypt key*/ byte* key) /*< out: crypt key*/
{ {
if (crypt_ver == UNENCRYPTED_KEY_VER) if (crypt_ver == UNENCRYPTED_KEY_VER) {
{
ib_logf(IB_LOG_LEVEL_INFO, ib_logf(IB_LOG_LEVEL_INFO,
"Redo log crypto: unencrypted key ver."); "Redo log crypto: unencrypted key ver.");
memset(key, 0, MY_AES_BLOCK_SIZE); memset(key, 0, MY_AES_BLOCK_SIZE);
return; return;
} }
if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) if (crypt_msg[PURPOSE_BYTE_OFFSET] != redo_log_purpose_byte) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: msg type mismatched. " "Redo log crypto: msg type mismatched. "
"Expected: %x; Actual: %x.", "Expected: %x; Actual: %x.",
...@@ -117,8 +121,8 @@ log_init_crypt_key( ...@@ -117,8 +121,8 @@ log_init_crypt_key(
} }
byte mysqld_key[MY_AES_BLOCK_SIZE] = {0}; byte mysqld_key[MY_AES_BLOCK_SIZE] = {0};
if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE))
{ if (get_encryption_key(crypt_ver, mysqld_key, MY_AES_BLOCK_SIZE)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: getting mysqld crypto key " "Redo log crypto: getting mysqld crypto key "
"from key version failed."); "from key version failed.");
...@@ -126,15 +130,16 @@ log_init_crypt_key( ...@@ -126,15 +130,16 @@ log_init_crypt_key(
} }
uint32 dst_len; uint32 dst_len;
my_aes_encrypt_dynamic_type func= get_aes_encrypt_func(MY_AES_ALGORITHM_ECB); my_aes_encrypt_dynamic_type func= get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
int rc= (*func)(crypt_msg, MY_AES_BLOCK_SIZE, //src, srclen int rc= (*func)(crypt_msg, MY_AES_BLOCK_SIZE, //src, srclen
key, &dst_len, //dst, &dstlen key, &dst_len, //dst, &dstlen
(unsigned char*)&mysqld_key, sizeof(mysqld_key), (unsigned char*)&mysqld_key, sizeof(mysqld_key),
NULL, 0, NULL, 0,
1); 1);
if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) if (rc != AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
{
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Redo log crypto: getting redo log crypto key " "Redo log crypto: getting redo log crypto key "
"failed."); "failed.");
...@@ -159,7 +164,7 @@ log_block_get_start_lsn( ...@@ -159,7 +164,7 @@ log_block_get_start_lsn(
} }
/*********************************************************************//** /*********************************************************************//**
Call AES CTR to encrypt/decrypt log blocks. */ Call AES to encrypt/decrypt log blocks. */
static static
Crypt_result Crypt_result
log_blocks_crypt( log_blocks_crypt(
...@@ -176,21 +181,22 @@ log_blocks_crypt( ...@@ -176,21 +181,22 @@ log_blocks_crypt(
ulint log_block_no, log_block_start_lsn; ulint log_block_no, log_block_start_lsn;
byte *key; byte *key;
ulint lsn; ulint lsn;
if (is_encrypt) uint aes_method = (uint)redo_aes_method;
{
if (is_encrypt) {
ut_a(log_sys && log_sys->redo_log_crypt_ver != UNENCRYPTED_KEY_VER); ut_a(log_sys && log_sys->redo_log_crypt_ver != UNENCRYPTED_KEY_VER);
key = (byte *)(log_sys->redo_log_crypt_key); key = (byte *)(log_sys->redo_log_crypt_key);
lsn = log_sys->lsn; lsn = log_sys->lsn;
} else { } else {
ut_a(recv_sys && recv_sys->recv_log_crypt_ver != UNENCRYPTED_KEY_VER); ut_a(recv_sys && recv_sys->recv_log_crypt_ver != UNENCRYPTED_KEY_VER);
key = (byte *)(recv_sys->recv_log_crypt_key); key = (byte *)(recv_sys->recv_log_crypt_key);
lsn = srv_start_lsn; lsn = srv_start_lsn;
} }
ut_a(size % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a(size % OS_FILE_LOG_BLOCK_SIZE == 0);
src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE; src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE;
for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE)
{ for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE) {
log_block_no = log_block_get_hdr_no(log_block); log_block_no = log_block_get_hdr_no(log_block);
log_block_start_lsn = log_block_get_start_lsn(lsn, log_block_no); log_block_start_lsn = log_block_get_start_lsn(lsn, log_block_no);
...@@ -206,11 +212,13 @@ log_blocks_crypt( ...@@ -206,11 +212,13 @@ log_blocks_crypt(
mach_write_to_4(aes_ctr_counter + 11, log_block_no); mach_write_to_4(aes_ctr_counter + 11, log_block_no);
bzero(aes_ctr_counter + 15, 1); bzero(aes_ctr_counter + 15, 1);
int rc = (* my_aes_encrypt_dynamic)(log_block + LOG_BLOCK_HDR_SIZE, src_len, my_aes_encrypt_dynamic_type func = get_aes_encrypt_func((enum_my_aes_encryption_algorithm)fil_crypt_map_aes_method(aes_method));
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
(unsigned char*)key, 16, int rc = (*func)(log_block + LOG_BLOCK_HDR_SIZE, src_len,
aes_ctr_counter, MY_AES_BLOCK_SIZE, dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
1); (unsigned char*)key, 16,
aes_ctr_counter, MY_AES_BLOCK_SIZE,
1);
ut_a(rc == AES_OK); ut_a(rc == AES_OK);
ut_a(dst_len == src_len); ut_a(dst_len == src_len);
...@@ -303,13 +311,17 @@ log_crypt_write_checkpoint_buf( ...@@ -303,13 +311,17 @@ log_crypt_write_checkpoint_buf(
{ {
ut_a(log_sys); ut_a(log_sys);
mach_write_to_4(buf + LOG_CRYPT_VER, log_sys->redo_log_crypt_ver); mach_write_to_4(buf + LOG_CRYPT_VER, log_sys->redo_log_crypt_ver);
if (!srv_encrypt_log || if (!srv_encrypt_log ||
log_sys->redo_log_crypt_ver == UNENCRYPTED_KEY_VER) { log_sys->redo_log_crypt_ver == UNENCRYPTED_KEY_VER) {
memset(buf + LOG_CRYPT_MSG, 0, MY_AES_BLOCK_SIZE); memset(buf + LOG_CRYPT_MSG, 0, MY_AES_BLOCK_SIZE);
memset(buf + LOG_CRYPT_IV, 0, MY_AES_BLOCK_SIZE); memset(buf + LOG_CRYPT_IV, 0, MY_AES_BLOCK_SIZE);
memset(buf + LOG_CRYPT_METHOD, 0, 1);
return; return;
} }
ut_a(redo_log_crypt_msg[PURPOSE_BYTE_OFFSET] == redo_log_purpose_byte); ut_a(redo_log_crypt_msg[PURPOSE_BYTE_OFFSET] == redo_log_purpose_byte);
memcpy(buf + LOG_CRYPT_MSG, redo_log_crypt_msg, MY_AES_BLOCK_SIZE); memcpy(buf + LOG_CRYPT_MSG, redo_log_crypt_msg, MY_AES_BLOCK_SIZE);
memcpy(buf + LOG_CRYPT_IV, aes_ctr_nonce, MY_AES_BLOCK_SIZE); memcpy(buf + LOG_CRYPT_IV, aes_ctr_nonce, MY_AES_BLOCK_SIZE);
mach_write_to_1(buf + LOG_CRYPT_METHOD, redo_aes_method);
} }
...@@ -3164,13 +3164,16 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3164,13 +3164,16 @@ recv_recovery_from_checkpoint_start_func(
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN); archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
recv_crypt_ver = mach_read_from_4(buf + LOG_CRYPT_VER); recv_crypt_ver = mach_read_from_4(buf + LOG_CRYPT_VER);
if (recv_crypt_ver == UNENCRYPTED_KEY_VER) if (recv_crypt_ver == UNENCRYPTED_KEY_VER)
{ {
log_init_crypt_msg_and_nonce(); log_init_crypt_msg_and_nonce();
} else { } else {
ut_memcpy(redo_log_crypt_msg, buf + LOG_CRYPT_MSG, MY_AES_BLOCK_SIZE); ut_memcpy(redo_log_crypt_msg, buf + LOG_CRYPT_MSG, MY_AES_BLOCK_SIZE);
ut_memcpy(aes_ctr_nonce, buf + LOG_CRYPT_IV, MY_AES_BLOCK_SIZE); ut_memcpy(aes_ctr_nonce, buf + LOG_CRYPT_IV, MY_AES_BLOCK_SIZE);
redo_aes_method = (byte)mach_read_from_1(buf + LOG_CRYPT_METHOD);
} }
/* Read the first log file header to print a note if this is /* Read the first log file header to print a note if this is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment