[Commits] 3dec5a7: MDEV-7796: encryption_algorithm configuration variable is static and can't be changed

Jan Lindström jan.lindstrom at mariadb.com
Mon Mar 23 17:47:55 EET 2015


revision-id: 3dec5a7e4d4b376a12bbd1addb499ad47f7ca015
parent(s): 3578419b778876fc1e7ec2a6994b9273b5d2b166
committer: Jan Lindström
branch nick: 10.1-innodb-bug
timestamp: 2015-03-23 17:39:15 +0200
message:

MDEV-7796: encryption_algorithm configuration variable is static and can't be changed

Major changes:
- Use same crypt scheme and InnoDB page storage format for both google and eperi
  AES_CTR / AES_CBC:
    L = AES_ECB(KEY, IV)
    CRYPT(PAGE) = AES_*(KEY=L, IV=C, PAGE)
- Cache also file_key_management_plugin keys
- Remove unnecessary page types
- Remove AES_ECB because it is too unsecure
- Make encryption_algorithm changeable
- Store used AES method on checkpoint and every log record
- Store used AES method on every InnoDB page that is encrypted on
  dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4
- Store used compression algorithm to dst_frame +  FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 6
- No checksum is stored for encrypted/compressed tables

Other:
- Add more comments and remove unnecessary code
- Beatify code to conform InnoDB coding style
- add UNIV_INTERN to avoid incorrect function usage

---
 include/my_aes.h                                   |   4 +-
 .../include/encryption_algorithms.combinations     |   3 -
 mysql-test/r/mysqld--help.result                   |   4 +-
 .../sys_vars/r/encryption_algorithm_basic.result   |   2 -
 .../sys_vars/r/sysvars_server_notembedded.result   |   4 +-
 .../sys_vars/t/encryption_algorithm_basic.test     |   5 -
 sql/sys_vars.cc                                    |   4 +-
 storage/xtradb/buf/buf0buf.cc                      |  20 +-
 storage/xtradb/fil/fil0crypt.cc                    | 884 +++++++++++++--------
 storage/xtradb/fil/fil0fil.cc                      |  21 +-
 storage/xtradb/fil/fil0pagecompress.cc             |   2 +
 storage/xtradb/include/fil0crypt.h                 |  41 +
 storage/xtradb/include/fil0fil.h                   |  74 +-
 storage/xtradb/include/fil0pagecompress.h          |  15 +-
 storage/xtradb/include/fil0pageencryption.h        |   8 -
 storage/xtradb/include/fsp0pageencryption.ic       |  18 +-
 storage/xtradb/include/log0crypt.h                 |   2 +
 storage/xtradb/include/log0log.h                   |   8 +-
 storage/xtradb/log/log0crypt.cc                    |  63 +-
 storage/xtradb/log/log0recv.cc                     |   3 +
 storage/xtradb/os/os0file.cc                       |   9 +-
 21 files changed, 750 insertions(+), 444 deletions(-)

diff --git a/include/my_aes.h b/include/my_aes.h
index 057fa1e..de56596 100644
--- a/include/my_aes.h
+++ b/include/my_aes.h
@@ -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);
diff --git a/mysql-test/include/encryption_algorithms.combinations b/mysql-test/include/encryption_algorithms.combinations
index 09c1e91..a97d6b7 100644
--- a/mysql-test/include/encryption_algorithms.combinations
+++ b/mysql-test/include/encryption_algorithms.combinations
@@ -1,8 +1,5 @@
 [cbc]
 encryption-algorithm=aes_cbc
 
-[ecb]
-encryption-algorithm=aes_ecb
-
 [ctr]
 encryption-algorithm=aes_ctr
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 7d59ecd..edc4fe2 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -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] 
diff --git a/mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result b/mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result
index a9101b0..c4522b5 100644
--- a/mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result
+++ b/mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result
@@ -3,5 +3,3 @@ 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
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 7908300..9d4c2f7 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -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
diff --git a/mysql-test/suite/sys_vars/t/encryption_algorithm_basic.test b/mysql-test/suite/sys_vars/t/encryption_algorithm_basic.test
index 065453e..fec377b 100644
--- a/mysql-test/suite/sys_vars/t/encryption_algorithm_basic.test
+++ b/mysql-test/suite/sys_vars/t/encryption_algorithm_basic.test
@@ -6,8 +6,3 @@ select @@global.encryption_algorithm;
 --error ER_INCORRECT_GLOBAL_LOCAL_VAR
 select @@session.encryption_algorithm;
 
-#
-# show that it's not writable
-#
---error 1238
-set global encryption_algorithm="none";
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 734b6ed..5130860 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5186,11 +5186,11 @@ static Sys_var_mybool Sys_encrypt_tmp_disk_tables(
        CMD_LINE(OPT_ARG), DEFAULT(FALSE));
 
 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(
        "encryption_algorithm",
        "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));
 
 static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var)
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 0ef97fd..b02dd7e 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -574,7 +574,7 @@ buf_page_is_corrupted(
 	ulint		zip_size)	/*!< in: size of compressed page;
 					0 for uncompressed pages */
 {
-	ulint		page_encrypted = fil_page_is_compressed_encrypted(read_buf) || fil_page_is_encrypted(read_buf);
+	ibool		page_encrypted = fil_page_is_encrypted(read_buf);
 	ulint		checksum_field1;
 	ulint		checksum_field2;
 	ibool		crc32_inited = FALSE;
@@ -2439,6 +2439,19 @@ buf_block_align_instance(
 				      == 0xffffffff);
 				break;
 			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
 				      == page_get_space_id(page_align(ptr)));
 				ut_ad(block->page.offset
@@ -5938,7 +5951,7 @@ buf_page_decrypt_after_read(
 
 	unsigned key_version =
 		mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
-	bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame);
+	bool page_compressed = fil_page_is_compressed(dst_frame);
 
 	if (key_version == 0) {
 		/* the page we read is unencrypted */
@@ -5968,13 +5981,14 @@ buf_page_decrypt_after_read(
 			src_frame = bpage->crypt_buf = (byte*)ut_align(bpage->crypt_buf_free, UNIV_PAGE_SIZE);
 			memcpy(bpage->crypt_buf, dst_frame, size);
 		}
+
 		/* decrypt from src_frame to dst_frame */
 		fil_space_decrypt(bpage->space,
 				  src_frame, size, dst_frame);
 
 		/* decompress from dst_frame to comp_buf and then copy to
 		buffer pool */
-		if (page_compressed_encrypted) {
+		if (page_compressed) {
 			if (bpage->comp_buf_free == NULL) {
 				bpage->comp_buf_free = (byte *)malloc(UNIV_PAGE_SIZE*2);
 				// TODO: is 4k aligment enough ?
diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc
index 0d2187c..00f5f9e 100644
--- a/storage/xtradb/fil/fil0crypt.cc
+++ b/storage/xtradb/fil/fil0crypt.cc
@@ -42,7 +42,7 @@ Modified           Jan Lindström jan.lindstrom at mariadb.com
 
 #include <my_aes.h>
 #include <math.h>
-
+#include "fil0crypt.h"
 
 /** Mutex for keys */
 UNIV_INTERN ib_mutex_t fil_crypt_key_mutex;
@@ -130,16 +130,28 @@ static const unsigned char EMPTY_PATTERN[MAGIC_SZ] = {
 /**
  * CRYPT_SCHEME_1
  *
- * L = AES_ECB(KEY, IV)
- * CRYPT(PAGE) = AES_CRT(KEY=L, IV=C, PAGE)
+ * AES_CTR / AES_CBC:
+ *  L = AES_ECB(KEY, IV)
+ *  CRYPT(PAGE) = AES_CRT(KEY=L, IV=C, PAGE)
  */
+
 #define CRYPT_SCHEME_1 1
 #define CRYPT_SCHEME_1_IV_LEN 16
-// cached L given key_version
+
+/* Currently supported encryption methods */
+typedef enum {
+	CRYPT_SCHEME_1_UNENCRYPTED = 0,		/*<! Space is unencrypted        */
+	CRYPT_SCHEME_1_CTR = 1,			/*<! Space is encrypted with CTR */
+	CRYPT_SCHEME_1_CBC = 4,			/*<! Space is encrypted with CBC */
+} fil_crypt_method_t;
+
+/* Cached L or key for given key_version */
 struct key_struct
 {
-	uint key_version;
-	byte key[CRYPT_SCHEME_1_IV_LEN];
+	uint key_version;			/*!< Key version used as
+						identifier */
+	byte key[MY_AES_MAX_KEY_LENGTH];	/*!< Cached L or key */
+	uint key_length;			/*!< Key length */
 };
 
 struct fil_space_rotate_state_t
@@ -175,11 +187,40 @@ struct fil_space_crypt_struct
 	byte iv[1];	    // IV-data
 };
 
+/******************************************************************
+Map used AES method to crypt scheme
+ at 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 */
 UNIV_INTERN
 void
 fil_space_crypt_init()
+/*==================*/
 {
 	mutex_create(fil_crypt_key_mutex_key,
 		     &fil_crypt_key_mutex, SYNC_NO_ORDER_CHECK);
@@ -196,6 +237,7 @@ Cleanup space crypt */
 UNIV_INTERN
 void
 fil_space_crypt_cleanup()
+/*=====================*/
 {
 	os_event_free(fil_crypt_throttle_sleep_event);
 }
@@ -204,31 +246,35 @@ fil_space_crypt_cleanup()
 Get key bytes for a space/key-version */
 static
 void
-fil_crypt_get_key(byte *dst, uint* key_length,
-	fil_space_crypt_t* crypt_data, uint version, bool page_encrypted)
+fil_crypt_get_key(
+/*==============*/
+	byte*		dst,		/*<! out: Key */
+	uint*		key_length,	/*<! out: Key length */
+	fil_space_crypt_t* crypt_data,	/*<! in: crypt data */
+	uint 		version)	/*<! in: Key version */
 {
         unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
 
 	mutex_enter(&crypt_data->mutex);
 
-        if (!page_encrypted) {
-		// Check if we already have key
-		for (uint i = 0; i < crypt_data->key_count; i++) {
-			if (crypt_data->keys[i].key_version == version) {
-				memcpy(dst, crypt_data->keys[i].key,
-					sizeof(crypt_data->keys[i].key));
-				mutex_exit(&crypt_data->mutex);
-				return;
-			}
+	// Check if we already have key
+	for (uint i = 0; i < crypt_data->key_count; i++) {
+		if (crypt_data->keys[i].key_version == version) {
+			memcpy(dst, crypt_data->keys[i].key,
+			       crypt_data->keys[i].key_length);
+			*key_length = crypt_data->keys[i].key_length;
+			mutex_exit(&crypt_data->mutex);
+			return;
 		}
-		// Not found!
-		crypt_data->keyserver_requests++;
+	}
 
-		// Rotate keys to make room for a new
-		for (uint i = 1; i < array_elements(crypt_data->keys); i++) {
-			crypt_data->keys[i] = crypt_data->keys[i - 1];
-		}
-        }
+	// Not found!
+	crypt_data->keyserver_requests++;
+
+	// Rotate keys to make room for a new
+	for (uint i = 1; i < array_elements(crypt_data->keys); i++) {
+		crypt_data->keys[i] = crypt_data->keys[i - 1];
+	}
 
 	if (has_encryption_key(version)) {
 		int rc;
@@ -247,51 +293,45 @@ fil_crypt_get_key(byte *dst, uint* key_length,
 		ut_error;
 	}
 
+	/* Now compute L by encrypting IV using this key. Note
+	that we use random IV from crypt data. */
+	const unsigned char* src = crypt_data->iv;
+	const int srclen = crypt_data->iv_length;
+	unsigned char* buf = crypt_data->keys[0].key;
+	uint32 buflen = CRYPT_SCHEME_1_IV_LEN;
 
-	// do ctr key initialization
-	if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR)
-	{
-		/* Now compute L by encrypting IV using this key. Note
-		that we use random IV from crypt data. */
-		const unsigned char* src = crypt_data->iv;
-		const int srclen = crypt_data->iv_length;
-		unsigned char* buf = page_encrypted ? keybuf : crypt_data->keys[0].key;
-		uint32 buflen = page_encrypted ? *key_length : sizeof(crypt_data->keys[0].key);
-
-		// call ecb explicit
-		my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
-		int rc = (*func)(src, srclen,
-			buf, &buflen,
-			(unsigned char*)keybuf, *key_length,
-			NULL, 0,
-			1);
-
-		if (rc != AES_OK) {
-			ib_logf(IB_LOG_LEVEL_FATAL,
-				"Unable to encrypt key-block "
-				" src: %p srclen: %d buf: %p buflen: %d."
-				" return-code: %d. Can't continue!\n",
-				src, srclen, buf, buflen, rc);
-			ut_error;
-		}
+	/* We use AES_ECB to encryp IV */
+	my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
 
-		if (!page_encrypted) {
-			crypt_data->keys[0].key_version = version;
-			crypt_data->key_count++;
+	int rc = (*func)(src,		/* Data to be encrypted = IV */
+			srclen,		/* data length */
+			buf,		/* Output buffer */
+			&buflen,	/* Output buffer */
+			keybuf,		/* Key */
+			*key_length,	/* Key length */
+			NULL,		/* AES_ECB does not use IV */
+			0,		/* IV-length */
+			1);		/* NoPadding */
 
-			if (crypt_data->key_count > array_elements(crypt_data->keys)) {
-				crypt_data->key_count = array_elements(crypt_data->keys);
-			}
-		}
+	if (rc != AES_OK) {
+		ib_logf(IB_LOG_LEVEL_FATAL,
+			"Unable to encrypt key-block "
+			" src: %p srclen: %d buf: %p buflen: %d."
+			" return-code: %d. Can't continue!\n",
+			src, srclen, buf, buflen, rc);
+		ut_error;
+	}
 
-		// set the key size to the aes block size because this encrypted data is the key
-		*key_length = MY_AES_BLOCK_SIZE;
-		memcpy(dst, buf, buflen);
-	} else {
-		// otherwise keybuf contains the right key
-		memcpy(dst, keybuf, *key_length);
+	crypt_data->keys[0].key_version = version;
+	crypt_data->key_count++;
+	*key_length = buflen;
+	crypt_data->keys[0].key_length = buflen;
+
+	if (crypt_data->key_count > array_elements(crypt_data->keys)) {
+		crypt_data->key_count = array_elements(crypt_data->keys);
 	}
 
+	memcpy(dst, buf, buflen);
 	mutex_exit(&crypt_data->mutex);
 }
 
@@ -299,8 +339,12 @@ fil_crypt_get_key(byte *dst, uint* key_length,
 Get key bytes for a space/latest(key-version) */
 static inline
 void
-fil_crypt_get_latest_key(byte *dst, uint* key_length,
-			 fil_space_crypt_t* crypt_data, uint *version)
+fil_crypt_get_latest_key(
+/*=====================*/
+	byte*		dst,		/*!< out: Key */
+	uint*		key_length,	/*!< out: Key length */
+	fil_space_crypt_t* crypt_data, 	/*!< in: crypt data */
+	uint*		version)	/*!< in: Key version */
 {
 	if (srv_encrypt_tables) {
 	        // used for key rotation - get the next key id from the key provider
@@ -312,29 +356,33 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length,
 		}
 	}
 
-	return fil_crypt_get_key(dst, key_length, crypt_data, *version, srv_encrypt_tables == FALSE);
+	return fil_crypt_get_key(dst, key_length, crypt_data, *version);
 }
 
 /******************************************************************
-Create a fil_space_crypt_t object */
+Create a fil_space_crypt_t object
+ at return crypt object */
 UNIV_INTERN
 fil_space_crypt_t*
 fil_space_create_crypt_data()
+/*=========================*/
 {
 	const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
 	const uint sz = sizeof(fil_space_crypt_t) + iv_length;
 	fil_space_crypt_t* crypt_data =
 		static_cast<fil_space_crypt_t*>(malloc(sz));
+	uint aes_method = current_aes_dynamic_method;
+
 	memset(crypt_data, 0, sz);
 
 	if (srv_encrypt_tables == FALSE) {
-		crypt_data->type = CRYPT_SCHEME_UNENCRYPTED;
 		crypt_data->min_key_version = 0;
 	} else {
-		crypt_data->type = CRYPT_SCHEME_1;
 		crypt_data->min_key_version = get_latest_encryption_key_version();
 	}
 
+	/* Set up the current AES method */
+	crypt_data->type = (fil_crypt_method_t)fil_crypt_get_aes_method(aes_method);
 	mutex_create(fil_crypt_data_mutex_key,
 		&crypt_data->mutex, SYNC_NO_ORDER_CHECK);
 	crypt_data->iv_length = iv_length;
@@ -346,13 +394,18 @@ fil_space_create_crypt_data()
 Compare two crypt objects */
 UNIV_INTERN
 int
-fil_space_crypt_compare(const fil_space_crypt_t* crypt_data1,
-			const fil_space_crypt_t* crypt_data2)
+fil_space_crypt_compare(
+/*====================*/
+	const fil_space_crypt_t* crypt_data1,/*!< in: Crypt data */
+	const fil_space_crypt_t* crypt_data2)/*!< in: Crypt data */
 {
-	ut_a(crypt_data1->type == CRYPT_SCHEME_UNENCRYPTED ||
-	     crypt_data1->type == CRYPT_SCHEME_1);
-	ut_a(crypt_data2->type == CRYPT_SCHEME_UNENCRYPTED ||
-	     crypt_data2->type == CRYPT_SCHEME_1);
+	ut_a(crypt_data1->type == CRYPT_SCHEME_1_UNENCRYPTED ||
+	     crypt_data1->type == CRYPT_SCHEME_1_CTR ||
+	     crypt_data1->type == CRYPT_SCHEME_1_CBC);
+
+	ut_a(crypt_data2->type == CRYPT_SCHEME_1_UNENCRYPTED ||
+	     crypt_data2->type == CRYPT_SCHEME_1_CTR ||
+	     crypt_data1->type == CRYPT_SCHEME_1_CBC);
 
 	ut_a(crypt_data1->iv_length == CRYPT_SCHEME_1_IV_LEN);
 	ut_a(crypt_data2->iv_length == CRYPT_SCHEME_1_IV_LEN);
@@ -365,10 +418,15 @@ fil_space_crypt_compare(const fil_space_crypt_t* crypt_data1,
 }
 
 /******************************************************************
-Read crypt data from a page (0) */
+Read crypt data from a page (0)
+ at return crypt data from page 0. */
 UNIV_INTERN
 fil_space_crypt_t*
-fil_space_read_crypt_data(ulint space, const byte* page, ulint offset)
+fil_space_read_crypt_data(
+/*======================*/
+	ulint		space,	/*!< in: file space id*/
+	const byte*	page,	/*!< in: page 0 */
+	ulint		offset)	/*!< in: offset */
 {
 	if (memcmp(page + offset, EMPTY_PATTERN, MAGIC_SZ) == 0) {
 		/* crypt is not stored */
@@ -393,8 +451,10 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset)
 
 	ulint type = mach_read_from_1(page + offset + MAGIC_SZ + 0);
 
-	if (! (type == CRYPT_SCHEME_UNENCRYPTED ||
-	       type == CRYPT_SCHEME_1)) {
+	if (! (type == CRYPT_SCHEME_1_UNENCRYPTED ||
+	       type == CRYPT_SCHEME_1_CTR ||
+	       type == CRYPT_SCHEME_1_CBC)) {
+
 		ib_logf(IB_LOG_LEVEL_ERROR,
 			"Found non sensible crypt scheme: %lu for space %lu "
 			" offset: %lu bytes: "
@@ -449,7 +509,9 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset)
 Free a crypt data object */
 UNIV_INTERN
 void
-fil_space_destroy_crypt_data(fil_space_crypt_t **crypt_data)
+fil_space_destroy_crypt_data(
+/*=========================*/
+	fil_space_crypt_t **crypt_data)	/*!< out: crypt data */
 {
 	if (crypt_data != NULL && (*crypt_data) != NULL) {
 		/* lock (and unlock) mutex to make sure no one has it locked
@@ -466,10 +528,14 @@ fil_space_destroy_crypt_data(fil_space_crypt_t **crypt_data)
 Write crypt data to a page (0) */
 static
 void
-fil_space_write_crypt_data_low(fil_space_crypt_t *crypt_data,
-			       ulint type,
-			       byte* page, ulint offset,
-			       ulint maxsize, mtr_t* mtr)
+fil_space_write_crypt_data_low(
+/*===========================*/
+	fil_space_crypt_t*	crypt_data,	/*<! out: crypt data */
+	ulint			type,		/*<! in: crypt scheme */
+	byte* 			page,		/*<! in: page 0 */
+	ulint			offset,		/*<! in: offset */
+	ulint			maxsize,	/*<! in: size of crypt data */
+	mtr_t*			mtr)		/*<! in: minitransaction */
 {
 	ut_a(offset > 0 && offset < UNIV_PAGE_SIZE);
 	ulint space_id = mach_read_from_4(
@@ -492,10 +558,8 @@ fil_space_write_crypt_data_low(fil_space_crypt_t *crypt_data,
 	mlog_write_ulint(page + offset + MAGIC_SZ + 2 + len, min_key_version,
 			 MLOG_4BYTES, mtr);
 
-	DBUG_EXECUTE_IF("ib_file_crypt_redo_crash_1",
-		ut_error;);
-
 	byte* log_ptr = mlog_open(mtr, 11 + 12 + len);
+
 	if (log_ptr != NULL) {
 		log_ptr = mlog_write_initial_log_record_fast(
 			page,
@@ -515,17 +579,19 @@ fil_space_write_crypt_data_low(fil_space_crypt_t *crypt_data,
 
 		mlog_catenate_string(mtr, crypt_data->iv, len);
 	}
-
-	DBUG_EXECUTE_IF("ib_file_crypt_redo_crash_2",
-		ut_error;);
 }
 
 /******************************************************************
 Write crypt data to a page (0) */
 UNIV_INTERN
 void
-fil_space_write_crypt_data(ulint space, byte* page, ulint offset,
-			   ulint maxsize, mtr_t* mtr)
+fil_space_write_crypt_data(
+/*=======================*/
+	ulint			space,		/*<! in: file space */
+	byte* 			page,		/*<! in: page 0 */
+	ulint			offset,		/*<! in: offset */
+	ulint			maxsize,	/*<! in: size of crypt data */
+	mtr_t*			mtr)		/*<! in: minitransaction */
 {
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
 	ibool page_encrypted = fil_space_is_page_encrypted(space);
@@ -542,11 +608,15 @@ fil_space_write_crypt_data(ulint space, byte* page, ulint offset,
 }
 
 /******************************************************************
-Parse a MLOG_FILE_WRITE_CRYPT_DATA log entry */
+Parse a MLOG_FILE_WRITE_CRYPT_DATA log entry
+ at return position on log buffer */
 UNIV_INTERN
 byte*
-fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
-			   buf_block_t* block)
+fil_parse_write_crypt_data(
+/*=======================*/
+	byte*		ptr,	/*!< in: Log entry start */
+	byte*		end_ptr,/*!< in: Log entry end */
+	buf_block_t*	block)	/*!< in: buffer block */
 {
 	/* check that redo log entry is complete */
 	uint entry_size =
@@ -569,8 +639,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
 	uint len = mach_read_from_1(ptr);
 	ptr += 1;
 
-	ut_a(type == CRYPT_SCHEME_UNENCRYPTED ||
-	     type == CRYPT_SCHEME_1); // only supported
+	ut_a(type == CRYPT_SCHEME_1_UNENCRYPTED ||
+	     type == CRYPT_SCHEME_1_CTR ||
+	     type == CRYPT_SCHEME_1_CBC); // supported methods
+
 	ut_a(len == CRYPT_SCHEME_1_IV_LEN); // only supported
 	uint min_key_version = mach_read_from_4(ptr);
 	ptr += 4;
@@ -595,7 +667,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
 Clear crypt data from a page (0) */
 UNIV_INTERN
 void
-fil_space_clear_crypt_data(byte* page, ulint offset)
+fil_space_clear_crypt_data(
+/*=======================*/
+	byte*	page, 	/*!< in/out: Page 0 */
+	ulint 	offset)	/*!< in: Offset */
 {
 	//TODO(jonaso): pass crypt-data and read len from there
 	ulint len = CRYPT_SCHEME_1_IV_LEN;
@@ -609,7 +684,8 @@ fil_space_clear_crypt_data(byte* page, ulint offset)
 }
 
 /*********************************************************************
-Check if page shall be encrypted before write */
+Check if page shall be encrypted before write
+ at return true if page should be encrypted, false if not */
 UNIV_INTERN
 bool
 fil_space_check_encryption_write(
@@ -633,26 +709,58 @@ fil_space_check_encryption_write(
 }
 
 /******************************************************************
+Map current aes method
+ at 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 */
 UNIV_INTERN
 void
-fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
-	const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key)
+fil_space_encrypt(
+/*==============*/
+	ulint		space,		/*!< in: Space id */
+	ulint		offset,		/*!< in: Page offset */
+	lsn_t		lsn,		/*!< in: lsn */
+	const byte*	src_frame,	/*!< in: Source page to be encrypted */
+	ulint		zip_size,	/*!< in: compressed size if
+					row_format compressed */
+	byte*		dst_frame,	/*!< in: outbut buffer */
+	ulint		encryption_key)	/*!< in: encryption key id if page
+					encrypted */
 {
 	fil_space_crypt_t* crypt_data=NULL;
 	ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
-
-	// get key (L)
-	uint key_version = encryption_key;
-	byte key[MY_AES_MAX_KEY_LENGTH];
+	uint key_version = (uint)encryption_key;
+	unsigned char key[MY_AES_MAX_KEY_LENGTH];
 	uint key_length=MY_AES_MAX_KEY_LENGTH;
+	uint aes_method;
+	unsigned char iv[MY_AES_BLOCK_SIZE];
 
 	ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
 
 	if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR
-			|| orig_page_type==FIL_PAGE_TYPE_XDES
-			|| orig_page_type== FIL_PAGE_PAGE_ENCRYPTED
-			|| orig_page_type== FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
+		|| orig_page_type==FIL_PAGE_TYPE_XDES) {
+		/* File space header or extent descriptor do not need to be
+		encrypted. */
 		//TODO: is this really needed ?
 		memcpy(dst_frame, src_frame, page_size);
 		return;
@@ -667,63 +775,56 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
 		return;
 	}
 
+	/* Load the IV or counter (depending to the encryption algorithm used) */
 	fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version);
+	aes_method =  fil_crypt_get_aes_method(current_aes_dynamic_method);
 
-	/* Load the iv or counter (depending to the encryption algorithm used) */
-	unsigned char iv[MY_AES_BLOCK_SIZE];
-
-	if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
-		// create counter block (C)
-		mach_write_to_4(iv + 0, space);
-		ulint space_offset = mach_read_from_4(
-			src_frame + FIL_PAGE_OFFSET);
-		mach_write_to_4(iv + 4, space_offset);
-		mach_write_to_8(iv + 8, lsn);
-	} else {
-		// Get random IV from crypt_data
-		mutex_enter(&crypt_data->mutex);
-		memcpy(iv, crypt_data->iv, crypt_data->iv_length);
-		mutex_exit(&crypt_data->mutex);
-	}
+	/* For AES CTR create counter and AES CBS IV */
+	mach_write_to_4(iv + 0, space);
+	ulint space_offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
+	mach_write_to_4(iv + 4, space_offset);
+	mach_write_to_8(iv + 8, lsn);
 
 	ibool page_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
-	ibool page_encrypted  = fil_space_is_page_encrypted(space);
-	ulint compression_alg = mach_read_from_8(src_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+	ulint compression_algo = page_compressed ? mach_read_from_8(src_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) : 0;
 
-	// copy page header
+	/* FIL page header is not encrypted */
 	memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
 
-	if (page_encrypted && !page_compressed) {
-		// key id
-		mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
-			key_version);
-		// original page type
-		mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 2,
-			orig_page_type);
-		// new page type
-		mach_write_to_2(dst_frame+FIL_PAGE_TYPE, FIL_PAGE_PAGE_ENCRYPTED);
-	} else {
-		// store key version
-		mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
-			        key_version);
-	}
+	/* Store key version */
+	mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, key_version);
 
-	// encrypt page data
+	/* Calculate the start offset in a page */
 	ulint unencrypted_bytes = FIL_PAGE_DATA + FIL_PAGE_DATA_END;
 	ulint srclen = page_size - unencrypted_bytes;
 	const byte* src = src_frame + FIL_PAGE_DATA;
 	byte* dst = dst_frame + FIL_PAGE_DATA;
-	uint32 dstlen;
+	uint32 dstlen=0;
 
+	/* For page compressed tables we encrypt only the actual compressed
+	payload. Note that first two bytes of page data is actual payload
+	size and that should not be encrypted. */
 	if (page_compressed) {
-		srclen = page_size -  FIL_PAGE_DATA;
-	}
-
-	int rc = (* my_aes_encrypt_dynamic)(src, srclen,
-	                                    dst, &dstlen,
-	                                    (unsigned char*)key, key_length,
-	                                    (unsigned char*)iv, sizeof(iv),
-	                                    1);
+		ulint payload = mach_read_from_2(src_frame +  FIL_PAGE_DATA);
+		mach_write_to_2(dst_frame +  FIL_PAGE_DATA, payload);
+		srclen = payload;
+		src+=2;
+		dst+=2;
+	}
+
+	/* Get encryption method */
+	my_aes_encrypt_dynamic_type func = get_aes_encrypt_func((enum_my_aes_encryption_algorithm)fil_crypt_map_aes_method(aes_method));
+
+	/* Encrypt the data */
+	int rc = (*func)(src,		/* Original page */
+			srclen,		/* Page length */
+			dst, 		/* Output buffer */
+			&dstlen,	/* Output length */
+			key,		/* Encryption key */
+			key_length,	/* Key length */
+			iv,		/* IV */
+			sizeof(iv),	/* IV length */
+			1);		/* Use noPadding */
 
 	if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) {
 		ib_logf(IB_LOG_LEVEL_FATAL,
@@ -735,65 +836,35 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
 		ut_error;
 	}
 
+	/* Set up the checksum */
+	mach_write_to_4(dst_frame+FIL_PAGE_SPACE_OR_CHKSUM, BUF_NO_CHECKSUM_MAGIC);
+
+	/* For compressed tables we do not store the FIL header because
+	the whole page is not stored to the disk. In compressed tables only
+	the FIL header + compressed (and now encrypted) payload alligned
+	to sector boundary is written. */
 	if (!page_compressed) {
-		// copy page trailer
+		/* FIL page trailer is also not encrypted */
 		memcpy(dst_frame + page_size - FIL_PAGE_DATA_END,
 			src_frame + page_size - FIL_PAGE_DATA_END,
 			FIL_PAGE_DATA_END);
-
-		/* handle post encryption checksum */
-		ib_uint32_t checksum = 0;
-		srv_checksum_algorithm_t algorithm =
-			static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
-
-		if (zip_size == 0) {
-			switch (algorithm) {
-			case SRV_CHECKSUM_ALGORITHM_CRC32:
-			case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
-				checksum = buf_calc_page_crc32(dst_frame);
-				break;
-			case SRV_CHECKSUM_ALGORITHM_INNODB:
-			case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
-				checksum = (ib_uint32_t) buf_calc_page_new_checksum(
-					dst_frame);
-				break;
-			case SRV_CHECKSUM_ALGORITHM_NONE:
-			case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
-				checksum = BUF_NO_CHECKSUM_MAGIC;
-				break;
-				/* no default so the compiler will emit a warning
-				* if new enum is added and not handled here */
-			}
-		} else {
-			checksum = page_zip_calc_checksum(dst_frame, zip_size,
-				                          algorithm);
-		}
-
-		// store the post-encryption checksum after the key-version
-		mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
-			        checksum);
-	} else {
-		/* Page compressed and encrypted tables have different
-		FIL_HEADER */
-		ulint page_len = log10((double)page_size)/log10((double)2);
-		/* Set up the correct page type */
-		mach_write_to_2(dst_frame+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
-		/* Set up the compression algorithm */
-		mach_write_to_2(dst_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+4, orig_page_type);
-		/* Set up the compressed size */
-		mach_write_to_1(dst_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+6, page_len);
-		/* Set up the compression method */
-		mach_write_to_1(dst_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+7, compression_alg);
 	}
 
+	/* Store AES encryption method */
+	mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
+		aes_method);
+	/* Store compression algorithm (for page compresed tables) or 0 */
+	mach_write_to_2(dst_frame +  FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 6,
+		compression_algo);
 }
 
 /*********************************************************************
-Check if extra buffer shall be allocated for decrypting after read */
+Check if extra buffer shall be allocated for decrypting after read
+ at return true if fil space has encryption data. */
 UNIV_INTERN
 bool
 fil_space_check_encryption_read(
-/*==============================*/
+/*=============================*/
 	ulint space)          /*!< in: tablespace id */
 {
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
@@ -810,101 +881,92 @@ fil_space_check_encryption_read(
 }
 
 /******************************************************************
-Decrypt a page */
+Decrypt a page
+ at return true if page was encrypted */
 UNIV_INTERN
 bool
-fil_space_decrypt(fil_space_crypt_t* crypt_data,
-		  const byte* src_frame, ulint page_size, byte* dst_frame)
+fil_space_decrypt(
+/*==============*/
+	fil_space_crypt_t*	crypt_data,	/*!< in: crypt data */
+	const byte*		src_frame,	/*!< in: input buffer */
+	ulint			page_size,	/*!< in: page size */
+	byte*			dst_frame)	/*!< out: output buffer */
 {
 	ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
-	// key version
-	uint key_version;
-	bool page_encrypted = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
-		               || page_type == FIL_PAGE_PAGE_ENCRYPTED);
-
-	bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
-            || page_type == FIL_PAGE_PAGE_COMPRESSED);
-
-	ulint orig_page_type=0;
-
-	if (page_type == FIL_PAGE_PAGE_ENCRYPTED) {
-		key_version = mach_read_from_2(
-			src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
-		orig_page_type =  mach_read_from_2(
-			src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 2);
-	} else {
-		key_version = mach_read_from_4(
-			src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
-	}
+	uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+	bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED);
+	ulint compression_algo = mach_read_from_2(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 6);
+	uint aes_method = 0;
 
-	if (key_version == 0 && !page_encrypted) {
+	/* Page is not encrypted if key_version is 0 */
+	if (key_version == 0) {
 		//TODO: is this really needed ?
 		memcpy(dst_frame, src_frame, page_size);
 		return false; /* page not decrypted */
 	}
 
-	// read space & offset & lsn
+	/* read space & offset & lsn */
 	ulint space = mach_read_from_4(
 		src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
 	ulint offset = mach_read_from_4(
 		src_frame + FIL_PAGE_OFFSET);
 	ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
 
-	// copy page header
+	/* Copy FIL page header, it is not encrypted */
 	memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
 
-	if (page_type == FIL_PAGE_PAGE_ENCRYPTED) {
-		// orig page type
-		mach_write_to_2(dst_frame+FIL_PAGE_TYPE, orig_page_type);
-	}
-
-	// get key
+	/* Get key */
 	byte key[MY_AES_MAX_KEY_LENGTH];
 	uint key_length;
-	fil_crypt_get_key(key, &key_length, crypt_data, key_version, page_encrypted);
-
-	// get the iv
 	unsigned char iv[MY_AES_BLOCK_SIZE];
+	fil_crypt_get_key(key, &key_length, crypt_data, key_version);
+	aes_method = mach_read_from_2(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
 
-	if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
-		// create counter block
-
-		mach_write_to_4(iv + 0, space);
-		mach_write_to_4(iv + 4, offset);
-		mach_write_to_8(iv + 8, lsn);
-	} else {
-		// Get random IV from crypt_data
-		mutex_enter(&crypt_data->mutex);
-		memcpy(iv, crypt_data->iv, crypt_data->iv_length);
-		mutex_exit(&crypt_data->mutex);
+	/* Verify used AES method */
+	if ( aes_method != CRYPT_SCHEME_1_CTR &&
+	     aes_method != CRYPT_SCHEME_1_CBC) {
+		ib_logf(IB_LOG_LEVEL_FATAL,
+			"Unable to decrypt data-block "
+			" aes_method: %d unknown!\n",
+			aes_method);
+		ut_error;
 	}
 
+	/* Create counter used as IV */
+	mach_write_to_4(iv + 0, space);
+	mach_write_to_4(iv + 4, offset);
+	mach_write_to_8(iv + 8, lsn);
+
+	/* Calculate the offset where decryption starts */
 	const byte* src = src_frame + FIL_PAGE_DATA;
 	byte* dst = dst_frame + FIL_PAGE_DATA;
-	uint32 dstlen;
+	uint32 dstlen=0;
 	ulint srclen = page_size - (FIL_PAGE_DATA + FIL_PAGE_DATA_END);
-	ulint compressed_len;
-	ulint compression_method;
 
+	/* For page compressed tables we decrypt only the actual compressed
+	payload. Note that first two bytes of page data is actual payload
+	size and that should not be decrypted. */
 	if (page_compressed) {
-		orig_page_type = mach_read_from_2(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+4);
-		compressed_len = mach_read_from_1(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+6);
-		compression_method = mach_read_from_1(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+7);
-	}
-
-	if (page_encrypted && !page_compressed) {
-		orig_page_type = mach_read_from_2(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION+2);
-	}
-
-	if (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
-		srclen = pow((double)2, (double)((int)compressed_len)) - FIL_PAGE_DATA;
-	}
-
-	int rc = (* my_aes_decrypt_dynamic)(src, srclen,
-	                                    dst, &dstlen,
-	                                    (unsigned char*)key, key_length,
-	                                    (unsigned char*)iv, sizeof(iv),
-	                                    1);
+		ulint compressed_len = mach_read_from_2(src_frame + FIL_PAGE_DATA);
+		src+=2;
+		dst+=2;
+		mach_write_to_2(dst_frame + FIL_PAGE_DATA, compressed_len);
+		srclen = compressed_len;
+	}
+
+	/* Get AES method */
+	my_aes_encrypt_dynamic_type func = get_aes_decrypt_func((enum_my_aes_encryption_algorithm)fil_crypt_map_aes_method(aes_method));
+
+	/* Decrypt the data */
+	int rc = (*func)(src,		/* Data to be encrypted */
+			srclen,		/* data length */
+			dst,		/* Output buffer */
+			&dstlen,	/* Output buffer */
+			key,		/* Key */
+			key_length,	/* Key length */
+			iv,		/* IV */
+			sizeof(iv),	/* IV-length */
+			1);		/* NoPadding */
 
 	if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) {
 		ib_logf(IB_LOG_LEVEL_FATAL,
@@ -916,22 +978,57 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
 		ut_error;
 	}
 
-	if (page_type != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
-		// copy page trailer
+	/* For compressed tables we do not store the FIL header because
+	the whole page is not stored to the disk. In compressed tables only
+	the FIL header + compressed (and now encrypted) payload alligned
+	to sector boundary is written. */
+	if (!page_compressed) {
+		/* Copy FIL trailer */
 		memcpy(dst_frame + page_size - FIL_PAGE_DATA_END,
 		       src_frame + page_size - FIL_PAGE_DATA_END,
 		       FIL_PAGE_DATA_END);
 
-		// clear key-version & crypt-checksum from dst
-		memset(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
-	} else {
-		/* For page compressed tables we set up the FIL_HEADER again */
-		/* setting original page type */
-		mach_write_to_2(dst_frame + FIL_PAGE_TYPE, orig_page_type);
-		/* page_compression uses BUF_NO_CHECKSUM_MAGIC as checksum */
-		mach_write_to_4(dst_frame + FIL_PAGE_SPACE_OR_CHKSUM, BUF_NO_CHECKSUM_MAGIC);
-		/* Set up the flush lsn to be compression algorithm */
-		mach_write_to_8(dst_frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, compression_method);
+		/* handle post decryption checksum */
+		ib_uint32_t checksum = 0;
+		srv_checksum_algorithm_t algorithm =
+			static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+
+		if (page_size == UNIV_PAGE_SIZE) {
+			switch (algorithm) {
+			case SRV_CHECKSUM_ALGORITHM_CRC32:
+			case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
+				checksum = buf_calc_page_crc32(dst_frame);
+				break;
+			case SRV_CHECKSUM_ALGORITHM_INNODB:
+			case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
+				checksum = (ib_uint32_t) buf_calc_page_new_checksum(
+					dst_frame);
+				break;
+			case SRV_CHECKSUM_ALGORITHM_NONE:
+			case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+				checksum = BUF_NO_CHECKSUM_MAGIC;
+				break;
+				/* no default so the compiler will emit a warning
+				* if new enum is added and not handled here */
+			}
+		} else {
+			checksum = page_zip_calc_checksum(dst_frame, page_size,
+				                          algorithm);
+		}
+
+		mach_write_to_4(dst_frame + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
+
+		fprintf(stderr, "KUKKU %ld:%lu\n", mach_read_from_4(dst_frame + FIL_PAGE_SPACE_OR_CHKSUM),
+			mach_read_from_4(dst_frame + FIL_PAGE_END_LSN_OLD_CHKSUM));
+	}
+
+	/* Clear key-version & aes_method from dst */
+	memset(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
+
+	/* For page compressed tables store compression algorithm back */
+	if (page_compressed) {
+		mach_write_to_8(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+			compression_algo);
 	}
 
 	return true; /* page was decrypted */
@@ -941,8 +1038,12 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
 Decrypt a page */
 UNIV_INTERN
 void
-fil_space_decrypt(ulint space,
-		  const byte* src_frame, ulint page_size, byte* dst_frame)
+fil_space_decrypt(
+/*==============*/
+	ulint		space,		/*!< in: Fil space id */
+	const byte*	src_frame,	/*!< in: input buffer */
+	ulint		page_size,	/*!< in: page size */
+	byte*		dst_frame)	/*!< out: output buffer */
 {
 	fil_space_decrypt(fil_space_get_crypt_data(space),
 			  src_frame, page_size, dst_frame);
@@ -953,8 +1054,13 @@ Verify checksum for a page (iff it's encrypted)
 NOTE: currently this function can only be run in single threaded mode
 as it modifies srv_checksum_algorithm (temporarily)
 @return true if page is encrypted AND OK, false otherwise */
+UNIV_INTERN
 bool
-fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size)
+fil_space_verify_crypt_checksum(
+/*============================*/
+	const byte* 	src_frame,	/*!< in: page the verify */
+	ulint		zip_size)  	/*!< in: compressed size if
+					row_format compressed */
 {
 	// key version
 	uint key_version = mach_read_from_4(
@@ -1041,7 +1147,8 @@ struct key_state_t {
 Copy global key state */
 static void
 fil_crypt_get_key_state(
-	key_state_t *new_state)
+/*====================*/
+	key_state_t *new_state)	/*!< out: key state */
 {
 	if (srv_encrypt_tables == TRUE) {
 		new_state->key_version = get_latest_encryption_key_version();
@@ -1054,9 +1161,13 @@ fil_crypt_get_key_state(
 }
 
 /***********************************************************************
-Check if a key needs rotation given a key_state */
+Check if a key needs rotation given a key_state
+ at return true if key needs rotation, false if not */
 static bool
-fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
+fil_crypt_needs_rotation(
+/*=====================*/
+	uint			key_version,	/*!< in: Key version */
+	const key_state_t*	key_state)	/*!< in: Key state */
 {
 	// TODO(jonaso): Add support for rotating encrypted => unencrypted
 
@@ -1081,9 +1192,13 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
 }
 
 /***********************************************************************
-Check if a space is closing (i.e just before drop) */
-UNIV_INTERN bool
-fil_crypt_is_closing(ulint space)
+Check if a space is closing (i.e just before drop)
+ at return true if space is closing, false if not. */
+UNIV_INTERN
+bool
+fil_crypt_is_closing(
+/*=================*/
+	ulint space)	/*!< in: FIL space id */
 {
 	bool closing;
 	fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
@@ -1097,11 +1212,17 @@ fil_crypt_is_closing(ulint space)
 Start encrypting a space
 @return true if a pending op (fil_inc_pending_ops/fil_decr_pending_ops) is held
 */
-static bool
-fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
+static
+bool
+fil_crypt_start_encrypting_space(
+/*=============================*/
+	ulint	space,	/*!< in: FIL space id */
+	bool*	recheck)/*!< out: true if recheck needed */
+{
 
 	/* we have a pending op when entering function */
 	bool pending_op = true;
+	uint aes_method = current_aes_dynamic_method;
 
 	mutex_enter(&fil_crypt_threads_mutex);
 
@@ -1184,7 +1305,7 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
 
 		/* 4 - write crypt data to page 0 */
 		fil_space_write_crypt_data_low(crypt_data,
-					       CRYPT_SCHEME_1,
+			                       fil_crypt_get_aes_method(aes_method),
 					       frame,
 					       crypt_data->page0_offset,
 					       maxsize, &mtr);
@@ -1232,7 +1353,7 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
 		/* 5 - publish crypt data */
 		mutex_enter(&fil_crypt_threads_mutex);
 		mutex_enter(&crypt_data->mutex);
-		crypt_data->type = CRYPT_SCHEME_1;
+		crypt_data->type = fil_crypt_get_aes_method(aes_method);
 		ut_a(crypt_data->rotate_state.active_threads == 1);
 		crypt_data->rotate_state.active_threads = 0;
 		crypt_data->rotate_state.starting = false;
@@ -1257,10 +1378,14 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
 }
 
 /***********************************************************************
-Check if space needs rotation given a key_state */
-static bool
-fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
-			       bool *recheck)
+Check if space needs rotation given a key_state
+ at return true if space needs key rotation */
+static
+bool
+fil_crypt_space_needs_rotation(
+	uint			space,		/*!< in: FIL space id */
+	const key_state_t*	key_state,	/*!< in: Key state */
+	bool*			recheck)	/*!< out: needs recheck ? */
 {
 	if (fil_space_get_type(space) != FIL_TABLESPACE) {
 		return false;
@@ -1374,7 +1499,9 @@ struct rotate_thread_t {
 /***********************************************************************
 Update global statistics with thread statistics */
 static void
-fil_crypt_update_total_stat(rotate_thread_t *state)
+fil_crypt_update_total_stat(
+/*========================*/
+	rotate_thread_t *state)	/*!< in: Key rotation status */
 {
 	mutex_enter(&crypt_stat_mutex);
 	crypt_stat.pages_read_from_cache +=
@@ -1397,9 +1524,13 @@ fil_crypt_update_total_stat(rotate_thread_t *state)
 
 /***********************************************************************
 Allocate iops to thread from global setting,
-used before starting to rotate a space */
-static bool
-fil_crypt_alloc_iops(rotate_thread_t *state)
+used before starting to rotate a space.
+ at return true if allocation succeeded, false if failed */
+static
+bool
+fil_crypt_alloc_iops(
+/*=================*/
+	rotate_thread_t *state)	/*!< in: Key rotation status */
 {
 	ut_ad(state->allocated_iops == 0);
 
@@ -1429,8 +1560,11 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
 /***********************************************************************
 Reallocate iops to thread,
 used when inside a space */
-static void
-fil_crypt_realloc_iops(rotate_thread_t *state)
+static
+void
+fil_crypt_realloc_iops(
+/*========================*/
+	rotate_thread_t *state)	/*!< in: Key rotation status */
 {
 	ut_a(state->allocated_iops > 0);
 
@@ -1519,8 +1653,11 @@ fil_crypt_realloc_iops(rotate_thread_t *state)
 
 /***********************************************************************
 Return allocated iops to global */
-static void
-fil_crypt_return_iops(rotate_thread_t *state)
+static
+void
+fil_crypt_return_iops(
+/*========================*/
+	rotate_thread_t *state)	/*!< in: Key rotation status */
 {
 	if (state->allocated_iops > 0) {
 		uint iops = state->allocated_iops;
@@ -1544,11 +1681,14 @@ fil_crypt_return_iops(rotate_thread_t *state)
 
 /***********************************************************************
 Search for a space needing rotation */
+UNIV_INTERN
 bool
 fil_crypt_find_space_to_rotate(
-	const key_state_t *key_state,
-	rotate_thread_t *state,
-	bool *recheck)
+/*===========================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state,		/*!< in: Key rotation state */
+	bool*			recheck)	/*!< out: true if recheck
+						needed */
 {
 	/* we need iops to start rotating */
 	while (!state->should_shutdown() && !fil_crypt_alloc_iops(state)) {
@@ -1591,8 +1731,9 @@ Start rotating a space */
 static
 void
 fil_crypt_start_rotate_space(
-	const key_state_t *key_state,
-	rotate_thread_t *state)
+/*=========================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state)		/*!< in: Key rotation state */
 {
 	ulint space = state->space;
 	fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
@@ -1629,12 +1770,14 @@ fil_crypt_start_rotate_space(
 }
 
 /***********************************************************************
-Search for batch of pages needing rotation */
+Search for batch of pages needing rotation
+ at return true if page needing key rotation found, false if not found */
 static
 bool
 fil_crypt_find_page_to_rotate(
-	const key_state_t *key_state,
-	rotate_thread_t *state)
+/*==========================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state)		/*!< in: Key rotation state */
 {
 	ulint batch = srv_alloc_time * state->allocated_iops;
 	ulint space = state->space;
@@ -1665,9 +1808,15 @@ fil_crypt_find_page_to_rotate(
 }
 
 /***********************************************************************
-Check if a page is uninitialized (doesn't need to be rotated) */
-static bool
-fil_crypt_is_page_uninitialized(const byte* frame, uint zip_size)
+Check if a page is uninitialized (doesn't need to be rotated)
+ at return true if page is uninitialized, false if not.*/
+static
+bool
+fil_crypt_is_page_uninitialized(
+/*============================*/
+	const byte	*frame, 	/*!< in: Page */
+	uint		zip_size)	/*!< in: compressed size if
+					row_format compressed */
 {
 	if (zip_size) {
 		ulint stored_checksum = mach_read_from_4(
@@ -1696,15 +1845,20 @@ fil_crypt_is_page_uninitialized(const byte* frame, uint zip_size)
 					 sleeptime_ms, __FILE__, __LINE__)
 
 /***********************************************************************
-Get a page and compute sleep time  */
+Get a page and compute sleep time
+ at return page */
 static
 buf_block_t*
-fil_crypt_get_page_throttle_func(rotate_thread_t *state,
-				 ulint space, uint zip_size, ulint offset,
-				 mtr_t *mtr,
-				 ulint *sleeptime_ms,
-				 const char *file,
-				 ulint line)
+fil_crypt_get_page_throttle_func(
+	rotate_thread_t*	state,		/*!< in/out: Key rotation state */
+	ulint			space,		/*!< in: FIL space id */
+	uint 			zip_size,	/*!< in: compressed size if
+						row_format compressed */
+	ulint 			offset,		/*!< in: page offsett */
+	mtr_t*			mtr,		/*!< in/out: minitransaction */
+	ulint*			sleeptime_ms,	/*!< out: sleep time */
+	const char*		file,		/*!< in: file name */
+	ulint 			line)		/*!< in: file line */
 {
 	buf_block_t* block = buf_page_try_get_func(space, offset, RW_X_LATCH,
 						   true,
@@ -1753,17 +1907,22 @@ Get block and allocation status
 
 note: innodb locks fil_space_latch and then block when allocating page
 but locks block and then fil_space_latch when freeing page.
+ at return block
 */
 static
 buf_block_t*
 btr_scrub_get_block_and_allocation_status(
-	rotate_thread_t *state,
-	ulint space,
-	ulint zip_size,
-	ulint offset,
-	mtr_t *mtr,
+/*======================================*/
+	rotate_thread_t*	state,		/*!< in/out: Key rotation state */
+	ulint			space,		/*!< in: FIL space id */
+	uint 			zip_size,	/*!< in: compressed size if
+						row_format compressed */
+	ulint 			offset,		/*!< in: page offsett */
+	mtr_t*			mtr,		/*!< in/out: minitransaction
+						*/
 	btr_scrub_page_allocation_status_t *allocation_status,
-	ulint *sleeptime_ms)
+						/*!< in/out: allocation status */
+	ulint*			sleeptime_ms)	/*!< out: sleep time */
 {
 	mtr_t local_mtr;
 	buf_block_t *block = NULL;
@@ -1807,8 +1966,9 @@ Rotate one page */
 static
 void
 fil_crypt_rotate_page(
-	const key_state_t *key_state,
-	rotate_thread_t *state)
+/*===================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state)		/*!< in: Key rotation state */
 {
 	ulint space = state->space;
 	ulint offset = state->offset;
@@ -1960,8 +2120,9 @@ Rotate a batch of pages */
 static
 void
 fil_crypt_rotate_pages(
-	const key_state_t *key_state,
-	rotate_thread_t *state)
+/*===================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state)		/*!< in: Key rotation state */
 {
 	ulint space = state->space;
 	ulint end = state->offset + state->batch;
@@ -1989,7 +2150,10 @@ fil_crypt_rotate_pages(
 Flush rotated pages and then update page 0 */
 static
 void
-fil_crypt_flush_space(rotate_thread_t *state, ulint space)
+fil_crypt_flush_space(
+/*==================*/
+	rotate_thread_t*	state,	/*!< in: Key rotation state */
+	ulint			space)	/*!< in: FIL space id */
 {
 	fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
 
@@ -2045,8 +2209,9 @@ Complete rotating a space */
 static
 void
 fil_crypt_complete_rotate_space(
-	const key_state_t *key_state,
-	rotate_thread_t *state)
+/*============================*/
+	const key_state_t*	key_state,	/*!< in: Key state */
+	rotate_thread_t*	state)		/*!< in: Key rotation state */
 {
 	ulint space = state->space;
 	fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
@@ -2120,7 +2285,7 @@ A thread which monitors global key state and rotates tablespaces accordingly
 extern "C" UNIV_INTERN
 os_thread_ret_t
 DECLARE_THREAD(fil_crypt_thread)(
-/*===============================*/
+/*=============================*/
 	void*	arg __attribute__((unused))) /*!< in: a dummy parameter required
 					     * by os_thread_create */
 {
@@ -2237,13 +2402,19 @@ DECLARE_THREAD(fil_crypt_thread)(
 Adjust thread count for key rotation */
 UNIV_INTERN
 void
-fil_crypt_set_thread_cnt(uint new_cnt)
+fil_crypt_set_thread_cnt(
+/*=====================*/
+	uint	new_cnt)	/*!< in: New key rotation thread count */
 {
 	if (new_cnt > srv_n_fil_crypt_threads) {
 		uint add = new_cnt - srv_n_fil_crypt_threads;
 		srv_n_fil_crypt_threads = new_cnt;
 		for (uint i = 0; i < add; i++) {
-			os_thread_create(fil_crypt_thread, NULL, NULL);
+			os_thread_id_t rotation_thread_id;
+			os_thread_create(fil_crypt_thread, NULL, &rotation_thread_id);
+			ib_logf(IB_LOG_LEVEL_INFO,
+				"Creating #%d thread id %lu total threads %du\n",
+				i, os_thread_pf(rotation_thread_id), new_cnt);
 		}
 	} else if (new_cnt < srv_n_fil_crypt_threads) {
 		srv_n_fil_crypt_threads = new_cnt;
@@ -2260,7 +2431,9 @@ fil_crypt_set_thread_cnt(uint new_cnt)
 Adjust max key age */
 UNIV_INTERN
 void
-fil_crypt_set_rotate_key_age(uint val)
+fil_crypt_set_rotate_key_age(
+/*=========================*/
+	uint	val)	/*!< in: New max key age */
 {
 	srv_fil_crypt_rotate_key_age = val;
 	os_event_set(fil_crypt_threads_event);
@@ -2270,7 +2443,9 @@ fil_crypt_set_rotate_key_age(uint val)
 Adjust rotation iops */
 UNIV_INTERN
 void
-fil_crypt_set_rotation_iops(uint val)
+fil_crypt_set_rotation_iops(
+/*========================*/
+	uint val)	/*!< in: New iops setting */
 {
 	srv_n_fil_crypt_iops = val;
 	os_event_set(fil_crypt_threads_event);
@@ -2281,6 +2456,7 @@ Init threads for key rotation */
 UNIV_INTERN
 void
 fil_crypt_threads_init()
+/*====================*/
 {
 	fil_crypt_event = os_event_create();
 	fil_crypt_threads_event = os_event_create();
@@ -2297,6 +2473,7 @@ End threads for key rotation */
 UNIV_INTERN
 void
 fil_crypt_threads_end()
+/*===================*/
 {
 	/* stop threads */
 	fil_crypt_set_thread_cnt(0);
@@ -2306,7 +2483,9 @@ fil_crypt_threads_end()
 Clean up key rotation threads resources */
 UNIV_INTERN
 void
-fil_crypt_threads_cleanup() {
+fil_crypt_threads_cleanup()
+/*=======================*/
+{
 	os_event_free(fil_crypt_event);
 	os_event_free(fil_crypt_threads_event);
 }
@@ -2316,7 +2495,8 @@ Mark a space as closing */
 UNIV_INTERN
 void
 fil_space_crypt_mark_space_closing(
-	ulint space)
+/*===============================*/
+	ulint	space)	/*!< in: Space id */
 {
 	mutex_enter(&fil_crypt_threads_mutex);
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
@@ -2337,7 +2517,8 @@ Wait for crypt threads to stop accessing space */
 UNIV_INTERN
 void
 fil_space_crypt_close_tablespace(
-	ulint space)
+/*=============================*/
+	ulint	space)	/*!< in: Space id */
 {
 	mutex_enter(&fil_crypt_threads_mutex);
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
@@ -2349,11 +2530,14 @@ fil_space_crypt_close_tablespace(
 
 	uint start = time(0);
 	uint last = start;
+
 	mutex_enter(&crypt_data->mutex);
 	mutex_exit(&fil_crypt_threads_mutex);
 	crypt_data->closing = true;
+
 	uint cnt = crypt_data->rotate_state.active_threads;
 	bool flushing = crypt_data->rotate_state.flushing;
+
 	while (cnt > 0 || flushing) {
 		mutex_exit(&crypt_data->mutex);
 		/* release dict mutex so that scrub threads can release their
@@ -2383,11 +2567,12 @@ fil_space_crypt_close_tablespace(
 /*********************************************************************
 Get crypt status for a space (used by information_schema)
 return 0 if crypt data present */
+UNIV_INTERN
 int
 fil_space_crypt_get_status(
-/*==================*/
-	ulint id,				  /*!< in: space id */
-	struct fil_space_crypt_status_t* status) /*!< out: status  */
+/*=======================*/
+	ulint				id,		/*!< in: space id */
+	struct fil_space_crypt_status_t* status)	/*!< out: status  */
 {
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
 
@@ -2397,6 +2582,7 @@ fil_space_crypt_get_status(
 		mutex_enter(&crypt_data->mutex);
 		status->keyserver_requests = crypt_data->keyserver_requests;
 		status->min_key_version = crypt_data->min_key_version;
+
 		if (crypt_data->rotate_state.active_threads > 0 ||
 		    crypt_data->rotate_state.flushing) {
 			status->rotating = true;
@@ -2424,8 +2610,11 @@ fil_space_crypt_get_status(
 
 /*********************************************************************
 Return crypt statistics */
+UNIV_INTERN
 void
-fil_crypt_total_stat(fil_crypt_stat_t *stat)
+fil_crypt_total_stat(
+/*=================*/
+	fil_crypt_stat_t *stat)	/*!< out: Crypt statistics */
 {
 	mutex_enter(&crypt_stat_mutex);
 	*stat = crypt_stat;
@@ -2435,11 +2624,12 @@ fil_crypt_total_stat(fil_crypt_stat_t *stat)
 /*********************************************************************
 Get scrub status for a space (used by information_schema)
 return 0 if data found */
+UNIV_INTERN
 int
 fil_space_get_scrub_status(
-/*==================*/
-	ulint id,				  /*!< in: space id */
-	struct fil_space_scrub_status_t* status) /*!< out: status  */
+/*=======================*/
+	ulint id,					/*!< in: space id */
+	struct fil_space_scrub_status_t* status)	/*!< out: status  */
 {
 	fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
 	memset(status, 0, sizeof(*status));
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 14878f5..cd25309 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -7061,7 +7061,7 @@ Get crypt data for a tablespace */
 UNIV_INTERN
 fil_space_crypt_t*
 fil_space_get_crypt_data(
-/*==================*/
+/*=====================*/
 	ulint id)	/*!< in: space id */
 {
 	fil_space_t*	space;
@@ -7085,9 +7085,26 @@ fil_space_get_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 */
+UNIV_INTERN
 void
 fil_space_set_crypt_data(
-/*==================*/
+/*=====================*/
 	ulint id, 	               /*!< in: space id */
 	fil_space_crypt_t* crypt_data) /*!< in: crypt data */
 {
diff --git a/storage/xtradb/fil/fil0pagecompress.cc b/storage/xtradb/fil/fil0pagecompress.cc
index 3c2edd8..80f55c0 100644
--- a/storage/xtradb/fil/fil0pagecompress.cc
+++ b/storage/xtradb/fil/fil0pagecompress.cc
@@ -254,6 +254,7 @@ fil_decompress_page_2(
 For page compressed pages compress the page before actual write
 operation.
 @return compressed page to be written*/
+UNIV_INTERN
 byte*
 fil_compress_page(
 /*==============*/
@@ -544,6 +545,7 @@ fil_compress_page(
 /****************************************************************//**
 For page compressed pages decompress the page after actual read
 operation. */
+UNIV_INTERN
 void
 fil_decompress_page(
 /*================*/
diff --git a/storage/xtradb/include/fil0crypt.h b/storage/xtradb/include/fil0crypt.h
new file mode 100644
index 0000000..8ee792e
--- /dev/null
+++ b/storage/xtradb/include/fil0crypt.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+
+Copyright (C) 2015 MariaDB Corporation
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+*****************************************************************************/
+
+#ifndef fil0crypt_h
+#define fil0crypt_h
+
+/******************************************************************//**
+ at file include/fil0crypt
+Helper functions for encryption/decryption.
+
+Created 20/03/2015 Jan Lindström jan.lindstrom at mariadb.com
+***********************************************************************/
+
+/******************************************************************
+Map current aes method */
+uint
+fil_crypt_map_aes_method(
+	uint aes_method);
+/******************************************************************
+Get current aes method */
+UNIV_INTERN
+uint
+fil_crypt_get_aes_method(
+	uint aes_method);
+
+#endif /* fil0crypt_h */
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 2e92c2b..705c5e9 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -172,7 +172,6 @@ static const ulint FIL_PAGE_COMPRESS_SIZE_V1 = FIL_PAGE_ORIGINAL_SIZE_V1 + 2;
 #define FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED 35631 /* page compressed +
 						 	 	 encrypted page */
 #define FIL_PAGE_PAGE_COMPRESSED 34354  /*!< Page compressed page */
-#define FIL_PAGE_PAGE_ENCRYPTED  34355  /*!< Page encrypted page  */
 #define FIL_PAGE_INDEX		17855	/*!< B-tree node */
 #define FIL_PAGE_UNDO_LOG	2	/*!< Undo log page */
 #define FIL_PAGE_INODE		3	/*!< Index node */
@@ -1246,6 +1245,7 @@ fil_mtr_rename_log(
 Finds the given page_no of the given space id from the double write buffer,
 and copies it to the corresponding .ibd file.
 @return true if copy was successful, or false. */
+UNIV_INTERN
 bool
 fil_user_tablespace_restore_page(
 /*==============================*/
@@ -1259,10 +1259,12 @@ fil_user_tablespace_restore_page(
 /*************************************************************************
 Return local hash table informations. */
 
+UNIV_INTERN
 ulint
 fil_system_hash_cells(void);
 /*========================*/
 
+UNIV_INTERN
 ulint
 fil_system_hash_nodes(void);
 /*========================*/
@@ -1270,11 +1272,13 @@ fil_system_hash_nodes(void);
 /*************************************************************************
 functions to access is_corrupt flag of fil_space_t*/
 
+UNIV_INTERN
 ibool
 fil_space_is_corrupt(
 /*=================*/
 	ulint	space_id);
 
+UNIV_INTERN
 void
 fil_space_set_corrupt(
 /*==================*/
@@ -1282,11 +1286,13 @@ fil_space_set_corrupt(
 
 /****************************************************************//**
 Acquire fil_system mutex */
+UNIV_INTERN
 void
 fil_system_enter(void);
 /*==================*/
 /****************************************************************//**
 Release fil_system mutex */
+UNIV_INTERN
 void
 fil_system_exit(void);
 /*==================*/
@@ -1294,12 +1300,14 @@ fil_system_exit(void);
 #ifndef UNIV_INNOCHECKSUM
 /*******************************************************************//**
 Returns the table space by a given id, NULL if not found. */
+UNIV_INTERN
 fil_space_t*
 fil_space_get_by_id(
 /*================*/
 	ulint	id);	/*!< in: space id */
 /*******************************************************************//**
 Return space name */
+UNIV_INTERN
 char*
 fil_space_name(
 /*===========*/
@@ -1325,11 +1333,13 @@ fil_space_crypt_init();
 
 /*********************************************************************
 Cleanup global resources needed for tablespace encryption/decryption */
+UNIV_INTERN
 void
 fil_space_crypt_cleanup();
 
 /*********************************************************************
 Create crypt data, i.e data that is used for a single tablespace */
+UNIV_INTERN
 fil_space_crypt_t *
 fil_space_create_crypt_data();
 
@@ -1343,13 +1353,22 @@ fil_space_destroy_crypt_data(
 
 /*********************************************************************
 Get crypt data for a space*/
+UNIV_INTERN
 fil_space_crypt_t *
 fil_space_get_crypt_data(
 /*======================*/
 	ulint space); /*!< in: tablespace id */
 
 /*********************************************************************
+Get crypt data for a space*/
+UNIV_INTERN
+fil_space_crypt_t *
+fil_space_crypt_data(
+/*=================*/
+	fil_space_t* space); /*!< in: tablespace */
+/*********************************************************************
 Set crypt data for a space*/
+UNIV_INTERN
 void
 fil_space_set_crypt_data(
 /*======================*/
@@ -1358,6 +1377,7 @@ fil_space_set_crypt_data(
 
 /*********************************************************************
 Compare crypt data*/
+UNIV_INTERN
 int
 fil_space_crypt_compare(
 /*======================*/
@@ -1366,6 +1386,7 @@ fil_space_crypt_compare(
 
 /*********************************************************************
 Read crypt data from buffer page */
+UNIV_INTERN
 fil_space_crypt_t *
 fil_space_read_crypt_data(
 /*======================*/
@@ -1375,6 +1396,7 @@ fil_space_read_crypt_data(
 
 /*********************************************************************
 Write crypt data to buffer page */
+UNIV_INTERN
 void
 fil_space_write_crypt_data(
 /*=======================*/
@@ -1386,6 +1408,7 @@ fil_space_write_crypt_data(
 
 /*********************************************************************
 Clear crypt data from page 0 (used for import tablespace) */
+UNIV_INTERN
 void
 fil_space_clear_crypt_data(
 /*======================*/
@@ -1394,6 +1417,7 @@ fil_space_clear_crypt_data(
 
 /*********************************************************************
 Parse crypt data log record */
+UNIV_INTERN
 byte*
 fil_parse_write_crypt_data(
 /*=======================*/
@@ -1406,7 +1430,7 @@ Check if extra buffer shall be allocated for decrypting after read */
 UNIV_INTERN
 bool
 fil_space_check_encryption_read(
-/*==============================*/
+/*============================*/
 	ulint space);          /*!< in: tablespace id */
 
 /*********************************************************************
@@ -1414,11 +1438,12 @@ Check if page shall be encrypted before write */
 UNIV_INTERN
 bool
 fil_space_check_encryption_write(
-/*==============================*/
+/*=============================*/
 	ulint space);          /*!< in: tablespace id */
 
 /*********************************************************************
 Encrypt buffer page */
+UNIV_INTERN
 void
 fil_space_encrypt(
 /*===============*/
@@ -1433,9 +1458,10 @@ fil_space_encrypt(
 
 /*********************************************************************
 Decrypt buffer page */
+UNIV_INTERN
 void
 fil_space_decrypt(
-/*===============*/
+/*==============*/
 	ulint space,          /*!< in: tablespace id */
 	const byte* src_frame,/*!< in: page frame */
 	ulint page_size,      /*!< in: size of data to encrypt */
@@ -1445,9 +1471,10 @@ fil_space_decrypt(
 /*********************************************************************
 Decrypt buffer page
 @return true if page was encrypted */
+UNIV_INTERN
 bool
 fil_space_decrypt(
-/*===============*/
+/*==============*/
 	fil_space_crypt_t* crypt_data, /*!< in: crypt data */
 	const byte* src_frame,/*!< in: page frame */
 	ulint page_size,      /*!< in: page size */
@@ -1458,19 +1485,22 @@ fil_space_verify_crypt_checksum
 NOTE: currently this function can only be run in single threaded mode
 as it modifies srv_checksum_algorithm (temporarily)
 @return true if page is encrypted AND OK, false otherwise */
+UNIV_INTERN
 bool
 fil_space_verify_crypt_checksum(
-/*===============*/
+/*============================*/
 	const byte* src_frame,/*!< in: page frame */
 	ulint zip_size);      /*!< in: size of data to encrypt */
 
 /*********************************************************************
 Init threads for key rotation */
+UNIV_INTERN
 void
 fil_crypt_threads_init();
 
 /*********************************************************************
 Set thread count (e.g start or stops threads) used for key rotation */
+UNIV_INTERN
 void
 fil_crypt_set_thread_cnt(
 /*=====================*/
@@ -1478,26 +1508,30 @@ fil_crypt_set_thread_cnt(
 
 /*********************************************************************
 End threads for key rotation */
+UNIV_INTERN
 void
 fil_crypt_threads_end();
 
 /*********************************************************************
 Cleanup resources for threads for key rotation */
+UNIV_INTERN
 void
 fil_crypt_threads_cleanup();
 
 /*********************************************************************
 Set rotate key age */
+UNIV_INTERN
 void
 fil_crypt_set_rotate_key_age(
-/*=====================*/
+/*=========================*/
 	uint rotate_age); /*!< in: requested rotate age */
 
 /*********************************************************************
 Set rotation threads iops */
+UNIV_INTERN
 void
 fil_crypt_set_rotation_iops(
-/*=====================*/
+/*========================*/
 	uint iops); /*!< in: requested iops */
 
 /*********************************************************************
@@ -1505,7 +1539,7 @@ Mark a space as closing */
 UNIV_INTERN
 void
 fil_space_crypt_mark_space_closing(
-/*===============*/
+/*===============================*/
 	ulint space);          /*!< in: tablespace id */
 
 /*********************************************************************
@@ -1513,7 +1547,7 @@ Wait for crypt threads to stop accessing space */
 UNIV_INTERN
 void
 fil_space_crypt_close_tablespace(
-/*===============*/
+/*=============================*/
 	ulint space);          /*!< in: tablespace id */
 
 /** Struct for retreiving info about encryption */
@@ -1532,9 +1566,10 @@ struct fil_space_crypt_status_t {
 /*********************************************************************
 Get crypt status for a space
 @return 0 if crypt data found */
+UNIV_INTERN
 int
 fil_space_crypt_get_status(
-/*==================*/
+/*=======================*/
 	ulint id,	                           /*!< in: space id */
 	struct fil_space_crypt_status_t * status); /*!< out: status  */
 
@@ -1549,6 +1584,7 @@ struct fil_crypt_stat_t {
 
 /*********************************************************************
 Get crypt rotation statistics */
+UNIV_INTERN
 void
 fil_crypt_total_stat(
 /*==================*/
@@ -1558,16 +1594,16 @@ fil_crypt_total_stat(
 
 /*******************************************************************//**
 Return space flags */
+UNIV_INTERN
 ulint
 fil_space_flags(
 /*===========*/
 	fil_space_t*	space);	/*!< in: space */
 
-
-
 /****************************************************************//**
 Does error handling when a file operation fails.
 @return	TRUE if we should retry the operation */
+UNIV_INTERN
 ibool
 os_file_handle_error_no_exit(
 /*=========================*/
@@ -1580,6 +1616,7 @@ os_file_handle_error_no_exit(
 
 /*******************************************************************//**
 Return page type name */
+UNIV_INTERN
 const char*
 fil_get_page_type_name(
 /*===================*/
@@ -1600,10 +1637,19 @@ struct fil_space_scrub_status_t {
 /*********************************************************************
 Get scrub status for a space
 @return 0 if no scrub info found */
+UNIV_INTERN
 int
 fil_space_get_scrub_status(
-/*==================*/
+/*=======================*/
 	ulint id,	                           /*!< in: space id */
 	struct fil_space_scrub_status_t * status); /*!< out: status  */
 
+/******************************************************************
+Map current aes method */
+UNIV_INTERN
+uint
+fil_crypt_map_aes_method(
+/*=====================*/
+	uint aes_method);
+
 #endif /* fil0fil_h */
diff --git a/storage/xtradb/include/fil0pagecompress.h b/storage/xtradb/include/fil0pagecompress.h
index c797c22..1c2c173 100644
--- a/storage/xtradb/include/fil0pagecompress.h
+++ b/storage/xtradb/include/fil0pagecompress.h
@@ -34,6 +34,7 @@ Created 11/12/2013 Jan Lindström jan.lindstrom at skysql.com
 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.
 @return	page compression level if page compressed, ULINT_UNDEFINED if space not found */
+UNIV_INTERN
 ulint
 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
 is not compressed. The tablespace must be cached in the memory cache.
 @return	true if page compressed, false if not or space not found */
+UNIV_INTERN
 ibool
 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
 is not compressed. The tablespace must be cached in the memory cache.
 @return	true if page compressed, false if not or space not found */
+UNIV_INTERN
 ibool
 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
 is not using atomic writes. The tablespace must be cached in the memory cache.
 @return	atomic write table option value */
+UNIV_INTERN
 atomic_writes_t
 fil_space_get_atomic_writes(
 /*=========================*/
@@ -65,6 +69,7 @@ fil_space_get_atomic_writes(
 /*******************************************************************//**
 Find out wheather the page is index page or not
 @return	true if page type index page, false if not */
+UNIV_INTERN
 ibool
 fil_page_is_index_page(
 /*===================*/
@@ -74,6 +79,7 @@ fil_page_is_index_page(
 Get the name of the compression algorithm used for page
 compression.
 @return compression algorithm name or "UNKNOWN" if not known*/
+UNIV_INTERN
 const char*
 fil_get_compression_alg_name(
 /*=========================*/
@@ -83,6 +89,7 @@ fil_get_compression_alg_name(
 For page compressed pages compress the page before actual write
 operation.
 @return compressed page to be written*/
+UNIV_INTERN
 byte*
 fil_compress_page(
 /*==============*/
@@ -102,6 +109,7 @@ fil_compress_page(
 For page compressed pages decompress the page after actual read
 operation.
 @return uncompressed page */
+UNIV_INTERN
 void
 fil_decompress_page(
 /*================*/
@@ -115,6 +123,7 @@ fil_decompress_page(
 /****************************************************************//**
 Get space id from fil node
 @return space id*/
+UNIV_INTERN
 ulint
 fil_node_get_space_id(
 /*==================*/
@@ -123,13 +132,16 @@ fil_node_get_space_id(
 /****************************************************************//**
 Get block size from fil node
 @return block size*/
+UNIV_INTERN
 ulint
 fil_node_get_block_size(
+/*====================*/
 	fil_node_t*     node);		/*!< in: Node where to get block
 					size */
 /*******************************************************************//**
 Find out wheather the page is page compressed
- at return	true if page is page compressed*/
+ at return	true if page is page compressed */
+UNIV_INTERN
 ibool
 fil_page_is_compressed(
 /*===================*/
@@ -138,6 +150,7 @@ fil_page_is_compressed(
 /*******************************************************************//**
 Find out wheather the page is page compressed with lzo method
 @return	true if page is page compressed with lzo method*/
+UNIV_INTERN
 ibool
 fil_page_is_lzo_compressed(
 /*=======================*/
diff --git a/storage/xtradb/include/fil0pageencryption.h b/storage/xtradb/include/fil0pageencryption.h
index fa2b1a5..fe33650 100644
--- a/storage/xtradb/include/fil0pageencryption.h
+++ b/storage/xtradb/include/fil0pageencryption.h
@@ -57,14 +57,6 @@ ibool
 fil_page_is_encrypted(
 /*==================*/
     const byte *buf);	/*!< in: page */
-/*******************************************************************//**
-Find out whether the page is page compressed and then encrypted
- at return	true if page is page compressed+encrypted, false if not */
-UNIV_INLINE
-ibool
-fil_page_is_compressed_encrypted(
-/*=============================*/
-    const byte *buf);	/*!< in: page */
 
 /*******************************************************************//**
 Find out whether the page can be decrypted
diff --git a/storage/xtradb/include/fsp0pageencryption.ic b/storage/xtradb/include/fsp0pageencryption.ic
index d313700..b386aac 100644
--- a/storage/xtradb/include/fsp0pageencryption.ic
+++ b/storage/xtradb/include/fsp0pageencryption.ic
@@ -98,8 +98,6 @@ fil_space_get_page_encryption_key(
 	return(flags);
 }
 
-
-
 /*******************************************************************//**
 Find out whether the page is page encrypted
 @return	true if page is page encrypted, false if not */
@@ -107,21 +105,9 @@ UNIV_INLINE
 ibool
 fil_page_is_encrypted(
 /*===================*/
-    const byte *buf)	/*!< in: page */
-{    
-    return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_ENCRYPTED); 
-}
-
-/*******************************************************************//**
-Find out whether the page is page is first compressed and then encrypted
- at return	true if page is page compressed+encrypted, false if not */
-UNIV_INLINE
-ibool
-fil_page_is_compressed_encrypted(
-/*=============================*/
 	const byte *buf)	/*!< in: page */
 {
-	return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
+	return(mach_read_from_4(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0);
 }
 
 /*******************************************************************//**
@@ -157,7 +143,7 @@ fil_page_encryption_status(
 		}
 	}
 
-	if(page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) {
+	if(fil_page_is_encrypted(buf)) {
 		ulint key = mach_read_from_4(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
 		if (!has_encryption_key(key)) {
 			return PAGE_ENCRYPTION_KEY_MISSING;
diff --git a/storage/xtradb/include/log0crypt.h b/storage/xtradb/include/log0crypt.h
index 9c7c022..cbb430d 100644
--- a/storage/xtradb/include/log0crypt.h
+++ b/storage/xtradb/include/log0crypt.h
@@ -23,6 +23,8 @@ extern my_bool srv_encrypt_log;
 extern byte redo_log_crypt_msg[MY_AES_BLOCK_SIZE];
 /* IV to concatenate with counter used by AES_CTR for redo log crypto. */
 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.
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index cda4a69..b40ebd5 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/include/log0log.h
@@ -748,7 +748,7 @@ extern log_t*	log_sys;
 #define LOG_CHECKPOINT_OFFSET_HIGH32	(16 + LOG_CHECKPOINT_ARRAY_END)
 #define LOG_CRYPT_VER			(20 + LOG_CHECKPOINT_ARRAY_END)
 					/*!< 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 */
 #define LOG_CRYPT_MSG			(24 + LOG_CHECKPOINT_ARRAY_END)
 					/*!< a 128-bit value used to
@@ -758,8 +758,10 @@ extern log_t*	log_sys;
 					15-byte random number.*/
 #define LOG_CRYPT_IV			(40 + LOG_CHECKPOINT_ARRAY_END)
 					/*!< a 128-bit random number used as
-					AES-CTR iv/nonce for redo log */
-#define LOG_CHECKPOINT_SIZE		(56 + LOG_CHECKPOINT_ARRAY_END)
+					AES-* iv/nonce for redo log */
+#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 */
 #define LOG_GROUP_ID		0	/* log group number */
diff --git a/storage/xtradb/log/log0crypt.cc b/storage/xtradb/log/log0crypt.cc
index abebdd8..1396a79 100644
--- a/storage/xtradb/log/log0crypt.cc
+++ b/storage/xtradb/log/log0crypt.cc
@@ -31,6 +31,7 @@ Modified           Jan Lindström jan.lindstrom at mariadb.com
 #include "log0log.h"
 #include "srv0start.h" // for srv_start_lsn
 #include "log0recv.h"  // for recv_sys
+#include "fil0crypt.h" // for aes_method
 
 #include "mysql/plugin_encryption_key_management.h" // for BAD_ENCRYPTION_KEY_VERSION
 #include "ha_prototypes.h" // IB_LOG_
@@ -44,15 +45,17 @@ UNIV_INTERN my_bool srv_encrypt_log = FALSE;
 static const byte redo_log_purpose_byte = 0x02;
 /* Plain text used by AES_ECB to generate redo log crypt key. */
 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. */
 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.
 It is generated via the concatenation of 1 purpose byte (0x02) and 15-byte
 random number.
-Init AES-CTR iv/nonce with random number.
+Init AES iv/nonce with random number.
 It is called when:
 - redo logs do not exist when start up, or
 - transition from without crypto.
@@ -70,8 +73,8 @@ log_init_crypt_msg_and_nonce(void)
 /*==============================*/
 {
 	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,
 			"Redo log crypto: generate "
 			"%u-byte random number as crypto msg failed.",
@@ -79,14 +82,16 @@ log_init_crypt_msg_and_nonce(void)
 		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,
 			"Redo log crypto: generate "
-			"%u-byte random number as AES_CTR nonce failed.",
+			"%u-byte random number failed.",
 			MY_AES_BLOCK_SIZE);
 		abort();
 	}
+
+	/* Set up current AES method */
+	redo_aes_method = (byte)fil_crypt_get_aes_method(current_aes_dynamic_method);
 }
 
 /*********************************************************************//**
@@ -99,16 +104,14 @@ log_init_crypt_key(
 	const uint crypt_ver,		/*< in: key version */
 	byte* key)			/*< out: crypt key*/
 {
-	if (crypt_ver == UNENCRYPTED_KEY_VER)
-	{
+	if (crypt_ver == UNENCRYPTED_KEY_VER) {
 		ib_logf(IB_LOG_LEVEL_INFO,
 			"Redo log crypto: unencrypted key ver.");
 		memset(key, 0, MY_AES_BLOCK_SIZE);
 		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,
 			"Redo log crypto: msg type mismatched. "
 			"Expected: %x; Actual: %x.",
@@ -117,8 +120,8 @@ log_init_crypt_key(
 	}
 
 	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,
 			"Redo log crypto: getting mysqld crypto key "
 			"from key version failed.");
@@ -126,15 +129,16 @@ log_init_crypt_key(
 	}
 
 	uint32 dst_len;
+
 	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
                         key, &dst_len, //dst, &dstlen
                         (unsigned char*)&mysqld_key, sizeof(mysqld_key),
                         NULL, 0,
                         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,
 			"Redo log crypto: getting redo log crypto key "
 			"failed.");
@@ -159,7 +163,7 @@ log_block_get_start_lsn(
 }
 
 /*********************************************************************//**
-Call AES CTR to encrypt/decrypt log blocks. */
+Call AES to encrypt/decrypt log blocks. */
 static
 Crypt_result
 log_blocks_crypt(
@@ -176,21 +180,22 @@ log_blocks_crypt(
 	ulint log_block_no, log_block_start_lsn;
 	byte *key;
 	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);
 		key = (byte *)(log_sys->redo_log_crypt_key);
 		lsn = log_sys->lsn;
-
 	} else {
 		ut_a(recv_sys && recv_sys->recv_log_crypt_ver != UNENCRYPTED_KEY_VER);
 		key = (byte *)(recv_sys->recv_log_crypt_key);
 		lsn = srv_start_lsn;
 	}
+
 	ut_a(size % OS_FILE_LOG_BLOCK_SIZE == 0);
 	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_start_lsn = log_block_get_start_lsn(lsn, log_block_no);
 
@@ -206,11 +211,13 @@ log_blocks_crypt(
 		mach_write_to_4(aes_ctr_counter + 11, log_block_no);
 		bzero(aes_ctr_counter + 15, 1);
 
-		int rc = (* my_aes_encrypt_dynamic)(log_block + LOG_BLOCK_HDR_SIZE, src_len,
-		                                dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
-		                                (unsigned char*)key, 16,
-		                                aes_ctr_counter, MY_AES_BLOCK_SIZE,
-		                                1);
+		my_aes_encrypt_dynamic_type func = get_aes_encrypt_func((enum_my_aes_encryption_algorithm)fil_crypt_map_aes_method(aes_method));
+
+		int rc = (*func)(log_block + LOG_BLOCK_HDR_SIZE, src_len,
+			         dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
+			         (unsigned char*)key, 16,
+			         aes_ctr_counter, MY_AES_BLOCK_SIZE,
+			         1);
 
 		ut_a(rc == AES_OK);
 		ut_a(dst_len == src_len);
@@ -303,13 +310,17 @@ log_crypt_write_checkpoint_buf(
 {
 	ut_a(log_sys);
 	mach_write_to_4(buf + LOG_CRYPT_VER, log_sys->redo_log_crypt_ver);
+
 	if (!srv_encrypt_log ||
 	    log_sys->redo_log_crypt_ver == UNENCRYPTED_KEY_VER) {
 		memset(buf + LOG_CRYPT_MSG, 0, MY_AES_BLOCK_SIZE);
 		memset(buf + LOG_CRYPT_IV, 0, MY_AES_BLOCK_SIZE);
+		memset(buf + LOG_CRYPT_METHOD, 0, 1);
 		return;
 	}
+
 	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_IV, aes_ctr_nonce, MY_AES_BLOCK_SIZE);
+	mach_write_to_1(buf + LOG_CRYPT_METHOD, redo_aes_method);
 }
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index c7fb3be..49a8714 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -3163,13 +3163,16 @@ recv_recovery_from_checkpoint_start_func(
 #ifdef UNIV_LOG_ARCHIVE
 	archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN);
 #endif /* UNIV_LOG_ARCHIVE */
+
 	recv_crypt_ver = mach_read_from_4(buf + LOG_CRYPT_VER);
+
 	if (recv_crypt_ver == UNENCRYPTED_KEY_VER)
 	{
 		log_init_crypt_msg_and_nonce();
 	} else {
 		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);
+		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
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index d7d224d..555ab1b 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -5486,8 +5486,7 @@ os_aio_windows_handle(
 	}
 
 	if (slot->type == OS_FILE_READ) {
-		if (fil_page_is_compressed_encrypted(slot->buf) ||
-			fil_page_is_encrypted(slot->buf)) {
+		if (fil_page_is_encrypted(slot->buf) && fil_space_get_crypt_data(slot->space_id)) {
 			ut_ad(slot->message1 != NULL);
 			os_slot_alloc_page_buf2(slot);
 			os_slot_alloc_tmp_encryption_buf(slot);
@@ -5618,8 +5617,7 @@ os_aio_linux_collect(
 
 			if (slot->type == OS_FILE_READ) {
 				/* If the page is page encrypted we decrypt */
-				if (fil_page_is_compressed_encrypted(slot->buf) ||
-					fil_page_is_encrypted(slot->buf)) {
+				if (fil_page_is_encrypted(slot->buf) && fil_space_get_crypt_data(slot->space_id)) {
 					os_slot_alloc_page_buf2(slot);
 					os_slot_alloc_tmp_encryption_buf(slot);
 					ut_ad(slot->message1 != NULL);
@@ -5651,8 +5649,7 @@ os_aio_linux_collect(
 			} else {
 				/* OS_FILE_WRITE */
 				if (slot->page_compression_success &&
-					(fil_page_is_compressed(slot->page_buf) ||
-					 fil_page_is_compressed_encrypted(slot->buf))) {
+				    fil_page_is_compressed(slot->page_buf)) {
 					ut_ad(slot->page_compression_page);
 					if (srv_use_trim && os_fallocate_failed == FALSE) {
 						// Deallocate unused blocks from file system



More information about the commits mailing list