Commit 3578419b authored by Jan Lindström's avatar Jan Lindström

MDEV-7797: file_key_management_plugin uses static IV for a key

Currently crypt data is written to file space always. Use
that to obtain random IV for every object (file).

Beatify code to confort InnoDB coding styles.

Conflicts:
	storage/innobase/fil/fil0crypt.cc
	storage/xtradb/fil/fil0crypt.cc
parent 0c26c003
...@@ -208,12 +208,10 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -208,12 +208,10 @@ fil_crypt_get_key(byte *dst, uint* key_length,
fil_space_crypt_t* crypt_data, uint version, bool page_encrypted) fil_space_crypt_t* crypt_data, uint version, bool page_encrypted)
{ {
unsigned char keybuf[MY_AES_MAX_KEY_LENGTH]; unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
unsigned char iv[CRYPT_SCHEME_1_IV_LEN];
ulint iv_len = sizeof(iv);
if (!page_encrypted) { mutex_enter(&crypt_data->mutex);
mutex_enter(&crypt_data->mutex);
if (!page_encrypted) {
// Check if we already have key // Check if we already have key
for (uint i = 0; i < crypt_data->key_count; i++) { for (uint i = 0; i < crypt_data->key_count; i++) {
if (crypt_data->keys[i].key_version == version) { if (crypt_data->keys[i].key_version == version) {
...@@ -231,29 +229,18 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -231,29 +229,18 @@ fil_crypt_get_key(byte *dst, uint* key_length,
crypt_data->keys[i] = crypt_data->keys[i - 1]; crypt_data->keys[i] = crypt_data->keys[i - 1];
} }
} }
else
{
// load iv
int rc = get_encryption_iv(version, (unsigned char*)iv, iv_len);
if (rc != CRYPT_KEY_OK) {
ib_logf(IB_LOG_LEVEL_FATAL,
"IV %d can not be found. Reason=%d", version, rc);
ut_error;
}
}
if (has_encryption_key(version)) { if (has_encryption_key(version)) {
*key_length = get_encryption_key_size(version); int rc;
*key_length = get_encryption_key_size(version);
int rc = get_encryption_key(version, (unsigned char*)keybuf, *key_length); rc = get_encryption_key(version, (unsigned char*)keybuf, *key_length);
if (rc != CRYPT_KEY_OK) { if (rc != CRYPT_KEY_OK) {
ib_logf(IB_LOG_LEVEL_FATAL, ib_logf(IB_LOG_LEVEL_FATAL,
"Key %d can not be found. Reason=%d", version, rc); "Key %d can not be found. Reason=%d", version, rc);
ut_error; ut_error;
} }
} else { } else {
ib_logf(IB_LOG_LEVEL_FATAL, ib_logf(IB_LOG_LEVEL_FATAL,
"Key %d not found", version); "Key %d not found", version);
...@@ -264,51 +251,48 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -264,51 +251,48 @@ fil_crypt_get_key(byte *dst, uint* key_length,
// do ctr key initialization // do ctr key initialization
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR)
{ {
// Now compute L by encrypting IV using this key /* Now compute L by encrypting IV using this key. Note
const unsigned char* src = page_encrypted ? iv : crypt_data->iv; that we use random IV from crypt data. */
const int srclen = page_encrypted ? iv_len : crypt_data->iv_length; const unsigned char* src = crypt_data->iv;
unsigned char* buf = page_encrypted ? keybuf : crypt_data->keys[0].key; const int srclen = crypt_data->iv_length;
uint32 buflen = page_encrypted ? *key_length : sizeof(crypt_data->keys[0].key); 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); // call ecb explicit
int rc = (*func)(src, srclen, my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
buf, &buflen, int rc = (*func)(src, srclen,
(unsigned char*)keybuf, *key_length, buf, &buflen,
NULL, 0, (unsigned char*)keybuf, *key_length,
1); NULL, 0,
1);
if (rc != AES_OK) {
ib_logf(IB_LOG_LEVEL_FATAL, if (rc != AES_OK) {
"Unable to encrypt key-block " ib_logf(IB_LOG_LEVEL_FATAL,
" src: %p srclen: %d buf: %p buflen: %d." "Unable to encrypt key-block "
" return-code: %d. Can't continue!\n", " src: %p srclen: %d buf: %p buflen: %d."
src, srclen, buf, buflen, rc); " return-code: %d. Can't continue!\n",
ut_error; 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);
}
if (!page_encrypted) { if (!page_encrypted) {
mutex_exit(&crypt_data->mutex); 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);
} }
mutex_exit(&crypt_data->mutex);
} }
/****************************************************************** /******************************************************************
...@@ -323,14 +307,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length, ...@@ -323,14 +307,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length,
int rc = get_latest_encryption_key_version(); int rc = get_latest_encryption_key_version();
// if no new key was created use the last one // if no new key was created use the last one
if (rc >= 0) if (rc >= 0) {
{ *version = rc;
*version = rc;
} }
return fil_crypt_get_key(dst, key_length, crypt_data, *version, false);
} }
return fil_crypt_get_key(dst, key_length, NULL, *version, true);
return fil_crypt_get_key(dst, key_length, crypt_data, *version, srv_encrypt_tables == FALSE);
} }
/****************************************************************** /******************************************************************
...@@ -354,7 +336,7 @@ fil_space_create_crypt_data() ...@@ -354,7 +336,7 @@ fil_space_create_crypt_data()
} }
mutex_create(fil_crypt_data_mutex_key, mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK); &crypt_data->mutex, SYNC_NO_ORDER_CHECK);
crypt_data->iv_length = iv_length; crypt_data->iv_length = iv_length;
my_random_bytes(crypt_data->iv, iv_length); my_random_bytes(crypt_data->iv, iv_length);
return crypt_data; return crypt_data;
...@@ -428,6 +410,7 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset) ...@@ -428,6 +410,7 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset)
} }
ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1); ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1);
if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) { if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Found non sensible iv length: %lu for space %lu " "Found non sensible iv length: %lu for space %lu "
...@@ -572,8 +555,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr, ...@@ -572,8 +555,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
1 + // size of type 1 + // size of type
1 + // size of iv-len 1 + // size of iv-len
4; // size of min_key_version 4; // size of min_key_version
if (end_ptr - ptr < entry_size)
if (end_ptr - ptr < entry_size){
return NULL; return NULL;
}
ulint space_id = mach_read_from_4(ptr); ulint space_id = mach_read_from_4(ptr);
ptr += 4; ptr += 4;
...@@ -590,8 +575,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr, ...@@ -590,8 +575,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
uint min_key_version = mach_read_from_4(ptr); uint min_key_version = mach_read_from_4(ptr);
ptr += 4; ptr += 4;
if (end_ptr - ptr < len) if (end_ptr - ptr < len) {
return NULL; return NULL;
}
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(); fil_space_crypt_t* crypt_data = fil_space_create_crypt_data();
crypt_data->page0_offset = offset; crypt_data->page0_offset = offset;
...@@ -634,11 +620,14 @@ fil_space_check_encryption_write( ...@@ -634,11 +620,14 @@ fil_space_check_encryption_write(
return false; return false;
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL)
if (crypt_data == NULL) {
return false; return false;
}
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
return false; return false;
}
return true; return true;
} }
...@@ -650,15 +639,16 @@ void ...@@ -650,15 +639,16 @@ void
fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key) const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key)
{ {
fil_space_crypt_t* crypt_data; fil_space_crypt_t* crypt_data=NULL;
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE; ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
// get key (L) // get key (L)
uint key_version; uint key_version = encryption_key;
byte key[MY_AES_MAX_KEY_LENGTH]; byte key[MY_AES_MAX_KEY_LENGTH];
uint key_length; uint key_length=MY_AES_MAX_KEY_LENGTH;
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR
|| orig_page_type==FIL_PAGE_TYPE_XDES || orig_page_type==FIL_PAGE_TYPE_XDES
|| orig_page_type== FIL_PAGE_PAGE_ENCRYPTED || orig_page_type== FIL_PAGE_PAGE_ENCRYPTED
...@@ -668,49 +658,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, ...@@ -668,49 +658,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
return; return;
} }
if (srv_encrypt_tables) { /* Get crypt data from file space */
crypt_data = fil_space_get_crypt_data(space); 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); if (crypt_data == NULL) {
} else { //TODO: Is this really needed ?
key_version = encryption_key; memcpy(dst_frame, src_frame, page_size);
fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version); return;
} }
fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version);
/* Load the iv or counter (depending to the encryption algorithm used) */ /* Load the iv or counter (depending to the encryption algorithm used) */
unsigned char iv[MY_AES_BLOCK_SIZE]; unsigned char iv[MY_AES_BLOCK_SIZE];
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
{ // create counter block (C)
// create counter block (C) mach_write_to_4(iv + 0, space);
mach_write_to_4(iv + 0, space); ulint space_offset = mach_read_from_4(
ulint space_offset = mach_read_from_4( src_frame + FIL_PAGE_OFFSET);
src_frame + FIL_PAGE_OFFSET); mach_write_to_4(iv + 4, space_offset);
mach_write_to_4(iv + 4, space_offset); mach_write_to_8(iv + 8, lsn);
mach_write_to_8(iv + 8, lsn);
} else { } else {
// take the iv from the key provider // Get random IV from crypt_data
mutex_enter(&crypt_data->mutex);
int load_iv_rc = get_encryption_iv(key_version, (uchar *) iv, sizeof(iv)); memcpy(iv, crypt_data->iv, crypt_data->iv_length);
mutex_exit(&crypt_data->mutex);
// 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_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
...@@ -720,7 +693,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, ...@@ -720,7 +693,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
// copy page header // copy page header
memcpy(dst_frame, src_frame, FIL_PAGE_DATA); memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
if (page_encrypted && !page_compressed) { if (page_encrypted && !page_compressed) {
// key id // key id
mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
...@@ -826,11 +798,13 @@ fil_space_check_encryption_read( ...@@ -826,11 +798,13 @@ fil_space_check_encryption_read(
{ {
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) if (crypt_data == NULL) {
return false; return false;
}
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
return false; return false;
}
return true; return true;
} }
...@@ -892,29 +866,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, ...@@ -892,29 +866,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
// get the iv // get the iv
unsigned char iv[MY_AES_BLOCK_SIZE]; unsigned char iv[MY_AES_BLOCK_SIZE];
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
{ // create counter block
// create counter block
mach_write_to_4(iv + 0, space); mach_write_to_4(iv + 0, space);
mach_write_to_4(iv + 4, offset); mach_write_to_4(iv + 4, offset);
mach_write_to_8(iv + 8, lsn); mach_write_to_8(iv + 8, lsn);
} else { } else {
// take the iv from the key provider // Get random IV from crypt_data
mutex_enter(&crypt_data->mutex);
int load_iv_rc = get_encryption_iv(key_version, (uchar *) iv, sizeof(iv)); memcpy(iv, crypt_data->iv, crypt_data->iv_length);
mutex_exit(&crypt_data->mutex);
// 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;
}
} }
const byte* src = src_frame + FIL_PAGE_DATA; const byte* src = src_frame + FIL_PAGE_DATA;
...@@ -1026,6 +988,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size) ...@@ -1026,6 +988,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size)
* srv_checksum_algorithm */ * srv_checksum_algorithm */
srv_checksum_algorithm_t save_checksum_algorithm = srv_checksum_algorithm_t save_checksum_algorithm =
(srv_checksum_algorithm_t)srv_checksum_algorithm; (srv_checksum_algorithm_t)srv_checksum_algorithm;
if (zip_size == 0 && if (zip_size == 0 &&
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB || (save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) { save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
...@@ -1110,8 +1073,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state) ...@@ -1110,8 +1073,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
/* this is rotation encrypted => encrypted, /* this is rotation encrypted => encrypted,
* only reencrypt if key is sufficiently old */ * only reencrypt if key is sufficiently old */
if (key_version + key_state->rotate_key_age < key_state->key_version) if (key_version + key_state->rotate_key_age < key_state->key_version) {
return true; return true;
}
return false; return false;
} }
...@@ -1189,8 +1153,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) { ...@@ -1189,8 +1153,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
do do
{ {
if (fil_crypt_is_closing(space) || if (fil_crypt_is_closing(space) ||
fil_tablespace_is_being_deleted(space)) fil_tablespace_is_being_deleted(space)) {
break; break;
}
mtr_t mtr; mtr_t mtr;
mtr_start(&mtr); mtr_start(&mtr);
...@@ -1252,8 +1217,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) { ...@@ -1252,8 +1217,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
!fil_tablespace_is_being_deleted(space)); !fil_tablespace_is_being_deleted(space));
/* try to reacquire pending op */ /* try to reacquire pending op */
if (fil_inc_pending_ops(space, true)) if (fil_inc_pending_ops(space, true)) {
break; break;
}
/* pending op reacquired! */ /* pending op reacquired! */
pending_op = true; pending_op = true;
...@@ -1338,11 +1304,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state, ...@@ -1338,11 +1304,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
} }
/* prevent threads from starting to rotate space */ /* prevent threads from starting to rotate space */
if (crypt_data->closing) if (crypt_data->closing) {
break; break;
}
if (crypt_data->rotate_state.flushing) if (crypt_data->rotate_state.flushing) {
break; break;
}
bool need_key_rotation = fil_crypt_needs_rotation( bool need_key_rotation = fil_crypt_needs_rotation(
crypt_data->min_key_version, key_state); crypt_data->min_key_version, key_state);
...@@ -1361,9 +1329,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state, ...@@ -1361,9 +1329,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
} while (0); } while (0);
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
if (pending_op) { if (pending_op) {
fil_decr_pending_ops(space); fil_decr_pending_ops(space);
} }
return false; return false;
} }
...@@ -1435,6 +1405,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state) ...@@ -1435,6 +1405,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
uint max_iops = state->estimated_max_iops; uint max_iops = state->estimated_max_iops;
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) { if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) {
/* this can happen when user decreases srv_fil_crypt_iops */ /* this can happen when user decreases srv_fil_crypt_iops */
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
...@@ -1442,8 +1413,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state) ...@@ -1442,8 +1413,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
} }
uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated; uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated;
if (alloc > max_iops)
if (alloc > max_iops) {
alloc = max_iops; alloc = max_iops;
}
n_fil_crypt_iops_allocated += alloc; n_fil_crypt_iops_allocated += alloc;
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
...@@ -1473,8 +1446,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state) ...@@ -1473,8 +1446,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state)
state->estimated_max_iops, state->estimated_max_iops,
1000000 / avg_wait_time_us); 1000000 / avg_wait_time_us);
#endif #endif
if (avg_wait_time_us == 0) if (avg_wait_time_us == 0) {
avg_wait_time_us = 1; // prevent division by zero avg_wait_time_us = 1; // prevent division by zero
}
state->estimated_max_iops = 1000000 / avg_wait_time_us; state->estimated_max_iops = 1000000 / avg_wait_time_us;
state->cnt_waited = 0; state->cnt_waited = 0;
...@@ -1622,7 +1596,9 @@ fil_crypt_start_rotate_space( ...@@ -1622,7 +1596,9 @@ fil_crypt_start_rotate_space(
{ {
ulint space = state->space; ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
if (crypt_data->rotate_state.active_threads == 0) { if (crypt_data->rotate_state.active_threads == 0) {
/* only first thread needs to init */ /* only first thread needs to init */
crypt_data->rotate_state.next_offset = 1; // skip page 0 crypt_data->rotate_state.next_offset = 1; // skip page 0
...@@ -1663,7 +1639,9 @@ fil_crypt_find_page_to_rotate( ...@@ -1663,7 +1639,9 @@ fil_crypt_find_page_to_rotate(
ulint batch = srv_alloc_time * state->allocated_iops; ulint batch = srv_alloc_time * state->allocated_iops;
ulint space = state->space; ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
if (crypt_data->closing == false && if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset < crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) { crypt_data->rotate_state.max_offset) {
...@@ -1757,6 +1735,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state, ...@@ -1757,6 +1735,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state,
ulint add_sleeptime_ms = 0; ulint add_sleeptime_ms = 0;
ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited; ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited;
ulint alloc_wait_us = 1000000 / state->allocated_iops; ulint alloc_wait_us = 1000000 / state->allocated_iops;
if (avg_wait_time_us < alloc_wait_us) { if (avg_wait_time_us < alloc_wait_us) {
/* we reading faster than we allocated */ /* we reading faster than we allocated */
add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000; add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000;
...@@ -1986,6 +1965,7 @@ fil_crypt_rotate_pages( ...@@ -1986,6 +1965,7 @@ fil_crypt_rotate_pages(
{ {
ulint space = state->space; ulint space = state->space;
ulint end = state->offset + state->batch; ulint end = state->offset + state->batch;
for (; state->offset < end; state->offset++) { for (; state->offset < end; state->offset++) {
/* we can't rotate pages in dblwr buffer as /* we can't rotate pages in dblwr buffer as
...@@ -2015,17 +1995,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space) ...@@ -2015,17 +1995,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space)
/* flush tablespace pages so that there are no pages left with old key */ /* flush tablespace pages so that there are no pages left with old key */
lsn_t end_lsn = crypt_data->rotate_state.end_lsn; lsn_t end_lsn = crypt_data->rotate_state.end_lsn;
if (end_lsn > 0 && !fil_crypt_is_closing(space)) { if (end_lsn > 0 && !fil_crypt_is_closing(space)) {
bool success = false; bool success = false;
ulint n_pages = 0; ulint n_pages = 0;
ulint sum_pages = 0; ulint sum_pages = 0;
ullint start = ut_time_us(NULL); ullint start = ut_time_us(NULL);
do { do {
success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages); success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
sum_pages += n_pages; sum_pages += n_pages;
} while (!success && !fil_crypt_is_closing(space)); } while (!success && !fil_crypt_is_closing(space));
ullint end = ut_time_us(NULL); ullint end = ut_time_us(NULL);
if (sum_pages && end > start) { if (sum_pages && end > start) {
state->cnt_waited += sum_pages; state->cnt_waited += sum_pages;
state->sum_waited_us += (end - start); state->sum_waited_us += (end - start);
...@@ -2169,6 +2153,7 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2169,6 +2153,7 @@ DECLARE_THREAD(fil_crypt_thread)(
fil_crypt_get_key_state(&new_state); fil_crypt_get_key_state(&new_state);
time_t wait_start = time(0); time_t wait_start = time(0);
while (!thr.should_shutdown() && key_state == new_state) { while (!thr.should_shutdown() && key_state == new_state) {
/* wait for key state changes /* wait for key state changes
...@@ -2186,8 +2171,10 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2186,8 +2171,10 @@ DECLARE_THREAD(fil_crypt_thread)(
} }
time_t waited = time(0) - wait_start; time_t waited = time(0) - wait_start;
if (waited >= srv_background_scrub_data_check_interval)
if (waited >= srv_background_scrub_data_check_interval) {
break; break;
}
} }
recheck = false; recheck = false;
...@@ -2250,7 +2237,8 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2250,7 +2237,8 @@ DECLARE_THREAD(fil_crypt_thread)(
Adjust thread count for key rotation */ Adjust thread count for key rotation */
UNIV_INTERN UNIV_INTERN
void void
fil_crypt_set_thread_cnt(uint new_cnt) { fil_crypt_set_thread_cnt(uint new_cnt)
{
if (new_cnt > srv_n_fil_crypt_threads) { if (new_cnt > srv_n_fil_crypt_threads) {
uint add = new_cnt - srv_n_fil_crypt_threads; uint add = new_cnt - srv_n_fil_crypt_threads;
srv_n_fil_crypt_threads = new_cnt; srv_n_fil_crypt_threads = new_cnt;
...@@ -2332,6 +2320,7 @@ fil_space_crypt_mark_space_closing( ...@@ -2332,6 +2320,7 @@ fil_space_crypt_mark_space_closing(
{ {
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) { if (crypt_data == NULL) {
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
return; return;
...@@ -2352,6 +2341,7 @@ fil_space_crypt_close_tablespace( ...@@ -2352,6 +2341,7 @@ fil_space_crypt_close_tablespace(
{ {
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) { if (crypt_data == NULL) {
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
return; return;
...@@ -2378,6 +2368,7 @@ fil_space_crypt_close_tablespace( ...@@ -2378,6 +2368,7 @@ fil_space_crypt_close_tablespace(
flushing = crypt_data->rotate_state.flushing; flushing = crypt_data->rotate_state.flushing;
uint now = time(0); uint now = time(0);
if (now >= last + 30) { if (now >= last + 30) {
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"Waited %u seconds to drop space: %lu.", "Waited %u seconds to drop space: %lu.",
...@@ -2385,6 +2376,7 @@ fil_space_crypt_close_tablespace( ...@@ -2385,6 +2376,7 @@ fil_space_crypt_close_tablespace(
last = now; last = now;
} }
} }
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
} }
...@@ -2451,6 +2443,7 @@ fil_space_get_scrub_status( ...@@ -2451,6 +2443,7 @@ fil_space_get_scrub_status(
{ {
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
memset(status, 0, sizeof(*status)); memset(status, 0, sizeof(*status));
if (crypt_data != NULL) { if (crypt_data != NULL) {
status->space = id; status->space = id;
status->compressed = fil_space_get_zip_size(id) > 0; status->compressed = fil_space_get_zip_size(id) > 0;
......
...@@ -208,12 +208,10 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -208,12 +208,10 @@ fil_crypt_get_key(byte *dst, uint* key_length,
fil_space_crypt_t* crypt_data, uint version, bool page_encrypted) fil_space_crypt_t* crypt_data, uint version, bool page_encrypted)
{ {
unsigned char keybuf[MY_AES_MAX_KEY_LENGTH]; unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
unsigned char iv[CRYPT_SCHEME_1_IV_LEN];
ulint iv_len = sizeof(iv);
if (!page_encrypted) { mutex_enter(&crypt_data->mutex);
mutex_enter(&crypt_data->mutex);
if (!page_encrypted) {
// Check if we already have key // Check if we already have key
for (uint i = 0; i < crypt_data->key_count; i++) { for (uint i = 0; i < crypt_data->key_count; i++) {
if (crypt_data->keys[i].key_version == version) { if (crypt_data->keys[i].key_version == version) {
...@@ -231,29 +229,18 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -231,29 +229,18 @@ fil_crypt_get_key(byte *dst, uint* key_length,
crypt_data->keys[i] = crypt_data->keys[i - 1]; crypt_data->keys[i] = crypt_data->keys[i - 1];
} }
} }
else
{
// load iv
int rc = get_encryption_iv(version, (unsigned char*)iv, iv_len);
if (rc != CRYPT_KEY_OK) {
ib_logf(IB_LOG_LEVEL_FATAL,
"IV %d can not be found. Reason=%d", version, rc);
ut_error;
}
}
if (has_encryption_key(version)) { if (has_encryption_key(version)) {
*key_length = get_encryption_key_size(version); int rc;
*key_length = get_encryption_key_size(version);
int rc = get_encryption_key(version, (unsigned char*)keybuf, *key_length); rc = get_encryption_key(version, (unsigned char*)keybuf, *key_length);
if (rc != CRYPT_KEY_OK) { if (rc != CRYPT_KEY_OK) {
ib_logf(IB_LOG_LEVEL_FATAL, ib_logf(IB_LOG_LEVEL_FATAL,
"Key %d can not be found. Reason=%d", version, rc); "Key %d can not be found. Reason=%d", version, rc);
ut_error; ut_error;
} }
} else { } else {
ib_logf(IB_LOG_LEVEL_FATAL, ib_logf(IB_LOG_LEVEL_FATAL,
"Key %d not found", version); "Key %d not found", version);
...@@ -264,51 +251,48 @@ fil_crypt_get_key(byte *dst, uint* key_length, ...@@ -264,51 +251,48 @@ fil_crypt_get_key(byte *dst, uint* key_length,
// do ctr key initialization // do ctr key initialization
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR)
{ {
// Now compute L by encrypting IV using this key /* Now compute L by encrypting IV using this key. Note
const unsigned char* src = page_encrypted ? iv : crypt_data->iv; that we use random IV from crypt data. */
const int srclen = page_encrypted ? iv_len : crypt_data->iv_length; const unsigned char* src = crypt_data->iv;
unsigned char* buf = page_encrypted ? keybuf : crypt_data->keys[0].key; const int srclen = crypt_data->iv_length;
uint32 buflen = page_encrypted ? *key_length : sizeof(crypt_data->keys[0].key); 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); // call ecb explicit
int rc = (*func)(src, srclen, my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
buf, &buflen, int rc = (*func)(src, srclen,
(unsigned char*)keybuf, *key_length, buf, &buflen,
NULL, 0, (unsigned char*)keybuf, *key_length,
1); NULL, 0,
1);
if (rc != AES_OK) {
ib_logf(IB_LOG_LEVEL_FATAL, if (rc != AES_OK) {
"Unable to encrypt key-block " ib_logf(IB_LOG_LEVEL_FATAL,
" src: %p srclen: %d buf: %p buflen: %d." "Unable to encrypt key-block "
" return-code: %d. Can't continue!\n", " src: %p srclen: %d buf: %p buflen: %d."
src, srclen, buf, buflen, rc); " return-code: %d. Can't continue!\n",
ut_error; 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);
}
if (!page_encrypted) { if (!page_encrypted) {
mutex_exit(&crypt_data->mutex); 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);
} }
mutex_exit(&crypt_data->mutex);
} }
/****************************************************************** /******************************************************************
...@@ -323,14 +307,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length, ...@@ -323,14 +307,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length,
int rc = get_latest_encryption_key_version(); int rc = get_latest_encryption_key_version();
// if no new key was created use the last one // if no new key was created use the last one
if (rc >= 0) if (rc >= 0) {
{ *version = rc;
*version = rc;
} }
return fil_crypt_get_key(dst, key_length, crypt_data, *version, false);
} }
return fil_crypt_get_key(dst, key_length, NULL, *version, true);
return fil_crypt_get_key(dst, key_length, crypt_data, *version, srv_encrypt_tables == FALSE);
} }
/****************************************************************** /******************************************************************
...@@ -354,7 +336,7 @@ fil_space_create_crypt_data() ...@@ -354,7 +336,7 @@ fil_space_create_crypt_data()
} }
mutex_create(fil_crypt_data_mutex_key, mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK); &crypt_data->mutex, SYNC_NO_ORDER_CHECK);
crypt_data->iv_length = iv_length; crypt_data->iv_length = iv_length;
my_random_bytes(crypt_data->iv, iv_length); my_random_bytes(crypt_data->iv, iv_length);
return crypt_data; return crypt_data;
...@@ -428,6 +410,7 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset) ...@@ -428,6 +410,7 @@ fil_space_read_crypt_data(ulint space, const byte* page, ulint offset)
} }
ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1); ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1);
if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) { if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
ib_logf(IB_LOG_LEVEL_ERROR, ib_logf(IB_LOG_LEVEL_ERROR,
"Found non sensible iv length: %lu for space %lu " "Found non sensible iv length: %lu for space %lu "
...@@ -572,8 +555,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr, ...@@ -572,8 +555,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
1 + // size of type 1 + // size of type
1 + // size of iv-len 1 + // size of iv-len
4; // size of min_key_version 4; // size of min_key_version
if (end_ptr - ptr < entry_size)
if (end_ptr - ptr < entry_size){
return NULL; return NULL;
}
ulint space_id = mach_read_from_4(ptr); ulint space_id = mach_read_from_4(ptr);
ptr += 4; ptr += 4;
...@@ -590,8 +575,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr, ...@@ -590,8 +575,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
uint min_key_version = mach_read_from_4(ptr); uint min_key_version = mach_read_from_4(ptr);
ptr += 4; ptr += 4;
if (end_ptr - ptr < len) if (end_ptr - ptr < len) {
return NULL; return NULL;
}
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(); fil_space_crypt_t* crypt_data = fil_space_create_crypt_data();
crypt_data->page0_offset = offset; crypt_data->page0_offset = offset;
...@@ -634,11 +620,14 @@ fil_space_check_encryption_write( ...@@ -634,11 +620,14 @@ fil_space_check_encryption_write(
return false; return false;
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL)
if (crypt_data == NULL) {
return false; return false;
}
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
return false; return false;
}
return true; return true;
} }
...@@ -650,15 +639,16 @@ void ...@@ -650,15 +639,16 @@ void
fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key) const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key)
{ {
fil_space_crypt_t* crypt_data; fil_space_crypt_t* crypt_data=NULL;
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE; ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
// get key (L) // get key (L)
uint key_version; uint key_version = encryption_key;
byte key[MY_AES_MAX_KEY_LENGTH]; byte key[MY_AES_MAX_KEY_LENGTH];
uint key_length; uint key_length=MY_AES_MAX_KEY_LENGTH;
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR
|| orig_page_type==FIL_PAGE_TYPE_XDES || orig_page_type==FIL_PAGE_TYPE_XDES
|| orig_page_type== FIL_PAGE_PAGE_ENCRYPTED || orig_page_type== FIL_PAGE_PAGE_ENCRYPTED
...@@ -668,49 +658,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, ...@@ -668,49 +658,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
return; return;
} }
if (srv_encrypt_tables) { /* Get crypt data from file space */
crypt_data = fil_space_get_crypt_data(space); 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); if (crypt_data == NULL) {
} else { //TODO: Is this really needed ?
key_version = encryption_key; memcpy(dst_frame, src_frame, page_size);
fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version); return;
} }
fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version);
/* Load the iv or counter (depending to the encryption algorithm used) */ /* Load the iv or counter (depending to the encryption algorithm used) */
unsigned char iv[MY_AES_BLOCK_SIZE]; unsigned char iv[MY_AES_BLOCK_SIZE];
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
{ // create counter block (C)
// create counter block (C) mach_write_to_4(iv + 0, space);
mach_write_to_4(iv + 0, space); ulint space_offset = mach_read_from_4(
ulint space_offset = mach_read_from_4( src_frame + FIL_PAGE_OFFSET);
src_frame + FIL_PAGE_OFFSET); mach_write_to_4(iv + 4, space_offset);
mach_write_to_4(iv + 4, space_offset); mach_write_to_8(iv + 8, lsn);
mach_write_to_8(iv + 8, lsn);
} else { } else {
// take the iv from the key provider // Get random IV from crypt_data
mutex_enter(&crypt_data->mutex);
int load_iv_rc = get_encryption_iv(key_version, (uchar *) iv, sizeof(iv)); memcpy(iv, crypt_data->iv, crypt_data->iv_length);
mutex_exit(&crypt_data->mutex);
// 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_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
...@@ -720,7 +693,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn, ...@@ -720,7 +693,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
// copy page header // copy page header
memcpy(dst_frame, src_frame, FIL_PAGE_DATA); memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
if (page_encrypted && !page_compressed) { if (page_encrypted && !page_compressed) {
// key id // key id
mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
...@@ -826,11 +798,13 @@ fil_space_check_encryption_read( ...@@ -826,11 +798,13 @@ fil_space_check_encryption_read(
{ {
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) if (crypt_data == NULL) {
return false; return false;
}
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
return false; return false;
}
return true; return true;
} }
...@@ -892,29 +866,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data, ...@@ -892,29 +866,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
// get the iv // get the iv
unsigned char iv[MY_AES_BLOCK_SIZE]; unsigned char iv[MY_AES_BLOCK_SIZE];
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR) {
{ // create counter block
// create counter block
mach_write_to_4(iv + 0, space); mach_write_to_4(iv + 0, space);
mach_write_to_4(iv + 4, offset); mach_write_to_4(iv + 4, offset);
mach_write_to_8(iv + 8, lsn); mach_write_to_8(iv + 8, lsn);
} else { } else {
// take the iv from the key provider // Get random IV from crypt_data
mutex_enter(&crypt_data->mutex);
int load_iv_rc = get_encryption_iv(key_version, (uchar *) iv, sizeof(iv)); memcpy(iv, crypt_data->iv, crypt_data->iv_length);
mutex_exit(&crypt_data->mutex);
// 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;
}
} }
const byte* src = src_frame + FIL_PAGE_DATA; const byte* src = src_frame + FIL_PAGE_DATA;
...@@ -1026,6 +988,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size) ...@@ -1026,6 +988,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size)
* srv_checksum_algorithm */ * srv_checksum_algorithm */
srv_checksum_algorithm_t save_checksum_algorithm = srv_checksum_algorithm_t save_checksum_algorithm =
(srv_checksum_algorithm_t)srv_checksum_algorithm; (srv_checksum_algorithm_t)srv_checksum_algorithm;
if (zip_size == 0 && if (zip_size == 0 &&
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB || (save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) { save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
...@@ -1110,8 +1073,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state) ...@@ -1110,8 +1073,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
/* this is rotation encrypted => encrypted, /* this is rotation encrypted => encrypted,
* only reencrypt if key is sufficiently old */ * only reencrypt if key is sufficiently old */
if (key_version + key_state->rotate_key_age < key_state->key_version) if (key_version + key_state->rotate_key_age < key_state->key_version) {
return true; return true;
}
return false; return false;
} }
...@@ -1189,8 +1153,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) { ...@@ -1189,8 +1153,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
do do
{ {
if (fil_crypt_is_closing(space) || if (fil_crypt_is_closing(space) ||
fil_tablespace_is_being_deleted(space)) fil_tablespace_is_being_deleted(space)) {
break; break;
}
mtr_t mtr; mtr_t mtr;
mtr_start(&mtr); mtr_start(&mtr);
...@@ -1252,8 +1217,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) { ...@@ -1252,8 +1217,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
!fil_tablespace_is_being_deleted(space)); !fil_tablespace_is_being_deleted(space));
/* try to reacquire pending op */ /* try to reacquire pending op */
if (fil_inc_pending_ops(space, true)) if (fil_inc_pending_ops(space, true)) {
break; break;
}
/* pending op reacquired! */ /* pending op reacquired! */
pending_op = true; pending_op = true;
...@@ -1338,11 +1304,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state, ...@@ -1338,11 +1304,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
} }
/* prevent threads from starting to rotate space */ /* prevent threads from starting to rotate space */
if (crypt_data->closing) if (crypt_data->closing) {
break; break;
}
if (crypt_data->rotate_state.flushing) if (crypt_data->rotate_state.flushing) {
break; break;
}
bool need_key_rotation = fil_crypt_needs_rotation( bool need_key_rotation = fil_crypt_needs_rotation(
crypt_data->min_key_version, key_state); crypt_data->min_key_version, key_state);
...@@ -1361,9 +1329,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state, ...@@ -1361,9 +1329,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
} while (0); } while (0);
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
if (pending_op) { if (pending_op) {
fil_decr_pending_ops(space); fil_decr_pending_ops(space);
} }
return false; return false;
} }
...@@ -1435,6 +1405,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state) ...@@ -1435,6 +1405,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
uint max_iops = state->estimated_max_iops; uint max_iops = state->estimated_max_iops;
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) { if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) {
/* this can happen when user decreases srv_fil_crypt_iops */ /* this can happen when user decreases srv_fil_crypt_iops */
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
...@@ -1442,8 +1413,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state) ...@@ -1442,8 +1413,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
} }
uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated; uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated;
if (alloc > max_iops)
if (alloc > max_iops) {
alloc = max_iops; alloc = max_iops;
}
n_fil_crypt_iops_allocated += alloc; n_fil_crypt_iops_allocated += alloc;
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
...@@ -1473,8 +1446,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state) ...@@ -1473,8 +1446,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state)
state->estimated_max_iops, state->estimated_max_iops,
1000000 / avg_wait_time_us); 1000000 / avg_wait_time_us);
#endif #endif
if (avg_wait_time_us == 0) if (avg_wait_time_us == 0) {
avg_wait_time_us = 1; // prevent division by zero avg_wait_time_us = 1; // prevent division by zero
}
state->estimated_max_iops = 1000000 / avg_wait_time_us; state->estimated_max_iops = 1000000 / avg_wait_time_us;
state->cnt_waited = 0; state->cnt_waited = 0;
...@@ -1622,7 +1596,9 @@ fil_crypt_start_rotate_space( ...@@ -1622,7 +1596,9 @@ fil_crypt_start_rotate_space(
{ {
ulint space = state->space; ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
if (crypt_data->rotate_state.active_threads == 0) { if (crypt_data->rotate_state.active_threads == 0) {
/* only first thread needs to init */ /* only first thread needs to init */
crypt_data->rotate_state.next_offset = 1; // skip page 0 crypt_data->rotate_state.next_offset = 1; // skip page 0
...@@ -1663,7 +1639,9 @@ fil_crypt_find_page_to_rotate( ...@@ -1663,7 +1639,9 @@ fil_crypt_find_page_to_rotate(
ulint batch = srv_alloc_time * state->allocated_iops; ulint batch = srv_alloc_time * state->allocated_iops;
ulint space = state->space; ulint space = state->space;
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
mutex_enter(&crypt_data->mutex); mutex_enter(&crypt_data->mutex);
if (crypt_data->closing == false && if (crypt_data->closing == false &&
crypt_data->rotate_state.next_offset < crypt_data->rotate_state.next_offset <
crypt_data->rotate_state.max_offset) { crypt_data->rotate_state.max_offset) {
...@@ -1757,6 +1735,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state, ...@@ -1757,6 +1735,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state,
ulint add_sleeptime_ms = 0; ulint add_sleeptime_ms = 0;
ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited; ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited;
ulint alloc_wait_us = 1000000 / state->allocated_iops; ulint alloc_wait_us = 1000000 / state->allocated_iops;
if (avg_wait_time_us < alloc_wait_us) { if (avg_wait_time_us < alloc_wait_us) {
/* we reading faster than we allocated */ /* we reading faster than we allocated */
add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000; add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000;
...@@ -1986,6 +1965,7 @@ fil_crypt_rotate_pages( ...@@ -1986,6 +1965,7 @@ fil_crypt_rotate_pages(
{ {
ulint space = state->space; ulint space = state->space;
ulint end = state->offset + state->batch; ulint end = state->offset + state->batch;
for (; state->offset < end; state->offset++) { for (; state->offset < end; state->offset++) {
/* we can't rotate pages in dblwr buffer as /* we can't rotate pages in dblwr buffer as
...@@ -2015,17 +1995,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space) ...@@ -2015,17 +1995,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space)
/* flush tablespace pages so that there are no pages left with old key */ /* flush tablespace pages so that there are no pages left with old key */
lsn_t end_lsn = crypt_data->rotate_state.end_lsn; lsn_t end_lsn = crypt_data->rotate_state.end_lsn;
if (end_lsn > 0 && !fil_crypt_is_closing(space)) { if (end_lsn > 0 && !fil_crypt_is_closing(space)) {
bool success = false; bool success = false;
ulint n_pages = 0; ulint n_pages = 0;
ulint sum_pages = 0; ulint sum_pages = 0;
ullint start = ut_time_us(NULL); ullint start = ut_time_us(NULL);
do { do {
success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages); success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
sum_pages += n_pages; sum_pages += n_pages;
} while (!success && !fil_crypt_is_closing(space)); } while (!success && !fil_crypt_is_closing(space));
ullint end = ut_time_us(NULL); ullint end = ut_time_us(NULL);
if (sum_pages && end > start) { if (sum_pages && end > start) {
state->cnt_waited += sum_pages; state->cnt_waited += sum_pages;
state->sum_waited_us += (end - start); state->sum_waited_us += (end - start);
...@@ -2169,6 +2153,7 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2169,6 +2153,7 @@ DECLARE_THREAD(fil_crypt_thread)(
fil_crypt_get_key_state(&new_state); fil_crypt_get_key_state(&new_state);
time_t wait_start = time(0); time_t wait_start = time(0);
while (!thr.should_shutdown() && key_state == new_state) { while (!thr.should_shutdown() && key_state == new_state) {
/* wait for key state changes /* wait for key state changes
...@@ -2186,8 +2171,10 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2186,8 +2171,10 @@ DECLARE_THREAD(fil_crypt_thread)(
} }
time_t waited = time(0) - wait_start; time_t waited = time(0) - wait_start;
if (waited >= srv_background_scrub_data_check_interval)
if (waited >= srv_background_scrub_data_check_interval) {
break; break;
}
} }
recheck = false; recheck = false;
...@@ -2250,7 +2237,8 @@ DECLARE_THREAD(fil_crypt_thread)( ...@@ -2250,7 +2237,8 @@ DECLARE_THREAD(fil_crypt_thread)(
Adjust thread count for key rotation */ Adjust thread count for key rotation */
UNIV_INTERN UNIV_INTERN
void void
fil_crypt_set_thread_cnt(uint new_cnt) { fil_crypt_set_thread_cnt(uint new_cnt)
{
if (new_cnt > srv_n_fil_crypt_threads) { if (new_cnt > srv_n_fil_crypt_threads) {
uint add = new_cnt - srv_n_fil_crypt_threads; uint add = new_cnt - srv_n_fil_crypt_threads;
srv_n_fil_crypt_threads = new_cnt; srv_n_fil_crypt_threads = new_cnt;
...@@ -2332,6 +2320,7 @@ fil_space_crypt_mark_space_closing( ...@@ -2332,6 +2320,7 @@ fil_space_crypt_mark_space_closing(
{ {
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) { if (crypt_data == NULL) {
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
return; return;
...@@ -2352,6 +2341,7 @@ fil_space_crypt_close_tablespace( ...@@ -2352,6 +2341,7 @@ fil_space_crypt_close_tablespace(
{ {
mutex_enter(&fil_crypt_threads_mutex); mutex_enter(&fil_crypt_threads_mutex);
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
if (crypt_data == NULL) { if (crypt_data == NULL) {
mutex_exit(&fil_crypt_threads_mutex); mutex_exit(&fil_crypt_threads_mutex);
return; return;
...@@ -2378,6 +2368,7 @@ fil_space_crypt_close_tablespace( ...@@ -2378,6 +2368,7 @@ fil_space_crypt_close_tablespace(
flushing = crypt_data->rotate_state.flushing; flushing = crypt_data->rotate_state.flushing;
uint now = time(0); uint now = time(0);
if (now >= last + 30) { if (now >= last + 30) {
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"Waited %u seconds to drop space: %lu.", "Waited %u seconds to drop space: %lu.",
...@@ -2385,6 +2376,7 @@ fil_space_crypt_close_tablespace( ...@@ -2385,6 +2376,7 @@ fil_space_crypt_close_tablespace(
last = now; last = now;
} }
} }
mutex_exit(&crypt_data->mutex); mutex_exit(&crypt_data->mutex);
} }
...@@ -2451,6 +2443,7 @@ fil_space_get_scrub_status( ...@@ -2451,6 +2443,7 @@ fil_space_get_scrub_status(
{ {
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
memset(status, 0, sizeof(*status)); memset(status, 0, sizeof(*status));
if (crypt_data != NULL) { if (crypt_data != NULL) {
status->space = id; status->space = id;
status->compressed = fil_space_get_zip_size(id) > 0; status->compressed = fil_space_get_zip_size(id) > 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment