diff options
Diffstat (limited to 'storage')
27 files changed, 699 insertions, 1281 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 5fcd30cfa18..3693620d394 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -359,8 +359,6 @@ SET(INNOBASE_SOURCES dict/dict0stats.cc dict/dict0stats_bg.cc dyn/dyn0dyn.cc - enc/EncKeys.cc - enc/KeySingleton.cc eval/eval0eval.cc eval/eval0proc.cc fil/fil0fil.cc diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index dbc6db8b4b8..49eef1c5f7a 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -16,7 +16,6 @@ #include <my_crypt_key_management.h> #include <my_aes.h> -#include <KeySingleton.h> #include <math.h> @@ -180,18 +179,14 @@ fil_space_crypt_cleanup() Get key bytes for a space/key-version */ static void -fil_crypt_get_key(byte *dst, uint dstlen, +fil_crypt_get_key(byte *dst, uint* key_length, fil_space_crypt_t* crypt_data, uint version, bool page_encrypted) { - /* TODO: Find a better way to do this */ - unsigned char keybuf[CRYPT_SCHEME_1_IV_LEN]; - byte key[CRYPT_SCHEME_1_IV_LEN]; - uint8 key_len = sizeof(keybuf); + unsigned char keybuf[MY_AES_MAX_KEY_LENGTH]; unsigned char iv[CRYPT_SCHEME_1_IV_LEN]; ulint iv_len = sizeof(iv); - bool key_error = false; - if (!page_encrypted) { + if (!page_encrypted) { mutex_enter(&crypt_data->mutex); // Check if we already have key @@ -210,77 +205,82 @@ fil_crypt_get_key(byte *dst, uint dstlen, for (uint i = 1; i < array_elements(crypt_data->keys); i++) { crypt_data->keys[i] = crypt_data->keys[i - 1]; } + } + else + { + // load iv - // TODO(jonaso): Integrate with real key server - int rc = GetCryptoKey(version, keybuf, key_len); - if (rc != 0) { - ib_logf(IB_LOG_LEVEL_FATAL, - "Unable to retrieve key with" - " version %u return-code: %d. Can't continue!\n", - version, rc); - ut_error; - } - } else { - /* For page encrypted tables we need to get the L */ - - /* Get key and IV */ - KeySingleton& keys = KeySingleton::getInstance(); - - if (keys.isAvailable() && keys.getKeys(version) != NULL) { - char* keyString = keys.getKeys(version)->key; - char* ivString = keys.getKeys(version)->iv; + int rc = GetCryptoIV(version, (unsigned char*)iv, iv_len); - if (keyString == NULL || ivString == NULL) { - key_error=true; - } else { - my_aes_hex2uint(keyString, (unsigned char*)&keybuf, key_len); - my_aes_hex2uint(ivString, (unsigned char*)&iv, iv_len); - } - } else { - key_error = true; - } - - if (key_error == true) { - ib_logf(IB_LOG_LEVEL_FATAL, - "Key file not found"); - ut_error; - } - } + if (rc != CRYPT_KEY_OK) { + ib_logf(IB_LOG_LEVEL_FATAL, + "IV %d can not be found. Reason=%d", version, rc); + ut_error; + } + } - // Now compute L by encrypting IV using this key - const unsigned char* src = page_encrypted ? iv : crypt_data->iv; - const int srclen = page_encrypted ? iv_len : crypt_data->iv_length; - unsigned char* buf = page_encrypted ? key : crypt_data->keys[0].key; - uint32 buflen = page_encrypted ? key_len : sizeof(crypt_data->keys[0].key); + if (HasCryptoKey(version)) { + *key_length = GetCryptoKeySize(version); - // 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_len, - NULL, 0, - 1); + int rc = GetCryptoKey(version, (unsigned char*)keybuf, *key_length); - if (rc != AES_OK) { + if (rc != CRYPT_KEY_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); + "Key %d can not be found. Reason=%d", version, rc); + ut_error; + } + } else { + ib_logf(IB_LOG_LEVEL_FATAL, + "Key %d not found", version); ut_error; } - if (!page_encrypted) { - crypt_data->keys[0].key_version = version; - crypt_data->key_count++; - if (crypt_data->key_count > array_elements(crypt_data->keys)) { - crypt_data->key_count = array_elements(crypt_data->keys); - } + // do ctr key initialization + if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) + { + // Now compute L by encrypting IV using this key + const unsigned char* src = page_encrypted ? iv : crypt_data->iv; + const int srclen = page_encrypted ? iv_len : 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; + } + + if (!page_encrypted) { + crypt_data->keys[0].key_version = version; + crypt_data->key_count++; + + if (crypt_data->key_count > array_elements(crypt_data->keys)) { + crypt_data->key_count = array_elements(crypt_data->keys); + } + } + + // 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); } - memcpy(dst, buf, buflen); - if (!page_encrypted) { mutex_exit(&crypt_data->mutex); } @@ -290,14 +290,22 @@ fil_crypt_get_key(byte *dst, uint dstlen, Get key bytes for a space/latest(key-version) */ static inline void -fil_crypt_get_latest_key(byte *dst, uint dstlen, +fil_crypt_get_latest_key(byte *dst, uint* key_length, fil_space_crypt_t* crypt_data, uint *version) { if (srv_encrypt_tables) { - *version = GetLatestCryptoKeyVersion(); - return fil_crypt_get_key(dst, dstlen, crypt_data, *version, false); + // used for key rotation - get the next key id from the key provider + int rc = GetLatestCryptoKeyVersion(); + + // if no new key was created use the last one + if (rc >= 0) + { + *version = rc; + } + + return fil_crypt_get_key(dst, key_length, crypt_data, *version, false); } else { - return fil_crypt_get_key(dst, dstlen, NULL, *version, true); + return fil_crypt_get_key(dst, key_length, NULL, *version, true); } } @@ -614,7 +622,8 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, // get key (L) uint key_version; - byte key[CRYPT_SCHEME_1_IV_LEN]; + byte key[MY_AES_MAX_KEY_LENGTH]; + uint key_length; if (srv_encrypt_tables) { crypt_data = fil_space_get_crypt_data(space); @@ -623,12 +632,45 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, memcpy(dst_frame, src_frame, page_size); return; } - fil_crypt_get_latest_key(key, sizeof(key), crypt_data, &key_version); + fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version); } else { key_version = encryption_key; - fil_crypt_get_latest_key(key, sizeof(key), NULL, (uint*)&key_version); + fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version); } + + /* 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 + { + // take the iv from the key provider + + int load_iv_rc = GetCryptoIV(key_version, (uchar *) iv, sizeof(iv)); + + // if the iv can not be loaded the whole page can not be encrypted + if (load_iv_rc != CRYPT_KEY_OK) + { + ib_logf(IB_LOG_LEVEL_FATAL, + "Unable to decrypt data-block. " + " Can not load iv for key %d" + " return-code: %d. Can't continue!\n", + key_version, load_iv_rc); + + ut_error; + } + } + + 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); @@ -662,14 +704,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, key_version); } - // create counter block (C) - unsigned char counter[MY_AES_BLOCK_SIZE]; - mach_write_to_4(counter + 0, space); - ulint space_offset = mach_read_from_4( - src_frame + FIL_PAGE_OFFSET); - mach_write_to_4(counter + 4, space_offset); - mach_write_to_8(counter + 8, lsn); - // encrypt page data ulint unencrypted_bytes = FIL_PAGE_DATA + FIL_PAGE_DATA_END; ulint srclen = page_size - unencrypted_bytes; @@ -683,10 +717,10 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, int rc = (* my_aes_encrypt_dynamic)(src, srclen, - dst, &dstlen, - (unsigned char*)&key, sizeof(key), - (unsigned char*)&counter, sizeof(counter), - 1); + dst, &dstlen, + (unsigned char*)key, key_length, + (unsigned char*)iv, sizeof(iv), + 1); if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) { ib_logf(IB_LOG_LEVEL_FATAL, @@ -776,6 +810,7 @@ bool fil_space_decrypt(fil_space_crypt_t* crypt_data, const byte* src_frame, ulint page_size, byte* dst_frame) { + ulint space_id = mach_read_from_4(src_frame + FIL_PAGE_SPACE_ID); ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); // key version uint key_version; @@ -791,7 +826,7 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, if (page_type == FIL_PAGE_PAGE_ENCRYPTED) { key_version = mach_read_from_2( src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - fprintf(stderr, "JAN: key_version %u\n", key_version); + fprintf(stderr, "JAN: key_version %lu\n", key_version); orig_page_type = mach_read_from_2( src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 2); fprintf(stderr, "JAN: decrypt: orig_page_type %lu\n", orig_page_type); @@ -816,10 +851,6 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, fprintf(stderr, "JAN: space %lu, offset %lu lsn %lu\n", space, offset, lsn); - // get key (L) - byte key[CRYPT_SCHEME_1_IV_LEN]; - fil_crypt_get_key(key, sizeof(key), crypt_data, key_version, page_encrypted); - // copy page header memcpy(dst_frame, src_frame, FIL_PAGE_DATA); @@ -828,11 +859,41 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, mach_write_to_2(dst_frame+FIL_PAGE_TYPE, orig_page_type); } - // create counter block - unsigned char counter[MY_AES_BLOCK_SIZE]; - mach_write_to_4(counter + 0, space); - mach_write_to_4(counter + 4, offset); - mach_write_to_8(counter + 8, lsn); + + // 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]; + + 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 + { + // take the iv from the key provider + + int load_iv_rc = GetCryptoIV(key_version, (uchar *) iv, sizeof(iv)); + + // if the iv can not be loaded the whole page can not be decrypted + if (load_iv_rc != CRYPT_KEY_OK) + { + ib_logf(IB_LOG_LEVEL_FATAL, + "Unable to decrypt data-block. " + " Can not load iv for key %d" + " return-code: %d. Can't continue!\n", + key_version, load_iv_rc); + + return AES_KEY_CREATION_FAILED; + } + } // decrypt page data ulint unencrypted_bytes = FIL_PAGE_DATA + FIL_PAGE_DATA_END; @@ -857,10 +918,10 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, srclen = pow((double)2, (double)((int)compressed_len)); } int rc = (* my_aes_decrypt_dynamic)(src, srclen, - dst, &dstlen, - (unsigned char*)&key, sizeof(key), - (unsigned char*)&counter, sizeof(counter), - 1); + dst, &dstlen, + (unsigned char*)key, key_length, + (unsigned char*)iv, sizeof(iv), + 1); if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) { ib_logf(IB_LOG_LEVEL_FATAL, diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 18b65c83949..30b021cb319 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -30,7 +30,6 @@ Created 10/25/1995 Heikki Tuuri #include "fil0pageencryption.h" #include "fsp0pageencryption.h" -#include "KeySingleton.h" #include <debug_sync.h> #include <my_dbug.h> @@ -824,7 +823,7 @@ fil_node_open_file( success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE, space->flags); - if (fil_page_can_not_decrypt(page)) { + if (fil_page_encryption_status(page)) { /* if page is (still) encrypted, write an error and return. * Otherwise the server would crash if decrypting is not possible. * This may be the case, if the key file could not be @@ -1329,8 +1328,7 @@ fil_space_create( ut_a(fil_system); if (fsp_flags_is_page_encrypted(flags)) { - if (!KeySingleton::getInstance().isAvailable() - || KeySingleton::getInstance().getKeys(fsp_flags_get_page_encryption_key(flags))==NULL) { + if (!HasCryptoKey(fsp_flags_get_page_encryption_key(flags))) { /* by returning here it should be avoided that * the server crashes, if someone tries to access an * encrypted table and the encryption key is not available. @@ -2099,7 +2097,7 @@ fil_check_first_page( or the encryption key is not available, the check for reading the first page should intentionally fail with "can not decrypt" message. */ - page_is_encrypted = fil_page_can_not_decrypt(page); + page_is_encrypted = fil_page_encryption_status(page); if ((page_is_encrypted == PAGE_ENCRYPTION_KEY_MISSING) && page_is_encrypted) { page_is_encrypted = 1; } else { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0f0ab32c7f5..99d619092d4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -104,8 +104,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "page0zip.h" #include "fil0pagecompress.h" -#include "KeySingleton.h" - #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -203,12 +201,6 @@ static char* innobase_disable_monitor_counter = NULL; static char* innobase_reset_monitor_counter = NULL; static char* innobase_reset_all_monitor_counter = NULL; -/* Encryption for tables and columns */ -static char* innobase_data_encryption_providername = NULL; -static char* innobase_data_encryption_providerurl = NULL; -static uint innobase_data_encryption_providertype = 0; // 1 == file, 2 == server -static char* innobase_data_encryption_filekey = NULL; - /* The highest file format being used in the database. The value can be set by user, however, it will be adjusted to the newer file format if a table of such format is created/opened. */ @@ -3131,10 +3123,6 @@ innobase_init( ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); - KeySingleton::getInstance( - innobase_data_encryption_providername, innobase_data_encryption_providerurl, - innobase_data_encryption_providertype, innobase_data_encryption_filekey); - #ifndef DBUG_OFF static const char test_filename[] = "-@"; char test_tablename[sizeof test_filename @@ -3760,8 +3748,6 @@ innobase_end( mysql_mutex_destroy(&pending_checkpoint_mutex); } - KeySingleton::getInstance().~KeySingleton(); - DBUG_RETURN(err); } @@ -11254,15 +11240,6 @@ ha_innobase::check_table_options( " innodb_file_per_table."); return "PAGE_ENCRYPTION"; } - - if (!KeySingleton::getInstance().isAvailable()) { - push_warning( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: PAGE_ENCRYPTION needs a key provider" - ); - return "PAGE_ENCRYPTION"; - } } /* Check page compression requirements */ @@ -11352,7 +11329,7 @@ ha_innobase::check_table_options( return "PAGE_ENCRYPTION_KEY"; } - if (!KeySingleton::getInstance().isAvailable() || KeySingleton::getInstance().getKeys(options->page_encryption_key)==NULL) { + if (!HasCryptoKey(options->page_encryption_key)) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, @@ -19044,26 +19021,6 @@ static MYSQL_SYSVAR_ULONG(fatal_semaphore_wait_threshold, srv_fatal_semaphore_wa UINT_MAX32, /* Maximum setting */ 0); -static MYSQL_SYSVAR_UINT(data_encryption_providertype, innobase_data_encryption_providertype, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Use table or column encryption / decryption. Default is 0 for no use, 1 for keyfile and 2 for keyserver.", - NULL, NULL, 1, 0, 2, 0); - -static MYSQL_SYSVAR_STR(data_encryption_providername, innobase_data_encryption_providername, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Name of keyfile or keyserver.", - NULL, NULL, NULL); - -static MYSQL_SYSVAR_STR(data_encryption_providerurl, innobase_data_encryption_providerurl, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Path or URL for keyfile or keyserver.", - NULL, NULL, NULL); - -static MYSQL_SYSVAR_STR(data_encryption_filekey, innobase_data_encryption_filekey, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Key to encrypt / decrypt the keyfile.", - NULL, NULL, NULL); - static MYSQL_SYSVAR_BOOL(encrypt_tables, srv_encrypt_tables, 0, "Encrypt tables", 0, 0, 0); @@ -19342,11 +19299,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(compression_algorithm), MYSQL_SYSVAR(mtflush_threads), MYSQL_SYSVAR(use_mtflush), - /* Table encryption feature */ - MYSQL_SYSVAR(data_encryption_providertype), - MYSQL_SYSVAR(data_encryption_providername), - MYSQL_SYSVAR(data_encryption_providerurl), - MYSQL_SYSVAR(data_encryption_filekey), /* Encryption feature */ MYSQL_SYSVAR(encrypt_tables), MYSQL_SYSVAR(encryption_threads), diff --git a/storage/innobase/include/EncKeys.h b/storage/innobase/include/EncKeys.h deleted file mode 100644 index 43f2920fd7f..00000000000 --- a/storage/innobase/include/EncKeys.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** -@file EncKeys.h -A structure and class to keep keys for encryption/decryption. - -Created 09/15/2014 -***********************************************************************/ - -#ifndef ENCKEYS_H_ -#define ENCKEYS_H_ - -#include "univ.i" -#include <sys/types.h> -#include <stdio.h> - - - - -struct keyentry { - ulint id; - char *iv; - char *key; -}; - - -class EncKeys -{ -private: - static const char *strMAGIC, *newLine; - static const int magicSize; - - enum constants { MAX_OFFSETS_IN_PCRE_PATTERNS = 30}; - enum keyAttributes { KEY_MIN = 1, KEY_MAX = 255, MAX_KEYS = 255, - MAX_IVLEN = 256, MAX_KEYLEN = 512, ivSize16 = 16, keySize32 = 32 }; - enum keyInitType { KEYINITTYPE_FILE = 1, KEYINITTYPE_SERVER = 2 }; - enum errorAttributes { MAX_KEY_LINE_SIZE = 3 * MAX_KEYLEN, MAX_KEY_FILE_SIZE = 1048576 }; - enum errorCodesLine { NO_ERROR_PARSE_OK = 0, NO_ERROR_ISCOMMENT = 10, NO_ERROR_KEY_GREATER_THAN_ASKED = 20, - ERROR_NOINITIALIZEDKEY = 30, ERROR_ID_TOO_BIG = 40, ERROR_WRONG_NUMBER_OF_MATCHES = 50, - ERROR_EQUAL_DOUBLE_KEY = 60, ERROR_UNEQUAL_DOUBLE_KEY = 70 }; - - static const char *errorNoKeyId, *errorInMatches, *errorExceedKeyFileSize, - *errorExceedKeySize, *errorEqualDoubleKey, *errorUnequalDoubleKey, - *errorNoInitializedKey, *errorFalseFileKey, - *errorNotImplemented, *errorOpenFile, *errorReadingFile, *errorFileSize; - - static const char* initialPwd; - ulint countKeys, keyLineInKeyFile; - keyentry keys[MAX_KEYS], *oneKey; - - void printKeyEntry( ulint id); - int initKeysThroughFile( const char *name, const char *path, const char *filekey); - int initKeysThroughServer( const char *name, const char *path, const char *filekey); - bool isComment( const char *line); - char * decryptFile( const char* filename, const char *secret, int *errorCode); - int parseFile( const char* filename, const ulint maxKeyId, const char *secret); - int parseLine( const char *line, const ulint maxKeyId); - -public: - static const size_t MAX_SECRET_SIZE = 256; - - enum errorCodesFile { NO_ERROR_KEY_FILE_PARSE_OK = 0, ERROR_KEY_FILE_PARSE_NULL = 110, - ERROR_KEY_FILE_TOO_BIG = 120, ERROR_KEY_FILE_EXCEEDS_MAX_NUMBERS_OF_KEYS = 130, - ERROR_OPEN_FILE = 140, ERROR_READING_FILE = 150, ERROR_FALSE_FILE_KEY = 160, - ERROR_KEYINITTYPE_SERVER_NOT_IMPLEMENTED = 170, ERROR_ENCRYPTION_SECRET_NULL = 180 }; - EncKeys(); - virtual ~EncKeys(); - bool initKeys( const char *name, const char *url, const int initType, const char *filekey); - keyentry *getKeys( int id); - /* made public for unit testing */ - static void parseSecret( const char *filename, char *secret ); - -}; - -#endif /* ENCKEYS_H_ */ diff --git a/storage/innobase/include/KeySingleton.h b/storage/innobase/include/KeySingleton.h deleted file mode 100644 index 2b2f3991998..00000000000 --- a/storage/innobase/include/KeySingleton.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** -@file KeySingletonPattern.h -Implementation of single pattern to keep keys for encrypting/decrypting pages. - -Created 09/13/2014 -***********************************************************************/ - - -#ifndef KEYSINGLETON_H_ -#define KEYSINGLETON_H_ - -#include "EncKeys.h" - - -class KeySingleton -{ -private: - static bool instanceInited; - static KeySingleton theInstance; - static EncKeys encKeys; - - // No new instance or object possible - KeySingleton() {} - - // No new instance possible through copy constructor - KeySingleton( const KeySingleton&) {} - - // No new instance possible through copy - KeySingleton & operator = (const KeySingleton&); - -public: - virtual ~KeySingleton() {encKeys.~EncKeys();} - static KeySingleton& getInstance(); - // Init the instance for only one time - static KeySingleton& getInstance(const char *name, const char *url, - const int initType, const char *filekey); - keyentry *getKeys(int id); - ibool hasKey(int id); - static bool isAvailable() { - return instanceInited; - } -}; - -#endif /* KEYSINGLETON_H_ */ diff --git a/storage/innobase/include/fil0pageencryption.h b/storage/innobase/include/fil0pageencryption.h index 395361bcd04..9769f8c1912 100644 --- a/storage/innobase/include/fil0pageencryption.h +++ b/storage/innobase/include/fil0pageencryption.h @@ -69,7 +69,7 @@ Find out whether the page can be decrypted @return true if page can be decrypted, false if not. */ UNIV_INLINE ulint -fil_page_can_not_decrypt( +fil_page_encryption_status( /*===================*/ const byte *buf); /*!< in: page */ diff --git a/storage/innobase/include/fsp0pageencryption.ic b/storage/innobase/include/fsp0pageencryption.ic index ad016c46fdb..42c980b0430 100644 --- a/storage/innobase/include/fsp0pageencryption.ic +++ b/storage/innobase/include/fsp0pageencryption.ic @@ -24,8 +24,8 @@ Created 08/28/2014 ***********************************************************************/ #include "fsp0fsp.h" -#include "KeySingleton.h" #include "fil0pageencryption.h" +#include <my_crypt_key_management.h> /********************************************************************//** @@ -138,7 +138,7 @@ The function for decrypting the page should already be executed before this. */ UNIV_INLINE ulint -fil_page_can_not_decrypt( +fil_page_encryption_status( /*=====================*/ const byte *buf) /*!< in: page */ { @@ -147,11 +147,9 @@ fil_page_can_not_decrypt( if (page_type == FIL_PAGE_TYPE_FSP_HDR) { ulint flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf); if (fsp_flags_is_page_encrypted(flags)) { - if (!KeySingleton::getInstance().isAvailable() || - !KeySingleton::getInstance().hasKey(fsp_flags_get_page_encryption_key(flags))) { + if (!HasCryptoKey(fsp_flags_get_page_encryption_key(flags))) { /* accessing table would surely fail, because no key or no key provider available */ - if (KeySingleton::getInstance().isAvailable() && - !KeySingleton::getInstance().hasKey(fsp_flags_get_page_encryption_key(flags))) { + if (!HasCryptoKey(fsp_flags_get_page_encryption_key(flags))) { return PAGE_ENCRYPTION_KEY_MISSING; } return PAGE_ENCRYPTION_ERROR; @@ -161,8 +159,7 @@ fil_page_can_not_decrypt( if(page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { ulint key = mach_read_from_4(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - if (KeySingleton::getInstance().isAvailable() && - !KeySingleton::getInstance().hasKey(key)) { + if (!HasCryptoKey(key)) { return PAGE_ENCRYPTION_KEY_MISSING; } return PAGE_ENCRYPTION_ERROR; diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index f902df61484..d7dd6b38459 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -4,11 +4,13 @@ Innodb log encrypt/decrypt Created 11/25/2013 Minli Zhu *******************************************************/ +#include "m_string.h" #include "log0crypt.h" +#include <my_crypt.h> + #include "log0log.h" #include "srv0start.h" // for srv_start_lsn #include "log0recv.h" // for recv_sys -#include <my_crypt.h> /* If true, enable redo log encryption. */ UNIV_INTERN my_bool srv_encrypt_log = FALSE; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 20f6d4d1db0..0bcbe01c0f6 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4703,9 +4703,9 @@ found: } - if (srv_encrypt_tables) { - page_encryption = TRUE; - } +// if (srv_encrypt_tables) { + //page_encryption = TRUE; +// } /* If the space is page encryption and this is write operation then we encrypt the page */ diff --git a/storage/tokudb/ft-index/ft/ftverify b/storage/tokudb/ft-index/ft/ftverify Binary files differnew file mode 100755 index 00000000000..96b86bfe250 --- /dev/null +++ b/storage/tokudb/ft-index/ft/ftverify diff --git a/storage/tokudb/ft-index/ft/tdb-recover b/storage/tokudb/ft-index/ft/tdb-recover Binary files differnew file mode 100755 index 00000000000..8df5480b705 --- /dev/null +++ b/storage/tokudb/ft-index/ft/tdb-recover diff --git a/storage/tokudb/ft-index/ft/tdb_logprint b/storage/tokudb/ft-index/ft/tdb_logprint Binary files differnew file mode 100755 index 00000000000..3055805b767 --- /dev/null +++ b/storage/tokudb/ft-index/ft/tdb_logprint diff --git a/storage/tokudb/ft-index/ft/tokuftdump b/storage/tokudb/ft-index/ft/tokuftdump Binary files differnew file mode 100755 index 00000000000..5b0b4c3b78a --- /dev/null +++ b/storage/tokudb/ft-index/ft/tokuftdump diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt index d0a8b137791..121d7914083 100644 --- a/storage/xtradb/CMakeLists.txt +++ b/storage/xtradb/CMakeLists.txt @@ -359,8 +359,6 @@ SET(INNOBASE_SOURCES dict/dict0stats.cc dict/dict0stats_bg.cc dyn/dyn0dyn.cc - enc/EncKeys.cc - enc/KeySingleton.cc eval/eval0eval.cc eval/eval0proc.cc fil/fil0fil.cc diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 227570626ca..d32c5fb138f 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -5807,7 +5807,7 @@ buf_page_encrypt_before_write( // encrypt page content fil_space_encrypt(bpage->space, bpage->offset, bpage->newest_modification, - src_frame, zip_size, dst_frame); + src_frame, zip_size, dst_frame, 0); unsigned key_version = mach_read_from_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); diff --git a/storage/xtradb/enc/EncKeys.cc b/storage/xtradb/enc/EncKeys.cc deleted file mode 100644 index 3b5e9f4121c..00000000000 --- a/storage/xtradb/enc/EncKeys.cc +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** - @file EncKeys.cc - A class to keep keys for encryption/decryption. - -How it works... -The location and usage can be configured via the configuration file. -Example - -[mysqld] -... -innodb_data_encryption_providertype = 1 -innodb_data_encryption_providername = keys.enc -innodb_data_encryption_providerurl = /home/mdb/ -innodb_data_encryption_filekey = secret -... - -As provider type currently only value 1 is supported, which means, the keys are read from a file. -The filename is set up via the innodb_data_encryption_providername configuration value. -innodb_data_encryption_providerurl is used to configure the path to this file. This is usually -a folder name. -Examples: -innodb_data_encryption_providerurl = \\\\unc (windows share) -innodb_data_encryption_providerurl = e:/tmp/ (windows path) -innodb_data_encryption_providerurl = /tmp (linux path) - -The key file contains AES keys and initialization vectors as hex-encoded Strings. -Supported are keys of size 128, 192 or 256 bits. IV consists of 16 bytes. - -The key file should be encrypted and the key to decrypt the file can be given with the -innodb_data_encryption_filekey parameter. - -The file key can also be located if FILE: is prepended to the key. Then the following part is interpreted -as absolut to the file containing the file key. This file can optionally be encrypted, currently with a fix key. -Example: -innodb_data_encryption_filekey = FILE:y:/secret256.enc - -If the key file can not be read at server startup, for example if the file key is not present, -page_encryption feature is not availabe and access to page_encryption tables is not possible. - -Example files can be found inside the unittest/eperi folder. - -Open SSL command line utility can be used to create an encrypted key file. -Examples: -openssl enc –aes-256-cbc –md sha1 –k secret –in keys.txt –out keys.enc -openssl enc –aes-256-cbc –md sha1 –k <initialPwd> –in secret –out secret.enc - - Created 09/15/2014 - ***********************************************************************/ -#ifdef __WIN__ -#define PCRE_STATIC 1 -#endif - -#include "EncKeys.h" -#include <my_global.h> -#include <my_aes.h> -#include <memory.h> -#include <my_sys.h> -#include <pcre.h> -#include <string.h> -#include <my_sys.h> - - - - -const char* EncKeys::strMAGIC = "Salted__"; -#define magicSize 8 //strlen(strMAGIC); // 8 byte -const char* EncKeys::newLine = "\n"; - -const char* EncKeys::errorNoKeyId = "KeyID = %u not found or with error. Check the key and the log file.\n"; -const char* EncKeys::errorInMatches = "Wrong match of the keyID in line %u, see the template.\n"; -const char* EncKeys::errorExceedKeyFileSize = "The size of the key file %s exceeds " - "the maximum allowed of %u bytes.\n"; -const char* EncKeys::errorExceedKeySize = "The key size exceeds the maximum allowed size of %u in line %u.\n"; -const char* EncKeys::errorEqualDoubleKey = "More than one identical key with keyID = %u found" - " in lines %u and %u.\nDelete one of them in the key file.\n"; -const char* EncKeys::errorUnequalDoubleKey = "More than one not identical key with keyID = %u found" - " in lines %u and %u.\nChoose the right one and delete the other in the key file.\n" - "I'll take the key from line %u\n"; -const char* EncKeys::errorNoInitializedKey = "The key could not be initialized.\n"; -const char* EncKeys::errorNotImplemented = "Initializing keys through key server is not" - " yet implemented.\nYou can not read encrypted tables or columns\n\n"; -const char* EncKeys::errorOpenFile = "Could not open %s for reading. You can not read encrypted tables or columns.\n\n"; -const char* EncKeys::errorReadingFile = "Could not read from %s. You can not read encrypted tables or columns\n\n"; -const char* EncKeys::errorFileSize = "Could not get the file size from %s. You can not read encrypted tables or columns\n\n"; -const char* EncKeys::errorFalseFileKey = "Wrong encryption / decryption key for keyfile '%s'.\n"; - -/* read this from a secret source in some later version */ -const char* EncKeys::initialPwd = "lg28s9ac5ffa537fd8798875c98e190df289da7e047c05"; - -EncKeys::EncKeys() { - countKeys = keyLineInKeyFile = 0; - for (int ii = 0; ii < MAX_KEYS; ii++) { - keys[ii].id = 0; - keys[ii].iv = keys[ii].key = NULL; - } - oneKey = NULL; -} - -EncKeys::~EncKeys() { - for (int ii = MAX_KEYS - 1; ii >= 0 ; ii--) { - delete[] keys[ii].iv; keys[ii].iv = NULL; - delete[] keys[ii].key; keys[ii].key = NULL; - - } -} - -bool EncKeys::initKeys(const char *name, const char *url, const int initType, const char *filekey) { - if (KEYINITTYPE_FILE == initType) - { - int result = initKeysThroughFile(name, url, filekey); - return ERROR_FALSE_FILE_KEY != result && ERROR_OPEN_FILE != result && ERROR_READING_FILE != result; - } - else if (KEYINITTYPE_SERVER == initType) - { - return NO_ERROR_KEY_FILE_PARSE_OK == initKeysThroughServer(name, url, filekey); - } - return false; -} - -int EncKeys::initKeysThroughFile(const char *name, const char *path, const char *filekey) { - if (path==NULL || name==NULL) return ERROR_OPEN_FILE; - size_t len1 = strlen(path); - size_t len2 = strlen(name); - const char *MAGIC = "FILE:"; - const short MAGIC_LEN = 5; - int ret = NO_ERROR_KEY_FILE_PARSE_OK; - bool isUncPath= (len1>2) ? ((strncmp("\\\\", path, 2)==0) ? TRUE : FALSE) : FALSE; - bool isSlash = ((isUncPath? '\\':'/') == path[len1 - 1]); - char *secret = (char*) malloc(MAX_SECRET_SIZE +1 * sizeof(char)); - char *filename = (char*) malloc((len1 + len2 + (isSlash ? 1 : 2)) * sizeof(char)); - if(filekey != NULL) - { - //If secret starts with FILE: interpret the secret as filename. - if(memcmp(MAGIC, filekey, MAGIC_LEN) == 0) { - int fk_len = strlen(filekey); - char *secretfile = (char*)malloc( (1 + fk_len - MAGIC_LEN)* sizeof(char)); - memcpy(secretfile, filekey+MAGIC_LEN, fk_len - MAGIC_LEN); - secretfile[fk_len-MAGIC_LEN] = '\0'; - parseSecret(secretfile, secret); - free(secretfile); - } else - { - sprintf(secret, "%s", filekey); - } - } - sprintf(filename, "%s%s%s", path, isSlash ? "" : (isUncPath ? "\\":"/"), name); - ret = parseFile((const char *)filename, 254, secret); - free(filename); - free(secret); - return ret; -} - -int EncKeys::initKeysThroughServer( const char *name, const char *path, const char *filekey) -{ - //TODO -#ifdef UNIV_DEBUG - fprintf(stderr, errorNotImplemented); -#endif //UNIV_DEBUG - return ERROR_KEYINITTYPE_SERVER_NOT_IMPLEMENTED; -} - - -/* - secret is limited to MAX_SECRET_SIZE characters -*/ - -void EncKeys::parseSecret(const char *secretfile, char *secret) -{ - int maxSize = (MAX_SECRET_SIZE +16 + magicSize*2) ; - uchar* buf = (uchar*)malloc((maxSize) * sizeof(uchar)); - char* _initPwd = (char*)malloc((strlen(initialPwd)+1) * sizeof(char)); - - FILE *fp = fopen(secretfile, "rb"); - fseek(fp, 0L, SEEK_END); - long file_size = ftell(fp); - rewind(fp); - int bytes_to_read = MY_MIN(maxSize, file_size); - if ((fread(buf, 1, bytes_to_read, fp)) != bytes_to_read) - { - secret[0]=0; - goto err; - } - - if (memcmp(buf, strMAGIC, magicSize)) - { - bytes_to_read = ((unsigned int) bytes_to_read>MAX_SECRET_SIZE) ? MAX_SECRET_SIZE : bytes_to_read; - memcpy(secret, buf, bytes_to_read); - secret[bytes_to_read] = '\0'; - } - else - { - unsigned char salt[magicSize]; - unsigned char *key = new unsigned char[keySize32]; - unsigned char *iv = new unsigned char[ivSize16]; - memcpy(&salt, buf + magicSize, magicSize); - memcpy(_initPwd, initialPwd, strlen(initialPwd)); - _initPwd[strlen(initialPwd)]= '\0'; - my_bytes_to_key((unsigned char *) salt, _initPwd, key, iv); - uint32 d_size = 0; - - /* This file is always encoded with cbc */ - enum_my_aes_encryption_algorithm org_method= current_aes_dynamic_method; - my_aes_init_dynamic_encrypt(MY_AES_ALGORITHM_CBC); - int res = my_aes_decrypt_dynamic((const uchar*)buf + 2 * magicSize, - bytes_to_read - 2 * magicSize, - (uchar*)secret, &d_size, (const uchar*)key, keySize32, - iv, ivSize16, 0); - my_aes_init_dynamic_encrypt(org_method); - /* We would prefer a better error handling, but this will due for now */ - if (res != 0) - d_size= 0; - if (d_size>EncKeys::MAX_SECRET_SIZE) - d_size = EncKeys::MAX_SECRET_SIZE; - secret[d_size] = '\0'; - delete[] key; - delete[] iv; - } - -err: - free(buf); - free(_initPwd); - fclose(fp); -} - -/** - * Returns a struct keyentry with the asked 'id' or NULL. - */ - -keyentry *EncKeys::getKeys(int id) -{ - if (KEY_MIN <= id && KEY_MAX >= id && (&keys[id - 1])->iv) - { - return &keys[id - 1]; - } - DBUG_PRINT("error", (errorNoKeyId, id)); - return NULL; -} - -/** - * Get the keys from the key file <filename> and decrypt it with the key <secret>. - * Store the keys with id smaller then <maxKeyId> in an array of structs keyentry. - * Returns NO_ERROR_PARSE_OK or an appropriate error code. - */ -int EncKeys::parseFile(const char* filename, const ulint maxKeyId, const char *secret) { - int errorCode = 0; - char *buffer = decryptFile(filename, secret, &errorCode); - ulint id = 0; - - if (NO_ERROR_PARSE_OK != errorCode) return errorCode; - else errorCode = NO_ERROR_KEY_FILE_PARSE_OK; - - char *line = strtok(buffer, newLine); - while ( NULL != line) { - keyLineInKeyFile++; - switch (parseLine(line, maxKeyId)) { - case NO_ERROR_PARSE_OK: - id = oneKey->id; - keys[oneKey->id - 1] = *oneKey; - delete(oneKey); - countKeys++; - fprintf(stderr, "Line: %u --> ", (uint) keyLineInKeyFile); printKeyEntry(id); - break; - case ERROR_ID_TOO_BIG: - fprintf(stderr, errorExceedKeySize, KEY_MAX, keyLineInKeyFile); - fprintf(stderr, " --> %s\n", line); - errorCode = ERROR_KEY_FILE_EXCEEDS_MAX_NUMBERS_OF_KEYS; - break; - case ERROR_NOINITIALIZEDKEY: - fprintf(stderr, errorNoInitializedKey); - fprintf(stderr, " --> %s\n", line); - errorCode = ERROR_KEY_FILE_PARSE_NULL; - break; - case ERROR_WRONG_NUMBER_OF_MATCHES: - fprintf(stderr, errorInMatches, keyLineInKeyFile); - fprintf(stderr, " --> %s\n", line); - errorCode = ERROR_KEY_FILE_PARSE_NULL; - break; - case NO_ERROR_KEY_GREATER_THAN_ASKED: - fprintf(stderr, "No asked key in line %lu: %s\n", keyLineInKeyFile, line); - break; - case NO_ERROR_ISCOMMENT: - fprintf(stderr, "Is comment in line %lu: %s\n", keyLineInKeyFile, line); - default: - break; - } - line = strtok(NULL, newLine); - } - - free(line); line = NULL; - delete[] buffer; buffer = NULL; - return errorCode; -} - -int EncKeys::parseLine(const char *line, const ulint maxKeyId) { - int ret = NO_ERROR_PARSE_OK; - if (isComment(line)) - ret = NO_ERROR_ISCOMMENT; - else { - const char *error_p = NULL; - int offset; - pcre *pattern = pcre_compile( - "([0-9]+);([0-9,a-f,A-F]{32});([0-9,a-f,A-F]{64}|[0-9,a-f,A-F]{48}|[0-9,a-f,A-F]{32})", - 0, &error_p, &offset, NULL); - if ( NULL != error_p) - fprintf(stderr, "Error: %s\nOffset: %d\n", error_p, offset); - - int m_len = (int) strlen(line), ovector[MAX_OFFSETS_IN_PCRE_PATTERNS]; - int rc = pcre_exec(pattern, NULL, line, m_len, 0, 0, ovector, MAX_OFFSETS_IN_PCRE_PATTERNS); - pcre_free(pattern); - if (4 == rc) { - char lin[MAX_KEY_LINE_SIZE + 1]; - strncpy( lin, line, MAX_KEY_LINE_SIZE); - lin[MAX_KEY_LINE_SIZE] = '\0'; - char *substring_start = lin + ovector[2]; - int substr_length = ovector[3] - ovector[2]; - if (3 < substr_length) - ret = ERROR_ID_TOO_BIG; - else { - char buffer[4]; - sprintf(buffer, "%.*s", substr_length, substring_start); - ulint id = atoi(buffer); - if (0 == id) ret = ERROR_NOINITIALIZEDKEY; - else if (KEY_MAX < id) ret = ERROR_ID_TOO_BIG; - else if (maxKeyId < id) ret = NO_ERROR_KEY_GREATER_THAN_ASKED; - else { - oneKey = new keyentry; - oneKey->id = id; - substring_start = lin + ovector[4]; - substr_length = ovector[5] - ovector[4]; - oneKey->iv = new char[substr_length + 1]; - sprintf(oneKey->iv, "%.*s", substr_length, substring_start); - substring_start = lin + ovector[6]; - substr_length = ovector[7] - ovector[6]; - oneKey->key = new char[substr_length + 1]; - sprintf(oneKey->key, "%.*s", substr_length, substring_start); - } - } - } - else - ret = ERROR_WRONG_NUMBER_OF_MATCHES; - } - return ret; -} - -/** - Decrypt the key file 'filename' if it is encrypted with the key 'secret'. - Store the content of the decrypted file in 'buffer'. The buffer has to be freed - in the calling function. -*/ - -char* EncKeys::decryptFile(const char* filename, const char *secret, int *errorCode) { - *errorCode = NO_ERROR_PARSE_OK; - fprintf(stderr, "Reading %s\n\n", filename); - FILE *fp = fopen(filename, "rb"); - if (NULL == fp) { - fprintf(stderr, errorOpenFile, filename); - *errorCode = ERROR_OPEN_FILE; - return NULL; - } - - if (fseek(fp, 0L, SEEK_END)) { - *errorCode = ERROR_READING_FILE; - return NULL; - } - long file_size = ftell(fp); // get the file size - if (MAX_KEY_FILE_SIZE < file_size) { - fprintf(stderr, errorExceedKeyFileSize, filename, MAX_KEY_FILE_SIZE); - *errorCode = ERROR_KEY_FILE_TOO_BIG; - fclose(fp); - return NULL; - } - else if (-1L == file_size) { - fprintf(stderr, errorFileSize, filename); - *errorCode = ERROR_READING_FILE; - return NULL; - } - - rewind(fp); - //Read file into buffer - uchar *buffer = new uchar[file_size + 1]; - file_size= fread(buffer, 1, file_size, fp); - buffer[file_size] = '\0'; - fclose(fp); - //Check for file encryption - if (0 == memcmp(buffer, strMAGIC, magicSize)) - { //If file is encrypted, decrypt it first. - unsigned char salt[magicSize]; - unsigned char *key = new unsigned char[keySize32]; - unsigned char *iv = new unsigned char[ivSize16]; - uchar *decrypted = new uchar[file_size]; - memcpy(&salt, buffer + magicSize, magicSize); - my_bytes_to_key((unsigned char *) salt, secret, key, iv); - uint32 d_size = 0; - - /* This file is always encoded with cbc */ - enum_my_aes_encryption_algorithm org_method= current_aes_dynamic_method; - my_aes_init_dynamic_encrypt(MY_AES_ALGORITHM_CBC); - int res = my_aes_decrypt_dynamic((const uchar*)buffer + 2 * magicSize, - file_size - 2 * magicSize, - decrypted, &d_size, - (const uchar*) key, keySize32, - iv, ivSize16, 0); - my_aes_init_dynamic_encrypt(org_method); - if(0 != res) { - *errorCode = ERROR_FALSE_FILE_KEY; - delete[] buffer; buffer = NULL; - fprintf(stderr, errorFalseFileKey, filename); - } - else { - memcpy(buffer, decrypted, d_size); - buffer[d_size] = '\0'; - } - - delete[] decrypted; decrypted = NULL; - delete[] key; key = NULL; - delete[] iv; iv = NULL; - } - return (char*) buffer; -} - -bool EncKeys::isComment(const char *line) { - const char *error_p; - int offset, m_len = (int) strlen(line), ovector[MAX_OFFSETS_IN_PCRE_PATTERNS]; - pcre *pattern = pcre_compile("\\s*#.*", 0, &error_p, &offset, NULL); - int rc = pcre_exec( pattern, NULL, line, m_len, 0, 0, ovector, MAX_OFFSETS_IN_PCRE_PATTERNS); - pcre_free(pattern); - if (0 > rc) return false; - else return true; -} - - -void EncKeys::printKeyEntry( ulint id) -{ -#ifdef UNIV_DEBUG - keyentry *entry = getKeys(id); - if( NULL == entry) { - fprintf(stderr, "No such keyID=%lu\n",id); - } - else { - fprintf(stderr, "Key: id:%3lu \tiv:%lu bytes\tkey:%lu bytes\n", entry->id, strlen(entry->iv)/2, strlen(entry->key)/2); - } -#endif //UNIV_DEBUG -} diff --git a/storage/xtradb/enc/KeySingleton.cc b/storage/xtradb/enc/KeySingleton.cc deleted file mode 100644 index b751bd79fe2..00000000000 --- a/storage/xtradb/enc/KeySingleton.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** -@file KeySingleton.cc -Implementation of single pattern to keep keys for encrypting/decrypting pages. - -Created 09/13/2014 -***********************************************************************/ - - -#include "KeySingleton.h" -#include <stdlib.h> - - -bool KeySingleton::instanceInited = false; -KeySingleton KeySingleton::theInstance; -EncKeys KeySingleton::encKeys; - - - -KeySingleton & KeySingleton::getInstance() { -#ifdef UNIV_DEBUG - if( !instanceInited) { - fprintf(stderr, "Encryption / decryption keys were not initialized. " - "You can not read encrypted tables or columns\n"); - } -#endif /* UNIV_DEBUG */ - return theInstance; -} - -KeySingleton & KeySingleton::getInstance(const char *name, const char *url, - const int initType, const char *filekey) { - - if(instanceInited) return theInstance; - instanceInited = encKeys.initKeys(name, url, initType, filekey); - if( !instanceInited) { - fprintf(stderr, "Could not initialize any of the encryption / decryption keys. " - "You can not read encrypted tables\n\n"); - fflush(stderr); - } - - return theInstance; -} - -keyentry *KeySingleton::getKeys(int id) { - return encKeys.getKeys(id); -} - -ibool KeySingleton::hasKey(int id) { - return encKeys.getKeys(id) != NULL; -} - diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 5024db0d0fb..0b61b31f7f5 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -9,10 +9,16 @@ #include "ut0ut.h" #include "btr0scrub.h" #include "fsp0fsp.h" +#include "fil0pagecompress.h" +#include "fil0pageencryption.h" #include <my_crypt.h> #include <my_crypt_key_management.h> +#include <my_aes.h> +#include <math.h> + + /** Mutex for keys */ UNIV_INTERN ib_mutex_t fil_crypt_key_mutex; @@ -173,85 +179,136 @@ fil_space_crypt_cleanup() Get key bytes for a space/key-version */ static void -fil_crypt_get_key(uchar *dst, uint dstlen, - fil_space_crypt_t* crypt_data, uint version) +fil_crypt_get_key(byte *dst, uint* key_length, + fil_space_crypt_t* crypt_data, uint version, bool page_encrypted) { -#ifndef HAVE_EncryptAes128Ctr - return; -#else - mutex_enter(&crypt_data->mutex); + unsigned char keybuf[MY_AES_MAX_KEY_LENGTH]; + unsigned char iv[CRYPT_SCHEME_1_IV_LEN]; + ulint iv_len = sizeof(iv); - // 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; + if (!page_encrypted) { + mutex_enter(&crypt_data->mutex); + + // 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; + } } - } - // Not found! - crypt_data->keyserver_requests++; + // 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]; - } + // 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]; + } + } + else + { + // load iv + fprintf(stderr, "%d... %d\n",iv_len, version); - // TODO(jonaso): Integrate with real key server + int rc = GetCryptoIV(version, (unsigned char*)iv, iv_len); + fprintf(stderr, " %d\n",rc); - // Get new key from key server - unsigned char keybuf[CRYPT_SCHEME_1_IV_LEN]; - unsigned keylen = sizeof(keybuf); - int rc = GetCryptoKey(version, keybuf, keylen); - if (rc != 0) { + if (rc != CRYPT_KEY_OK) { ib_logf(IB_LOG_LEVEL_FATAL, - "Unable to retrieve key with" - " version %u return-code: %d. Can't continue!\n", - version, rc); + "IV %d can not be found. Reason=%d", version, rc); ut_error; - } + } + } + + if (HasCryptoKey(version)) { + *key_length = GetCryptoKeySize(version); + + int rc = GetCryptoKey(version, (unsigned char*)keybuf, *key_length); - // Now compute L by encrypting IV using this key - const unsigned char* src = crypt_data->iv; - const int srclen = crypt_data->iv_length; - unsigned char* buf = crypt_data->keys[0].key; - int buflen = sizeof(crypt_data->keys[0].key); - rc = my_aes_encrypt_ecb(src, srclen, - buf, &buflen, - keybuf, sizeof(keybuf), - 0,0,0); - if (rc != CRYPT_OK) { + if (rc != CRYPT_KEY_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); + "Key %d can not be found. Reason=%d", version, rc); + ut_error; + } + } else { + ib_logf(IB_LOG_LEVEL_FATAL, + "Key %d not found", version); ut_error; } - crypt_data->keys[0].key_version = version; - crypt_data->key_count++; - if (crypt_data->key_count > array_elements(crypt_data->keys)) { - crypt_data->key_count = array_elements(crypt_data->keys); + // do ctr key initialization + if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) + { + // Now compute L by encrypting IV using this key + const unsigned char* src = page_encrypted ? iv : crypt_data->iv; + const int srclen = page_encrypted ? iv_len : 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; + } + + if (!page_encrypted) { + crypt_data->keys[0].key_version = version; + crypt_data->key_count++; + + if (crypt_data->key_count > array_elements(crypt_data->keys)) { + crypt_data->key_count = array_elements(crypt_data->keys); + } + } + + // 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); } - memcpy(dst, crypt_data->keys[0].key, - sizeof(crypt_data->keys[0].key)); - mutex_exit(&crypt_data->mutex); -#endif + if (!page_encrypted) { + mutex_exit(&crypt_data->mutex); + } } /****************************************************************** Get key bytes for a space/latest(key-version) */ static inline void -fil_crypt_get_latest_key(uchar *dst, uint dstlen, +fil_crypt_get_latest_key(byte *dst, uint* key_length, fil_space_crypt_t* crypt_data, uint *version) { - *version = GetLatestCryptoKeyVersion(); - return fil_crypt_get_key(dst, dstlen, crypt_data, *version); + if (srv_encrypt_tables) { + // used for key rotation - get the next key id from the key provider + int rc = GetLatestCryptoKeyVersion(); + + // if no new key was created use the last one + if (rc >= 0) + { + *version = rc; + } + + return fil_crypt_get_key(dst, key_length, crypt_data, *version, false); + } else { + return fil_crypt_get_key(dst, key_length, NULL, *version, true); + } } /****************************************************************** @@ -260,9 +317,6 @@ UNIV_INTERN fil_space_crypt_t* fil_space_create_crypt_data() { -#ifndef HAVE_EncryptAes128Ctr - return 0; -#else 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 = @@ -282,7 +336,6 @@ fil_space_create_crypt_data() crypt_data->iv_length = iv_length; my_random_bytes(crypt_data->iv, iv_length); return crypt_data; -#endif } /****************************************************************** @@ -558,52 +611,120 @@ fil_space_check_encryption_write( } /****************************************************************** - 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) + const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key) { - fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); + fil_space_crypt_t* crypt_data; ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE; - if (crypt_data == NULL || srv_encrypt_tables == FALSE) { - memcpy(dst_frame, src_frame, page_size); - return; - } + + fprintf(stderr, "JAN: page_size %lu\n", page_size); // get key (L) uint key_version; - uchar key[CRYPT_SCHEME_1_IV_LEN]; - fil_crypt_get_latest_key(key, sizeof(key), crypt_data, &key_version); + byte key[MY_AES_MAX_KEY_LENGTH]; + uint key_length; + + if (srv_encrypt_tables) { + crypt_data = fil_space_get_crypt_data(space); + if (crypt_data == NULL) { + //TODO: Is this really needed ? + memcpy(dst_frame, src_frame, page_size); + return; + } + fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version); + } else { + key_version = encryption_key; + fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version); + } + + + /* 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 + { + // take the iv from the key provider + + int load_iv_rc = GetCryptoIV(key_version, (uchar *) iv, sizeof(iv)); + + // if the iv can not be loaded the whole page can not be encrypted + if (load_iv_rc != CRYPT_KEY_OK) + { + ib_logf(IB_LOG_LEVEL_FATAL, + "Unable to decrypt data-block. " + " Can not load iv for key %d" + " return-code: %d. Can't continue!\n", + key_version, load_iv_rc); + + ut_error; + } + } + + + 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 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) { + memcpy(dst_frame, src_frame, page_size); + return; + } // copy page header memcpy(dst_frame, src_frame, FIL_PAGE_DATA); - // store key version - mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, - key_version); - // create counter block (C) - unsigned char counter[MY_AES_BLOCK_SIZE]; - mach_write_to_4(counter + 0, space); - mach_write_to_4(counter + 4, offset); - mach_write_to_8(counter + 8, lsn); + 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); + } // encrypt page data ulint unencrypted_bytes = FIL_PAGE_DATA + FIL_PAGE_DATA_END; - - const uchar* src = (uchar*) src_frame + FIL_PAGE_DATA; - uchar* dst = (uchar*) dst_frame + FIL_PAGE_DATA; + ulint srclen = page_size - unencrypted_bytes; + const byte* src = src_frame + FIL_PAGE_DATA; + byte* dst = dst_frame + FIL_PAGE_DATA; uint32 dstlen; - int rc = my_aes_encrypt_dynamic(src, (page_size - unencrypted_bytes), - dst, &dstlen, - key, sizeof(key), - counter, sizeof(counter), - 0); - if (! ((rc == AES_OK) && - ((ulint) dstlen == (page_size - unencrypted_bytes)))) - { + + if (page_compressed) { + srclen = page_size; + } + + + int rc = (* my_aes_encrypt_dynamic)(src, srclen, + dst, &dstlen, + (unsigned char*)key, key_length, + (unsigned char*)iv, sizeof(iv), + 1); + + if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) { ib_logf(IB_LOG_LEVEL_FATAL, "Unable to encrypt data-block " " src: %p srclen: %ld buf: %p buflen: %d." @@ -613,42 +734,57 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, ut_error; } - // copy page trailer - memcpy(dst_frame + page_size - FIL_PAGE_DATA_END, - src_frame + page_size - FIL_PAGE_DATA_END, - FIL_PAGE_DATA_END); + if (!page_compressed) { + // copy page trailer + 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); + /* 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 */ + 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 { - checksum = page_zip_calc_checksum(dst_frame, zip_size, - algorithm); + /* Page compressed and encrypted tables have different + FIL_HEADER */ + ulint page_len = log10((double)srclen)/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 the post-encryption checksum after the key-version - mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, - checksum); } /********************************************************************* @@ -676,21 +812,38 @@ bool fil_space_decrypt(fil_space_crypt_t* crypt_data, const byte* src_frame, ulint page_size, byte* dst_frame) { + ulint space_id = mach_read_from_4(src_frame + FIL_PAGE_SPACE_ID); + ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); // key version - uint key_version = mach_read_from_4( - src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_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; + fprintf(stderr, "JAN: page type %lu\n", page_type); + + if (page_type == FIL_PAGE_PAGE_ENCRYPTED) { + key_version = mach_read_from_2( + src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); + fprintf(stderr, "JAN: key_version %lu\n", key_version); + orig_page_type = mach_read_from_2( + src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 2); + fprintf(stderr, "JAN: decrypt: orig_page_type %lu\n", orig_page_type); + } else { + key_version = mach_read_from_4( + src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); + } - if (key_version == 0) { + if (key_version == 0 && !page_encrypted) { + fprintf(stderr, "JAN: unencrypted\n"); + //TODO: is this really needed ? memcpy(dst_frame, src_frame, page_size); return false; /* page not decrypted */ } -#ifndef HAVE_EncryptAes128Ctr - ib_logf(IB_LOG_LEVEL_FATAL, - "Unable to decrypt data-block as server not compiled with CTR encyption"); - ut_error; - return false; -#else // read space & offset & lsn ulint space = mach_read_from_4( src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); @@ -698,32 +851,81 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, src_frame + FIL_PAGE_OFFSET); ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); - ut_a(crypt_data != NULL); - - // get key (L) - byte key[CRYPT_SCHEME_1_IV_LEN]; - fil_crypt_get_key(key, sizeof(key), crypt_data, key_version); + fprintf(stderr, "JAN: space %lu, offset %lu lsn %lu\n", space, offset, lsn); // copy page header memcpy(dst_frame, src_frame, FIL_PAGE_DATA); - // create counter block - unsigned char counter[MY_AES_BLOCK_SIZE]; - mach_write_to_4(counter + 0, space); - mach_write_to_4(counter + 4, offset); - mach_write_to_8(counter + 8, lsn); + if (page_type == FIL_PAGE_PAGE_ENCRYPTED) { + // orig page type + mach_write_to_2(dst_frame+FIL_PAGE_TYPE, orig_page_type); + } + + + // 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]; + + 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 + { + // take the iv from the key provider + + int load_iv_rc = GetCryptoIV(key_version, (uchar *) iv, sizeof(iv)); + + // if the iv can not be loaded the whole page can not be decrypted + if (load_iv_rc != CRYPT_KEY_OK) + { + ib_logf(IB_LOG_LEVEL_FATAL, + "Unable to decrypt data-block. " + " Can not load iv for key %d" + " return-code: %d. Can't continue!\n", + key_version, load_iv_rc); + + return AES_KEY_CREATION_FAILED; + } + } // decrypt page data ulint unencrypted_bytes = FIL_PAGE_DATA + FIL_PAGE_DATA_END; const byte* src = src_frame + FIL_PAGE_DATA; byte* dst = dst_frame + FIL_PAGE_DATA; - int dstlen; - int rc = my_aes_decrypt_ctr(src, (page_size - unencrypted_bytes), - dst, &dstlen, key, sizeof(key), - counter, sizeof(counter), 0); - if (! ((rc == AES_OK) && - ((ulint) dstlen == (page_size - unencrypted_bytes)))) { + uint32 dstlen; + ulint srclen = page_size - (FIL_PAGE_DATA + FIL_PAGE_DATA_END); + + ulint compressed_len; + ulint compression_method; + 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)); + } + int rc = (* my_aes_decrypt_dynamic)(src, srclen, + dst, &dstlen, + (unsigned char*)key, key_length, + (unsigned char*)iv, sizeof(iv), + 1); + + if (! ((rc == AES_OK) && ((ulint) dstlen == srclen))) { ib_logf(IB_LOG_LEVEL_FATAL, "Unable to decrypt data-block " " src: %p srclen: %ld buf: %p buflen: %d." @@ -733,16 +935,26 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, ut_error; } - // copy page trailer - memcpy(dst_frame + page_size - FIL_PAGE_DATA_END, - src_frame + page_size - FIL_PAGE_DATA_END, - FIL_PAGE_DATA_END); + if (page_type != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { + fprintf(stderr, "JAN: trailer...\n"); + // copy page 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); + // 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); + } return true; /* page was decrypted */ -#endif } /****************************************************************** diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index e45a4b5bbf8..0799e9921bf 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -26,7 +26,6 @@ Created 10/25/1995 Heikki Tuuri #include "fil0fil.h" -#include "KeySingleton.h" #include <debug_sync.h> #include <my_dbug.h> @@ -1361,8 +1360,7 @@ fil_space_create( ut_a(fil_system); if (fsp_flags_is_page_encrypted(flags)) { - if (!KeySingleton::getInstance().isAvailable() - || KeySingleton::getInstance().getKeys(fsp_flags_get_page_encryption_key(flags))==NULL) { + if (!HasCryptoKey(fsp_flags_get_page_encryption_key(flags))) { /* by returning here it should be avoided that * the server crashes, if someone tries to access an * encrypted table and the encryption key is not available. diff --git a/storage/xtradb/fil/fil0pageencryption.cc b/storage/xtradb/fil/fil0pageencryption.cc index 114064984e3..49c42615e19 100644 --- a/storage/xtradb/fil/fil0pageencryption.cc +++ b/storage/xtradb/fil/fil0pageencryption.cc @@ -33,7 +33,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "buf0checksum.h" #include <my_global.h> #include <my_aes.h> -#include <KeySingleton.h> #include <math.h> /* @@ -217,35 +216,28 @@ fil_encrypt_page( data_size = ((len - FIL_PAGE_DATA - FIL_PAGE_DATA_END) / MY_AES_BLOCK_SIZE) * MY_AES_BLOCK_SIZE; - const unsigned char rkey[] = {0xbd, 0xe4, 0x72, 0xa2, 0x95, 0x67, 0x5c, 0xa9, - 0x2e, 0x04, 0x67, 0xea, 0xdb, 0xc0, 0xe0, 0x23, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8 key_len = 16; + unsigned char rkey[GetCryptoKeySize(encryption_key)]; + uint key_len = sizeof(rkey); - const unsigned char iv[] = {0x2d, 0x1a, 0xf8, 0xd3, 0x97, 0x4e, 0x0b, 0xd3, 0xef, 0xed, - 0x5a, 0x6f, 0x82, 0x59, 0x4f,0x5e}; + unsigned char iv[16]; + uint iv_len = sizeof(iv); - ulint iv_len = 16; - - KeySingleton& keys = KeySingleton::getInstance(); - - if (!keys.isAvailable()) { - err = AES_KEY_CREATION_FAILED; - } else if (keys.getKeys(encryption_key) == NULL) { + if (!HasCryptoKey(encryption_key)) { err = PAGE_ENCRYPTION_KEY_MISSING; } else { - char* keyString = keys.getKeys(encryption_key)->key; - char* ivString = keys.getKeys(encryption_key)->iv; + int rc; + + rc = GetCryptoKey(encryption_key, rkey, key_len); + if (rc != AES_OK) + { + err = PAGE_ENCRYPTION_KEY_MISSING; + } - if (keyString == NULL || ivString == NULL) { - *errorCode = PAGE_ENCRYPTION_WILL_NOT_ENCRYPT; - *out_len = len; - return (buf); + rc = GetCryptoIV(encryption_key, iv, iv_len); + if (rc != AES_OK) + { + err = PAGE_ENCRYPTION_KEY_MISSING; } - key_len = strlen(keyString)/2; - my_aes_hex2uint(keyString, (unsigned char*)&rkey, key_len); - my_aes_hex2uint(ivString, (unsigned char*)&iv, 16); } /* 1st encryption: data_size bytes starting from FIL_PAGE_DATA */ @@ -255,9 +247,9 @@ fil_encrypt_page( data_size, (uchar *) out_buf + FIL_PAGE_DATA, &write_size, - (const unsigned char *) &rkey, + (const unsigned char *) rkey, key_len, - (const unsigned char *) &iv, + (const unsigned char *) iv, iv_len, 1); @@ -285,9 +277,9 @@ fil_encrypt_page( 64, (uchar*)tmp_buf, &write_size, - (const unsigned char *)&rkey, + (const unsigned char *)rkey, key_len, - (const unsigned char *)&iv, + (const unsigned char *)iv, iv_len, 1); ut_ad(write_size == 64); @@ -449,34 +441,32 @@ fil_decrypt_page( data_size = ((len - FIL_PAGE_DATA - FIL_PAGE_DATA_END) / MY_AES_BLOCK_SIZE) * MY_AES_BLOCK_SIZE; - const unsigned char rkey[] = {0xbd, 0xe4, 0x72, 0xa2, 0x95, 0x67, 0x5c, 0xa9, - 0x2e, 0x04, 0x67, 0xea, 0xdb, 0xc0,0xe0, 0x23, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8 key_len = 16; - const unsigned char iv[] = {0x2d, 0x1a, 0xf8, 0xd3, 0x97, 0x4e, 0x0b, 0xd3, 0xef, 0xed, - 0x5a, 0x6f, 0x82, 0x59, 0x4f,0x5e}; - uint8 iv_len = 16; + unsigned char rkey[GetCryptoKeySize(page_decryption_key)]; + uint key_len = sizeof(rkey); - KeySingleton& keys = KeySingleton::getInstance(); + unsigned char iv[16]; + uint iv_len = sizeof(iv); - if (!keys.isAvailable()) { - err = PAGE_ENCRYPTION_ERROR; - } else if (keys.getKeys(page_decryption_key) == NULL) { + if (!HasCryptoKey(page_decryption_key)) { err = PAGE_ENCRYPTION_KEY_MISSING; } else { - char* keyString = keys.getKeys(page_decryption_key)->key; - char* ivString = keys.getKeys(page_decryption_key)->iv; - key_len = strlen(keyString)/2; - if (keyString == NULL || ivString == NULL) { - return err; + int rc; + + rc = GetCryptoKey(page_decryption_key, rkey, key_len); + if (rc != AES_OK) + { + err = PAGE_ENCRYPTION_KEY_MISSING; } - my_aes_hex2uint(keyString, (unsigned char*)&rkey, key_len); - my_aes_hex2uint(ivString, (unsigned char*)&iv, 16); + rc = GetCryptoIV(page_decryption_key, iv, iv_len); + if (rc != AES_OK) + { + err = PAGE_ENCRYPTION_KEY_MISSING; + } } + if (err != AES_OK) { /* surely key could not be determined. */ fprintf(stderr, "InnoDB: Corruption: Page is marked as encrypted\n" @@ -514,9 +504,9 @@ fil_decrypt_page( 64, (uchar *) in_buf + len - offset - 64, &tmp_write_size, - (const unsigned char *) &rkey, + (const unsigned char *) rkey, key_len, - (const unsigned char *) &iv, + (const unsigned char *) iv, iv_len, 1); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index c319f1a1d84..21d7cee0fba 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -107,8 +107,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "page0zip.h" #include "fil0pagecompress.h" -#include "KeySingleton.h" - #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -213,12 +211,6 @@ static char* innobase_disable_monitor_counter = NULL; static char* innobase_reset_monitor_counter = NULL; static char* innobase_reset_all_monitor_counter = NULL; -/* Encryption for tables and columns */ -static char* innobase_data_encryption_providername = NULL; -static char* innobase_data_encryption_providerurl = NULL; -static uint innobase_data_encryption_providertype = 0; // 1 == file, 2 == server -static char* innobase_data_encryption_filekey = NULL; - /* The highest file format being used in the database. The value can be set by user, however, it will be adjusted to the newer file format if a table of such format is created/opened. */ @@ -3505,10 +3497,6 @@ innobase_init( ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); - KeySingleton::getInstance( - innobase_data_encryption_providername, innobase_data_encryption_providerurl, - innobase_data_encryption_providertype, innobase_data_encryption_filekey); - #ifndef DBUG_OFF static const char test_filename[] = "-@"; char test_tablename[sizeof test_filename @@ -4173,8 +4161,6 @@ innobase_end( mysql_mutex_destroy(&pending_checkpoint_mutex); } - KeySingleton::getInstance().~KeySingleton(); - DBUG_RETURN(err); } @@ -11883,15 +11869,6 @@ ha_innobase::check_table_options( " innodb_file_per_table."); return "PAGE_ENCRYPTION"; } - - if (!KeySingleton::getInstance().isAvailable()) { - push_warning( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: PAGE_ENCRYPTION needs a key provider" - ); - return "PAGE_ENCRYPTION"; - } } /* Check page compression requirements */ @@ -11981,7 +11958,7 @@ ha_innobase::check_table_options( return "PAGE_ENCRYPTION_KEY"; } - if (KeySingleton::getInstance().getKeys(options->page_encryption_key)==NULL) { + if (!HasCryptoKey(options->page_encryption_key)) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, @@ -20333,26 +20310,6 @@ static MYSQL_SYSVAR_ULONG(fatal_semaphore_wait_threshold, srv_fatal_semaphore_wa UINT_MAX32, /* Maximum setting */ 0); -static MYSQL_SYSVAR_UINT(data_encryption_providertype, innobase_data_encryption_providertype, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Use table or column encryption / decryption. Default is 0 for no use, 1 for keyfile and 2 for keyserver.", - NULL, NULL, 1, 0, 2, 0); - -static MYSQL_SYSVAR_STR(data_encryption_providername, innobase_data_encryption_providername, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Name of keyfile or keyserver.", - NULL, NULL, NULL); - -static MYSQL_SYSVAR_STR(data_encryption_providerurl, innobase_data_encryption_providerurl, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Path or URL for keyfile or keyserver.", - NULL, NULL, NULL); - -static MYSQL_SYSVAR_STR(data_encryption_filekey, innobase_data_encryption_filekey, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Key to encrypt / decrypt the keyfile.", - NULL, NULL, NULL); - static MYSQL_SYSVAR_BOOL(encrypt_tables, srv_encrypt_tables, 0, "Encrypt tables", 0, 0, 0); @@ -20669,11 +20626,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(compression_algorithm), MYSQL_SYSVAR(mtflush_threads), MYSQL_SYSVAR(use_mtflush), - /* Table encryption feature */ - MYSQL_SYSVAR(data_encryption_providertype), - MYSQL_SYSVAR(data_encryption_providername), - MYSQL_SYSVAR(data_encryption_providerurl), - MYSQL_SYSVAR(data_encryption_filekey), /* Encryption feature */ MYSQL_SYSVAR(encrypt_tables), MYSQL_SYSVAR(encryption_threads), diff --git a/storage/xtradb/include/EncKeys.h b/storage/xtradb/include/EncKeys.h deleted file mode 100644 index 43f2920fd7f..00000000000 --- a/storage/xtradb/include/EncKeys.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** -@file EncKeys.h -A structure and class to keep keys for encryption/decryption. - -Created 09/15/2014 -***********************************************************************/ - -#ifndef ENCKEYS_H_ -#define ENCKEYS_H_ - -#include "univ.i" -#include <sys/types.h> -#include <stdio.h> - - - - -struct keyentry { - ulint id; - char *iv; - char *key; -}; - - -class EncKeys -{ -private: - static const char *strMAGIC, *newLine; - static const int magicSize; - - enum constants { MAX_OFFSETS_IN_PCRE_PATTERNS = 30}; - enum keyAttributes { KEY_MIN = 1, KEY_MAX = 255, MAX_KEYS = 255, - MAX_IVLEN = 256, MAX_KEYLEN = 512, ivSize16 = 16, keySize32 = 32 }; - enum keyInitType { KEYINITTYPE_FILE = 1, KEYINITTYPE_SERVER = 2 }; - enum errorAttributes { MAX_KEY_LINE_SIZE = 3 * MAX_KEYLEN, MAX_KEY_FILE_SIZE = 1048576 }; - enum errorCodesLine { NO_ERROR_PARSE_OK = 0, NO_ERROR_ISCOMMENT = 10, NO_ERROR_KEY_GREATER_THAN_ASKED = 20, - ERROR_NOINITIALIZEDKEY = 30, ERROR_ID_TOO_BIG = 40, ERROR_WRONG_NUMBER_OF_MATCHES = 50, - ERROR_EQUAL_DOUBLE_KEY = 60, ERROR_UNEQUAL_DOUBLE_KEY = 70 }; - - static const char *errorNoKeyId, *errorInMatches, *errorExceedKeyFileSize, - *errorExceedKeySize, *errorEqualDoubleKey, *errorUnequalDoubleKey, - *errorNoInitializedKey, *errorFalseFileKey, - *errorNotImplemented, *errorOpenFile, *errorReadingFile, *errorFileSize; - - static const char* initialPwd; - ulint countKeys, keyLineInKeyFile; - keyentry keys[MAX_KEYS], *oneKey; - - void printKeyEntry( ulint id); - int initKeysThroughFile( const char *name, const char *path, const char *filekey); - int initKeysThroughServer( const char *name, const char *path, const char *filekey); - bool isComment( const char *line); - char * decryptFile( const char* filename, const char *secret, int *errorCode); - int parseFile( const char* filename, const ulint maxKeyId, const char *secret); - int parseLine( const char *line, const ulint maxKeyId); - -public: - static const size_t MAX_SECRET_SIZE = 256; - - enum errorCodesFile { NO_ERROR_KEY_FILE_PARSE_OK = 0, ERROR_KEY_FILE_PARSE_NULL = 110, - ERROR_KEY_FILE_TOO_BIG = 120, ERROR_KEY_FILE_EXCEEDS_MAX_NUMBERS_OF_KEYS = 130, - ERROR_OPEN_FILE = 140, ERROR_READING_FILE = 150, ERROR_FALSE_FILE_KEY = 160, - ERROR_KEYINITTYPE_SERVER_NOT_IMPLEMENTED = 170, ERROR_ENCRYPTION_SECRET_NULL = 180 }; - EncKeys(); - virtual ~EncKeys(); - bool initKeys( const char *name, const char *url, const int initType, const char *filekey); - keyentry *getKeys( int id); - /* made public for unit testing */ - static void parseSecret( const char *filename, char *secret ); - -}; - -#endif /* ENCKEYS_H_ */ diff --git a/storage/xtradb/include/KeySingleton.h b/storage/xtradb/include/KeySingleton.h deleted file mode 100644 index 2b2f3991998..00000000000 --- a/storage/xtradb/include/KeySingleton.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2014 eperi GmbH. All Rights Reserved. - - 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 */ - -/******************************************************************//** -@file KeySingletonPattern.h -Implementation of single pattern to keep keys for encrypting/decrypting pages. - -Created 09/13/2014 -***********************************************************************/ - - -#ifndef KEYSINGLETON_H_ -#define KEYSINGLETON_H_ - -#include "EncKeys.h" - - -class KeySingleton -{ -private: - static bool instanceInited; - static KeySingleton theInstance; - static EncKeys encKeys; - - // No new instance or object possible - KeySingleton() {} - - // No new instance possible through copy constructor - KeySingleton( const KeySingleton&) {} - - // No new instance possible through copy - KeySingleton & operator = (const KeySingleton&); - -public: - virtual ~KeySingleton() {encKeys.~EncKeys();} - static KeySingleton& getInstance(); - // Init the instance for only one time - static KeySingleton& getInstance(const char *name, const char *url, - const int initType, const char *filekey); - keyentry *getKeys(int id); - ibool hasKey(int id); - static bool isAvailable() { - return instanceInited; - } -}; - -#endif /* KEYSINGLETON_H_ */ diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index e0004311404..6d9c2d0404e 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -168,6 +168,8 @@ static const ulint FIL_PAGE_COMPRESS_SIZE_V1 = FIL_PAGE_ORIGINAL_SIZE_V1 + 2; /* @} */ /** File page types (values of FIL_PAGE_TYPE) @{ */ +#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 */ @@ -1236,7 +1238,9 @@ fil_space_encrypt( lsn_t lsn, /*!< in: page lsn */ const byte* src_frame,/*!< in: page frame */ ulint size, /*!< in: size of data to encrypt */ - byte* dst_frame); /*!< in: where to encrypt to */ + byte* dst_frame, /*!< in: where to encrypt to */ + ulint page_encryption_key); /*!< in: page encryption key id if page + encrypted */ /********************************************************************* Decrypt buffer page */ diff --git a/storage/xtradb/include/fsp0pageencryption.ic b/storage/xtradb/include/fsp0pageencryption.ic index c78ed40bcc6..7ff002b203e 100644 --- a/storage/xtradb/include/fsp0pageencryption.ic +++ b/storage/xtradb/include/fsp0pageencryption.ic @@ -24,7 +24,6 @@ Created 08/28/2014 ***********************************************************************/ #include "fsp0fsp.h" -#include "KeySingleton.h" #include "fil0pageencryption.h" @@ -116,6 +115,17 @@ fil_page_is_encrypted( 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 +@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); +} /*******************************************************************//** Find out whether the page can be decrypted. @@ -139,22 +149,16 @@ fil_page_encryption_status( if (page_type == FIL_PAGE_TYPE_FSP_HDR) { ulint flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf); if (fsp_flags_is_page_encrypted(flags)) { - if (!KeySingleton::getInstance().isAvailable() || - !KeySingleton::getInstance().hasKey(fsp_flags_get_page_encryption_key(flags))) { + if (!HasCryptoKey(fsp_flags_get_page_encryption_key(flags))) { /* accessing table would surely fail, because no key or no key provider available */ - if (KeySingleton::getInstance().isAvailable() && - !KeySingleton::getInstance().hasKey(fsp_flags_get_page_encryption_key(flags))) { - return PAGE_ENCRYPTION_KEY_MISSING; - } - return PAGE_ENCRYPTION_ERROR; + return PAGE_ENCRYPTION_KEY_MISSING; } } } if(page_type == FIL_PAGE_PAGE_ENCRYPTED) { ulint key = mach_read_from_1(buf + FIL_PAGE_SPACE_OR_CHKSUM); - if (KeySingleton::getInstance().isAvailable() && - !KeySingleton::getInstance().hasKey(key)) { - return PAGE_ENCRYPTION_KEY_MISSING; + if (!HasCryptoKey(key)) { + return PAGE_ENCRYPTION_KEY_MISSING; } return PAGE_ENCRYPTION_ERROR; } diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index e2a409011b2..9cb1bd8d7f9 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -3152,6 +3152,7 @@ try_again: if (ret && len == n) { /* If page is encrypted we need to decrypt it first */ + /* if (fil_page_is_encrypted((byte *)buf)) { if (fil_decrypt_page( NULL, @@ -3163,6 +3164,22 @@ try_again: return FALSE; } } + */ + + if (fil_page_is_compressed_encrypted((byte *)buf) || + fil_page_is_encrypted((byte *)buf)) { + + byte * dst_frm = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE)); + // Decrypt the data + fil_space_decrypt( + (fil_space_crypt_t* ) NULL, + (byte *)buf, + n, + dst_frm); + // Copy decrypted buffer back to buf + memcpy(buf, dst_frm, n); + ut_free(dst_frm); + } /* Note that InnoDB writes files that are not formated as file spaces and they do not have FIL_PAGE_TYPE @@ -3185,6 +3202,7 @@ try_again: if ((ulint) ret == n) { /* If page is encrypted we need to decrypt it first */ + /* if (fil_page_is_encrypted((byte *)buf)) { if (fil_decrypt_page( NULL, @@ -3196,6 +3214,21 @@ try_again: return FALSE; } } + */ + if (fil_page_is_compressed_encrypted((byte *)buf) || + fil_page_is_encrypted((byte *)buf)) { + + byte * dst_frm = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE)); + // Decrypt the data + fil_space_decrypt( + (fil_space_crypt_t*) NULL, + (byte *)buf, + n, + dst_frm); + // Copy decrypted buffer back to buf + memcpy(buf, dst_frm, n); + ut_free(dst_frm); + } /* Note that InnoDB writes files that are not formated as file spaces and they do not have FIL_PAGE_TYPE @@ -3296,6 +3329,7 @@ try_again: if (ret && len == n) { /* If page is encrypted we need to decrypt it first */ + /* if (fil_page_is_encrypted((byte *)buf)) { if (fil_decrypt_page( NULL, @@ -3307,6 +3341,20 @@ try_again: return (FALSE); } } + */ + if (fil_page_is_compressed_encrypted((byte *)buf) || + fil_page_is_encrypted((byte *)buf)) { + byte * dst_frm = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE)); + // Decrypt the data + fil_space_decrypt( + (fil_space_crypt_t* ) NULL, + (byte *)buf, + n, + dst_frm); + // Copy decrypted buffer back to buf + memcpy(buf, dst_frm, n); + ut_free(dst_frm); + } /* Note that InnoDB writes files that are not formated as file spaces and they do not have FIL_PAGE_TYPE @@ -3330,6 +3378,7 @@ try_again: if ((ulint) ret == n) { /* If the page is encrypted we need to decrypt it first */ + /* if (fil_page_is_encrypted((byte *)buf)) { if (fil_decrypt_page( NULL, @@ -3341,6 +3390,23 @@ try_again: return (FALSE); } } + */ + + if (fil_page_is_compressed_encrypted((byte *)buf) || + fil_page_is_encrypted((byte *)buf)) { + + byte * dst_frm = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE)); + // Decrypt the data + fil_space_decrypt( + (fil_space_crypt_t* ) NULL, + (byte *)buf, + n, + dst_frm); + // Copy decrypted buffer back to buf + memcpy(buf, dst_frm, n); + ut_free(dst_frm); + } + /* Note that InnoDB writes files that are not formated as file spaces and they do not have FIL_PAGE_TYPE @@ -4901,6 +4967,10 @@ found: os_mutex_enter(array->mutex); } +// if (srv_encrypt_tables) { +// page_encryption = TRUE; +// } + /* If the space is page encryption and this is write operation then we encrypt the page */ if (message1 && type == OS_FILE_WRITE && page_encryption ) { @@ -4915,28 +4985,18 @@ found: // if it is not yet allocated. os_slot_alloc_page_buf2(slot); os_slot_alloc_tmp_encryption_buf(slot); - - tmp = fil_encrypt_page( + /* ctr not yet supported in xtradb, lsn is null*/ + fil_space_encrypt( fil_node_get_space_id(slot->message1), + slot->offset, + NULL, (byte *)buf, + slot->len, slot->page_buf2, - len, - page_encryption_key, - &real_len, - &ec, - slot->tmp_encryption_buf); + slot->page_encryption_key); - /* If encryption succeeded, set up the length and buffer */ - if (tmp != buf) { - len = real_len; - buf = slot->page_buf2; - slot->len = real_len; - slot->page_encryption_success = TRUE; - } else { - /* Use original not encrypted page */ - slot->page_encryption_success = FALSE; - buf = slot->buf; - } + slot->page_encryption_success = TRUE; + buf = slot->page_buf2; /* Take array mutex back */ os_mutex_enter(array->mutex); @@ -5575,16 +5635,20 @@ os_aio_windows_handle( } if (slot->type == OS_FILE_READ) { - if (fil_page_is_encrypted(slot->buf)) { + if (fil_page_is_compressed_encrypted(slot->buf) || + fil_page_is_encrypted(slot->buf)) { + ut_ad(slot->message1 != NULL); os_slot_alloc_page_buf2(slot); os_slot_alloc_tmp_encryption_buf(slot); - fil_decrypt_page( - slot->page_buf2, + + // Decrypt the data + fil_space_decrypt( + fil_node_get_space_id(slot->message1), slot->buf, slot->len, - slot->write_size, - NULL, - slot->tmp_encryption_buf); + slot->page_buf2); + // Copy decrypted buffer back to buf + memcpy(slot->buf, slot->page_buf2, slot->len); } if (fil_page_is_compressed(slot->buf)) { @@ -5702,16 +5766,21 @@ retry: ut_a(slot->pos < end_pos); if (slot->type == OS_FILE_READ) { - if (fil_page_is_encrypted(slot->buf)) { + /* If the page is page encrypted we decrypt */ + if (fil_page_is_compressed_encrypted(slot->buf) || + fil_page_is_encrypted(slot->buf)) { os_slot_alloc_page_buf2(slot); os_slot_alloc_tmp_encryption_buf(slot); - fil_decrypt_page( - slot->page_buf2, + ut_ad(slot->message1 != NULL); + + // Decrypt the data + fil_space_decrypt( + fil_node_get_space_id(slot->message1), slot->buf, slot->len, - slot->write_size, - NULL, - slot->tmp_encryption_buf); + slot->page_buf2); + // Copy decrypted buffer back to buf + memcpy(slot->buf, slot->page_buf2, slot->len); } /* If the page is page compressed and this is read, |