Skip to content

Commit

Permalink
Encryption cleanup
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Jan Lindström authored and vuvova committed Apr 7, 2015
1 parent 0ba9fa3 commit 71ec046
Show file tree
Hide file tree
Showing 30 changed files with 676 additions and 186 deletions.
4 changes: 2 additions & 2 deletions include/my_aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ extern MYSQL_PLUGIN_IMPORT my_aes_decrypt_dynamic_type my_aes_decrypt_dynamic;

enum enum_my_aes_encryption_algorithm
{
MY_AES_ALGORITHM_NONE, MY_AES_ALGORITHM_ECB, MY_AES_ALGORITHM_CBC,
MY_AES_ALGORITHM_CTR
MY_AES_ALGORITHM_NONE, 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);
Expand Down
3 changes: 0 additions & 3 deletions mysql-test/include/encryption_algorithms.combinations
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
[cbc]
encryption-algorithm=aes_cbc

[ecb]
encryption-algorithm=aes_ecb

[ctr]
encryption-algorithm=aes_ctr
4 changes: 2 additions & 2 deletions mysql-test/r/mysqld--help.result
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ The following options may be given as the first argument:
execution)
--encryption-algorithm=name
Which encryption algorithm to use for table encryption.
aes_cbc is the recommended one.. One of: none, aes_ecb,
aes_cbc, aes_ctr
aes_cbc is the recommended one.. One of: none, aes_cbc,
aes_ctr
--enforce-storage-engine=name
Force the use of a storage engine for new tables
--event-scheduler[=name]
Expand Down
89 changes: 89 additions & 0 deletions mysql-test/suite/innodb/r/innodb_encryption_change.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
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;
7 changes: 7 additions & 0 deletions mysql-test/suite/innodb/t/innodb_encryption_change.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--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

229 changes: 229 additions & 0 deletions mysql-test/suite/innodb/t/innodb_encryption_change.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#
#
#
-- 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

5 changes: 3 additions & 2 deletions mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ select @@global.encryption_algorithm;
none
select @@session.encryption_algorithm;
ERROR HY000: Variable 'encryption_algorithm' is a GLOBAL variable
set global encryption_algorithm="none";
ERROR HY000: Variable 'encryption_algorithm' is a read only variable
set global encryption_algorithm = aes_cbc;
set global encryption_algorithm = aes_cbc;
ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
4 changes: 2 additions & 2 deletions mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -706,8 +706,8 @@ VARIABLE_COMMENT Which encryption algorithm to use for table encryption. aes_cbc
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST none,aes_ecb,aes_cbc,aes_ctr
READ_ONLY YES
ENUM_VALUE_LIST none,aes_cbc,aes_ctr
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME ENCRYPT_TMP_DISK_TABLES
SESSION_VALUE NULL
Expand Down
Loading

0 comments on commit 71ec046

Please sign in to comment.