summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-09-04 10:32:52 +0200
committerSergei Golubchik <serg@mariadb.org>2015-09-04 10:33:50 +0200
commit66b9a9409c73e298d6ceb668783a7cdd5ee85a69 (patch)
treebe04b2c42d1b858756c5a8ba5355abd961589ec8
parentd94a982adbc21d74c0202f1ef64119baeb27c597 (diff)
downloadmariadb-git-66b9a9409c73e298d6ceb668783a7cdd5ee85a69.tar.gz
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.
-rw-r--r--include/my_crypt.h82
-rw-r--r--include/mysql/plugin_audit.h.pp49
-rw-r--r--include/mysql/plugin_auth.h.pp49
-rw-r--r--include/mysql/plugin_encryption.h15
-rw-r--r--include/mysql/plugin_encryption.h.pp60
-rw-r--r--include/mysql/plugin_ftparser.h.pp49
-rw-r--r--include/mysql/plugin_password_validation.h.pp49
-rw-r--r--include/mysql/service_encryption.h84
-rw-r--r--mysys/mf_iocache.c2
-rw-r--r--mysys_ssl/my_crypt.cc449
-rw-r--r--mysys_ssl/yassl.cc194
-rw-r--r--plugin/debug_key_management/debug_key_management_plugin.cc3
-rw-r--r--plugin/example_key_management/example_key_management_plugin.cc35
-rw-r--r--plugin/file_key_management/file_key_management_plugin.cc92
-rw-r--r--plugin/file_key_management/parser.cc9
-rw-r--r--sql/encryption.cc65
-rw-r--r--sql/item_strfunc.cc16
-rw-r--r--sql/item_strfunc.h5
-rw-r--r--sql/mf_iocache_encr.cc16
-rw-r--r--storage/innobase/log/log0crypt.cc42
-rw-r--r--storage/maria/ma_check_standalone.h2
-rw-r--r--storage/xtradb/log/log0crypt.cc40
-rw-r--r--unittest/mysys/aes-t.c103
-rw-r--r--unittest/sql/mf_iocache-t.cc33
24 files changed, 896 insertions, 647 deletions
diff --git a/include/my_crypt.h b/include/my_crypt.h
index 3e6da6aa212..e1e94c9bd9d 100644
--- a/include/my_crypt.h
+++ b/include/my_crypt.h
@@ -36,58 +36,54 @@ extern "C" {
/* The max key length of all supported algorithms */
#define MY_AES_MAX_KEY_LENGTH 32
-#ifdef HAVE_EncryptAes128Ctr
-
-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
+#define MY_AES_CTX_SIZE 512
+enum my_aes_mode {
+ MY_AES_ECB, MY_AES_CBC
+#ifdef HAVE_EncryptAes128Ctr
+ , MY_AES_CTR
#endif
-
#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,
- const uchar* key, uint key_length,
- const uchar* iv, uint iv_length);
-
-int my_aes_decrypt_gcm(const uchar* source, uint source_length,
- uchar* dest, uint* dest_length,
- const uchar* key, uint key_length,
- const uchar* iv, uint iv_length);
+/*
+ calculate the length of the cyphertext from the length of the plaintext
+ for different AES encryption modes with padding enabled.
+ Without padding (ENCRYPTION_FLAG_NOPAD) cyphertext has the same length
+ as the plaintext
+*/
+static inline uint my_aes_get_size(enum my_aes_mode mode __attribute__((unused)), uint source_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
+ return (source_length / MY_AES_BLOCK_SIZE + 1) * MY_AES_BLOCK_SIZE;
+}
-int my_aes_encrypt_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_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);
+static inline uint my_aes_ctx_size(enum my_aes_mode mode __attribute__((unused)))
+{
+ return MY_AES_CTX_SIZE;
+}
int my_random_bytes(uchar* buf, int num);
-uint my_aes_get_size(uint source_length);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 5a10835be56..f4df16afa67 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(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);
-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 {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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;
+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 {
unsigned int version;
unsigned char key[16];
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index 97aca99b257..046f92b5ab8 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(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);
-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 {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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;
+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 {
unsigned int version;
unsigned char key[16];
diff --git a/include/mysql/plugin_encryption.h b/include/mysql/plugin_encryption.h
index 90979017101..673599bfaf3 100644
--- a/include/mysql/plugin_encryption.h
+++ b/include/mysql/plugin_encryption.h
@@ -36,6 +36,8 @@ struct st_mariadb_encryption
{
int interface_version; /**< version plugin uses */
+ /*********** KEY MANAGEMENT ********************************************/
+
/**
function returning latest key version for a given key id
@@ -66,8 +68,17 @@ struct st_mariadb_encryption
unsigned int (*get_key)(unsigned int key_id, unsigned int version,
unsigned char *key, unsigned int *key_length);
- encrypt_decrypt_func encrypt;
- encrypt_decrypt_func decrypt;
+ /*********** ENCRYPTION ************************************************/
+
+ 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
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index 36b4eca0473..e4845fc35ae 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(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);
-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 {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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;
+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 {
unsigned int version;
unsigned char key[16];
@@ -392,6 +417,13 @@ struct st_mariadb_encryption
unsigned int (*get_latest_key_version)(unsigned int key_id);
unsigned int (*get_key)(unsigned int key_id, unsigned int version,
unsigned char *key, unsigned int *key_length);
- encrypt_decrypt_func encrypt;
- 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);
};
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index 29b24c0fafa..ee1056a36d7 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(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);
-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 {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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;
+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 {
unsigned int version;
unsigned char key[16];
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index 8d3a300f02c..0f14ac1eb53 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -181,21 +181,46 @@ int thd_key_create(MYSQL_THD_KEY_T *key);
void thd_key_delete(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);
-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 {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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;
+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 {
unsigned int version;
unsigned char key[16];
diff --git a/include/mysql/service_encryption.h b/include/mysql/service_encryption.h
index 2b79e00fa40..eb1a6b0e629 100644
--- a/include/mysql/service_encryption.h
+++ b/include/mysql/service_encryption.h
@@ -20,7 +20,7 @@
Functions to support data encryption and encryption key management.
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).
*/
@@ -28,6 +28,15 @@
extern "C" {
#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() */
#define ENCRYPTION_KEY_VERSION_INVALID (~(unsigned int)0)
#define ENCRYPTION_KEY_NOT_ENCRYPTED (0)
@@ -38,20 +47,23 @@ extern "C" {
/* returned from encryption_key_get() */
#define ENCRYPTION_KEY_BUFFER_TOO_SMALL (100)
-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);
+#define ENCRYPTION_FLAG_DECRYPT 0
+#define ENCRYPTION_FLAG_ENCRYPT 1
+#define ENCRYPTION_FLAG_NOPAD 2
struct encryption_service_st {
- unsigned int (*encryption_key_get_latest_version_func)(unsigned int);
- unsigned int (*encryption_key_id_exists_func)(unsigned int);
- unsigned int (*encryption_key_version_exists_func)(unsigned int, unsigned int);
- unsigned int (*encryption_key_get_func)(unsigned int, unsigned int, unsigned char*, unsigned int*);
- encrypt_decrypt_func encryption_encrypt_func;
- encrypt_decrypt_func encryption_decrypt_func;
+ unsigned int (*encryption_key_get_latest_version_func)(unsigned int key_id);
+ unsigned int (*encryption_key_get_func)(unsigned int key_id, unsigned int key_version,
+ unsigned char* buffer, unsigned int* length);
+ unsigned int (*encryption_ctx_size_func)(unsigned int key_id, unsigned int key_version);
+ 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);
+ 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
@@ -59,23 +71,53 @@ struct encryption_service_st {
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_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_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_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_size(KI,KV) encryption_service->encryption_ctx_size_func((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
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_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_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_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_size(KI,KV) encryption_handler.encryption_ctx_size_func((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
+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
}
#endif
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 4591557baf0..28e5e72130d 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -265,7 +265,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if (type == SEQ_READ_APPEND)
buffer_block *= 2;
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)
flags|= (myf) MY_WME;
diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
index dc3c4f63bdb..1e76b34a1fb 100644
--- a/mysys_ssl/my_crypt.cc
+++ b/mysys_ssl/my_crypt.cc
@@ -16,199 +16,115 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <my_global.h>
+#include <string.h>
#include <my_crypt.h>
#ifdef HAVE_YASSL
-#include "aes.hpp"
-
-typedef TaoCrypt::CipherDir Dir;
-static const Dir CRYPT_ENCRYPT = TaoCrypt::ENCRYPTION;
-static const Dir CRYPT_DECRYPT = TaoCrypt::DECRYPTION;
-
-typedef TaoCrypt::Mode CipherMode;
-static inline CipherMode aes_ecb(uint) { return TaoCrypt::ECB; }
-static inline CipherMode aes_cbc(uint) { return TaoCrypt::CBC; }
-
-typedef TaoCrypt::byte KeyByte;
-
+#include "yassl.cc"
#else
+
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/err.h>
-typedef int Dir;
-static const Dir CRYPT_ENCRYPT = 1;
-static const Dir CRYPT_DECRYPT = 0;
-
-typedef const EVP_CIPHER *CipherMode;
-
-#define make_aes_dispatcher(mode) \
- static inline CipherMode aes_ ## mode(uint key_length) \
- { \
- switch (key_length) { \
- case 16: return EVP_aes_128_ ## mode(); \
- case 24: return EVP_aes_192_ ## mode(); \
- case 32: return EVP_aes_256_ ## mode(); \
- default: return 0; \
- } \
- }
-
-make_aes_dispatcher(ecb)
-make_aes_dispatcher(cbc)
-
-typedef uchar KeyByte;
-
-struct MyCTX : EVP_CIPHER_CTX {
- MyCTX() { EVP_CIPHER_CTX_init(this); }
- ~MyCTX() { EVP_CIPHER_CTX_cleanup(this); ERR_remove_state(0); }
-};
#endif
-static int block_crypt(CipherMode cipher, Dir dir,
- const uchar* source, uint source_length,
- uchar* dest, uint* dest_length,
- const KeyByte *key, uint key_length,
- const KeyByte *iv, uint iv_length, int no_padding)
+class MyCTX
{
- int tail= source_length % MY_AES_BLOCK_SIZE;
+public:
+ EVP_CIPHER_CTX ctx;
+ MyCTX() { EVP_CIPHER_CTX_init(&ctx); }
+ virtual ~MyCTX() { EVP_CIPHER_CTX_cleanup(&ctx); ERR_remove_state(0); }
- if (likely(source_length >= MY_AES_BLOCK_SIZE || !no_padding))
+ virtual int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key,
+ uint klen, const uchar *iv, uint ivlen)
{
-#ifdef HAVE_YASSL
- TaoCrypt::AES ctx(dir, cipher);
-
- if (unlikely(key_length != 16 && key_length != 24 && key_length != 32))
- return MY_AES_BAD_KEYSIZE;
-
- ctx.SetKey(key, key_length);
- if (iv)
- {
- ctx.SetIV(iv);
- DBUG_ASSERT(TaoCrypt::AES::BLOCK_SIZE <= iv_length);
- }
- DBUG_ASSERT(TaoCrypt::AES::BLOCK_SIZE == MY_AES_BLOCK_SIZE);
-
- ctx.Process(dest, source, source_length - tail);
- *dest_length= source_length - tail;
-
- /* unlike OpenSSL, YaSSL doesn't support PKCS#7 padding */
- if (!no_padding)
- {
- if (dir == CRYPT_ENCRYPT)
- {
- uchar buf[MY_AES_BLOCK_SIZE];
- memcpy(buf, source + source_length - tail, tail);
- memset(buf + tail, MY_AES_BLOCK_SIZE - tail, MY_AES_BLOCK_SIZE - tail);
- ctx.Process(dest + *dest_length, buf, MY_AES_BLOCK_SIZE);
- *dest_length+= MY_AES_BLOCK_SIZE;
- }
- else
- {
- int n= source_length ? dest[source_length - 1] : 0;
- if (tail || n == 0 || n > MY_AES_BLOCK_SIZE)
- return MY_AES_BAD_DATA;
- *dest_length-= n;
- }
- }
-
-#else // HAVE_OPENSSL
- int fin;
- struct MyCTX ctx;
-
if (unlikely(!cipher))
return MY_AES_BAD_KEYSIZE;
- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, dir))
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, encrypt))
return MY_AES_OPENSSL_ERROR;
- EVP_CIPHER_CTX_set_padding(&ctx, !no_padding);
+ DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)klen);
+ DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) <= (int)ivlen);
- DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)key_length);
- DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) <= (int)iv_length);
- DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == MY_AES_BLOCK_SIZE);
-
- /* use built-in OpenSSL padding, if possible */
- if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length,
- source, source_length - (no_padding ? tail : 0)))
+ return MY_AES_OK;
+ }
+ virtual int update(const uchar *src, uint slen, uchar *dst, uint *dlen)
+ {
+ if (!EVP_CipherUpdate(&ctx, dst, (int*)dlen, src, slen))
return MY_AES_OPENSSL_ERROR;
- if (!EVP_CipherFinal_ex(&ctx, dest + *dest_length, &fin))
+ return MY_AES_OK;
+ }
+ virtual int finish(uchar *dst, uint *dlen)
+ {
+ if (!EVP_CipherFinal_ex(&ctx, dst, (int*)dlen))
return MY_AES_BAD_DATA;
- *dest_length += fin;
+ return MY_AES_OK;
+ }
+};
-#endif
+class MyCTX_nopad : public MyCTX
+{
+public:
+ const uchar *key;
+ int klen;
+
+ MyCTX_nopad() : MyCTX() { }
+ ~MyCTX_nopad() { }
+
+ int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, uint klen,
+ const uchar *iv, uint ivlen)
+ {
+ compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_nopad));
+ this->key= key;
+ this->klen= klen;
+ int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen);
+ memcpy(ctx.oiv, iv, ivlen); // in ECB mode OpenSSL doesn't do that itself
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ return res;
}
- if (no_padding)
+ int finish(uchar *dst, uint *dlen)
{
- if (tail)
+ if (ctx.buf_len)
{
/*
Not much we can do, block ciphers cannot encrypt data that aren't
a multiple of the block length. At least not without padding.
Let's do something CTR-like for the last partial block.
*/
-
uchar mask[MY_AES_BLOCK_SIZE];
uint mlen;
- DBUG_ASSERT(iv_length >= sizeof(mask));
- my_aes_encrypt_ecb(iv, sizeof(mask), mask, &mlen,
- key, key_length, 0, 0, 1);
+ my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
+ ctx.oiv, sizeof(mask), mask, &mlen, key, klen, 0, 0);
DBUG_ASSERT(mlen == sizeof(mask));
- const uchar *s= source + source_length - tail;
- const uchar *e= source + source_length;
- uchar *d= dest + source_length - tail;
- const uchar *m= mask;
- while (s < e)
- *d++ = *s++ ^ *m++;
+ for (int i=0; i < ctx.buf_len; i++)
+ dst[i]= ctx.buf[i] ^ mask[i];
}
- *dest_length= source_length;
+ *dlen= ctx.buf_len;
+ return MY_AES_OK;
}
+};
- return MY_AES_OK;
-}
-
-C_MODE_START
+#define make_aes_dispatcher(mode) \
+ static inline const EVP_CIPHER *aes_ ## mode(uint klen) \
+ { \
+ switch (klen) { \
+ case 16: return EVP_aes_128_ ## mode(); \
+ case 24: return EVP_aes_192_ ## mode(); \
+ case 32: return EVP_aes_256_ ## mode(); \
+ default: return 0; \
+ } \
+ }
+make_aes_dispatcher(ecb)
+make_aes_dispatcher(cbc)
#ifdef HAVE_EncryptAes128Ctr
make_aes_dispatcher(ctr)
-
-/*
- special simplified implementation for CTR, because it's a stream cipher
- (doesn't need padding, always encrypts the specified number of bytes), and
- because encrypting and decrypting code is exactly the same (courtesy of XOR)
-*/
-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)
-{
- CipherMode cipher= aes_ctr(key_length);
- struct MyCTX ctx;
- int fin __attribute__((unused));
-
- if (unlikely(!cipher))
- return MY_AES_BAD_KEYSIZE;
-
- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, CRYPT_ENCRYPT))
- return MY_AES_OPENSSL_ERROR;
-
- DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)key_length);
- DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) <= (int)iv_length);
- DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == 1);
-
- if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length))
- return MY_AES_OPENSSL_ERROR;
-
- DBUG_ASSERT(EVP_CipherFinal_ex(&ctx, dest + *dest_length, &fin));
- DBUG_ASSERT(fin == 0);
-
- return MY_AES_OK;
-}
-
#endif /* HAVE_EncryptAes128Ctr */
-
#ifdef HAVE_EncryptAes128Gcm
make_aes_dispatcher(gcm)
@@ -218,145 +134,146 @@ make_aes_dispatcher(gcm)
- IV tail (over 12 bytes) goes to AAD
- the tag is appended to the ciphertext
*/
-int do_gcm(const uchar* source, uint source_length,
- uchar* dest, uint* dest_length,
- const uchar* key, uint key_length,
- const uchar* iv, uint iv_length, Dir dir)
-{
- CipherMode cipher= aes_gcm(key_length);
- struct MyCTX ctx;
- int fin;
- uint real_iv_length;
-
- if (unlikely(!cipher))
- return MY_AES_BAD_KEYSIZE;
-
- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, dir))
- return MY_AES_OPENSSL_ERROR;
- real_iv_length= EVP_CIPHER_CTX_iv_length(&ctx);
-
- DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)key_length);
- DBUG_ASSERT(real_iv_length <= iv_length);
- DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == 1);
-
- if (dir == CRYPT_DECRYPT)
+class MyCTX_gcm : public MyCTX
+{
+public:
+ const uchar *aad;
+ int aadlen;
+ MyCTX_gcm() : MyCTX() { }
+ ~MyCTX_gcm() { }
+
+ int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, uint klen,
+ const uchar *iv, uint ivlen)
{
- source_length-= MY_AES_BLOCK_SIZE;
- if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE,
- (void*)(source + source_length)))
- return MY_AES_OPENSSL_ERROR;
+ compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_gcm));
+ int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen);
+ int real_ivlen= EVP_CIPHER_CTX_iv_length(&ctx);
+ aad= iv + real_ivlen;
+ aadlen= ivlen - real_ivlen;
+ return res;
}
- if (real_iv_length < iv_length)
+ int update(const uchar *src, uint slen, uchar *dst, uint *dlen)
{
- if (!EVP_CipherUpdate(&ctx, NULL, &fin,
- iv + real_iv_length, iv_length - real_iv_length))
+ /*
+ note that this GCM class cannot do streaming decryption, because
+ it needs the tag (which is located at the end of encrypted data)
+ before decrypting the data. it can encrypt data piecewise, like, first
+ half, then the second half, but it must decrypt all at once
+ */
+ if (!ctx.encrypt)
+ {
+ slen-= MY_AES_BLOCK_SIZE;
+ if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE,
+ (void*)(src + slen)))
+ return MY_AES_OPENSSL_ERROR;
+ }
+ int unused;
+ if (aadlen && !EVP_CipherUpdate(&ctx, NULL, &unused, aad, aadlen))
return MY_AES_OPENSSL_ERROR;
+ aadlen= 0;
+ return MyCTX::update(src, slen, dst, dlen);
}
- if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length))
- return MY_AES_OPENSSL_ERROR;
-
- if (!EVP_CipherFinal_ex(&ctx, dest + *dest_length, &fin))
- return MY_AES_BAD_DATA;
- DBUG_ASSERT(fin == 0);
-
- if (dir == CRYPT_ENCRYPT)
+ int finish(uchar *dst, uint *dlen)
{
- if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE,
- dest + *dest_length))
- return MY_AES_OPENSSL_ERROR;
- *dest_length+= MY_AES_BLOCK_SIZE;
- }
-
- return MY_AES_OK;
-}
+ int fin;
+ if (!EVP_CipherFinal_ex(&ctx, dst, &fin))
+ return MY_AES_BAD_DATA;
+ DBUG_ASSERT(fin == 0);
-int my_aes_encrypt_gcm(const uchar* source, uint source_length,
- uchar* dest, uint* dest_length,
- const uchar* key, uint key_length,
- const uchar* iv, uint iv_length)
-{
- return do_gcm(source, source_length, dest, dest_length,
- key, key_length, iv, iv_length, CRYPT_ENCRYPT);
-}
+ if (ctx.encrypt)
+ {
+ if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE, dst))
+ return MY_AES_OPENSSL_ERROR;
+ *dlen= MY_AES_BLOCK_SIZE;
+ }
+ else
+ *dlen= 0;
+ return MY_AES_OK;
+ }
+};
-int my_aes_decrypt_gcm(const uchar* source, uint source_length,
- uchar* dest, uint* dest_length,
- const uchar* key, uint key_length,
- const uchar* iv, uint iv_length)
-{
- return do_gcm(source, source_length, dest, dest_length,
- key, key_length, iv, iv_length, CRYPT_DECRYPT);
-}
+#endif
+const EVP_CIPHER *(*ciphers[])(uint)= {
+ aes_ecb, aes_cbc
+#ifdef HAVE_EncryptAes128Ctr
+ , aes_ctr
+#ifdef HAVE_EncryptAes128Gcm
+ , aes_gcm
+#endif
#endif
+};
+
+extern "C" {
-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_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)
{
- return block_crypt(aes_ecb(key_length), CRYPT_ENCRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, no_padding);
+#ifdef HAVE_EncryptAes128Ctr
+#ifdef HAVE_EncryptAes128Gcm
+ if (mode == MY_AES_GCM)
+ if (flags & ENCRYPTION_FLAG_NOPAD)
+ return MY_AES_OPENSSL_ERROR;
+ else
+ new (ctx) MyCTX_gcm();
+ else
+#endif
+ if (mode == MY_AES_CTR)
+ new (ctx) MyCTX();
+ else
+#endif
+ if (flags & ENCRYPTION_FLAG_NOPAD)
+ new (ctx) MyCTX_nopad();
+ else
+ new (ctx) MyCTX();
+ return ((MyCTX*)ctx)->init(ciphers[mode](klen), flags & 1,
+ key, klen, iv, ivlen);
}
-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_aes_crypt_update(void *ctx, const uchar *src, uint slen,
+ uchar *dst, uint *dlen)
{
- return block_crypt(aes_ecb(key_length), CRYPT_DECRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, no_padding);
+ return ((MyCTX*)ctx)->update(src, slen, dst, dlen);
}
-int my_aes_encrypt_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_crypt_finish(void *ctx, uchar *dst, uint *dlen)
{
- return block_crypt(aes_cbc(key_length), CRYPT_ENCRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, no_padding);
+ int res= ((MyCTX*)ctx)->finish(dst, dlen);
+ ((MyCTX*)ctx)->~MyCTX();
+ return res;
}
-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_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)
{
- return block_crypt(aes_cbc(key_length), CRYPT_DECRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, no_padding);
+ void *ctx= alloca(MY_AES_CTX_SIZE);
+ int res1, res2;
+ uint d1, d2;
+ if ((res1= my_aes_crypt_init(ctx, mode, flags, key, klen, iv, ivlen)))
+ return res1;
+ res1= my_aes_crypt_update(ctx, src, slen, dst, &d1);
+ res2= my_aes_crypt_finish(ctx, dst + d1, &d2);
+ *dlen= d1 + d2;
+ return res1 ? res1 : res2;
}
-C_MODE_END
-
-#if defined(HAVE_YASSL)
-
+#ifdef HAVE_YASSL
#include <random.hpp>
-
-C_MODE_START
-
int my_random_bytes(uchar* buf, int num)
{
TaoCrypt::RandomNumberGenerator rand;
rand.GenerateBlock((TaoCrypt::byte*) buf, num);
return MY_AES_OK;
}
-
-C_MODE_END
-
-#else /* OpenSSL */
-
+#else
#include <openssl/rand.h>
-C_MODE_START
-
-int my_random_bytes(uchar* buf, int num)
+int my_random_bytes(uchar *buf, int num)
{
/*
Unfortunately RAND_bytes manual page does not provide any guarantees
@@ -364,30 +281,12 @@ int my_random_bytes(uchar* buf, int num)
instead of whatever random engine is currently set in OpenSSL. That way
we are guaranteed to have a non-blocking random.
*/
- RAND_METHOD* rand = RAND_SSLeay();
+ RAND_METHOD *rand = RAND_SSLeay();
if (rand == NULL || rand->bytes(buf, num) != 1)
return MY_AES_OPENSSL_ERROR;
return MY_AES_OK;
}
+#endif
-C_MODE_END
-#endif /* HAVE_YASSL */
-
-/**
- Get size of buffer which will be large enough for encrypted data
-
- The buffer should be sufficiently large to fit encrypted data
- independently from the encryption algorithm and mode. With padding up to
- MY_AES_BLOCK_SIZE bytes can be added. With GCM, exactly MY_AES_BLOCK_SIZE
- bytes are added.
-
- The actual length of the encrypted data is returned from the encryption
- function (e.g. from my_aes_encrypt_cbc).
-
- @return required buffer size
-*/
-
-uint my_aes_get_size(uint source_length)
-{
- return source_length + MY_AES_BLOCK_SIZE;
}
+
diff --git a/mysys_ssl/yassl.cc b/mysys_ssl/yassl.cc
new file mode 100644
index 00000000000..9717870fe26
--- /dev/null
+++ b/mysys_ssl/yassl.cc
@@ -0,0 +1,194 @@
+/*
+ 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;
+}
+
diff --git a/plugin/debug_key_management/debug_key_management_plugin.cc b/plugin/debug_key_management/debug_key_management_plugin.cc
index 33e0c6ab318..23ff78dece2 100644
--- a/plugin/debug_key_management/debug_key_management_plugin.cc
+++ b/plugin/debug_key_management/debug_key_management_plugin.cc
@@ -74,7 +74,8 @@ struct st_mariadb_encryption debug_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_key_version,
get_key,
- 0, 0 // use default encrypt/decrypt functions
+ // use default encrypt/decrypt functions
+ 0, 0, 0, 0, 0
};
/*
diff --git a/plugin/example_key_management/example_key_management_plugin.cc b/plugin/example_key_management/example_key_management_plugin.cc
index 32fa135d33a..fb19710c0ef 100644
--- a/plugin/example_key_management/example_key_management_plugin.cc
+++ b/plugin/example_key_management/example_key_management_plugin.cc
@@ -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 different keys.
+ for different keys versions:
*/
-int 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)
+static inline enum my_aes_mode mode(unsigned int key_version)
{
- return ((key_version & 1) ? my_aes_encrypt_cbc : my_aes_encrypt_ecb)
- (src, slen, dst, dlen, key, klen, iv, ivlen, no_padding);
+ return key_version & 1 ? MY_AES_ECB : MY_AES_CBC;
}
-int decrypt(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)
+int 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)
{
- return ((key_version & 1) ? my_aes_decrypt_cbc : my_aes_decrypt_ecb)
- (src, slen, dst, dlen, key, klen, iv, ivlen, no_padding);
+ return my_aes_crypt_init(ctx, mode(key_version), 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(mode(key_version), slen);
}
static int example_key_management_plugin_init(void *p)
@@ -119,8 +117,11 @@ struct st_mariadb_encryption example_key_management_plugin= {
MariaDB_ENCRYPTION_INTERFACE_VERSION,
get_latest_key_version,
get_key,
- encrypt,
- decrypt
+ (uint (*)(unsigned int, unsigned int))my_aes_ctx_size,
+ ctx_init,
+ my_aes_crypt_update,
+ my_aes_crypt_finish,
+ get_length
};
/*
diff --git a/plugin/file_key_management/file_key_management_plugin.cc b/plugin/file_key_management/file_key_management_plugin.cc
index 53cb4069a95..970fae9c189 100644
--- a/plugin/file_key_management/file_key_management_plugin.cc
+++ b/plugin/file_key_management/file_key_management_plugin.cc
@@ -113,65 +113,59 @@ static unsigned int get_key_from_key_file(unsigned int key_id,
return 0;
}
-struct st_mariadb_encryption file_key_management_plugin= {
- MariaDB_ENCRYPTION_INTERFACE_VERSION,
- get_latest_version,
- get_key_from_key_file,
- 0,0
-};
+// let's simplify the condition below
+#ifndef HAVE_EncryptAes128Gcm
+#define MY_AES_GCM MY_AES_CTR
+#ifndef HAVE_EncryptAes128Ctr
+#define MY_AES_CTR MY_AES_CBC
+#endif
+#endif
-#ifdef HAVE_EncryptAes128Gcm
-/*
- 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)
+static inline enum my_aes_mode mode(int flags)
{
- 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,
- 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)
+static int 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)
{
- return (no_padding ? my_aes_decrypt_ctr : my_aes_decrypt_gcm)
- (src, slen, dst, dlen, key, klen, iv, ivlen);
+ return my_aes_crypt_init(ctx, mode(flags), 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(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)
{
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);
}
diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc
index 552dd7df970..9204f39326d 100644
--- a/plugin/file_key_management/parser.cc
+++ b/plugin/file_key_management/parser.cc
@@ -336,10 +336,11 @@ char* Parser::read_and_decrypt_file(const char *secret)
bytes_to_key(buffer + OpenSSL_prefix_len, secret, key, iv);
uint32 d_size;
- if (my_aes_decrypt_cbc(buffer + OpenSSL_prefix_len + OpenSSL_salt_len,
- file_size - OpenSSL_prefix_len - OpenSSL_salt_len,
- decrypted, &d_size, key, OpenSSL_key_len,
- iv, OpenSSL_iv_len, 0))
+ if (my_aes_crypt(MY_AES_CBC, ENCRYPTION_FLAG_DECRYPT,
+ buffer + OpenSSL_prefix_len + OpenSSL_salt_len,
+ file_size - OpenSSL_prefix_len - OpenSSL_salt_len,
+ 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);
diff --git a/sql/encryption.cc b/sql/encryption.cc
index 520eb8b898f..9fa000abf34 100644
--- a/sql/encryption.cc
+++ b/sql/encryption.cc
@@ -25,31 +25,23 @@ void init_io_cache_encryption();
static plugin_ref encryption_manager= 0;
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)
{
return ENCRYPTION_KEY_VERSION_INVALID;
}
-static int no_crypt(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, uint key_id, uint key_version)
+static int 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)
{
- 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)
{
@@ -67,13 +59,21 @@ int initialize_encryption_plugin(st_plugin_int *plugin)
st_mariadb_encryption *handle=
(struct st_mariadb_encryption*) plugin->plugin->info;
- encryption_handler.encryption_encrypt_func=
- handle->encrypt ? handle->encrypt
- : (encrypt_decrypt_func)my_aes_encrypt_cbc;
+ encryption_handler.encryption_ctx_size_func=
+ handle->crypt_ctx_size ? handle->crypt_ctx_size :
+ (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=
- handle->decrypt ? handle->decrypt
- : (encrypt_decrypt_func)my_aes_decrypt_cbc;
+ encryption_handler.encryption_encrypted_length_func=
+ handle->encrypted_length ? handle->encrypted_length : get_length;
encryption_handler.encryption_key_get_func=
handle->get_key;
@@ -88,10 +88,6 @@ int initialize_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=
(uint (*)(uint, uint, uchar*, uint*))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,
goto ret;
/* 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,
- global_key, global_key_len, NULL, 0, 1);
+ rc = my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
+ scheme->iv, sizeof(scheme->iv), key->key, &key_len,
+ global_key, global_key_len, NULL, 0);
DBUG_ASSERT(key_len == sizeof(key->key));
@@ -169,7 +166,7 @@ int do_crypt(const unsigned char* src, unsigned int slen,
struct st_encryption_scheme *scheme,
unsigned int key_version, unsigned int i32_1,
unsigned int i32_2, unsigned long long i64,
- encrypt_decrypt_func crypt)
+ int flag)
{
compile_time_assert(ENCRYPTION_SCHEME_KEY_INVALID ==
(int)ENCRYPTION_KEY_VERSION_INVALID);
@@ -197,8 +194,8 @@ int do_crypt(const unsigned char* src, unsigned int slen,
int4store(iv + 4, i32_2);
int8store(iv + 8, i64);
- return crypt(src, slen, dst, dlen, key.key, sizeof(key.key),
- iv, sizeof(iv), 1, scheme->key_id, key_version);
+ return encryption_crypt(src, slen, dst, dlen, key.key, sizeof(key.key),
+ iv, sizeof(iv), flag, scheme->key_id, key_version);
}
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)
{
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,
unsigned int i32_2, unsigned long long i64)
{
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);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7dfe8605b63..7f466e86afb 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -402,16 +402,16 @@ String *Item_aes_crypt::val_str(String *str)
if (sptr && user_key) // we need both arguments to be not NULL
{
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
{
uchar rkey[AES_KEY_LENGTH / 8];
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,
- rkey, AES_KEY_LENGTH / 8, 0, 0, 0))
+ rkey, AES_KEY_LENGTH / 8, 0, 0))
{
str_value.length((uint) aes_length);
return &str_value;
@@ -424,16 +424,16 @@ String *Item_aes_crypt::val_str(String *str)
void Item_func_aes_encrypt::fix_length_and_dec()
{
- max_length=my_aes_get_size(args[0]->max_length);
- crypt= my_aes_encrypt_ecb;
+ max_length=my_aes_get_size(MY_AES_ECB, args[0]->max_length);
+ what= ENCRYPTION_FLAG_ENCRYPT;
}
void Item_func_aes_decrypt::fix_length_and_dec()
{
- max_length=args[0]->max_length;
- maybe_null= 1;
- crypt= my_aes_decrypt_ecb;
+ max_length=args[0]->max_length;
+ maybe_null= 1;
+ what= ENCRYPTION_FLAG_DECRYPT;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index e7d509206f2..d1abbe198b1 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -148,10 +148,7 @@ class Item_aes_crypt :public Item_str_func
void create_key(String *user_key, uchar* key);
protected:
- int (*crypt)(const uchar* src, uint slen, uchar* dst, uint* dlen,
- const uchar* key, uint klen, const uchar* iv, uint ivlen,
- int no_padding);
-
+ int what;
public:
Item_aes_crypt(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
diff --git a/sql/mf_iocache_encr.cc b/sql/mf_iocache_encr.cc
index d215636d62a..96658e2e3d0 100644
--- a/sql/mf_iocache_encr.cc
+++ b/sql/mf_iocache_encr.cc
@@ -95,9 +95,10 @@ static int my_b_encr_read(IO_CACHE *info, uchar *Buffer, size_t Count)
elength= wlength - (ebuffer - wbuffer);
set_iv(iv, pos_in_file, crypt_data->inbuf_counter);
- if (encryption_decrypt(ebuffer, elength, info->buffer, &length,
- crypt_data->key, sizeof(crypt_data->key),
- iv, sizeof(iv), 0, keyid, keyver))
+ if (encryption_crypt(ebuffer, elength, info->buffer, &length,
+ crypt_data->key, sizeof(crypt_data->key),
+ iv, sizeof(iv), ENCRYPTION_FLAG_DECRYPT,
+ keyid, keyver))
{
my_errno= 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)
crypt_data->inbuf_counter= crypt_data->counter;
set_iv(iv, info->pos_in_file, crypt_data->inbuf_counter);
- if (encryption_encrypt(Buffer, length, ebuffer, &elength,
- crypt_data->key, sizeof(crypt_data->key),
- iv, sizeof(iv), 0, keyid, keyver))
+ if (encryption_crypt(Buffer, length, ebuffer, &elength,
+ crypt_data->key, sizeof(crypt_data->key),
+ iv, sizeof(iv), ENCRYPTION_FLAG_ENCRYPT,
+ keyid, keyver))
{
my_errno= 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)
buffer_length bytes should *always* produce block_length bytes
*/
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;
}
else
diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc
index 6d0a2d6a1f8..8c4fd623fc6 100644
--- a/storage/innobase/log/log0crypt.cc
+++ b/storage/innobase/log/log0crypt.cc
@@ -131,15 +131,16 @@ log_blocks_crypt(
const byte* block, /*!< in: blocks before encrypt/decrypt*/
ulint size, /*!< in: size of block */
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;
Crypt_result rc = MY_AES_OK;
uint dst_len;
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;
- 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) {
ulint log_block_no = log_block_get_hdr_no(log_block);
lsn_t log_block_start_lsn = log_block_get_start_lsn(
@@ -174,21 +175,13 @@ log_blocks_crypt(
bzero(aes_ctr_counter + 15, 1);
int rc;
- if (is_encrypt) {
- rc = encryption_encrypt(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);
- } 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);
- }
+ rc = encryption_crypt(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,
+ what | ENCRYPTION_FLAG_NOPAD,
+ LOG_DEFAULT_ENCRYPTION_KEY,
+ info->key_version);
ut_a(rc == MY_AES_OK);
ut_a(dst_len == src_len);
@@ -230,10 +223,11 @@ init_crypt_key(
}
uint dst_len;
- int rc= my_aes_encrypt_ecb(info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
- info->crypt_key, &dst_len, //dst, &dstlen
- (unsigned char*)&mysqld_key, sizeof(mysqld_key),
- NULL, 0, 1);
+ int rc= my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_NOPAD|ENCRYPTION_FLAG_ENCRYPT,
+ info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
+ info->crypt_key, &dst_len, //dst, &dstlen
+ (unsigned char*)&mysqld_key, sizeof(mysqld_key),
+ NULL, 0);
if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
fprintf(stderr,
@@ -296,7 +290,7 @@ log_blocks_encrypt(
const ulint size, /*!< in: size of blocks, must be multiple of a log block */
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(
byte* dst_frame = (byte*)malloc(size);
//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) {
ut_ad(block[0] == dst_frame[0]);
@@ -392,7 +386,7 @@ log_decrypt_after_read(
byte* dst_frame = (byte*)malloc(size);
// 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) {
memcpy(frame, dst_frame, size);
diff --git a/storage/maria/ma_check_standalone.h b/storage/maria/ma_check_standalone.h
index c240ca056e7..6626a62c4ef 100644
--- a/storage/maria/ma_check_standalone.h
+++ b/storage/maria/ma_check_standalone.h
@@ -30,7 +30,7 @@ static unsigned int no_key()
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)),
diff --git a/storage/xtradb/log/log0crypt.cc b/storage/xtradb/log/log0crypt.cc
index 38b82d6ceb4..8c4fd623fc6 100644
--- a/storage/xtradb/log/log0crypt.cc
+++ b/storage/xtradb/log/log0crypt.cc
@@ -131,12 +131,13 @@ log_blocks_crypt(
const byte* block, /*!< in: blocks before encrypt/decrypt*/
ulint size, /*!< in: size of block */
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;
Crypt_result rc = MY_AES_OK;
uint dst_len;
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;
const uint src_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE;
@@ -174,21 +175,13 @@ log_blocks_crypt(
bzero(aes_ctr_counter + 15, 1);
int rc;
- if (is_encrypt) {
- rc = encryption_encrypt(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);
- } 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);
- }
+ rc = encryption_crypt(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,
+ what | ENCRYPTION_FLAG_NOPAD,
+ LOG_DEFAULT_ENCRYPTION_KEY,
+ info->key_version);
ut_a(rc == MY_AES_OK);
ut_a(dst_len == src_len);
@@ -230,10 +223,11 @@ init_crypt_key(
}
uint dst_len;
- int rc= my_aes_encrypt_ecb(info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
- info->crypt_key, &dst_len, //dst, &dstlen
- (unsigned char*)&mysqld_key, sizeof(mysqld_key),
- NULL, 0, 1);
+ int rc= my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_NOPAD|ENCRYPTION_FLAG_ENCRYPT,
+ info->crypt_msg, sizeof(info->crypt_msg), //src, srclen
+ info->crypt_key, &dst_len, //dst, &dstlen
+ (unsigned char*)&mysqld_key, sizeof(mysqld_key),
+ NULL, 0);
if (rc != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
fprintf(stderr,
@@ -296,7 +290,7 @@ log_blocks_encrypt(
const ulint size, /*!< in: size of blocks, must be multiple of a log block */
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(
byte* dst_frame = (byte*)malloc(size);
//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) {
ut_ad(block[0] == dst_frame[0]);
@@ -392,7 +386,7 @@ log_decrypt_after_read(
byte* dst_frame = (byte*)malloc(size);
// 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) {
memcpy(frame, dst_frame, size);
diff --git a/unittest/mysys/aes-t.c b/unittest/mysys/aes-t.c
index 124cc472259..2d65b434cc3 100644
--- a/unittest/mysys/aes-t.c
+++ b/unittest/mysys/aes-t.c
@@ -21,54 +21,27 @@
#include <string.h>
#include <ctype.h>
-#define DO_TEST_P(mode, slen, fill, dlen, hash) \
- do { \
+#define DO_TEST(mode, nopad, slen, fill, dlen, hash) \
+ SKIP_BLOCK_IF(mode == 0xDEADBEAF, nopad ? 4 : 5, #mode " not supported") \
+ { \
memset(src, fill, src_len= slen); \
- ok(my_aes_encrypt_ ## mode(src, src_len, dst, &dst_len, \
- key, sizeof(key), iv, sizeof(iv), 0) == MY_AES_OK, \
- "encrypt " #mode " %u", src_len); \
- ok(dst_len <= my_aes_get_size(src_len), \
- "my_aes_get_size(%u) >= %u", src_len, dst_len); \
+ ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_ENCRYPT, \
+ src, src_len, dst, &dst_len, \
+ key, sizeof(key), iv, sizeof(iv)) == MY_AES_OK, \
+ "encrypt " #mode " %u %s", src_len, nopad ? "nopad" : "pad"); \
+ if (!nopad) \
+ ok (dst_len == my_aes_get_size(mode, src_len), "my_aes_get_size");\
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), 0) == MY_AES_OK, \
+ ok(my_aes_crypt(mode, nopad | ENCRYPTION_FLAG_DECRYPT, \
+ 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)
+ }
-#define DO_TEST_N(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), 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
+#define DO_TEST_P(M,S,F,D,H) DO_TEST(M,0,S,F,D,H)
+#define DO_TEST_N(M,S,F,D,H) DO_TEST(M,ENCRYPTION_FLAG_NOPAD,S,F,D,H)
/* useful macro for debugging */
#define PRINT_MD5() \
@@ -80,6 +53,12 @@
printf("\"\n"); \
} while(0);
+#ifndef HAVE_EncryptAes128Ctr
+const uint MY_AES_CTR=0xDEADBEAF;
+#endif
+#ifndef HAVE_EncryptAes128Gcm
+const uint MY_AES_GCM=0xDEADBEAF;
+#endif
int
main(int argc __attribute__((unused)),char *argv[])
@@ -92,28 +71,28 @@ main(int argc __attribute__((unused)),char *argv[])
MY_INIT(argv[0]);
- plan(84);
- 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(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(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(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(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_X(gcm, 128, '?', 144, "\x54\x6a\x7c\xa2\x04\xdc\x6e\x80\x1c\xcd\x5f\x7a\x7b\x08\x9e\x9d");
+ plan(87);
+ 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(MY_AES_ECB, 128, '?', 144, "\x19\x58\x33\x85\x4c\xaa\x7f\x06\xd1\xb2\xec\xd7\xb7\x6a\xa9\x5b");
+ 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(MY_AES_CBC, 192, '@', 208, "\x54\xc4\x75\x1d\xff\xe0\xf6\x80\xf0\x85\xbb\x8b\xda\x07\x21\x17");
+ 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(MY_AES_ECB, 128, '?', 128, "\x5b\x44\x20\xf3\xd9\xb4\x9d\x74\x5e\xb7\x5a\x0a\xe7\x32\x35\xc3");
+ 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(MY_AES_CBC, 192, '@', 192, "\x30\xe5\x28\x8c\x4a\x3b\x02\xd7\x56\x40\x59\x25\xac\x58\x09\x22");
+ 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_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) */
- 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(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(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(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(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_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, 2, '?', 16, "\xdb\x84\x9e\xaf\x5f\xcc\xdb\x6b\xf2\x1c\xeb\x53\x75\xa3\x53\x5e");
+ 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(MY_AES_CBC, 4, '@', 16, "\x90\xc2\x6b\xf8\x84\x79\x83\xbd\xc1\x60\x71\x04\x55\x6a\xce\x9e");
+ 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(MY_AES_ECB, 6, '?', 6, "\x35\x8f\xb7\x9d\xd9\x61\x21\xcf\x25\x66\xd5\x9e\x91\xc1\x42\x7e");
+ 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(MY_AES_CBC, 8, '@', 8, "\xb8\x53\x97\xb9\x40\xa6\x98\xaf\x0c\x7b\x9a\xac\xad\x7e\x3c\xe0");
+ 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);
return exit_status();
diff --git a/unittest/sql/mf_iocache-t.cc b/unittest/sql/mf_iocache-t.cc
index eb503d2f8de..c89f8a9f038 100644
--- a/unittest/sql/mf_iocache-t.cc
+++ b/unittest/sql/mf_iocache-t.cc
@@ -49,19 +49,34 @@ uint encryption_key_get_func(uint, uint, uchar* key, uint* size)
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=
{
encryption_key_get_latest_version_func,
- encryption_key_id_exists_func,
- encryption_key_version_exists_func,
encryption_key_get_func,
-#ifdef HAVE_EncryptAes128Gcm
- (encrypt_decrypt_func)my_aes_encrypt_gcm,
- (encrypt_decrypt_func)my_aes_decrypt_gcm
-#else
- (encrypt_decrypt_func)my_aes_encrypt_cbc,
- (encrypt_decrypt_func)my_aes_decrypt_cbc
-#endif
+ (uint (*)(unsigned int, unsigned int))my_aes_ctx_size,
+ encryption_ctx_init_func,
+ my_aes_crypt_update,
+ my_aes_crypt_finish,
+ encryption_encrypted_length_func
};
void sql_print_information(const char *format, ...)