Commit a35b538b authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-8040 make aria encryption use real keys

applied upstream patch
parent ab8415d9
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "ma_blockrec.h" #include "ma_blockrec.h"
#include <my_crypt.h> #include <my_crypt.h>
#define HARD_CODED_ENCRYPTION_KEY_VERSION 1
#define HARD_CODED_ENCRYPTION_KEY_ID 1 #define HARD_CODED_ENCRYPTION_KEY_ID 1
#define CRYPT_SCHEME_1 1 #define CRYPT_SCHEME_1 1
...@@ -28,12 +27,26 @@ ...@@ -28,12 +27,26 @@
#define CRYPT_SCHEME_1_IV_LEN 16 #define CRYPT_SCHEME_1_IV_LEN 16
#define CRYPT_SCHEME_1_KEY_VERSION_SIZE 4 #define CRYPT_SCHEME_1_KEY_VERSION_SIZE 4
#ifdef HAVE_PSI_INTERFACE
PSI_mutex_key key_CRYPT_DATA_lock;
#endif
struct st_crypt_key
{
uint key_version;
uchar key[CRYPT_SCHEME_1_IV_LEN];
};
struct st_maria_crypt_data struct st_maria_crypt_data
{ {
uchar type; uchar type;
uint keyid; uint keyid;
mysql_mutex_t lock; /* protecting keys */
uint keyserver_requests; /* # of key requests to key server */
uint key_count; /* # of initalized key-structs */
struct st_crypt_key keys[3]; /* cached L = AES_ECB(KEY, IV) */
uchar iv_length; uchar iv_length;
uchar iv[1]; // var size uchar iv[1]; /* variable size */
}; };
uint uint
...@@ -72,6 +85,8 @@ ma_crypt_create(MARIA_SHARE* share) ...@@ -72,6 +85,8 @@ ma_crypt_create(MARIA_SHARE* share)
MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0)); MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0));
bzero(crypt_data, sz); bzero(crypt_data, sz);
crypt_data->type= CRYPT_SCHEME_1; crypt_data->type= CRYPT_SCHEME_1;
crypt_data->key_count= 0;
mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock, MY_MUTEX_INIT_FAST);
crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID; crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID;
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);
...@@ -85,6 +100,7 @@ ma_crypt_free(MARIA_SHARE* share) ...@@ -85,6 +100,7 @@ ma_crypt_free(MARIA_SHARE* share)
{ {
if (share->crypt_data != NULL) if (share->crypt_data != NULL)
{ {
mysql_mutex_destroy(&share->crypt_data->lock);
my_free(share->crypt_data); my_free(share->crypt_data);
share->crypt_data= NULL; share->crypt_data= NULL;
} }
...@@ -98,8 +114,8 @@ ma_crypt_write(MARIA_SHARE* share, File file) ...@@ -98,8 +114,8 @@ ma_crypt_write(MARIA_SHARE* share, File file)
if (crypt_data == 0) if (crypt_data == 0)
return 0; return 0;
buff[0] = crypt_data->type; buff[0]= crypt_data->type;
buff[1] = crypt_data->iv_length; buff[1]= crypt_data->iv_length;
if (mysql_file_write(file, buff, 2, MYF(MY_NABP))) if (mysql_file_write(file, buff, 2, MYF(MY_NABP)))
return 1; return 1;
...@@ -123,6 +139,9 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) ...@@ -123,6 +139,9 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff)
MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0)); MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0));
crypt_data->type= type; crypt_data->type= type;
crypt_data->key_count= 0;
mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock,
MY_MUTEX_INIT_FAST);
crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID; crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID;
crypt_data->iv_length= iv_length; crypt_data->iv_length= iv_length;
memcpy(crypt_data->iv, buff + 2, iv_length); memcpy(crypt_data->iv, buff + 2, iv_length);
...@@ -215,7 +234,7 @@ static my_bool ma_crypt_data_post_read_hook(int res, ...@@ -215,7 +234,7 @@ static my_bool ma_crypt_data_post_read_hook(int res,
static void store_rand_lsn(uchar * page) static void store_rand_lsn(uchar * page)
{ {
LSN lsn = 0; LSN lsn= 0;
lsn+= rand(); lsn+= rand();
lsn<<= 32; lsn<<= 32;
lsn+= rand(); lsn+= rand();
...@@ -407,6 +426,98 @@ void ma_crypt_set_index_pagecache_callbacks(PAGECACHE_FILE *file, ...@@ -407,6 +426,98 @@ void ma_crypt_set_index_pagecache_callbacks(PAGECACHE_FILE *file,
file->post_write_hook= ma_crypt_post_write_hook; file->post_write_hook= ma_crypt_post_write_hook;
} }
/**
get key bytes for a table and key-version
*/
static int ma_crypt_get_key(uchar *dst, uint dstlen,
MARIA_CRYPT_DATA *crypt_data, uint version)
{
int rc;
uint i;
uchar keybuf[CRYPT_SCHEME_1_IV_LEN];
uint keylen= sizeof(keybuf);
DBUG_ASSERT(dstlen == sizeof(crypt_data->keys[0].key));
mysql_mutex_lock(&crypt_data->lock);
/* Check if we already have key */
for (i= 0; i < crypt_data->key_count; i++)
{
if (crypt_data->keys[i].key_version == version)
{
memcpy(dst, crypt_data->keys[i].key, sizeof(crypt_data->keys[i].key));
mysql_mutex_unlock(&crypt_data->lock);
return 0;
}
}
/* Not found! */
crypt_data->keyserver_requests++;
/* Rotate keys to make room for a new */
for (i= 1; i < array_elements(crypt_data->keys); i++)
crypt_data->keys[i]= crypt_data->keys[i - 1];
/* Get new key from key server */
rc= encryption_key_get(crypt_data->keyid, version, keybuf, &keylen);
if (rc != 0)
{
my_printf_error(HA_ERR_GENERIC,
"Key id %u version %u can not be found. Reason=%u",
MYF(ME_FATALERROR|ME_NOREFRESH),
crypt_data->keyid, version, rc );
return 1;
}
/* Now compute L by encrypting IV using this key */
{
const uchar* src= crypt_data->iv;
const int srclen= CRYPT_SCHEME_1_IV_LEN;
uchar* buf= crypt_data->keys[0].key;
uint buflen= sizeof(crypt_data->keys[0].key);
rc = my_aes_encrypt_ecb(src, srclen, buf, &buflen,
keybuf, keylen, NULL, 0, 1);
if (rc != MY_AES_OK)
{
my_printf_error(HA_ERR_GENERIC,
"Unable to encrypt key-block "
" src: %p srclen: %d buf: %p buflen: %d."
" return-code: %d. Can't continue!",
MYF(ME_FATALERROR|ME_NOREFRESH),
src, srclen, buf, buflen, rc);
return 1;
}
}
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);
memcpy(dst, crypt_data->keys[0].key, sizeof(crypt_data->keys[0].key));
mysql_mutex_unlock(&crypt_data->lock);
return 0;
}
/******************************************************************
Get key bytes for a table and latest key-version */
static int ma_crypt_get_latest_key(uchar *dst, uint dstlen,
MARIA_CRYPT_DATA* crypt_data, uint *version)
{
uint rc = *version = encryption_key_get_latest_version(crypt_data->keyid);
if (rc == ENCRYPTION_KEY_VERSION_INVALID)
{
my_printf_error(HA_ERR_GENERIC,
"Unknown key id %u. Can't continue!",
MYF(ME_FATALERROR|ME_NOREFRESH),
crypt_data->keyid);
return 1;
}
return ma_crypt_get_key(dst, dstlen, crypt_data, *version);
}
#define COUNTER_LEN MY_AES_BLOCK_SIZE #define COUNTER_LEN MY_AES_BLOCK_SIZE
static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data, static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data,
...@@ -417,17 +528,21 @@ static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data, ...@@ -417,17 +528,21 @@ static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data,
int rc; int rc;
uint32 dstlen; uint32 dstlen;
uchar counter[COUNTER_LEN]; uchar counter[COUNTER_LEN];
*key_version= HARD_CODED_ENCRYPTION_KEY_VERSION; uchar key[CRYPT_SCHEME_1_IV_LEN];
// create counter block // get key (L) and key_version
if (ma_crypt_get_latest_key(key, sizeof(key), crypt_data, key_version))
return 1;
/* create counter block */
memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4); memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4);
int4store(counter + 4, pageno); int4store(counter + 4, pageno);
int8store(counter + 8, lsn); int8store(counter + 8, lsn);
rc = encryption_encrypt(src, size, dst, &dstlen, rc= encryption_encrypt(src, size, dst, &dstlen,
crypt_data->iv, CRYPT_SCHEME_1_IV_LEN, crypt_data->iv, CRYPT_SCHEME_1_IV_LEN,
counter, sizeof(counter), 1, counter, sizeof(counter), 1,
crypt_data->keyid, *key_version); crypt_data->keyid, *key_version);
DBUG_ASSERT(rc == MY_AES_OK); DBUG_ASSERT(rc == MY_AES_OK);
DBUG_ASSERT(dstlen == size); DBUG_ASSERT(dstlen == size);
...@@ -451,8 +566,13 @@ static int ma_decrypt(MARIA_CRYPT_DATA *crypt_data, ...@@ -451,8 +566,13 @@ static int ma_decrypt(MARIA_CRYPT_DATA *crypt_data,
int rc; int rc;
uint32 dstlen; uint32 dstlen;
uchar counter[COUNTER_LEN]; uchar counter[COUNTER_LEN];
uchar key[CRYPT_SCHEME_1_IV_LEN];
// get key (L) and key_version
if (ma_crypt_get_key(key, sizeof(key), crypt_data, key_version))
return 1;
// create counter block /* create counter block */
memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4); memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4);
int4store(counter + 4, pageno); int4store(counter + 4, pageno);
int8store(counter + 8, lsn); int8store(counter + 8, lsn);
......
...@@ -946,6 +946,8 @@ extern PSI_mutex_key key_SHARE_BITMAP_lock, key_SORT_INFO_mutex, ...@@ -946,6 +946,8 @@ extern PSI_mutex_key key_SHARE_BITMAP_lock, key_SORT_INFO_mutex,
key_SERVICE_THREAD_CONTROL_lock, key_SERVICE_THREAD_CONTROL_lock,
key_PAGECACHE_cache_lock; key_PAGECACHE_cache_lock;
extern PSI_mutex_key key_CRYPT_DATA_lock;
extern PSI_cond_key key_SHARE_key_del_cond, key_SERVICE_THREAD_CONTROL_cond, extern PSI_cond_key key_SHARE_key_del_cond, key_SERVICE_THREAD_CONTROL_cond,
key_SORT_INFO_cond, key_SHARE_BITMAP_cond, key_SORT_INFO_cond, key_SHARE_BITMAP_cond,
key_COND_soft_sync, key_TRANSLOG_BUFFER_waiting_filling_buffer, key_COND_soft_sync, key_TRANSLOG_BUFFER_waiting_filling_buffer,
......
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