Commit 66b9a940 authored by Sergei Golubchik's avatar Sergei Golubchik

New encryption API. Piece-wise encryption.

Instead of encrypt(src, dst, key, iv) that encrypts all
data in one go, now we have encrypt_init(key,iv),
encrypt_update(src,dst), and encrypt_finish(dst).

This also causes collateral changes in the internal my_crypt.cc
encryption functions and in the encryption service.

There are wrappers to provide the old all-at-once encryption
functionality. But binlog events are often written piecewise,
they'll need the new api.
parent d94a982a
...@@ -36,58 +36,54 @@ extern "C" { ...@@ -36,58 +36,54 @@ extern "C" {
/* The max key length of all supported algorithms */ /* The max key length of all supported algorithms */
#define MY_AES_MAX_KEY_LENGTH 32 #define MY_AES_MAX_KEY_LENGTH 32
#ifdef HAVE_EncryptAes128Ctr #define MY_AES_CTX_SIZE 512
int my_aes_encrypt_ctr(const uchar* source, uint source_length,
uchar* dest, uint* dest_length,
const uchar* key, uint key_length,
const uchar* iv, uint iv_length);
#define my_aes_decrypt_ctr my_aes_encrypt_ctr
enum my_aes_mode {
MY_AES_ECB, MY_AES_CBC
#ifdef HAVE_EncryptAes128Ctr
, MY_AES_CTR
#endif #endif
#ifdef HAVE_EncryptAes128Gcm #ifdef HAVE_EncryptAes128Gcm
, MY_AES_GCM
#endif
};
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen);
int my_aes_crypt_update(void *ctx, const uchar *src, uint slen,
uchar *dst, uint *dlen);
int my_aes_crypt_finish(void *ctx, uchar *dst, uint *dlen);
int my_aes_crypt(enum my_aes_mode mode, int flags,
const uchar *src, uint slen, uchar *dst, uint *dlen,
const uchar *key, uint klen, const uchar *iv, uint ivlen);
int my_aes_encrypt_gcm(const uchar* source, uint source_length, /*
uchar* dest, uint* dest_length, calculate the length of the cyphertext from the length of the plaintext
const uchar* key, uint key_length, for different AES encryption modes with padding enabled.
const uchar* iv, uint iv_length); Without padding (ENCRYPTION_FLAG_NOPAD) cyphertext has the same length
as the plaintext
int my_aes_decrypt_gcm(const uchar* source, uint source_length, */
uchar* dest, uint* dest_length, static inline uint my_aes_get_size(enum my_aes_mode mode __attribute__((unused)), uint source_length)
const uchar* key, uint key_length, {
const uchar* iv, uint iv_length); #ifdef HAVE_EncryptAes128Ctr
if (mode == MY_AES_CTR)
return source_length;
#ifdef HAVE_EncryptAes128Gcm
if (mode == MY_AES_GCM)
return source_length + MY_AES_BLOCK_SIZE;
#endif
#endif #endif
return (source_length / MY_AES_BLOCK_SIZE + 1) * MY_AES_BLOCK_SIZE;
}
int my_aes_encrypt_cbc(const uchar* source, uint source_length, static inline uint my_aes_ctx_size(enum my_aes_mode mode __attribute__((unused)))
uchar* dest, uint* dest_length, {
const uchar* key, uint key_length, return MY_AES_CTX_SIZE;
const uchar* iv, uint iv_length, }
int no_padding);
int my_aes_decrypt_cbc(const uchar* source, uint source_length,
uchar* dest, uint* dest_length,
const uchar* key, uint key_length,
const uchar* iv, uint iv_length,
int no_padding);
int my_aes_encrypt_ecb(const uchar* source, uint source_length,
uchar* dest, uint* dest_length,
const uchar* key, uint key_length,
const uchar* iv, uint iv_length,
int no_padding);
int my_aes_decrypt_ecb(const uchar* source, uint source_length,
uchar* dest, uint* dest_length,
const uchar* key, uint key_length,
const uchar* iv, uint iv_length,
int no_padding);
int my_random_bytes(uchar* buf, int num); int my_random_bytes(uchar* buf, int num);
uint my_aes_get_size(uint source_length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key); ...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(MYSQL_THD_KEY_T *key); void thd_key_delete(MYSQL_THD_KEY_T *key);
void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key); void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key);
int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value); int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value);
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0);
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0);
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version)));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version))))
return res1;
res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1));
res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2));
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
struct st_encryption_scheme_key { struct st_encryption_scheme_key {
unsigned int version; unsigned int version;
unsigned char key[16]; unsigned char key[16];
......
...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key); ...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(MYSQL_THD_KEY_T *key); void thd_key_delete(MYSQL_THD_KEY_T *key);
void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key); void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key);
int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value); int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value);
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0);
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0);
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version)));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version))))
return res1;
res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1));
res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2));
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
struct st_encryption_scheme_key { struct st_encryption_scheme_key {
unsigned int version; unsigned int version;
unsigned char key[16]; unsigned char key[16];
......
...@@ -36,6 +36,8 @@ struct st_mariadb_encryption ...@@ -36,6 +36,8 @@ struct st_mariadb_encryption
{ {
int interface_version; /**< version plugin uses */ int interface_version; /**< version plugin uses */
/*********** KEY MANAGEMENT ********************************************/
/** /**
function returning latest key version for a given key id function returning latest key version for a given key id
...@@ -66,8 +68,17 @@ struct st_mariadb_encryption ...@@ -66,8 +68,17 @@ struct st_mariadb_encryption
unsigned int (*get_key)(unsigned int key_id, unsigned int version, unsigned int (*get_key)(unsigned int key_id, unsigned int version,
unsigned char *key, unsigned int *key_length); unsigned char *key, unsigned int *key_length);
encrypt_decrypt_func encrypt; /*********** ENCRYPTION ************************************************/
encrypt_decrypt_func decrypt;
uint (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version);
int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen);
uint (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
#endif #endif
...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key); ...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(MYSQL_THD_KEY_T *key); void thd_key_delete(MYSQL_THD_KEY_T *key);
void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key); void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key);
int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value); int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value);
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0);
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0);
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version)));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version))))
return res1;
res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1));
res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2));
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
struct st_encryption_scheme_key { struct st_encryption_scheme_key {
unsigned int version; unsigned int version;
unsigned char key[16]; unsigned char key[16];
...@@ -392,6 +417,13 @@ struct st_mariadb_encryption ...@@ -392,6 +417,13 @@ struct st_mariadb_encryption
unsigned int (*get_latest_key_version)(unsigned int key_id); unsigned int (*get_latest_key_version)(unsigned int key_id);
unsigned int (*get_key)(unsigned int key_id, unsigned int version, unsigned int (*get_key)(unsigned int key_id, unsigned int version,
unsigned char *key, unsigned int *key_length); unsigned char *key, unsigned int *key_length);
encrypt_decrypt_func encrypt; uint (*crypt_ctx_size)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func decrypt; int (*crypt_ctx_init)(void *ctx, const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*crypt_ctx_update)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*crypt_ctx_finish)(void *ctx, unsigned char* dst, unsigned int* dlen);
uint (*encrypted_length)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key); ...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(MYSQL_THD_KEY_T *key); void thd_key_delete(MYSQL_THD_KEY_T *key);
void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key); void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key);
int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value); int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value);
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0);
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0);
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version)));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version))))
return res1;
res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1));
res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2));
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
struct st_encryption_scheme_key { struct st_encryption_scheme_key {
unsigned int version; unsigned int version;
unsigned char key[16]; unsigned char key[16];
......
...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key); ...@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(MYSQL_THD_KEY_T *key); void thd_key_delete(MYSQL_THD_KEY_T *key);
void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key); void* thd_getspecific(void* thd, MYSQL_THD_KEY_T key);
int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value); int thd_setspecific(void* thd, MYSQL_THD_KEY_T key, void *value);
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_handler.encryption_key_get_latest_version_func(id) != (~(unsigned int)0);
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_handler.encryption_key_get_func((id),(version),(NULL),(&unused)) != (~(unsigned int)0);
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_handler.encryption_ctx_size_func((key_id),(key_version)));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_handler.encryption_ctx_init_func((ctx),(key),(klen),(iv),(ivlen),(flags),(key_id),(key_version))))
return res1;
res1= encryption_handler.encryption_ctx_update_func((ctx),(src),(slen),(dst),(&d1));
res2= encryption_handler.encryption_ctx_finish_func((ctx),(dst + d1),(&d2));
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
struct st_encryption_scheme_key { struct st_encryption_scheme_key {
unsigned int version; unsigned int version;
unsigned char key[16]; unsigned char key[16];
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
Functions to support data encryption and encryption key management. Functions to support data encryption and encryption key management.
They are normally implemented in an encryption plugin, so this service They are normally implemented in an encryption plugin, so this service
connects encryption *consumers* (storage engines) to the encryption connects encryption *consumers* (e.g. storage engines) to the encryption
*provider* (encryption plugin). *provider* (encryption plugin).
*/ */
...@@ -28,6 +28,15 @@ ...@@ -28,6 +28,15 @@
extern "C" { extern "C" {
#endif #endif
#ifndef MYSQL_ABI_CHECK
#ifdef _WIN32
#include <malloc.h>
#define inline __inline
#else
#include <alloca.h>
#endif
#endif
/* returned from encryption_key_get_latest_version() */ /* returned from encryption_key_get_latest_version() */
#define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0) #define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0)
#define ENCRYPTION_KEY_NOT_ENCRYPTED (0) #define ENCRYPTION_KEY_NOT_ENCRYPTED (0)
...@@ -38,20 +47,23 @@ extern "C" { ...@@ -38,20 +47,23 @@ extern "C" {
/* returned from encryption_key_get() */ /* returned from encryption_key_get() */
#define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100) #define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100)
typedef int (*encrypt_decrypt_func)(const unsigned char* src, unsigned int slen, #define ENCRYPTION_FLAG_DECRYPT 0
unsigned char* dst, unsigned int* dlen, #define ENCRYPTION_FLAG_ENCRYPT 1
const unsigned char* key, unsigned int klen, #define ENCRYPTION_FLAG_NOPAD 2
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int key_id,
unsigned int key_version);
struct encryption_service_st { struct encryption_service_st {
unsigned int (*encryption_key_get_latest_version_func)(unsigned int); unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
unsigned int (*encryption_key_id_exists_func)(unsigned int); unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int); unsigned char* buffer, unsigned int* length);
unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*); unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
encrypt_decrypt_func encryption_encrypt_func; int (*encryption_ctx_init_func)(void *ctx, const unsigned char* key, unsigned int klen,
encrypt_decrypt_func encryption_decrypt_func; const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version);
int (*encryption_ctx_update_func)(void *ctx, const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen);
int (*encryption_ctx_finish_func)(void *ctx, unsigned char* dst, unsigned int* dlen);
unsigned int (*encryption_encrypted_length_func)(unsigned int slen, unsigned int key_id, unsigned int key_version);
}; };
#ifdef MYSQL_DYNAMIC_PLUGIN #ifdef MYSQL_DYNAMIC_PLUGIN
...@@ -59,23 +71,53 @@ struct encryption_service_st { ...@@ -59,23 +71,53 @@ struct encryption_service_st {
extern struct encryption_service_st *encryption_service; extern struct encryption_service_st *encryption_service;
#define encryption_key_get_latest_version(KI) encryption_service->encryption_key_get_latest_version_func(KI) #define encryption_key_get_latest_version(KI) encryption_service->encryption_key_get_latest_version_func(KI)
#define encryption_key_id_exists(KI) encryption_service->encryption_key_id_exists_func((KI))
#define encryption_key_version_exists(KI,KV) encryption_service->encryption_key_version_exists_func((KI),(KV))
#define encryption_key_get(KI,KV,K,S) encryption_service->encryption_key_get_func((KI),(KV),(K),(S)) #define encryption_key_get(KI,KV,K,S) encryption_service->encryption_key_get_func((KI),(KV),(K),(S))
#define encryption_encrypt(S,SL,D,DL,K,KL,I,IL,NP,KI,KV) encryption_service->encryption_encrypt_func((S),(SL),(D),(DL),(K),(KL),(I),(IL),(NP),(KI),(KV)) #define encryption_ctx_size(KI,KV) encryption_service->encryption_ctx_size_func((KI),(KV))
#define encryption_decrypt(S,SL,D,DL,K,KL,I,IL,NP,KI,KV) encryption_service->encryption_decrypt_func((S),(SL),(D),(DL),(K),(KL),(I),(IL),(NP),(KI),(KV)) #define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_service->encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV))
#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_service->encryption_ctx_update_func((CTX),(S),(SL),(D),(DL))
#define encryption_ctx_finish(CTX,D,DL) encryption_service->encryption_ctx_finish_func((CTX),(D),(DL))
#define encryption_encrypted_length(SL,KI,KV) encryption_service->encryption_encrypted_length_func((SL),(KI),(KV))
#else #else
extern struct encryption_service_st encryption_handler; extern struct encryption_service_st encryption_handler;
#define encryption_key_get_latest_version(KI) encryption_handler.encryption_key_get_latest_version_func(KI) #define encryption_key_get_latest_version(KI) encryption_handler.encryption_key_get_latest_version_func(KI)
#define encryption_key_id_exists(KI) encryption_handler.encryption_key_id_exists_func((KI))
#define encryption_key_version_exists(KI,KV) encryption_handler.encryption_key_version_exists_func((KI),(KV))
#define encryption_key_get(KI,KV,K,S) encryption_handler.encryption_key_get_func((KI),(KV),(K),(S)) #define encryption_key_get(KI,KV,K,S) encryption_handler.encryption_key_get_func((KI),(KV),(K),(S))
#define encryption_encrypt(S,SL,D,DL,K,KL,I,IL,NP,KI,KV) encryption_handler.encryption_encrypt_func((S),(SL),(D),(DL),(K),(KL),(I),(IL),(NP),(KI),(KV)) #define encryption_ctx_size(KI,KV) encryption_handler.encryption_ctx_size_func((KI),(KV))
#define encryption_decrypt(S,SL,D,DL,K,KL,I,IL,NP,KI,KV) encryption_handler.encryption_decrypt_func((S),(SL),(D),(DL),(K),(KL),(I),(IL),(NP),(KI),(KV)) #define encryption_ctx_init(CTX,K,KL,IV,IVL,F,KI,KV) encryption_handler.encryption_ctx_init_func((CTX),(K),(KL),(IV),(IVL),(F),(KI),(KV))
#define encryption_ctx_update(CTX,S,SL,D,DL) encryption_handler.encryption_ctx_update_func((CTX),(S),(SL),(D),(DL))
#define encryption_ctx_finish(CTX,D,DL) encryption_handler.encryption_ctx_finish_func((CTX),(D),(DL))
#define encryption_encrypted_length(SL,KI,KV) encryption_handler.encryption_encrypted_length_func((SL),(KI),(KV))
#endif #endif
static inline unsigned int encryption_key_id_exists(unsigned int id)
{
return encryption_key_get_latest_version(id) != ENCRYPTION_KEY_VERSION_INVALID;
}
static inline unsigned int encryption_key_version_exists(unsigned int id, unsigned int version)
{
unsigned int unused;
return encryption_key_get(id, version, NULL, &unused) != ENCRYPTION_KEY_VERSION_INVALID;
}
static inline int encryption_crypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id, unsigned int key_version)
{
void *ctx= alloca(encryption_ctx_size(key_id, key_version));
int res1, res2;
unsigned int d1, d2;
if ((res1= encryption_ctx_init(ctx, key, klen, iv, ivlen, flags, key_id, key_version)))
return res1;
res1= encryption_ctx_update(ctx, src, slen, dst, &d1);
res2= encryption_ctx_finish(ctx, dst + d1, &d2);
*dlen= d1 + d2;
return res1 ? res1 : res2;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -265,7 +265,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, ...@@ -265,7 +265,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if (type == SEQ_READ_APPEND) if (type == SEQ_READ_APPEND)
buffer_block *= 2; buffer_block *= 2;
else if (cache_myflags & MY_ENCRYPT) else if (cache_myflags & MY_ENCRYPT)
buffer_block= 2*my_aes_get_size(buffer_block) + sizeof(IO_CACHE_CRYPT); buffer_block= 2*(buffer_block + MY_AES_BLOCK_SIZE) + sizeof(IO_CACHE_CRYPT);
if (cachesize == min_cache) if (cachesize == min_cache)
flags|= (myf) MY_WME; flags|= (myf) MY_WME;
......
This diff is collapsed.
/*
Copyright (c) 2015 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
The very minimal subset of OpenSSL's EVP* functions.
Just enough for my_crypt.cc to work.
On the other hand, where it has to implement OpenSSL functionality,
it tries to be compatible (e.g. same flags and struct member names).
*/
#include <openssl/ssl.h>
#include "aes.hpp"
using yaSSL::yaERR_remove_state;
#define EVP_CIPH_ECB_MODE 0x1
#define EVP_CIPH_CBC_MODE 0x2
#define EVP_CIPH_NO_PADDING 0x100
/*
note that TaoCrypt::AES object is not explicitly put into EVP_CIPHER_CTX.
That's because we need to control when TaoCrypt::AES constructor and
destructor are called.
*/
typedef struct
{
ulong flags;
int encrypt;
int key_len;
int buf_len;
int final_used;
uchar tao_buf[sizeof(TaoCrypt::AES)]; // TaoCrypt::AES object
uchar oiv[TaoCrypt::AES::BLOCK_SIZE]; // original IV
uchar buf[TaoCrypt::AES::BLOCK_SIZE]; // last partial input block
uchar final[TaoCrypt::AES::BLOCK_SIZE]; // last decrypted (output) block
} EVP_CIPHER_CTX;
typedef struct {
TaoCrypt::Mode mode;
TaoCrypt::word32 key_len;
} EVP_CIPHER;
#define gen_cipher(mode, MODE, len) \
static const EVP_CIPHER *EVP_aes_ ## len ## _ ## mode() \
{ static const EVP_CIPHER c={TaoCrypt::MODE, len/8}; return &c; }
gen_cipher(ecb,ECB,128)
gen_cipher(ecb,ECB,192)
gen_cipher(ecb,ECB,256)
gen_cipher(cbc,CBC,128)
gen_cipher(cbc,CBC,192)
gen_cipher(cbc,CBC,256)
static inline TaoCrypt::AES *TAO(EVP_CIPHER_CTX *ctx)
{
return (TaoCrypt::AES *)(ctx->tao_buf);
}
static void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
{
ctx->final_used= ctx->buf_len= ctx->flags= 0;
}
static int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx)
{
TAO(ctx)->~AES();
return 1;
}
static int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
{
if (pad)
ctx->flags&= ~EVP_CIPH_NO_PADDING;
else
ctx->flags|= EVP_CIPH_NO_PADDING;
return 1;
}
static int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
void *, const uchar *key, const uchar *iv, int enc)
{
new (ctx->tao_buf) TaoCrypt::AES(enc ? TaoCrypt::ENCRYPTION
: TaoCrypt::DECRYPTION, cipher->mode);
TAO(ctx)->SetKey(key, cipher->key_len);
if (iv)
{
TAO(ctx)->SetIV(iv);
memcpy(ctx->oiv, iv, TaoCrypt::AES::BLOCK_SIZE);
}
ctx->encrypt= enc;
ctx->key_len= cipher->key_len;
ctx->flags|= cipher->mode == TaoCrypt::CBC ? EVP_CIPH_CBC_MODE : EVP_CIPH_ECB_MODE;
return 1;
}
static int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
{
return ctx->key_len;
}
static int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
{
return ctx->flags & EVP_CIPH_ECB_MODE ? 0 : TaoCrypt::AES::BLOCK_SIZE;
}
static void do_whole_blocks(EVP_CIPHER_CTX *ctx, uchar *out, int *outl,
const uchar *in, int inl)
{
DBUG_ASSERT(inl);
DBUG_ASSERT(inl % TaoCrypt::AES::BLOCK_SIZE == 0);
if (ctx->encrypt || (ctx->flags & EVP_CIPH_NO_PADDING))
{
TAO(ctx)->Process(out, in, inl);
*outl+= inl;
return;
}
/* 'final' is only needed when decrypting with padding */
if (ctx->final_used)
{
memcpy(out, ctx->final, TaoCrypt::AES::BLOCK_SIZE);
*outl+= TaoCrypt::AES::BLOCK_SIZE;
out+= TaoCrypt::AES::BLOCK_SIZE;
}
inl-= TaoCrypt::AES::BLOCK_SIZE;
TAO(ctx)->Process(out, in, inl);
*outl+= inl;
TAO(ctx)->Process(ctx->final, in + inl, TaoCrypt::AES::BLOCK_SIZE);
ctx->final_used= 1;
}
static int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uchar *out, int *outl,
const uchar *in, int inl)
{
*outl= 0;
if (ctx->buf_len)
{
int prefixl= TaoCrypt::AES::BLOCK_SIZE - ctx->buf_len;
if (prefixl > inl)
{
memcpy(ctx->buf + ctx->buf_len, in, inl);
ctx->buf_len+= inl;
return 1;
}
memcpy(ctx->buf + ctx->buf_len, in, prefixl);
do_whole_blocks(ctx, out, outl, ctx->buf, TaoCrypt::AES::BLOCK_SIZE);
in+= prefixl;
inl-= prefixl;
out+= *outl;
}
ctx->buf_len= inl % TaoCrypt::AES::BLOCK_SIZE;
inl-= ctx->buf_len;
memcpy(ctx->buf, in + inl, ctx->buf_len);
if (inl)
do_whole_blocks(ctx, out, outl, in, inl);
return 1;
}
static int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uchar *out, int *outl)
{
if (ctx->flags & EVP_CIPH_NO_PADDING)
return ctx->buf_len == 0;
// PKCS#7 padding
*outl= 0;
if (ctx->encrypt)
{
int v= TaoCrypt::AES::BLOCK_SIZE - ctx->buf_len;
memset(ctx->buf + ctx->buf_len, v, v);
do_whole_blocks(ctx, out, outl, ctx->buf, TaoCrypt::AES::BLOCK_SIZE);
return 1;
}
int n= ctx->final[TaoCrypt::AES::BLOCK_SIZE - 1];
if (ctx->buf_len || !ctx->final_used ||
n < 1 || n > TaoCrypt::AES::BLOCK_SIZE)
return 0;
*outl= TaoCrypt::AES::BLOCK_SIZE - n;
memcpy(out, ctx->final, *outl);
return 1;
}
...@@ -74,7 +74,8 @@ struct st_mariadb_encryption debug_key_management_plugin= { ...@@ -74,7 +74,8 @@ struct st_mariadb_encryption debug_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION, MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_key_version, get_latest_key_version,
get_key, get_key,
0, 0 // use default encrypt/decrypt functions // use default encrypt/decrypt functions
0, 0, 0, 0, 0
}; };
/* /*
......
...@@ -77,26 +77,24 @@ get_key(unsigned int key_id, unsigned int version, ...@@ -77,26 +77,24 @@ get_key(unsigned int key_id, unsigned int version,
/* /*
for the sake of an example, let's use different encryption algorithms/modes for the sake of an example, let's use different encryption algorithms/modes
for different keys. for different keys versions:
*/ */
int encrypt(const unsigned char* src, unsigned int slen, static inline enum my_aes_mode mode(unsigned int key_version)
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int keyid, unsigned int key_version)
{ {
return ((key_version & 1) ? my_aes_encrypt_cbc : my_aes_encrypt_ecb) return key_version & 1 ? MY_AES_ECB : MY_AES_CBC;
(src, slen, dst, dlen, key, klen, iv, ivlen, no_padding);
} }
int decrypt(const unsigned char* src, unsigned int slen, int ctx_init(void *ctx, const unsigned char* key, unsigned int klen, const
unsigned char* dst, unsigned int* dlen, unsigned char* iv, unsigned int ivlen, int flags, unsigned int
const unsigned char* key, unsigned int klen, key_id, unsigned int key_version)
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int keyid, unsigned int key_version)
{ {
return ((key_version & 1) ? my_aes_decrypt_cbc : my_aes_decrypt_ecb) return my_aes_crypt_init(ctx, mode(key_version), flags, key, klen, iv, ivlen);
(src, slen, dst, dlen, key, klen, iv, ivlen, no_padding); }
static unsigned int get_length(unsigned int slen, unsigned int key_id,
unsigned int key_version)
{
return my_aes_get_size(mode(key_version), slen);
} }
static int example_key_management_plugin_init(void *p) static int example_key_management_plugin_init(void *p)
...@@ -119,8 +117,11 @@ struct st_mariadb_encryption example_key_management_plugin= { ...@@ -119,8 +117,11 @@ struct st_mariadb_encryption example_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION, MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_key_version, get_latest_key_version,
get_key, get_key,
encrypt, (uint (*)(unsigned int, unsigned int))my_aes_ctx_size,
decrypt ctx_init,
my_aes_crypt_update,
my_aes_crypt_finish,
get_length
}; };
/* /*
......
...@@ -113,65 +113,59 @@ static unsigned int get_key_from_key_file(unsigned int key_id, ...@@ -113,65 +113,59 @@ static unsigned int get_key_from_key_file(unsigned int key_id,
return 0; return 0;
} }
struct st_mariadb_encryption file_key_management_plugin= { // let's simplify the condition below
MariaDB_ENCRYPTION_INTERFACE_VERSION, #ifndef HAVE_EncryptAes128Gcm
get_latest_version, #define MY_AES_GCM MY_AES_CTR
get_key_from_key_file, #ifndef HAVE_EncryptAes128Ctr
0,0 #define MY_AES_CTR MY_AES_CBC
}; #endif
#endif
#ifdef HAVE_EncryptAes128Gcm static inline enum my_aes_mode mode(int flags)
/*
use AES-CTR when cyphertext length must be the same as plaintext length,
and AES-GCM when cyphertext can be longer than plaintext.
*/
static int ctr_gcm_encrypt(const unsigned char* src, unsigned int slen,
unsigned char* dst, unsigned int* dlen,
const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int keyid, unsigned int key_version)
{ {
return (no_padding ? my_aes_encrypt_ctr : my_aes_encrypt_gcm) /*
(src, slen, dst, dlen, key, klen, iv, ivlen); If encryption_algorithm is AES_CTR then
if no-padding, use AES_CTR
else use AES_GCM (like CTR but appends a "checksum" block)
else
use AES_CBC
*/
if (encryption_algorithm)
if (flags & ENCRYPTION_FLAG_NOPAD)
return MY_AES_CTR;
else
return MY_AES_GCM;
else
return MY_AES_CBC;
} }
static int ctr_gcm_decrypt(const unsigned char* src, unsigned int slen, static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen,
unsigned char* dst, unsigned int* dlen, const unsigned char* iv, unsigned int ivlen, int flags,
const unsigned char* key, unsigned int klen, unsigned int key_id, unsigned int key_version)
const unsigned char* iv, unsigned int ivlen,
int no_padding, unsigned int keyid, unsigned int key_version)
{ {
return (no_padding ? my_aes_decrypt_ctr : my_aes_decrypt_gcm) return my_aes_crypt_init(ctx, mode(flags), flags, key, klen, iv, ivlen);
(src, slen, dst, dlen, key, klen, iv, ivlen); }
static unsigned int get_length(unsigned int slen, unsigned int key_id,
unsigned int key_version)
{
return my_aes_get_size(mode(0), slen);
} }
#endif
struct st_mariadb_encryption file_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_version,
get_key_from_key_file,
(uint (*)(unsigned int, unsigned int))my_aes_ctx_size,
ctx_init,
my_aes_crypt_update,
my_aes_crypt_finish,
get_length
};
static int file_key_management_plugin_init(void *p) static int file_key_management_plugin_init(void *p)
{ {
Parser parser(filename, filekey); Parser parser(filename, filekey);
switch (encryption_algorithm) {
case 0: // AES_CBC
file_key_management_plugin.encrypt=
(encrypt_decrypt_func)my_aes_encrypt_cbc;
file_key_management_plugin.decrypt=
(encrypt_decrypt_func)my_aes_decrypt_cbc;
break;
#ifdef HAVE_EncryptAes128Ctr
case 1: // AES_CTR
#ifdef HAVE_EncryptAes128Gcm
file_key_management_plugin.encrypt= ctr_gcm_encrypt;
file_key_management_plugin.decrypt= ctr_gcm_decrypt;
#else
file_key_management_plugin.encrypt=
(encrypt_decrypt_func)my_aes_encrypt_ctr;
file_key_management_plugin.decrypt=
(encrypt_decrypt_func)my_aes_decrypt_ctr;
#endif
break;
#endif
default:
return 1; // cannot happen
}
return parser.parse(&keys); return parser.parse(&keys);
} }
......
...@@ -336,10 +336,11 @@ char* Parser::read_and_decrypt_file(const char *secret) ...@@ -336,10 +336,11 @@ char* Parser::read_and_decrypt_file(const char *secret)
bytes_to_key(buffer + OpenSSL_prefix_len, secret, key, iv); bytes_to_key(buffer + OpenSSL_prefix_len, secret, key, iv);
uint32 d_size; uint32 d_size;
if (my_aes_decrypt_cbc(buffer + OpenSSL_prefix_len + OpenSSL_salt_len, if (my_aes_crypt(MY_AES_CBC, ENCRYPTION_FLAG_DECRYPT,
file_size - OpenSSL_prefix_len - OpenSSL_salt_len, buffer + OpenSSL_prefix_len + OpenSSL_salt_len,
decrypted, &d_size, key, OpenSSL_key_len, file_size - OpenSSL_prefix_len - OpenSSL_salt_len,
iv, OpenSSL_iv_len, 0)) decrypted, &d_size, key, OpenSSL_key_len,
iv, OpenSSL_iv_len))
{ {
my_printf_error(EE_READ, "Cannot decrypt %s. Wrong key?", MYF(ME_NOREFRESH), filename); my_printf_error(EE_READ, "Cannot decrypt %s. Wrong key?", MYF(ME_NOREFRESH), filename);
......
...@@ -25,31 +25,23 @@ void init_io_cache_encryption(); ...@@ -25,31 +25,23 @@ void init_io_cache_encryption();
static plugin_ref encryption_manager= 0; static plugin_ref encryption_manager= 0;
struct encryption_service_st encryption_handler; struct encryption_service_st encryption_handler;
unsigned int has_key_id(uint id)
{
return encryption_key_get_latest_version(id) != ENCRYPTION_KEY_VERSION_INVALID;
}
unsigned int has_key_version(uint id, uint version)
{
uint unused;
return encryption_key_get(id, version, NULL, &unused) != ENCRYPTION_KEY_VERSION_INVALID;
}
uint no_key(uint) uint no_key(uint)
{ {
return ENCRYPTION_KEY_VERSION_INVALID; return ENCRYPTION_KEY_VERSION_INVALID;
} }
static int no_crypt(const uchar* source, uint source_length, static int ctx_init(void *ctx, const unsigned char* key, unsigned int klen,
uchar* dest, uint* dest_length, const unsigned char* iv, unsigned int ivlen, int flags,
const uchar* key, uint key_length, unsigned int key_id, unsigned int key_version)
const uchar* iv, uint iv_length,
int no_padding, uint key_id, uint key_version)
{ {
return 1; return my_aes_crypt_init(ctx, MY_AES_CBC, flags, key, klen, iv, ivlen);
} }
static unsigned int get_length(unsigned int slen, unsigned int key_id,
unsigned int key_version)
{
return my_aes_get_size(MY_AES_CBC, slen);
}
int initialize_encryption_plugin(st_plugin_int *plugin) int initialize_encryption_plugin(st_plugin_int *plugin)
{ {
...@@ -67,13 +59,21 @@ int initialize_encryption_plugin(st_plugin_int *plugin) ...@@ -67,13 +59,21 @@ int initialize_encryption_plugin(st_plugin_int *plugin)
st_mariadb_encryption *handle= st_mariadb_encryption *handle=
(struct st_mariadb_encryption*) plugin->plugin->info; (struct st_mariadb_encryption*) plugin->plugin->info;
encryption_handler.encryption_encrypt_func= encryption_handler.encryption_ctx_size_func=
handle->encrypt ? handle->encrypt handle->crypt_ctx_size ? handle->crypt_ctx_size :
: (encrypt_decrypt_func)my_aes_encrypt_cbc; (uint (*)(unsigned int, unsigned int))my_aes_ctx_size;
encryption_handler.encryption_ctx_init_func=
handle->crypt_ctx_init ? handle->crypt_ctx_init : ctx_init;
encryption_handler.encryption_ctx_update_func=
handle->crypt_ctx_update ? handle->crypt_ctx_update : my_aes_crypt_update;
encryption_handler.encryption_ctx_finish_func=
handle->crypt_ctx_finish ? handle->crypt_ctx_finish : my_aes_crypt_finish;
encryption_handler.encryption_decrypt_func= encryption_handler.encryption_encrypted_length_func=
handle->decrypt ? handle->decrypt handle->encrypted_length ? handle->encrypted_length : get_length;
: (encrypt_decrypt_func)my_aes_decrypt_cbc;
encryption_handler.encryption_key_get_func= encryption_handler.encryption_key_get_func=
handle->get_key; handle->get_key;
...@@ -88,10 +88,6 @@ int initialize_encryption_plugin(st_plugin_int *plugin) ...@@ -88,10 +88,6 @@ int initialize_encryption_plugin(st_plugin_int *plugin)
int finalize_encryption_plugin(st_plugin_int *plugin) int finalize_encryption_plugin(st_plugin_int *plugin)
{ {
encryption_handler.encryption_encrypt_func= no_crypt;
encryption_handler.encryption_decrypt_func= no_crypt;
encryption_handler.encryption_key_id_exists_func= has_key_id;
encryption_handler.encryption_key_version_exists_func= has_key_version;
encryption_handler.encryption_key_get_func= encryption_handler.encryption_key_get_func=
(uint (*)(uint, uint, uchar*, uint*))no_key; (uint (*)(uint, uint, uchar*, uint*))no_key;
encryption_handler.encryption_key_get_latest_version_func= no_key; encryption_handler.encryption_key_get_latest_version_func= no_key;
...@@ -144,8 +140,9 @@ static uint scheme_get_key(st_encryption_scheme *scheme, ...@@ -144,8 +140,9 @@ static uint scheme_get_key(st_encryption_scheme *scheme,
goto ret; goto ret;
/* Now generate the local key by encrypting IV using the global key */ /* Now generate the local key by encrypting IV using the global key */
rc = my_aes_encrypt_ecb(scheme->iv, sizeof(scheme->iv), key->key, &key_len, rc = my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
global_key, global_key_len, NULL, 0, 1); scheme->iv, sizeof(scheme->iv), key->key, &key_len,
global_key, global_key_len, NULL, 0);
DBUG_ASSERT(key_len == sizeof(key->key)); DBUG_ASSERT(key_len == sizeof(key->key));
...@@ -169,7 +166,7 @@ int do_crypt(const unsigned char* src, unsigned int slen, ...@@ -169,7 +166,7 @@ int do_crypt(const unsigned char* src, unsigned int slen,
struct st_encryption_scheme *scheme, struct st_encryption_scheme *scheme,
unsigned int key_version, unsigned int i32_1, unsigned int key_version, unsigned int i32_1,
unsigned int i32_2, unsigned long long i64, unsigned int i32_2, unsigned long long i64,
encrypt_decrypt_func crypt) int flag)
{ {
compile_time_assert(ENCRYPTION_SCHEME_KEY_INVALID == compile_time_assert(ENCRYPTION_SCHEME_KEY_INVALID ==
(int)ENCRYPTION_KEY_VERSION_INVALID); (int)ENCRYPTION_KEY_VERSION_INVALID);
...@@ -197,8 +194,8 @@ int do_crypt(const unsigned char* src, unsigned int slen, ...@@ -197,8 +194,8 @@ int do_crypt(const unsigned char* src, unsigned int slen,
int4store(iv + 4, i32_2); int4store(iv + 4, i32_2);
int8store(iv + 8, i64); int8store(iv + 8, i64);
return crypt(src, slen, dst, dlen, key.key, sizeof(key.key), return encryption_crypt(src, slen, dst, dlen, key.key, sizeof(key.key),
iv, sizeof(iv), 1, scheme->key_id, key_version); iv, sizeof(iv), flag, scheme->key_id, key_version);
} }
int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
...@@ -208,7 +205,7 @@ int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen, ...@@ -208,7 +205,7 @@ int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
unsigned int i32_2, unsigned long long i64) unsigned int i32_2, unsigned long long i64)
{ {
return do_crypt(src, slen, dst, dlen, scheme, key_version, i32_1, return do_crypt(src, slen, dst, dlen, scheme, key_version, i32_1,
i32_2, i64, encryption_handler.encryption_encrypt_func); i32_2, i64, ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT);
} }
...@@ -219,5 +216,5 @@ int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen, ...@@ -219,5 +216,5 @@ int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
unsigned int i32_2, unsigned long long i64) unsigned int i32_2, unsigned long long i64)
{ {
return do_crypt(src, slen, dst, dlen, scheme, key_version, i32_1, return do_crypt(src, slen, dst, dlen, scheme, key_version, i32_1,
i32_2, i64, encryption_handler.encryption_decrypt_func); i32_2, i64, ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_DECRYPT);
} }
...@@ -402,16 +402,16 @@ String *Item_aes_crypt::val_str(String *str) ...@@ -402,16 +402,16 @@ String *Item_aes_crypt::val_str(String *str)
if (sptr && user_key) // we need both arguments to be not NULL if (sptr && user_key) // we need both arguments to be not NULL
{ {
null_value=0; null_value=0;
aes_length=my_aes_get_size(sptr->length()); // Calculate result length aes_length=my_aes_get_size(MY_AES_ECB, sptr->length());
if (!str_value.alloc(aes_length)) // Ensure that memory is free if (!str_value.alloc(aes_length)) // Ensure that memory is free
{ {
uchar rkey[AES_KEY_LENGTH / 8]; uchar rkey[AES_KEY_LENGTH / 8];
create_key(user_key, rkey); create_key(user_key, rkey);
if (!crypt((uchar*)sptr->ptr(), sptr->length(), if (!my_aes_crypt(MY_AES_ECB, what, (uchar*)sptr->ptr(), sptr->length(),
(uchar*)str_value.ptr(), &aes_length, (uchar*)str_value.ptr(), &aes_length,
rkey, AES_KEY_LENGTH / 8, 0, 0, 0)) rkey, AES_KEY_LENGTH / 8, 0, 0))
{ {
str_value.length((uint) aes_length); str_value.length((uint) aes_length);
return &str_value; return &str_value;
...@@ -424,16 +424,16 @@ String *Item_aes_crypt::val_str(String *str) ...@@ -424,16 +424,16 @@ String *Item_aes_crypt::val_str(String *str)
void Item_func_aes_encrypt::fix_length_and_dec() void Item_func_aes_encrypt::fix_length_and_dec()
{ {
max_length=my_aes_get_size(args[0]->max_length); max_length=my_aes_get_size(MY_AES_ECB, args[0]->max_length);
crypt= my_aes_encrypt_ecb; what= ENCRYPTION_FLAG_ENCRYPT;
} }
void Item_func_aes_decrypt::fix_length_and_dec() void Item_func_aes_decrypt::fix_length_and_dec()
{ {
max_length=args[0]->max_length; max_length=args[0]->max_length;
maybe_null= 1; maybe_null= 1;
crypt= my_aes_decrypt_ecb; what= ENCRYPTION_FLAG_DECRYPT;
} }
......
...@@ -148,10 +148,7 @@ class Item_aes_crypt :public Item_str_func ...@@ -148,10 +148,7 @@ class Item_aes_crypt :public Item_str_func
void create_key(String *user_key, uchar* key); void create_key(String *user_key, uchar* key);
protected: protected:
int (*crypt)(const uchar* src, uint slen, uchar* dst, uint* dlen, int what;
const uchar* key, uint klen, const uchar* iv, uint ivlen,
int no_padding);
public: public:
Item_aes_crypt(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} Item_aes_crypt(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *); String *val_str(String *);
......
...@@ -95,9 +95,10 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count) ...@@ -95,9 +95,10 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count)
elength= wlength - (ebuffer - wbuffer); elength= wlength - (ebuffer - wbuffer);
set_iv(iv, pos_in_file, crypt_data->inbuf_counter); set_iv(iv, pos_in_file, crypt_data->inbuf_counter);
if (encryption_decrypt(ebuffer, elength, info->buffer, &length, if (encryption_crypt(ebuffer, elength, info->buffer, &length,
crypt_data->key, sizeof(crypt_data->key), crypt_data->key, sizeof(crypt_data->key),
iv, sizeof(iv), 0, keyid, keyver)) iv, sizeof(iv), ENCRYPTION_FLAG_DECRYPT,
keyid, keyver))
{ {
my_errno= 1; my_errno= 1;
DBUG_RETURN(info->error= -1); DBUG_RETURN(info->error= -1);
...@@ -175,9 +176,10 @@ static int my_b_encr_write(IO_CACHE *info, const uchar *Buffer, size_t Count) ...@@ -175,9 +176,10 @@ static int my_b_encr_write(IO_CACHE *info, const uchar *Buffer, size_t Count)
crypt_data->inbuf_counter= crypt_data->counter; crypt_data->inbuf_counter= crypt_data->counter;
set_iv(iv, info->pos_in_file, crypt_data->inbuf_counter); set_iv(iv, info->pos_in_file, crypt_data->inbuf_counter);
if (encryption_encrypt(Buffer, length, ebuffer, &elength, if (encryption_crypt(Buffer, length, ebuffer, &elength,
crypt_data->key, sizeof(crypt_data->key), crypt_data->key, sizeof(crypt_data->key),
iv, sizeof(iv), 0, keyid, keyver)) iv, sizeof(iv), ENCRYPTION_FLAG_ENCRYPT,
keyid, keyver))
{ {
my_errno= 1; my_errno= 1;
DBUG_RETURN(info->error= -1); DBUG_RETURN(info->error= -1);
...@@ -191,7 +193,7 @@ static int my_b_encr_write(IO_CACHE *info, const uchar *Buffer, size_t Count) ...@@ -191,7 +193,7 @@ static int my_b_encr_write(IO_CACHE *info, const uchar *Buffer, size_t Count)
buffer_length bytes should *always* produce block_length bytes buffer_length bytes should *always* produce block_length bytes
*/ */
DBUG_ASSERT(crypt_data->block_length == 0 || crypt_data->block_length == wlength); DBUG_ASSERT(crypt_data->block_length == 0 || crypt_data->block_length == wlength);
DBUG_ASSERT(elength <= my_aes_get_size(length)); DBUG_ASSERT(elength <= encryption_encrypted_length(length, keyid, keyver));
crypt_data->block_length= wlength; crypt_data->block_length= wlength;
} }
else else
......
...@@ -131,15 +131,16 @@ log_blocks_crypt( ...@@ -131,15 +131,16 @@ log_blocks_crypt(
const byte* block, /*!< in: blocks before encrypt/decrypt*/ const byte* block, /*!< in: blocks before encrypt/decrypt*/
ulint size, /*!< in: size of block */ ulint size, /*!< in: size of block */
byte* dst_block, /*!< out: blocks after encrypt/decrypt */ byte* dst_block, /*!< out: blocks after encrypt/decrypt */
bool is_encrypt) /*!< in: encrypt or decrypt*/ int what) /*!< in: encrypt or decrypt*/
{ {
byte *log_block = (byte*)block; byte *log_block = (byte*)block;
Crypt_result rc = MY_AES_OK; Crypt_result rc = MY_AES_OK;
uint dst_len; uint dst_len;
byte aes_ctr_counter[MY_AES_BLOCK_SIZE]; byte aes_ctr_counter[MY_AES_BLOCK_SIZE];
byte is_encrypt= what == ENCRYPTION_FLAG_ENCRYPT;
lsn_t lsn = is_encrypt ? log_sys->lsn : srv_start_lsn; lsn_t lsn = is_encrypt ? log_sys->lsn : srv_start_lsn;
const int src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE; const uint src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE;
for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE) { for (ulint i = 0; i < size ; i += OS_FILE_LOG_BLOCK_SIZE) {
ulint log_block_no = log_block_get_hdr_no(log_block); ulint log_block_no = log_block_get_hdr_no(log_block);
lsn_t log_block_start_lsn = log_block_get_start_lsn( lsn_t log_block_start_lsn = log_block_get_start_lsn(
...@@ -174,21 +175,13 @@ log_blocks_crypt( ...@@ -174,21 +175,13 @@ log_blocks_crypt(
bzero(aes_ctr_counter + 15, 1); bzero(aes_ctr_counter + 15, 1);
int rc; int rc;
if (is_encrypt) { rc = encryption_crypt(log_block + LOG_BLOCK_HDR_SIZE, src_len,
rc = encryption_encrypt(log_block + LOG_BLOCK_HDR_SIZE, src_len, dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len, (unsigned char*)(info->crypt_key), 16,
(unsigned char*)(info->crypt_key), 16, aes_ctr_counter, MY_AES_BLOCK_SIZE,
aes_ctr_counter, MY_AES_BLOCK_SIZE, 1, what | ENCRYPTION_FLAG_NOPAD,
LOG_DEFAULT_ENCRYPTION_KEY, LOG_DEFAULT_ENCRYPTION_KEY,
info->key_version); info->key_version);
} else {
rc = encryption_decrypt(log_block + LOG_BLOCK_HDR_SIZE, src_len,
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
(unsigned char*)(info->crypt_key), 16,
aes_ctr_counter, MY_AES_BLOCK_SIZE, 1,
LOG_DEFAULT_ENCRYPTION_KEY,
info->key_version);
}
ut_a(rc == MY_AES_OK); ut_a(rc == MY_AES_OK);
ut_a(dst_len == src_len); ut_a(dst_len == src_len);
...@@ -230,10 +223,11 @@ init_crypt_key( ...@@ -230,10 +223,11 @@ init_crypt_key(
} }
uint dst_len; uint dst_len;
int rc= my_aes_encrypt_ecb(info->crypt_msg, sizeof(info->crypt_msg), //src, srclen int rc= my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_NOPAD|ENCRYPTION_FLAG_ENCRYPT,
info->crypt_key, &dst_len, //dst, &dstlen info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
(unsigned char*)&mysqld_key, sizeof(mysqld_key), info->crypt_key, &dst_len, //dst, &dstlen
NULL, 0, 1); (unsigned char*)&mysqld_key, sizeof(mysqld_key),
NULL, 0);
if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) { if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
fprintf(stderr, fprintf(stderr,
...@@ -296,7 +290,7 @@ log_blocks_encrypt( ...@@ -296,7 +290,7 @@ log_blocks_encrypt(
const ulint size, /*!< in: size of blocks, must be multiple of a log block */ const ulint size, /*!< in: size of blocks, must be multiple of a log block */
byte* dst_block) /*!< out: blocks after encryption */ byte* dst_block) /*!< out: blocks after encryption */
{ {
return log_blocks_crypt(block, size, dst_block, true); return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -366,7 +360,7 @@ log_encrypt_before_write( ...@@ -366,7 +360,7 @@ log_encrypt_before_write(
byte* dst_frame = (byte*)malloc(size); byte* dst_frame = (byte*)malloc(size);
//encrypt log blocks content //encrypt log blocks content
Crypt_result result = log_blocks_crypt(block, size, dst_frame, true); Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT);
if (result == MY_AES_OK) { if (result == MY_AES_OK) {
ut_ad(block[0] == dst_frame[0]); ut_ad(block[0] == dst_frame[0]);
...@@ -392,7 +386,7 @@ log_decrypt_after_read( ...@@ -392,7 +386,7 @@ log_decrypt_after_read(
byte* dst_frame = (byte*)malloc(size); byte* dst_frame = (byte*)malloc(size);
// decrypt log blocks content // decrypt log blocks content
Crypt_result result = log_blocks_crypt(frame, size, dst_frame, false); Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT);
if (result == MY_AES_OK) { if (result == MY_AES_OK) {
memcpy(frame, dst_frame, size); memcpy(frame, dst_frame, size);
......
...@@ -30,7 +30,7 @@ static unsigned int no_key() ...@@ -30,7 +30,7 @@ static unsigned int no_key()
struct encryption_service_st encryption_handler= struct encryption_service_st encryption_handler=
{ {
no_key, 0, 0, 0, 0, 0 no_key, 0, 0, 0, 0, 0, 0
}; };
int encryption_scheme_encrypt(const unsigned char* src __attribute__((unused)), int encryption_scheme_encrypt(const unsigned char* src __attribute__((unused)),
......
...@@ -131,12 +131,13 @@ log_blocks_crypt( ...@@ -131,12 +131,13 @@ log_blocks_crypt(
const byte* block, /*!< in: blocks before encrypt/decrypt*/ const byte* block, /*!< in: blocks before encrypt/decrypt*/
ulint size, /*!< in: size of block */ ulint size, /*!< in: size of block */
byte* dst_block, /*!< out: blocks after encrypt/decrypt */ byte* dst_block, /*!< out: blocks after encrypt/decrypt */
bool is_encrypt) /*!< in: encrypt or decrypt*/ int what) /*!< in: encrypt or decrypt*/
{ {
byte *log_block = (byte*)block; byte *log_block = (byte*)block;
Crypt_result rc = MY_AES_OK; Crypt_result rc = MY_AES_OK;
uint dst_len; uint dst_len;
byte aes_ctr_counter[MY_AES_BLOCK_SIZE]; byte aes_ctr_counter[MY_AES_BLOCK_SIZE];
byte is_encrypt= what == ENCRYPTION_FLAG_ENCRYPT;
lsn_t lsn = is_encrypt ? log_sys->lsn : srv_start_lsn; lsn_t lsn = is_encrypt ? log_sys->lsn : srv_start_lsn;
const uint src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE; const uint src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE;
...@@ -174,21 +175,13 @@ log_blocks_crypt( ...@@ -174,21 +175,13 @@ log_blocks_crypt(
bzero(aes_ctr_counter + 15, 1); bzero(aes_ctr_counter + 15, 1);
int rc; int rc;
if (is_encrypt) { rc = encryption_crypt(log_block + LOG_BLOCK_HDR_SIZE, src_len,
rc = encryption_encrypt(log_block + LOG_BLOCK_HDR_SIZE, src_len, dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len, (unsigned char*)(info->crypt_key), 16,
(unsigned char*)(info->crypt_key), 16, aes_ctr_counter, MY_AES_BLOCK_SIZE,
aes_ctr_counter, MY_AES_BLOCK_SIZE, 1, what | ENCRYPTION_FLAG_NOPAD,
LOG_DEFAULT_ENCRYPTION_KEY, LOG_DEFAULT_ENCRYPTION_KEY,
info->key_version); info->key_version);
} else {
rc = encryption_decrypt(log_block + LOG_BLOCK_HDR_SIZE, src_len,
dst_block + LOG_BLOCK_HDR_SIZE, &dst_len,
(unsigned char*)(info->crypt_key), 16,
aes_ctr_counter, MY_AES_BLOCK_SIZE, 1,
LOG_DEFAULT_ENCRYPTION_KEY,
info->key_version);
}
ut_a(rc == MY_AES_OK); ut_a(rc == MY_AES_OK);
ut_a(dst_len == src_len); ut_a(dst_len == src_len);
...@@ -230,10 +223,11 @@ init_crypt_key( ...@@ -230,10 +223,11 @@ init_crypt_key(
} }
uint dst_len; uint dst_len;
int rc= my_aes_encrypt_ecb(info->crypt_msg, sizeof(info->crypt_msg), //src, srclen int rc= my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_NOPAD|ENCRYPTION_FLAG_ENCRYPT,
info->crypt_key, &dst_len, //dst, &dstlen info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
(unsigned char*)&mysqld_key, sizeof(mysqld_key), info->crypt_key, &dst_len, //dst, &dstlen
NULL, 0, 1); (unsigned char*)&mysqld_key, sizeof(mysqld_key),
NULL, 0);
if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) { if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
fprintf(stderr, fprintf(stderr,
...@@ -296,7 +290,7 @@ log_blocks_encrypt( ...@@ -296,7 +290,7 @@ log_blocks_encrypt(
const ulint size, /*!< in: size of blocks, must be multiple of a log block */ const ulint size, /*!< in: size of blocks, must be multiple of a log block */
byte* dst_block) /*!< out: blocks after encryption */ byte* dst_block) /*!< out: blocks after encryption */
{ {
return log_blocks_crypt(block, size, dst_block, true); return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -366,7 +360,7 @@ log_encrypt_before_write( ...@@ -366,7 +360,7 @@ log_encrypt_before_write(
byte* dst_frame = (byte*)malloc(size); byte* dst_frame = (byte*)malloc(size);
//encrypt log blocks content //encrypt log blocks content
Crypt_result result = log_blocks_crypt(block, size, dst_frame, true); Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT);
if (result == MY_AES_OK) { if (result == MY_AES_OK) {
ut_ad(block[0] == dst_frame[0]); ut_ad(block[0] == dst_frame[0]);
...@@ -392,7 +386,7 @@ log_decrypt_after_read( ...@@ -392,7 +386,7 @@ log_decrypt_after_read(
byte* dst_frame = (byte*)malloc(size); byte* dst_frame = (byte*)malloc(size);
// decrypt log blocks content // decrypt log blocks content
Crypt_result result = log_blocks_crypt(frame, size, dst_frame, false); Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT);
if (result == MY_AES_OK) { if (result == MY_AES_OK) {
memcpy(frame, dst_frame, size); memcpy(frame, dst_frame, size);
......
...@@ -21,54 +21,27 @@ ...@@ -21,54 +21,27 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#define DO_TEST_P(mode, slen, fill, dlen, hash) \ #define DO_TEST(mode, nopad, slen, fill, dlen, hash) \
do { \ SKIP_BLOCK_IF(mode == 0xDEADBEAF, nopad ? 4 : 5, #mode " not supported") \
{ \
memset(src, fill, src_len= slen); \ memset(src, fill, src_len= slen); \
ok(my_aes_encrypt_ ## mode(src, src_len, dst, &dst_len, \ ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_ENCRYPT, \
key, sizeof(key), iv, sizeof(iv), 0) == MY_AES_OK, \ src, src_len, dst, &dst_len, \
"encrypt " #mode " %u", src_len); \ key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
ok(dst_len <= my_aes_get_size(src_len), \ "encrypt " #mode " %u %s", src_len, nopad ? "nopad" : "pad"); \
"my_aes_get_size(%u) >= %u", src_len, dst_len); \ if (!nopad) \
ok (dst_len == my_aes_get_size(mode, src_len), "my_aes_get_size");\
my_md5(md5, (char*)dst, dst_len); \ my_md5(md5, (char*)dst, dst_len); \
ok(dst_len == dlen && memcmp(md5, hash, sizeof(md5)) == 0, "md5"); \ ok(dst_len == dlen && memcmp(md5, hash, sizeof(md5)) == 0, "md5"); \
ok(my_aes_decrypt_ ## mode(dst, dst_len, ddst, &ddst_len, \ ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_DECRYPT, \
key, sizeof(key), iv, sizeof(iv), 0) == MY_AES_OK, \ dst, dst_len, ddst, &ddst_len, \
key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
"decrypt " #mode " %u", dst_len); \ "decrypt " #mode " %u", dst_len); \
ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp"); \ ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp"); \
} while(0) }
#define DO_TEST_N(mode, slen, fill, dlen, hash) \ #define DO_TEST_P(M,S,F,D,H) DO_TEST(M,0,S,F,D,H)
do { \ #define DO_TEST_N(M,S,F,D,H) DO_TEST(M,ENCRYPTION_FLAG_NOPAD,S,F,D,H)
memset(src, fill, src_len= slen); \
ok(my_aes_encrypt_ ## mode(src, src_len, dst, &dst_len, \
key, sizeof(key), iv, sizeof(iv), 1) == MY_AES_OK, \
"encrypt " #mode " %u nopad", src_len); \
my_md5(md5, (char*)dst, dst_len); \
ok(dst_len == dlen && memcmp(md5, hash, sizeof(md5)) == 0, "md5"); \
ok(my_aes_decrypt_ ## mode(dst, dst_len, ddst, &ddst_len, \
key, sizeof(key), iv, sizeof(iv), 1) == MY_AES_OK, \
"decrypt " #mode " %u", dst_len); \
ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp"); \
} while(0)
#ifdef HAVE_YASSL
#define DO_TEST_X(mode, slen, fill, dlen, hash) \
skip(4, #mode " is not supported")
#else
#define DO_TEST_X(mode, slen, fill, dlen, hash) \
do { \
memset(src, fill, src_len= slen); \
ok(my_aes_encrypt_ ## mode(src, src_len, dst, &dst_len, \
key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
"encrypt " #mode " %u", src_len); \
my_md5(md5, (char*)dst, dst_len); \
ok(dst_len == dlen && memcmp(md5, hash, sizeof(md5)) == 0, "md5"); \
ok(my_aes_decrypt_ ## mode(dst, dst_len, ddst, &ddst_len, \
key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
"decrypt " #mode " %u", dst_len); \
ok(ddst_len == src_len && memcmp(src, ddst, src_len) == 0, "memcmp"); \
} while(0)
#endif
/* useful macro for debugging */ /* useful macro for debugging */
#define PRINT_MD5() \ #define PRINT_MD5() \
...@@ -80,6 +53,12 @@ ...@@ -80,6 +53,12 @@
printf("\"\n"); \ printf("\"\n"); \
} while(0); } while(0);
#ifndef HAVE_EncryptAes128Ctr
const uint MY_AES_CTR=0xDEADBEAF;
#endif
#ifndef HAVE_EncryptAes128Gcm
const uint MY_AES_GCM=0xDEADBEAF;
#endif
int int
main(int argc __attribute__((unused)),char *argv[]) main(int argc __attribute__((unused)),char *argv[])
...@@ -92,28 +71,28 @@ main(int argc __attribute__((unused)),char *argv[]) ...@@ -92,28 +71,28 @@ main(int argc __attribute__((unused)),char *argv[])
MY_INIT(argv[0]); MY_INIT(argv[0]);
plan(84); plan(87);
DO_TEST_P(ecb, 200, '.', 208, "\xd8\x73\x8e\x3a\xbc\x66\x99\x13\x7f\x90\x23\x52\xee\x97\x6f\x9a"); DO_TEST_P(MY_AES_ECB, 200, '.', 208, "\xd8\x73\x8e\x3a\xbc\x66\x99\x13\x7f\x90\x23\x52\xee\x97\x6f\x9a");
DO_TEST_P(ecb, 128, '?', 144, "\x19\x58\x33\x85\x4c\xaa\x7f\x06\xd1\xb2\xec\xd7\xb7\x6a\xa9\x5b"); DO_TEST_P(MY_AES_ECB, 128, '?', 144, "\x19\x58\x33\x85\x4c\xaa\x7f\x06\xd1\xb2\xec\xd7\xb7\x6a\xa9\x5b");
DO_TEST_P(cbc, 159, '%', 160, "\x4b\x03\x18\x3d\xf1\xa7\xcd\xa1\x46\xb3\xc6\x8a\x92\xc0\x0f\xc9"); DO_TEST_P(MY_AES_CBC, 159, '%', 160, "\x4b\x03\x18\x3d\xf1\xa7\xcd\xa1\x46\xb3\xc6\x8a\x92\xc0\x0f\xc9");
DO_TEST_P(cbc, 192, '@', 208, "\x54\xc4\x75\x1d\xff\xe0\xf6\x80\xf0\x85\xbb\x8b\xda\x07\x21\x17"); DO_TEST_P(MY_AES_CBC, 192, '@', 208, "\x54\xc4\x75\x1d\xff\xe0\xf6\x80\xf0\x85\xbb\x8b\xda\x07\x21\x17");
DO_TEST_N(ecb, 200, '.', 200, "\xbf\xec\x43\xd1\x66\x8d\x01\xad\x3a\x25\xee\xa6\x3d\xc6\xc4\x68"); DO_TEST_N(MY_AES_ECB, 200, '.', 200, "\xbf\xec\x43\xd1\x66\x8d\x01\xad\x3a\x25\xee\xa6\x3d\xc6\xc4\x68");
DO_TEST_N(ecb, 128, '?', 128, "\x5b\x44\x20\xf3\xd9\xb4\x9d\x74\x5e\xb7\x5a\x0a\xe7\x32\x35\xc3"); DO_TEST_N(MY_AES_ECB, 128, '?', 128, "\x5b\x44\x20\xf3\xd9\xb4\x9d\x74\x5e\xb7\x5a\x0a\xe7\x32\x35\xc3");
DO_TEST_N(cbc, 159, '%', 159, "\xf3\x6e\x40\x00\x3c\x08\xa0\xb1\x2d\x1f\xcf\xce\x54\xc9\x73\x83"); DO_TEST_N(MY_AES_CBC, 159, '%', 159, "\xf3\x6e\x40\x00\x3c\x08\xa0\xb1\x2d\x1f\xcf\xce\x54\xc9\x73\x83");
DO_TEST_N(cbc, 192, '@', 192, "\x30\xe5\x28\x8c\x4a\x3b\x02\xd7\x56\x40\x59\x25\xac\x58\x09\x22"); DO_TEST_N(MY_AES_CBC, 192, '@', 192, "\x30\xe5\x28\x8c\x4a\x3b\x02\xd7\x56\x40\x59\x25\xac\x58\x09\x22");
DO_TEST_X(ctr, 200, '.', 200, "\x5a\x77\x19\xea\x67\x50\xe3\xab\x7f\x39\x6f\xc4\xa8\x09\xc5\x88"); DO_TEST_P(MY_AES_CTR, 200, '.', 200, "\x5a\x77\x19\xea\x67\x50\xe3\xab\x7f\x39\x6f\xc4\xa8\x09\xc5\x88");
DO_TEST_X(gcm, 128, '?', 144, "\x54\x6a\x7c\xa2\x04\xdc\x6e\x80\x1c\xcd\x5f\x7a\x7b\x08\x9e\x9d"); DO_TEST_P(MY_AES_GCM, 128, '?', 144, "\x54\x6a\x7c\xa2\x04\xdc\x6e\x80\x1c\xcd\x5f\x7a\x7b\x08\x9e\x9d");
/* test short inputs (less that one block) */ /* test short inputs (less that one block) */
DO_TEST_P(ecb, 1, '.', 16, "\x6c\xd7\x66\x5b\x1b\x1e\x3a\x04\xfd\xb1\x91\x8d\x0e\xfd\xf1\x86"); DO_TEST_P(MY_AES_ECB, 1, '.', 16, "\x6c\xd7\x66\x5b\x1b\x1e\x3a\x04\xfd\xb1\x91\x8d\x0e\xfd\xf1\x86");
DO_TEST_P(ecb, 2, '?', 16, "\xdb\x84\x9e\xaf\x5f\xcc\xdb\x6b\xf2\x1c\xeb\x53\x75\xa3\x53\x5e"); DO_TEST_P(MY_AES_ECB, 2, '?', 16, "\xdb\x84\x9e\xaf\x5f\xcc\xdb\x6b\xf2\x1c\xeb\x53\x75\xa3\x53\x5e");
DO_TEST_P(cbc, 3, '%', 16, "\x60\x8e\x45\x9a\x07\x39\x63\xce\x02\x19\xdd\x52\xe3\x09\x2a\x66"); DO_TEST_P(MY_AES_CBC, 3, '%', 16, "\x60\x8e\x45\x9a\x07\x39\x63\xce\x02\x19\xdd\x52\xe3\x09\x2a\x66");
DO_TEST_P(cbc, 4, '@', 16, "\x90\xc2\x6b\xf8\x84\x79\x83\xbd\xc1\x60\x71\x04\x55\x6a\xce\x9e"); DO_TEST_P(MY_AES_CBC, 4, '@', 16, "\x90\xc2\x6b\xf8\x84\x79\x83\xbd\xc1\x60\x71\x04\x55\x6a\xce\x9e");
DO_TEST_N(ecb, 5, '.', 5, "\x6b\x60\xdc\xa4\x24\x9b\x02\xbb\x24\x41\x9b\xb0\xd1\x01\xcd\xba"); DO_TEST_N(MY_AES_ECB, 5, '.', 5, "\x6b\x60\xdc\xa4\x24\x9b\x02\xbb\x24\x41\x9b\xb0\xd1\x01\xcd\xba");
DO_TEST_N(ecb, 6, '?', 6, "\x35\x8f\xb7\x9d\xd9\x61\x21\xcf\x25\x66\xd5\x9e\x91\xc1\x42\x7e"); DO_TEST_N(MY_AES_ECB, 6, '?', 6, "\x35\x8f\xb7\x9d\xd9\x61\x21\xcf\x25\x66\xd5\x9e\x91\xc1\x42\x7e");
DO_TEST_N(cbc, 7, '%', 7, "\x94\x5e\x80\x71\x41\x7a\x64\x5d\x6f\x2e\x5b\x66\x9b\x5a\x3d\xda"); DO_TEST_N(MY_AES_CBC, 7, '%', 7, "\x94\x5e\x80\x71\x41\x7a\x64\x5d\x6f\x2e\x5b\x66\x9b\x5a\x3d\xda");
DO_TEST_N(cbc, 8, '@', 8, "\xb8\x53\x97\xb9\x40\xa6\x98\xaf\x0c\x7b\x9a\xac\xad\x7e\x3c\xe0"); DO_TEST_N(MY_AES_CBC, 8, '@', 8, "\xb8\x53\x97\xb9\x40\xa6\x98\xaf\x0c\x7b\x9a\xac\xad\x7e\x3c\xe0");
DO_TEST_X(gcm, 9, '?', 25, "\x5e\x05\xfd\xb2\x8e\x17\x04\x1e\xff\x6d\x71\x81\xcd\x85\x8d\xb5"); DO_TEST_P(MY_AES_GCM, 9, '?', 25, "\x5e\x05\xfd\xb2\x8e\x17\x04\x1e\xff\x6d\x71\x81\xcd\x85\x8d\xb5");
my_end(0); my_end(0);
return exit_status(); return exit_status();
......
...@@ -49,19 +49,34 @@ uint encryption_key_get_func(uint, uint, uchar* key, uint* size) ...@@ -49,19 +49,34 @@ uint encryption_key_get_func(uint, uint, uchar* key, uint* size)
return 0; return 0;
} }
#ifdef HAVE_EncryptAes128Gcm
enum my_aes_mode aes_mode= MY_AES_GCM;
#else
enum my_aes_mode aes_mode= MY_AES_CBC;
#endif
int encryption_ctx_init_func(void *ctx, const unsigned char* key, unsigned int klen,
const unsigned char* iv, unsigned int ivlen,
int flags, unsigned int key_id,
unsigned int key_version)
{
return my_aes_crypt_init(ctx, aes_mode, flags, key, klen, iv, ivlen);
}
uint encryption_encrypted_length_func(unsigned int slen, unsigned int key_id, unsigned int key_version)
{
return my_aes_get_size(aes_mode, slen);
}
struct encryption_service_st encryption_handler= struct encryption_service_st encryption_handler=
{ {
encryption_key_get_latest_version_func, encryption_key_get_latest_version_func,
encryption_key_id_exists_func,
encryption_key_version_exists_func,
encryption_key_get_func, encryption_key_get_func,
#ifdef HAVE_EncryptAes128Gcm (uint (*)(unsigned int, unsigned int))my_aes_ctx_size,
(encrypt_decrypt_func)my_aes_encrypt_gcm, encryption_ctx_init_func,
(encrypt_decrypt_func)my_aes_decrypt_gcm my_aes_crypt_update,
#else my_aes_crypt_finish,
(encrypt_decrypt_func)my_aes_encrypt_cbc, encryption_encrypted_length_func
(encrypt_decrypt_func)my_aes_decrypt_cbc
#endif
}; };
void sql_print_information(const char *format, ...) void sql_print_information(const char *format, ...)
......
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