mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
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.
This commit is contained in:
@@ -209,12 +209,10 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
fil_space_crypt_t* crypt_data, uint version, bool page_encrypted)
|
||||
{
|
||||
unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
|
||||
unsigned char iv[CRYPT_SCHEME_1_IV_LEN];
|
||||
ulint iv_len = sizeof(iv);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
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) {
|
||||
@@ -232,29 +230,18 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
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)) {
|
||||
*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) {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d can not be found. Reason=%d", version, rc);
|
||||
ut_error;
|
||||
}
|
||||
if (rc != CRYPT_KEY_OK) {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d can not be found. Reason=%d", version, rc);
|
||||
ut_error;
|
||||
}
|
||||
} else {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d not found", version);
|
||||
@@ -265,51 +252,48 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
// 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);
|
||||
/* Now compute L by encrypting IV using this key. Note
|
||||
that we use random IV from crypt data. */
|
||||
const unsigned char* src = crypt_data->iv;
|
||||
const int srclen = crypt_data->iv_length;
|
||||
unsigned char* buf = page_encrypted ? keybuf : crypt_data->keys[0].key;
|
||||
uint32 buflen = page_encrypted ? *key_length : sizeof(crypt_data->keys[0].key);
|
||||
|
||||
// call ecb explicit
|
||||
my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
|
||||
int rc = (*func)(src, srclen,
|
||||
buf, &buflen,
|
||||
(unsigned char*)keybuf, *key_length,
|
||||
NULL, 0,
|
||||
1);
|
||||
// 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 (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 (!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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
// 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) {
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
@@ -324,14 +308,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length,
|
||||
int rc = get_latest_encryption_key_version();
|
||||
|
||||
// if no new key was created use the last one
|
||||
if (rc >= 0)
|
||||
{
|
||||
*version = rc;
|
||||
if (rc >= 0) {
|
||||
*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);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
@@ -355,7 +337,7 @@ fil_space_create_crypt_data()
|
||||
}
|
||||
|
||||
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;
|
||||
my_random_bytes(crypt_data->iv, iv_length);
|
||||
return crypt_data;
|
||||
@@ -429,6 +411,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);
|
||||
|
||||
if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Found non sensible iv length: %lu for space %lu "
|
||||
@@ -546,6 +529,7 @@ fil_space_write_crypt_data(ulint space, byte* page, ulint offset,
|
||||
ulint maxsize, mtr_t* mtr)
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -568,8 +552,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
|
||||
1 + // size of type
|
||||
1 + // size of iv-len
|
||||
4; // size of min_key_version
|
||||
if (end_ptr - ptr < entry_size)
|
||||
|
||||
if (end_ptr - ptr < entry_size){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulint space_id = mach_read_from_4(ptr);
|
||||
ptr += 4;
|
||||
@@ -586,8 +572,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
|
||||
uint min_key_version = mach_read_from_4(ptr);
|
||||
ptr += 4;
|
||||
|
||||
if (end_ptr - ptr < len)
|
||||
if (end_ptr - ptr < len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data();
|
||||
crypt_data->page0_offset = offset;
|
||||
@@ -630,11 +617,14 @@ fil_space_check_encryption_write(
|
||||
return false;
|
||||
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
if (crypt_data == NULL)
|
||||
return false;
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED)
|
||||
if (crypt_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -646,15 +636,16 @@ void
|
||||
fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key)
|
||||
{
|
||||
fil_space_crypt_t* crypt_data;
|
||||
fil_space_crypt_t* crypt_data=NULL;
|
||||
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
|
||||
|
||||
// get key (L)
|
||||
uint key_version;
|
||||
uint key_version = encryption_key;
|
||||
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);
|
||||
|
||||
if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR
|
||||
|| orig_page_type==FIL_PAGE_TYPE_XDES
|
||||
|| orig_page_type== FIL_PAGE_PAGE_ENCRYPTED
|
||||
@@ -664,49 +655,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
return;
|
||||
}
|
||||
|
||||
if (srv_encrypt_tables) {
|
||||
crypt_data = fil_space_get_crypt_data(space);
|
||||
/* Get crypt data from file 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);
|
||||
} else {
|
||||
key_version = encryption_key;
|
||||
fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
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 = get_encryption_iv(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;
|
||||
}
|
||||
// Get random IV from crypt_data
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
memcpy(iv, crypt_data->iv, crypt_data->iv_length);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
ibool page_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
|
||||
@@ -716,7 +690,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
// copy page header
|
||||
memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
|
||||
|
||||
|
||||
if (page_encrypted && !page_compressed) {
|
||||
// key id
|
||||
mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
|
||||
@@ -822,11 +795,13 @@ fil_space_check_encryption_read(
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL)
|
||||
if (crypt_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED)
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -888,29 +863,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
|
||||
// get the iv
|
||||
unsigned char iv[MY_AES_BLOCK_SIZE];
|
||||
|
||||
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR)
|
||||
{
|
||||
// create counter block
|
||||
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);
|
||||
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 = get_encryption_iv(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;
|
||||
}
|
||||
// Get random IV from crypt_data
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
memcpy(iv, crypt_data->iv, crypt_data->iv_length);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
const byte* src = src_frame + FIL_PAGE_DATA;
|
||||
@@ -1022,6 +985,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size)
|
||||
* srv_checksum_algorithm */
|
||||
srv_checksum_algorithm_t save_checksum_algorithm =
|
||||
(srv_checksum_algorithm_t)srv_checksum_algorithm;
|
||||
|
||||
if (zip_size == 0 &&
|
||||
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
|
||||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
|
||||
@@ -1106,8 +1070,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
|
||||
|
||||
/* this is rotation encrypted => encrypted,
|
||||
* 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 false;
|
||||
}
|
||||
@@ -1137,6 +1102,7 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data != NULL || fil_crypt_start_converting) {
|
||||
/* someone beat us to it */
|
||||
if (fil_crypt_start_converting)
|
||||
@@ -1174,8 +1140,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
do
|
||||
{
|
||||
if (fil_crypt_is_closing(space) ||
|
||||
fil_tablespace_is_being_deleted(space))
|
||||
fil_tablespace_is_being_deleted(space)) {
|
||||
break;
|
||||
}
|
||||
|
||||
mtr_t mtr;
|
||||
mtr_start(&mtr);
|
||||
@@ -1237,8 +1204,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
!fil_tablespace_is_being_deleted(space));
|
||||
|
||||
/* try to reacquire pending op */
|
||||
if (fil_inc_pending_ops(space, true))
|
||||
if (fil_inc_pending_ops(space, true)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* pending op reacquired! */
|
||||
pending_op = true;
|
||||
@@ -1281,8 +1249,9 @@ static bool
|
||||
fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
bool *recheck)
|
||||
{
|
||||
if (fil_space_get_type(space) != FIL_TABLESPACE)
|
||||
if (fil_space_get_type(space) != FIL_TABLESPACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fil_inc_pending_ops(space, true)) {
|
||||
/* tablespace being dropped */
|
||||
@@ -1293,6 +1262,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
bool pending_op = true;
|
||||
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
/**
|
||||
* space has no crypt data
|
||||
@@ -1300,6 +1270,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
*/
|
||||
pending_op = fil_crypt_start_encrypting_space(space, recheck);
|
||||
crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
if (pending_op) {
|
||||
fil_decr_pending_ops(space);
|
||||
@@ -1309,6 +1280,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
}
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
do {
|
||||
/* prevent threads from starting to rotate space */
|
||||
if (crypt_data->rotate_state.starting) {
|
||||
@@ -1318,11 +1290,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
}
|
||||
|
||||
/* prevent threads from starting to rotate space */
|
||||
if (crypt_data->closing)
|
||||
if (crypt_data->closing) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (crypt_data->rotate_state.flushing)
|
||||
if (crypt_data->rotate_state.flushing) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool need_key_rotation = fil_crypt_needs_rotation(
|
||||
crypt_data->min_key_version, key_state);
|
||||
@@ -1341,9 +1315,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
} while (0);
|
||||
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
|
||||
if (pending_op) {
|
||||
fil_decr_pending_ops(space);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1415,6 +1391,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
|
||||
|
||||
uint max_iops = state->estimated_max_iops;
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
|
||||
if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) {
|
||||
/* this can happen when user decreases srv_fil_crypt_iops */
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
@@ -1422,8 +1399,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
|
||||
}
|
||||
|
||||
uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated;
|
||||
if (alloc > max_iops)
|
||||
|
||||
if (alloc > max_iops) {
|
||||
alloc = max_iops;
|
||||
}
|
||||
|
||||
n_fil_crypt_iops_allocated += alloc;
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
@@ -1453,8 +1432,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state)
|
||||
state->estimated_max_iops,
|
||||
1000000 / avg_wait_time_us);
|
||||
#endif
|
||||
if (avg_wait_time_us == 0)
|
||||
if (avg_wait_time_us == 0) {
|
||||
avg_wait_time_us = 1; // prevent division by zero
|
||||
}
|
||||
|
||||
state->estimated_max_iops = 1000000 / avg_wait_time_us;
|
||||
state->cnt_waited = 0;
|
||||
@@ -1602,7 +1582,9 @@ fil_crypt_start_rotate_space(
|
||||
{
|
||||
ulint space = state->space;
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
if (crypt_data->rotate_state.active_threads == 0) {
|
||||
/* only first thread needs to init */
|
||||
crypt_data->rotate_state.next_offset = 1; // skip page 0
|
||||
@@ -1643,7 +1625,9 @@ fil_crypt_find_page_to_rotate(
|
||||
ulint batch = srv_alloc_time * state->allocated_iops;
|
||||
ulint space = state->space;
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
if (crypt_data->closing == false &&
|
||||
crypt_data->rotate_state.next_offset <
|
||||
crypt_data->rotate_state.max_offset) {
|
||||
@@ -1737,6 +1721,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state,
|
||||
ulint add_sleeptime_ms = 0;
|
||||
ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited;
|
||||
ulint alloc_wait_us = 1000000 / state->allocated_iops;
|
||||
|
||||
if (avg_wait_time_us < alloc_wait_us) {
|
||||
/* we reading faster than we allocated */
|
||||
add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000;
|
||||
@@ -1817,8 +1802,9 @@ fil_crypt_rotate_page(
|
||||
ulint sleeptime_ms = 0;
|
||||
|
||||
/* check if tablespace is closing before reading page */
|
||||
if (fil_crypt_is_closing(space))
|
||||
if (fil_crypt_is_closing(space)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (space == TRX_SYS_SPACE && offset == TRX_SYS_PAGE_NO) {
|
||||
/* don't encrypt this as it contains address to dblwr buffer */
|
||||
@@ -1965,6 +1951,7 @@ fil_crypt_rotate_pages(
|
||||
{
|
||||
ulint space = state->space;
|
||||
ulint end = state->offset + state->batch;
|
||||
|
||||
for (; state->offset < end; state->offset++) {
|
||||
|
||||
/* we can't rotate pages in dblwr buffer as
|
||||
@@ -1994,17 +1981,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space)
|
||||
|
||||
/* flush tablespace pages so that there are no pages left with old key */
|
||||
lsn_t end_lsn = crypt_data->rotate_state.end_lsn;
|
||||
|
||||
if (end_lsn > 0 && !fil_crypt_is_closing(space)) {
|
||||
bool success = false;
|
||||
ulint n_pages = 0;
|
||||
ulint sum_pages = 0;
|
||||
ullint start = ut_time_us(NULL);
|
||||
|
||||
do {
|
||||
success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages);
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
sum_pages += n_pages;
|
||||
} while (!success && !fil_crypt_is_closing(space));
|
||||
|
||||
ullint end = ut_time_us(NULL);
|
||||
|
||||
if (sum_pages && end > start) {
|
||||
state->cnt_waited += sum_pages;
|
||||
state->sum_waited_us += (end - start);
|
||||
@@ -2148,6 +2139,7 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
fil_crypt_get_key_state(&new_state);
|
||||
|
||||
time_t wait_start = time(0);
|
||||
|
||||
while (!thr.should_shutdown() && key_state == new_state) {
|
||||
|
||||
/* wait for key state changes
|
||||
@@ -2165,8 +2157,10 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
}
|
||||
|
||||
time_t waited = time(0) - wait_start;
|
||||
if (waited >= srv_background_scrub_data_check_interval)
|
||||
|
||||
if (waited >= srv_background_scrub_data_check_interval) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
recheck = false;
|
||||
@@ -2229,7 +2223,8 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
Adjust thread count for key rotation */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_crypt_set_thread_cnt(uint new_cnt) {
|
||||
fil_crypt_set_thread_cnt(uint new_cnt)
|
||||
{
|
||||
if (new_cnt > srv_n_fil_crypt_threads) {
|
||||
uint add = new_cnt - srv_n_fil_crypt_threads;
|
||||
srv_n_fil_crypt_threads = new_cnt;
|
||||
@@ -2311,6 +2306,7 @@ fil_space_crypt_mark_space_closing(
|
||||
{
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
return;
|
||||
@@ -2331,6 +2327,7 @@ fil_space_crypt_close_tablespace(
|
||||
{
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
return;
|
||||
@@ -2357,6 +2354,7 @@ fil_space_crypt_close_tablespace(
|
||||
flushing = crypt_data->rotate_state.flushing;
|
||||
|
||||
uint now = time(0);
|
||||
|
||||
if (now >= last + 30) {
|
||||
ib_logf(IB_LOG_LEVEL_WARN,
|
||||
"Waited %u seconds to drop space: %lu.",
|
||||
@@ -2364,6 +2362,7 @@ fil_space_crypt_close_tablespace(
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
@@ -2430,6 +2429,7 @@ fil_space_get_scrub_status(
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
if (crypt_data != NULL) {
|
||||
status->space = id;
|
||||
status->compressed = fil_space_get_zip_size(id) > 0;
|
||||
|
@@ -209,12 +209,10 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
fil_space_crypt_t* crypt_data, uint version, bool page_encrypted)
|
||||
{
|
||||
unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
|
||||
unsigned char iv[CRYPT_SCHEME_1_IV_LEN];
|
||||
ulint iv_len = sizeof(iv);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
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) {
|
||||
@@ -232,29 +230,18 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
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)) {
|
||||
*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) {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d can not be found. Reason=%d", version, rc);
|
||||
ut_error;
|
||||
}
|
||||
if (rc != CRYPT_KEY_OK) {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d can not be found. Reason=%d", version, rc);
|
||||
ut_error;
|
||||
}
|
||||
} else {
|
||||
ib_logf(IB_LOG_LEVEL_FATAL,
|
||||
"Key %d not found", version);
|
||||
@@ -265,51 +252,48 @@ fil_crypt_get_key(byte *dst, uint* key_length,
|
||||
// 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);
|
||||
/* Now compute L by encrypting IV using this key. Note
|
||||
that we use random IV from crypt data. */
|
||||
const unsigned char* src = crypt_data->iv;
|
||||
const int srclen = crypt_data->iv_length;
|
||||
unsigned char* buf = page_encrypted ? keybuf : crypt_data->keys[0].key;
|
||||
uint32 buflen = page_encrypted ? *key_length : sizeof(crypt_data->keys[0].key);
|
||||
|
||||
// call ecb explicit
|
||||
my_aes_encrypt_dynamic_type func = get_aes_encrypt_func(MY_AES_ALGORITHM_ECB);
|
||||
int rc = (*func)(src, srclen,
|
||||
buf, &buflen,
|
||||
(unsigned char*)keybuf, *key_length,
|
||||
NULL, 0,
|
||||
1);
|
||||
// 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 (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 (!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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
// 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) {
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
@@ -324,14 +308,12 @@ fil_crypt_get_latest_key(byte *dst, uint* key_length,
|
||||
int rc = get_latest_encryption_key_version();
|
||||
|
||||
// if no new key was created use the last one
|
||||
if (rc >= 0)
|
||||
{
|
||||
*version = rc;
|
||||
if (rc >= 0) {
|
||||
*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);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
@@ -355,7 +337,7 @@ fil_space_create_crypt_data()
|
||||
}
|
||||
|
||||
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;
|
||||
my_random_bytes(crypt_data->iv, iv_length);
|
||||
return crypt_data;
|
||||
@@ -429,6 +411,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);
|
||||
|
||||
if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
|
||||
ib_logf(IB_LOG_LEVEL_ERROR,
|
||||
"Found non sensible iv length: %lu for space %lu "
|
||||
@@ -546,6 +529,7 @@ fil_space_write_crypt_data(ulint space, byte* page, ulint offset,
|
||||
ulint maxsize, mtr_t* mtr)
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -568,8 +552,10 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
|
||||
1 + // size of type
|
||||
1 + // size of iv-len
|
||||
4; // size of min_key_version
|
||||
if (end_ptr - ptr < entry_size)
|
||||
|
||||
if (end_ptr - ptr < entry_size){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulint space_id = mach_read_from_4(ptr);
|
||||
ptr += 4;
|
||||
@@ -586,8 +572,9 @@ fil_parse_write_crypt_data(byte* ptr, byte* end_ptr,
|
||||
uint min_key_version = mach_read_from_4(ptr);
|
||||
ptr += 4;
|
||||
|
||||
if (end_ptr - ptr < len)
|
||||
if (end_ptr - ptr < len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fil_space_crypt_t* crypt_data = fil_space_create_crypt_data();
|
||||
crypt_data->page0_offset = offset;
|
||||
@@ -630,11 +617,14 @@ fil_space_check_encryption_write(
|
||||
return false;
|
||||
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
if (crypt_data == NULL)
|
||||
return false;
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED)
|
||||
if (crypt_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -646,15 +636,16 @@ void
|
||||
fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
const byte* src_frame, ulint zip_size, byte* dst_frame, ulint encryption_key)
|
||||
{
|
||||
fil_space_crypt_t* crypt_data;
|
||||
fil_space_crypt_t* crypt_data=NULL;
|
||||
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
|
||||
|
||||
// get key (L)
|
||||
uint key_version;
|
||||
uint key_version = encryption_key;
|
||||
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);
|
||||
|
||||
if (orig_page_type==FIL_PAGE_TYPE_FSP_HDR
|
||||
|| orig_page_type==FIL_PAGE_TYPE_XDES
|
||||
|| orig_page_type== FIL_PAGE_PAGE_ENCRYPTED
|
||||
@@ -664,49 +655,32 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
return;
|
||||
}
|
||||
|
||||
if (srv_encrypt_tables) {
|
||||
crypt_data = fil_space_get_crypt_data(space);
|
||||
/* Get crypt data from file 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);
|
||||
} else {
|
||||
key_version = encryption_key;
|
||||
fil_crypt_get_latest_key(key, &key_length, NULL, (uint*)&key_version);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
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 = get_encryption_iv(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;
|
||||
}
|
||||
// Get random IV from crypt_data
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
memcpy(iv, crypt_data->iv, crypt_data->iv_length);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
ibool page_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
|
||||
@@ -716,7 +690,6 @@ fil_space_encrypt(ulint space, ulint offset, lsn_t lsn,
|
||||
// copy page header
|
||||
memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
|
||||
|
||||
|
||||
if (page_encrypted && !page_compressed) {
|
||||
// key id
|
||||
mach_write_to_2(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
|
||||
@@ -822,11 +795,13 @@ fil_space_check_encryption_read(
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL)
|
||||
if (crypt_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED)
|
||||
if (crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -888,29 +863,17 @@ fil_space_decrypt(fil_space_crypt_t* crypt_data,
|
||||
// get the iv
|
||||
unsigned char iv[MY_AES_BLOCK_SIZE];
|
||||
|
||||
if (current_aes_dynamic_method == MY_AES_ALGORITHM_CTR)
|
||||
{
|
||||
// create counter block
|
||||
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);
|
||||
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 = get_encryption_iv(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;
|
||||
}
|
||||
// Get random IV from crypt_data
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
memcpy(iv, crypt_data->iv, crypt_data->iv_length);
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
const byte* src = src_frame + FIL_PAGE_DATA;
|
||||
@@ -1022,6 +985,7 @@ fil_space_verify_crypt_checksum(const byte* src_frame, ulint zip_size)
|
||||
* srv_checksum_algorithm */
|
||||
srv_checksum_algorithm_t save_checksum_algorithm =
|
||||
(srv_checksum_algorithm_t)srv_checksum_algorithm;
|
||||
|
||||
if (zip_size == 0 &&
|
||||
(save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB ||
|
||||
save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) {
|
||||
@@ -1106,8 +1070,9 @@ fil_crypt_needs_rotation(uint key_version, const key_state_t *key_state)
|
||||
|
||||
/* this is rotation encrypted => encrypted,
|
||||
* 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 false;
|
||||
}
|
||||
@@ -1137,6 +1102,7 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data != NULL || fil_crypt_start_converting) {
|
||||
/* someone beat us to it */
|
||||
if (fil_crypt_start_converting)
|
||||
@@ -1174,8 +1140,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
do
|
||||
{
|
||||
if (fil_crypt_is_closing(space) ||
|
||||
fil_tablespace_is_being_deleted(space))
|
||||
fil_tablespace_is_being_deleted(space)) {
|
||||
break;
|
||||
}
|
||||
|
||||
mtr_t mtr;
|
||||
mtr_start(&mtr);
|
||||
@@ -1237,8 +1204,9 @@ fil_crypt_start_encrypting_space(ulint space, bool *recheck) {
|
||||
!fil_tablespace_is_being_deleted(space));
|
||||
|
||||
/* try to reacquire pending op */
|
||||
if (fil_inc_pending_ops(space, true))
|
||||
if (fil_inc_pending_ops(space, true)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* pending op reacquired! */
|
||||
pending_op = true;
|
||||
@@ -1281,8 +1249,9 @@ static bool
|
||||
fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
bool *recheck)
|
||||
{
|
||||
if (fil_space_get_type(space) != FIL_TABLESPACE)
|
||||
if (fil_space_get_type(space) != FIL_TABLESPACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fil_inc_pending_ops(space, true)) {
|
||||
/* tablespace being dropped */
|
||||
@@ -1293,6 +1262,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
bool pending_op = true;
|
||||
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
/**
|
||||
* space has no crypt data
|
||||
@@ -1300,6 +1270,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
*/
|
||||
pending_op = fil_crypt_start_encrypting_space(space, recheck);
|
||||
crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
if (pending_op) {
|
||||
fil_decr_pending_ops(space);
|
||||
@@ -1309,6 +1280,7 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
}
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
do {
|
||||
/* prevent threads from starting to rotate space */
|
||||
if (crypt_data->rotate_state.starting) {
|
||||
@@ -1318,11 +1290,13 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
}
|
||||
|
||||
/* prevent threads from starting to rotate space */
|
||||
if (crypt_data->closing)
|
||||
if (crypt_data->closing) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (crypt_data->rotate_state.flushing)
|
||||
if (crypt_data->rotate_state.flushing) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool need_key_rotation = fil_crypt_needs_rotation(
|
||||
crypt_data->min_key_version, key_state);
|
||||
@@ -1341,9 +1315,11 @@ fil_crypt_space_needs_rotation(uint space, const key_state_t *key_state,
|
||||
} while (0);
|
||||
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
|
||||
if (pending_op) {
|
||||
fil_decr_pending_ops(space);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1415,6 +1391,7 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
|
||||
|
||||
uint max_iops = state->estimated_max_iops;
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
|
||||
if (n_fil_crypt_iops_allocated >= srv_n_fil_crypt_iops) {
|
||||
/* this can happen when user decreases srv_fil_crypt_iops */
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
@@ -1422,8 +1399,10 @@ fil_crypt_alloc_iops(rotate_thread_t *state)
|
||||
}
|
||||
|
||||
uint alloc = srv_n_fil_crypt_iops - n_fil_crypt_iops_allocated;
|
||||
if (alloc > max_iops)
|
||||
|
||||
if (alloc > max_iops) {
|
||||
alloc = max_iops;
|
||||
}
|
||||
|
||||
n_fil_crypt_iops_allocated += alloc;
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
@@ -1453,8 +1432,9 @@ fil_crypt_realloc_iops(rotate_thread_t *state)
|
||||
state->estimated_max_iops,
|
||||
1000000 / avg_wait_time_us);
|
||||
#endif
|
||||
if (avg_wait_time_us == 0)
|
||||
if (avg_wait_time_us == 0) {
|
||||
avg_wait_time_us = 1; // prevent division by zero
|
||||
}
|
||||
|
||||
state->estimated_max_iops = 1000000 / avg_wait_time_us;
|
||||
state->cnt_waited = 0;
|
||||
@@ -1602,7 +1582,9 @@ fil_crypt_start_rotate_space(
|
||||
{
|
||||
ulint space = state->space;
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
if (crypt_data->rotate_state.active_threads == 0) {
|
||||
/* only first thread needs to init */
|
||||
crypt_data->rotate_state.next_offset = 1; // skip page 0
|
||||
@@ -1643,7 +1625,9 @@ fil_crypt_find_page_to_rotate(
|
||||
ulint batch = srv_alloc_time * state->allocated_iops;
|
||||
ulint space = state->space;
|
||||
fil_space_crypt_t *crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
mutex_enter(&crypt_data->mutex);
|
||||
|
||||
if (crypt_data->closing == false &&
|
||||
crypt_data->rotate_state.next_offset <
|
||||
crypt_data->rotate_state.max_offset) {
|
||||
@@ -1737,6 +1721,7 @@ fil_crypt_get_page_throttle_func(rotate_thread_t *state,
|
||||
ulint add_sleeptime_ms = 0;
|
||||
ulint avg_wait_time_us = state->sum_waited_us / state->cnt_waited;
|
||||
ulint alloc_wait_us = 1000000 / state->allocated_iops;
|
||||
|
||||
if (avg_wait_time_us < alloc_wait_us) {
|
||||
/* we reading faster than we allocated */
|
||||
add_sleeptime_ms = (alloc_wait_us - avg_wait_time_us) / 1000;
|
||||
@@ -1817,8 +1802,9 @@ fil_crypt_rotate_page(
|
||||
ulint sleeptime_ms = 0;
|
||||
|
||||
/* check if tablespace is closing before reading page */
|
||||
if (fil_crypt_is_closing(space))
|
||||
if (fil_crypt_is_closing(space)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (space == TRX_SYS_SPACE && offset == TRX_SYS_PAGE_NO) {
|
||||
/* don't encrypt this as it contains address to dblwr buffer */
|
||||
@@ -1965,6 +1951,7 @@ fil_crypt_rotate_pages(
|
||||
{
|
||||
ulint space = state->space;
|
||||
ulint end = state->offset + state->batch;
|
||||
|
||||
for (; state->offset < end; state->offset++) {
|
||||
|
||||
/* we can't rotate pages in dblwr buffer as
|
||||
@@ -1994,17 +1981,21 @@ fil_crypt_flush_space(rotate_thread_t *state, ulint space)
|
||||
|
||||
/* flush tablespace pages so that there are no pages left with old key */
|
||||
lsn_t end_lsn = crypt_data->rotate_state.end_lsn;
|
||||
|
||||
if (end_lsn > 0 && !fil_crypt_is_closing(space)) {
|
||||
bool success = false;
|
||||
ulint n_pages = 0;
|
||||
ulint sum_pages = 0;
|
||||
ullint start = ut_time_us(NULL);
|
||||
|
||||
do {
|
||||
success = buf_flush_list(ULINT_MAX, end_lsn, &n_pages);
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
sum_pages += n_pages;
|
||||
} while (!success && !fil_crypt_is_closing(space));
|
||||
|
||||
ullint end = ut_time_us(NULL);
|
||||
|
||||
if (sum_pages && end > start) {
|
||||
state->cnt_waited += sum_pages;
|
||||
state->sum_waited_us += (end - start);
|
||||
@@ -2148,6 +2139,7 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
fil_crypt_get_key_state(&new_state);
|
||||
|
||||
time_t wait_start = time(0);
|
||||
|
||||
while (!thr.should_shutdown() && key_state == new_state) {
|
||||
|
||||
/* wait for key state changes
|
||||
@@ -2165,8 +2157,10 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
}
|
||||
|
||||
time_t waited = time(0) - wait_start;
|
||||
if (waited >= srv_background_scrub_data_check_interval)
|
||||
|
||||
if (waited >= srv_background_scrub_data_check_interval) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
recheck = false;
|
||||
@@ -2229,7 +2223,8 @@ DECLARE_THREAD(fil_crypt_thread)(
|
||||
Adjust thread count for key rotation */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_crypt_set_thread_cnt(uint new_cnt) {
|
||||
fil_crypt_set_thread_cnt(uint new_cnt)
|
||||
{
|
||||
if (new_cnt > srv_n_fil_crypt_threads) {
|
||||
uint add = new_cnt - srv_n_fil_crypt_threads;
|
||||
srv_n_fil_crypt_threads = new_cnt;
|
||||
@@ -2311,6 +2306,7 @@ fil_space_crypt_mark_space_closing(
|
||||
{
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
return;
|
||||
@@ -2331,6 +2327,7 @@ fil_space_crypt_close_tablespace(
|
||||
{
|
||||
mutex_enter(&fil_crypt_threads_mutex);
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space);
|
||||
|
||||
if (crypt_data == NULL) {
|
||||
mutex_exit(&fil_crypt_threads_mutex);
|
||||
return;
|
||||
@@ -2357,6 +2354,7 @@ fil_space_crypt_close_tablespace(
|
||||
flushing = crypt_data->rotate_state.flushing;
|
||||
|
||||
uint now = time(0);
|
||||
|
||||
if (now >= last + 30) {
|
||||
ib_logf(IB_LOG_LEVEL_WARN,
|
||||
"Waited %u seconds to drop space: %lu.",
|
||||
@@ -2364,6 +2362,7 @@ fil_space_crypt_close_tablespace(
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&crypt_data->mutex);
|
||||
}
|
||||
|
||||
@@ -2430,6 +2429,7 @@ fil_space_get_scrub_status(
|
||||
{
|
||||
fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(id);
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
if (crypt_data != NULL) {
|
||||
status->space = id;
|
||||
status->compressed = fil_space_get_zip_size(id) > 0;
|
||||
|
Reference in New Issue
Block a user