MDEV-19582 WolfSSL decyption function can read memory out-of-bounds.
MDEV-19581 Valgrind error with WolfSSL and encrypted binlog WolfSSL can read memory out of bounds in EVP_CipherUpdate() in decrypt/NOPAD mode, when the input length is not multiple of AES block size. The workaround ensures that input will have some padding at the end by having slightly larger allocated buffer, or padding the structures with 16 more bytes.
This commit is contained in:
parent
5d2619b693
commit
88b7926ff8
@ -1847,8 +1847,16 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
|
||||
{
|
||||
uchar iv[BINLOG_IV_LENGTH];
|
||||
fdle->crypto_data.set_iv(iv, (uint32) (my_b_tell(file) - data_len));
|
||||
|
||||
char *newpkt= (char*)my_malloc(data_len + ev_offset + 1, MYF(MY_WME));
|
||||
size_t sz= data_len + ev_offset + 1;
|
||||
#ifdef HAVE_WOLFSSL
|
||||
/*
|
||||
Workaround for MDEV-19582.
|
||||
WolfSSL reads memory out of bounds with decryption/NOPAD)
|
||||
We allocate a little more memory therefore.
|
||||
*/
|
||||
sz += MY_AES_BLOCK_SIZE;
|
||||
#endif
|
||||
char *newpkt= (char*)my_malloc(sz, MYF(MY_WME));
|
||||
if (!newpkt)
|
||||
DBUG_RETURN(LOG_READ_MEM);
|
||||
memcpy(newpkt, packet->ptr(), ev_offset);
|
||||
|
@ -39,10 +39,15 @@ my_bool srv_encrypt_log;
|
||||
/** Redo log encryption key ID */
|
||||
#define LOG_DEFAULT_ENCRYPTION_KEY 1
|
||||
|
||||
typedef union {
|
||||
uint32_t words[MY_AES_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
struct aes_block_t {
|
||||
byte bytes[MY_AES_BLOCK_SIZE];
|
||||
} aes_block_t;
|
||||
#ifdef HAVE_WOLFSSL
|
||||
// Workaround for MDEV-19582.
|
||||
// WolfSSL reads memory out of bounds with decrypt/NOPAD
|
||||
// Pad the structure to workaround
|
||||
byte pad[MY_AES_BLOCK_SIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct crypt_info_t {
|
||||
ulint checkpoint_no; /*!< checkpoint no; 32 bits */
|
||||
@ -91,7 +96,8 @@ static bool init_crypt_key(crypt_info_t* info, bool upgrade = false)
|
||||
byte mysqld_key[MY_AES_MAX_KEY_LENGTH];
|
||||
uint keylen = sizeof mysqld_key;
|
||||
|
||||
compile_time_assert(16 == sizeof info->crypt_key);
|
||||
compile_time_assert(16 == sizeof info->crypt_key.bytes);
|
||||
compile_time_assert(16 == MY_AES_BLOCK_SIZE);
|
||||
|
||||
if (uint rc = encryption_key_get(LOG_DEFAULT_ENCRYPTION_KEY,
|
||||
info->key_version, mysqld_key,
|
||||
@ -113,7 +119,7 @@ static bool init_crypt_key(crypt_info_t* info, bool upgrade = false)
|
||||
uint dst_len;
|
||||
int err= my_aes_crypt(MY_AES_ECB,
|
||||
ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT,
|
||||
info->crypt_msg.bytes, sizeof info->crypt_msg,
|
||||
info->crypt_msg.bytes, MY_AES_BLOCK_SIZE,
|
||||
info->crypt_key.bytes, &dst_len,
|
||||
mysqld_key, keylen, NULL, 0);
|
||||
|
||||
@ -212,7 +218,7 @@ bool log_crypt(byte* buf, lsn_t lsn, ulint size, log_crypt_t op)
|
||||
buf + LOG_CRYPT_HDR_SIZE, dst_size,
|
||||
reinterpret_cast<byte*>(dst), &dst_len,
|
||||
const_cast<byte*>(info.crypt_key.bytes),
|
||||
sizeof info.crypt_key,
|
||||
MY_AES_BLOCK_SIZE,
|
||||
reinterpret_cast<byte*>(aes_ctr_iv), sizeof aes_ctr_iv,
|
||||
op == LOG_DECRYPT
|
||||
? ENCRYPTION_FLAG_DECRYPT | ENCRYPTION_FLAG_NOPAD
|
||||
@ -249,7 +255,7 @@ log_crypt_init()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (my_random_bytes(info.crypt_msg.bytes, sizeof info.crypt_msg)
|
||||
if (my_random_bytes(info.crypt_msg.bytes, MY_AES_BLOCK_SIZE)
|
||||
!= MY_AES_OK
|
||||
|| my_random_bytes(info.crypt_nonce.bytes, sizeof info.crypt_nonce)
|
||||
!= MY_AES_OK) {
|
||||
@ -287,7 +293,7 @@ log_crypt_101_read_checkpoint(const byte* buf)
|
||||
infos_used++;
|
||||
info.checkpoint_no = checkpoint_no;
|
||||
info.key_version = mach_read_from_4(buf + 4);
|
||||
memcpy(info.crypt_msg.bytes, buf + 8, sizeof info.crypt_msg);
|
||||
memcpy(info.crypt_msg.bytes, buf + 8, MY_AES_BLOCK_SIZE);
|
||||
memcpy(info.crypt_nonce.bytes, buf + 24,
|
||||
sizeof info.crypt_nonce);
|
||||
|
||||
@ -371,13 +377,14 @@ void
|
||||
log_crypt_write_checkpoint_buf(byte* buf)
|
||||
{
|
||||
ut_ad(info.key_version);
|
||||
compile_time_assert(16 == sizeof info.crypt_msg);
|
||||
compile_time_assert(16 == sizeof info.crypt_msg.bytes);
|
||||
compile_time_assert(16 == MY_AES_BLOCK_SIZE);
|
||||
compile_time_assert(LOG_CHECKPOINT_CRYPT_MESSAGE
|
||||
- LOG_CHECKPOINT_CRYPT_NONCE
|
||||
== sizeof info.crypt_nonce);
|
||||
|
||||
memcpy(buf + LOG_CHECKPOINT_CRYPT_MESSAGE, info.crypt_msg.bytes,
|
||||
sizeof info.crypt_msg);
|
||||
MY_AES_BLOCK_SIZE);
|
||||
memcpy(buf + LOG_CHECKPOINT_CRYPT_NONCE, info.crypt_nonce.bytes,
|
||||
sizeof info.crypt_nonce);
|
||||
mach_write_to_4(buf + LOG_CHECKPOINT_CRYPT_KEY, info.key_version);
|
||||
@ -396,13 +403,14 @@ log_crypt_read_checkpoint_buf(const byte* buf)
|
||||
#if MY_AES_BLOCK_SIZE != 16
|
||||
# error "MY_AES_BLOCK_SIZE != 16; redo log checkpoint format affected"
|
||||
#endif
|
||||
compile_time_assert(16 == sizeof info.crypt_msg);
|
||||
compile_time_assert(16 == sizeof info.crypt_msg.bytes);
|
||||
compile_time_assert(16 == MY_AES_BLOCK_SIZE);
|
||||
compile_time_assert(LOG_CHECKPOINT_CRYPT_MESSAGE
|
||||
- LOG_CHECKPOINT_CRYPT_NONCE
|
||||
== sizeof info.crypt_nonce);
|
||||
|
||||
memcpy(info.crypt_msg.bytes, buf + LOG_CHECKPOINT_CRYPT_MESSAGE,
|
||||
sizeof info.crypt_msg);
|
||||
MY_AES_BLOCK_SIZE);
|
||||
memcpy(info.crypt_nonce.bytes, buf + LOG_CHECKPOINT_CRYPT_NONCE,
|
||||
sizeof info.crypt_nonce);
|
||||
|
||||
@ -435,7 +443,7 @@ log_tmp_block_encrypt(
|
||||
|
||||
int rc = encryption_crypt(
|
||||
src, (uint)size, dst, &dst_len,
|
||||
const_cast<byte*>(info.crypt_key.bytes), (uint)(sizeof info.crypt_key),
|
||||
info.crypt_key.bytes, MY_AES_BLOCK_SIZE,
|
||||
reinterpret_cast<byte*>(aes_ctr_iv), (uint)(sizeof aes_ctr_iv),
|
||||
encrypt
|
||||
? ENCRYPTION_FLAG_ENCRYPT|ENCRYPTION_FLAG_NOPAD
|
||||
|
@ -42,6 +42,14 @@ Created 2011-05-26 Marko Makela
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#ifdef HAVE_WOLFSSL
|
||||
// Workaround for MDEV-19582
|
||||
// (WolfSSL reads memory out of bounds with decryption/NOPAD)
|
||||
#define WOLFSSL_PAD_SIZE MY_AES_BLOCK_SIZE
|
||||
#else
|
||||
#define WOLFSSL_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
Atomic_counter<ulint> onlineddl_rowlog_rows;
|
||||
ulint onlineddl_rowlog_pct_used;
|
||||
ulint onlineddl_pct_progress;
|
||||
@ -3231,7 +3239,7 @@ row_log_allocate(
|
||||
index->online_log = log;
|
||||
|
||||
if (log_tmp_is_encrypted()) {
|
||||
ulint size = srv_sort_buf_size;
|
||||
ulint size = srv_sort_buf_size + WOLFSSL_PAD_SIZE;
|
||||
log->crypt_head = static_cast<byte *>(os_mem_alloc_large(&size));
|
||||
log->crypt_tail = static_cast<byte *>(os_mem_alloc_large(&size));
|
||||
|
||||
@ -3265,11 +3273,11 @@ row_log_free(
|
||||
row_merge_file_destroy_low(log->fd);
|
||||
|
||||
if (log->crypt_head) {
|
||||
os_mem_free_large(log->crypt_head, srv_sort_buf_size);
|
||||
os_mem_free_large(log->crypt_head, srv_sort_buf_size + WOLFSSL_PAD_SIZE);
|
||||
}
|
||||
|
||||
if (log->crypt_tail) {
|
||||
os_mem_free_large(log->crypt_tail, srv_sort_buf_size);
|
||||
os_mem_free_large(log->crypt_tail, srv_sort_buf_size + WOLFSSL_PAD_SIZE);
|
||||
}
|
||||
|
||||
mutex_free(&log->mutex);
|
||||
|
Loading…
x
Reference in New Issue
Block a user