summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_crypt.h8
-rw-r--r--include/mysql/plugin.h2
-rw-r--r--include/mysql/plugin_audit.h.pp37
-rw-r--r--include/mysql/plugin_auth.h.pp37
-rw-r--r--include/mysql/plugin_encryption.h.pp37
-rw-r--r--include/mysql/plugin_ftparser.h.pp37
-rw-r--r--include/mysql/plugin_password_validation.h.pp37
-rw-r--r--include/mysql/service_encryption_scheme.h133
-rw-r--r--include/mysql/services.h1
-rw-r--r--include/service_versions.h1
-rw-r--r--libservices/CMakeLists.txt1
-rw-r--r--libservices/encryption_scheme_service.c17
-rw-r--r--mysql-test/r/handlersocket.result2
-rw-r--r--mysql-test/r/plugin.result6
-rw-r--r--mysql-test/suite/plugins/r/show_all_plugins.result4
-rw-r--r--mysql-test/suite/plugins/r/simple_password_check.result2
-rw-r--r--sql/encryption.cc107
-rw-r--r--sql/sql_plugin_services.h7
-rw-r--r--storage/innobase/fil/fil0crypt.cc164
-rw-r--r--storage/innobase/handler/ha_innodb.cc3
-rw-r--r--storage/innobase/include/fil0crypt.h10
-rw-r--r--storage/maria/ma_check_standalone.h27
-rw-r--r--storage/maria/ma_crypt.c221
-rw-r--r--storage/xtradb/fil/fil0crypt.cc164
-rw-r--r--storage/xtradb/handler/ha_innodb.cc3
-rw-r--r--storage/xtradb/include/fil0crypt.h10
26 files changed, 612 insertions, 466 deletions
diff --git a/include/my_crypt.h b/include/my_crypt.h
index bfde4d3c0f7..655d1641136 100644
--- a/include/my_crypt.h
+++ b/include/my_crypt.h
@@ -25,10 +25,10 @@ extern "C" {
#endif
/* return values from my_aes_encrypt/my_aes_decrypt functions */
-#define MY_AES_OK 0
-#define MY_AES_BAD_DATA -1
-#define MY_AES_OPENSSL_ERROR -2
-#define MY_AES_BAD_KEYSIZE -3
+#define MY_AES_OK 0
+#define MY_AES_BAD_DATA -100
+#define MY_AES_OPENSSL_ERROR -101
+#define MY_AES_BAD_KEYSIZE -102
/* The block size for all supported algorithms */
#define MY_AES_BLOCK_SIZE 16
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index 09026514a88..cfa4b13a7ef 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -75,7 +75,7 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
/* MariaDB plugin interface version */
-#define MARIA_PLUGIN_INTERFACE_VERSION 0x010a
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x010b
/*
The allowable types of plugins
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 7346c4f29b0..669be094542 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -213,6 +213,43 @@ struct encryption_service_st {
encrypt_decrypt_func encryption_decrypt_func;
};
extern struct encryption_service_st encryption_handler;
+#include <mysql/service_encryption_scheme.h>
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[16];
+};
+struct st_encryption_scheme {
+ unsigned char iv[16];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
struct st_mysql_xid {
long formatID;
long gtrid_length;
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index 1df73b0a41e..1b795079c22 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -213,6 +213,43 @@ struct encryption_service_st {
encrypt_decrypt_func encryption_decrypt_func;
};
extern struct encryption_service_st encryption_handler;
+#include <mysql/service_encryption_scheme.h>
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[16];
+};
+struct st_encryption_scheme {
+ unsigned char iv[16];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
struct st_mysql_xid {
long formatID;
long gtrid_length;
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index 2cf344864e4..56cad7ab716 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -213,6 +213,43 @@ struct encryption_service_st {
encrypt_decrypt_func encryption_decrypt_func;
};
extern struct encryption_service_st encryption_handler;
+#include <mysql/service_encryption_scheme.h>
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[16];
+};
+struct st_encryption_scheme {
+ unsigned char iv[16];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
struct st_mysql_xid {
long formatID;
long gtrid_length;
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index ee8ebc4299c..3c07800a656 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -213,6 +213,43 @@ struct encryption_service_st {
encrypt_decrypt_func encryption_decrypt_func;
};
extern struct encryption_service_st encryption_handler;
+#include <mysql/service_encryption_scheme.h>
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[16];
+};
+struct st_encryption_scheme {
+ unsigned char iv[16];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
struct st_mysql_xid {
long formatID;
long gtrid_length;
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index e7dcc44f07a..6b8a886dc25 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -213,6 +213,43 @@ struct encryption_service_st {
encrypt_decrypt_func encryption_decrypt_func;
};
extern struct encryption_service_st encryption_handler;
+#include <mysql/service_encryption_scheme.h>
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[16];
+};
+struct st_encryption_scheme {
+ unsigned char iv[16];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
struct st_mysql_xid {
long formatID;
long gtrid_length;
diff --git a/include/mysql/service_encryption_scheme.h b/include/mysql/service_encryption_scheme.h
new file mode 100644
index 00000000000..195c7aa4a5c
--- /dev/null
+++ b/include/mysql/service_encryption_scheme.h
@@ -0,0 +1,133 @@
+#ifndef MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED
+/* Copyright (c) 2015, MariaDB
+
+ 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 */
+
+/**
+ @file
+ encryption scheme service
+
+ A higher-level access to encryption service.
+
+ This is a helper service that storage engines use to encrypt tables on disk.
+ It requests keys from the plugin, generates temporary or local keys
+ from the global (as returned by the plugin) keys, etc.
+
+ To use the service:
+
+ * st_encryption_scheme object is created per space. A "space" can be
+ a table space in XtraDB/InnoDB, a file in Aria, etc. The whole
+ space is encrypted with the one key id.
+
+ * The service does not take the key and the IV as parameters for
+ encryption or decryption. Instead it takes two 32-bit integers and
+ one 64-bit integer (and requests the key from an encryption
+ plugin, if needed).
+
+ * The service requests the global key from the encryption plugin
+ automatically as needed. Three last keys are cached in the
+ st_encryption_scheme. Number of key requests (number of cache
+ misses) are counted in st_encryption_scheme::keyserver_requests
+
+ * If an st_encryption_scheme can be used concurrently by different
+ threads, it needs to be able to lock itself when accessing the key
+ cache. Set the st_encryption_scheme::locker appropriately. If
+ non-zero, it will be invoked by encrypt/decrypt functions to lock
+ and unlock the scheme when needed.
+
+ * Implementation details (in particular, key derivation) are defined
+ by the scheme type. Currently only schema type 1 is supported.
+
+ In the schema type 1, every "space" (table space in XtraDB/InnoDB,
+ file in Aria) is encrypted with a different space-local key:
+
+ * Every space has a 16-byte unique identifier (typically it's
+ generated randomly and stored in the space). The caller should
+ put it into st_encryption_scheme::iv.
+
+ * Space-local key is generated by encrypting this identifier with
+ the global encryption key (of the given id and version) using AES_ECB.
+
+ * Encryption/decryption parameters for a page are typically the
+ 4-byte space id, 4-byte page position (offset, page number, etc),
+ and the 8-byte LSN. This guarantees that they'll be different for
+ any two pages (of the same or different tablespaces) and also that
+ they'll change for the same page when it's modified. They don't need
+ to be secret (they create the IV, not the encryption key).
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ENCRYPTION_SCHEME_KEY_INVALID -1
+#define ENCRYPTION_SCHEME_BLOCK_LENGTH 16
+
+struct st_encryption_scheme_key {
+ unsigned int version;
+ unsigned char key[ENCRYPTION_SCHEME_BLOCK_LENGTH];
+};
+
+struct st_encryption_scheme {
+ unsigned char iv[ENCRYPTION_SCHEME_BLOCK_LENGTH];
+ struct st_encryption_scheme_key key[3];
+ unsigned int keyserver_requests;
+ unsigned int key_id;
+ unsigned int type;
+
+ void (*locker)(struct st_encryption_scheme *self, int release);
+};
+
+extern struct encryption_scheme_service_st {
+ int (*encryption_scheme_encrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+ int (*encryption_scheme_decrypt_func)
+ (const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+} *encryption_scheme_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define encryption_scheme_encrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_encrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64)
+#define encryption_scheme_decrypt(S,SL,D,DL,SCH,KV,I32,J32,I64) encryption_scheme_service->encryption_scheme_decrypt_func(S,SL,D,DL,SCH,KV,I32,J32,I64)
+
+#else
+
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ unsigned int i32_2, unsigned long long i64);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MYSQL_SERVICE_ENCRYPTION_SCHEME_INCLUDED
+#endif
diff --git a/include/mysql/services.h b/include/mysql/services.h
index f8f41b19bd9..9d031a9b094 100644
--- a/include/mysql/services.h
+++ b/include/mysql/services.h
@@ -33,6 +33,7 @@ extern "C" {
#include <mysql/service_thd_error_context.h>
#include <mysql/service_thd_specifics.h>
#include <mysql/service_encryption.h>
+#include <mysql/service_encryption_scheme.h>
/*#include <mysql/service_wsrep.h>*/
#ifdef __cplusplus
diff --git a/include/service_versions.h b/include/service_versions.h
index 0f3d8af5723..79b36092a0d 100644
--- a/include/service_versions.h
+++ b/include/service_versions.h
@@ -36,4 +36,5 @@
#define VERSION_thd_error_context 0x0100
#define VERSION_thd_specifics 0x0100
#define VERSION_encryption 0x0200
+#define VERSION_encryption_scheme 0x0100
diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt
index 1dc472612e6..62181a00aa2 100644
--- a/libservices/CMakeLists.txt
+++ b/libservices/CMakeLists.txt
@@ -29,6 +29,7 @@ SET(MYSQLSERVICES_SOURCES
my_md5_service.c
wsrep_service.c
encryption_service.c
+ encryption_scheme_service.c
kill_statement_service.c
logger_service.c)
diff --git a/libservices/encryption_scheme_service.c b/libservices/encryption_scheme_service.c
new file mode 100644
index 00000000000..87d85df16b4
--- /dev/null
+++ b/libservices/encryption_scheme_service.c
@@ -0,0 +1,17 @@
+/* Copyright (c) 2015 MariaDB
+
+ 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 */
+
+#include <service_versions.h>
+SERVICE_VERSION encryption_scheme_service= (void*)VERSION_encryption_scheme;
diff --git a/mysql-test/r/handlersocket.result b/mysql-test/r/handlersocket.result
index 2332a8b2c7f..e38de6bf5c2 100644
--- a/mysql-test/r/handlersocket.result
+++ b/mysql-test/r/handlersocket.result
@@ -5,7 +5,7 @@ plugin_version 1.0
plugin_status ACTIVE
plugin_type DAEMON
plugin_library handlersocket.so
-plugin_library_version 1.10
+plugin_library_version 1.11
plugin_author higuchi dot akira at dena dot jp
plugin_description Direct access into InnoDB
plugin_license BSD
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index 9f4aff6bae9..42a29f25432 100644
--- a/mysql-test/r/plugin.result
+++ b/mysql-test/r/plugin.result
@@ -15,7 +15,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE STORAGE ENGINE
PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so
-PLUGIN_LIBRARY_VERSION 1.10
+PLUGIN_LIBRARY_VERSION 1.11
PLUGIN_AUTHOR Brian Aker, MySQL AB
PLUGIN_DESCRIPTION Example storage engine
PLUGIN_LICENSE GPL
@@ -28,7 +28,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE DAEMON
PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so
-PLUGIN_LIBRARY_VERSION 1.10
+PLUGIN_LIBRARY_VERSION 1.11
PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Unusable Daemon
PLUGIN_LICENSE GPL
@@ -67,7 +67,7 @@ PLUGIN_STATUS DELETED
PLUGIN_TYPE STORAGE ENGINE
PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so
-PLUGIN_LIBRARY_VERSION 1.10
+PLUGIN_LIBRARY_VERSION 1.11
PLUGIN_AUTHOR Brian Aker, MySQL AB
PLUGIN_DESCRIPTION Example storage engine
PLUGIN_LICENSE GPL
diff --git a/mysql-test/suite/plugins/r/show_all_plugins.result b/mysql-test/suite/plugins/r/show_all_plugins.result
index f07bafe3536..623e8e9314b 100644
--- a/mysql-test/suite/plugins/r/show_all_plugins.result
+++ b/mysql-test/suite/plugins/r/show_all_plugins.result
@@ -4,8 +4,8 @@ Variable_name Value
Opened_plugin_libraries 0
select * from information_schema.all_plugins where plugin_library='ha_example.so';
PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE LOAD_OPTION PLUGIN_MATURITY PLUGIN_AUTH_VERSION
-EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.10 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1
-UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.10 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926
+EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.11 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1
+UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.11 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926
show status like '%libraries%';
Variable_name Value
Opened_plugin_libraries 1
diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result
index b6906fc923a..c74471a651a 100644
--- a/mysql-test/suite/plugins/r/simple_password_check.result
+++ b/mysql-test/suite/plugins/r/simple_password_check.result
@@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE PASSWORD VALIDATION
PLUGIN_TYPE_VERSION 1.0
PLUGIN_LIBRARY simple_password_check.so
-PLUGIN_LIBRARY_VERSION 1.10
+PLUGIN_LIBRARY_VERSION 1.11
PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Simple password strength checks
PLUGIN_LICENSE GPL
diff --git a/sql/encryption.cc b/sql/encryption.cc
index 44208baf8b3..ab551e00d07 100644
--- a/sql/encryption.cc
+++ b/sql/encryption.cc
@@ -103,3 +103,110 @@ int finalize_encryption_plugin(st_plugin_int *plugin)
return 0;
}
+/******************************************************************
+ Encryption Scheme service
+******************************************************************/
+static uint scheme_get_key(st_encryption_scheme *scheme,
+ st_encryption_scheme_key *key)
+{
+ if (scheme->locker)
+ scheme->locker(scheme, 0);
+
+ // Check if we already have key
+ for (uint i = 0; i < array_elements(scheme->key); i++)
+ {
+ if (scheme->key[i].version == 0) // no more keys
+ break;
+
+ if (scheme->key[i].version == key->version)
+ {
+ *key= scheme->key[i];
+ if (scheme->locker)
+ scheme->locker(scheme, 1);
+ return 0;
+ }
+ }
+
+ // Not found!
+ scheme->keyserver_requests++;
+
+ uchar global_key[MY_AES_MAX_KEY_LENGTH];
+ uint global_key_len= sizeof(global_key), key_len;
+
+ uint rc = encryption_key_get(scheme->key_id, key->version,
+ global_key, & global_key_len);
+ if (rc)
+ 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);
+
+ DBUG_ASSERT(key_len == sizeof(key->key));
+
+ if (rc)
+ goto ret;
+
+ // Rotate keys to make room for a new
+ for (uint i = array_elements(scheme->key) - 1; i; i--)
+ scheme->key[i] = scheme->key[i - 1];
+
+ scheme->key[0]= *key;
+
+ret:
+ if (scheme->locker)
+ scheme->locker(scheme, 1);
+ return rc;
+}
+
+int do_crypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ 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)
+{
+ compile_time_assert(ENCRYPTION_SCHEME_KEY_INVALID ==
+ (int)ENCRYPTION_KEY_VERSION_INVALID);
+
+ DBUG_ASSERT(scheme->type == 1);
+
+ if (key_version == ENCRYPTION_KEY_VERSION_INVALID ||
+ key_version == ENCRYPTION_KEY_NOT_ENCRYPTED)
+ return ENCRYPTION_SCHEME_KEY_INVALID;
+
+ st_encryption_scheme_key key;
+ key.version= key_version;
+ uint rc= scheme_get_key(scheme, &key);
+ if (rc)
+ return (int)rc;
+
+ unsigned char iv[4 + 4 + 8];
+ int4store(iv + 0, i32_1);
+ 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);
+}
+
+int encryption_scheme_encrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ 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);
+}
+
+
+int encryption_scheme_decrypt(const unsigned char* src, unsigned int slen,
+ unsigned char* dst, unsigned int* dlen,
+ struct st_encryption_scheme *scheme,
+ unsigned int key_version, unsigned int i32_1,
+ 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);
+}
diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h
index b848dfb8f6b..4bb1861281e 100644
--- a/sql/sql_plugin_services.h
+++ b/sql/sql_plugin_services.h
@@ -147,6 +147,12 @@ static struct thd_specifics_service_st thd_specifics_handler=
thd_setspecific
};
+static struct encryption_scheme_service_st encryption_scheme_handler=
+{
+ encryption_scheme_encrypt,
+ encryption_scheme_decrypt
+};
+
static struct st_service_ref list_of_services[]=
{
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
@@ -162,6 +168,7 @@ static struct st_service_ref list_of_services[]=
{ "thd_autoinc_service", VERSION_thd_autoinc, &thd_autoinc_handler },
{ "wsrep_service", VERSION_wsrep, &wsrep_handler },
{ "encryption_service", VERSION_encryption, &encryption_handler },
+ { "encryption_scheme_service", VERSION_encryption_scheme, &encryption_scheme_handler },
{ "thd_specifics_service", VERSION_thd_specifics, &thd_specifics_handler },
{ "thd_error_context_service", VERSION_thd_error_context, &thd_error_conext_handler },
};
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 513bdf594e9..7d7755efdf9 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -150,82 +150,6 @@ fil_space_crypt_cleanup()
}
/******************************************************************
-Get key bytes for a space/key-version */
-static
-void
-fil_crypt_get_key(
-/*==============*/
- byte* dst, /*<! out: Key */
- uint* key_length, /*<! out: Key length */
- fil_space_crypt_t* crypt_data, /*<! in: crypt data */
- uint version) /*<! in: Key version */
-{
- unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
-
- mutex_enter(&crypt_data->mutex);
-
- // Check if we already have key
- for (uint i = 0; i < crypt_data->key_count; i++) {
- if (crypt_data->keys[i].key_version == version) {
- memcpy(dst, crypt_data->keys[i].key,
- crypt_data->keys[i].key_length);
- *key_length = crypt_data->keys[i].key_length;
- mutex_exit(&crypt_data->mutex);
- return;
- }
- }
-
- // Not found!
- crypt_data->keyserver_requests++;
-
- // Rotate keys to make room for a new
- for (uint i = 1; i < array_elements(crypt_data->keys); i++) {
- crypt_data->keys[i] = crypt_data->keys[i - 1];
- }
-
- *key_length = sizeof(keybuf);
- uint rc = encryption_key_get(crypt_data->key_id, version, keybuf, key_length);
- if (rc) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Key id %u version %u can not be found. Reason=%u",
- crypt_data->key_id, version, rc);
- ut_error;
- }
-
- /* Now compute L by encrypting IV using this key. Note
- that we use random IV from crypt data. */
- const unsigned char* src = crypt_data->iv;
- const int srclen = crypt_data->iv_length;
- unsigned char* buf = crypt_data->keys[0].key;
- uint32 buflen = CRYPT_SCHEME_1_IV_LEN;
-
- /* We use AES_ECB to encrypt IV */
- rc = my_aes_encrypt_ecb(src, srclen, buf, &buflen,
- keybuf, *key_length, NULL, 0, 1);
-
- if (rc != MY_AES_OK) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Unable to encrypt key-block "
- " src: %p srclen: %d buf: %p buflen: %d."
- " return-code: %d. Can't continue!\n",
- src, srclen, buf, buflen, rc);
- ut_error;
- }
-
- crypt_data->keys[0].key_version = version;
- crypt_data->key_count++;
- *key_length = buflen;
- crypt_data->keys[0].key_length = buflen;
-
- if (crypt_data->key_count > array_elements(crypt_data->keys)) {
- crypt_data->key_count = array_elements(crypt_data->keys);
- }
-
- memcpy(dst, buf, buflen);
- mutex_exit(&crypt_data->mutex);
-}
-
-/******************************************************************
Get the latest(key-version), waking the encrypt thread, if needed */
static inline
uint
@@ -244,27 +168,17 @@ fil_crypt_get_latest_key_version(
}
/******************************************************************
-Get key bytes for a space/latest(key-version) */
-static inline
-void
-fil_crypt_get_latest_key(
-/*=====================*/
- byte* dst, /*!< out: Key */
- uint* key_length, /*!< out: Key length */
- fil_space_crypt_t* crypt_data, /*!< in: crypt data */
- uint* version) /*!< in: Key version */
+Mutex helper for crypt_data->scheme */
+static void crypt_data_scheme_locker(st_encryption_scheme *scheme, int exit)
{
- // used for key rotation - get the next key id from the key provider
- uint rc = *version = fil_crypt_get_latest_key_version(crypt_data);
+ fil_space_crypt_t* crypt_data =
+ static_cast<fil_space_crypt_t*>(scheme);
- if (rc == ENCRYPTION_KEY_VERSION_INVALID) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Unknown key id %u. Can't continue!\n",
- crypt_data->key_id);
- ut_error;
+ if (exit) {
+ mutex_exit(&crypt_data->mutex);
+ } else {
+ mutex_enter(&crypt_data->mutex);
}
-
- return fil_crypt_get_key(dst, key_length, crypt_data, *version);
}
/******************************************************************
@@ -277,8 +191,7 @@ fil_space_create_crypt_data(
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
uint key_id) /*!< in: encryption key id */
{
- const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
- const uint sz = sizeof(fil_space_crypt_t) + iv_length;
+ const uint sz = sizeof(fil_space_crypt_t);
fil_space_crypt_t* crypt_data =
static_cast<fil_space_crypt_t*>(malloc(sz));
@@ -290,14 +203,14 @@ fil_space_create_crypt_data(
crypt_data->min_key_version = 0;
} else {
crypt_data->type = CRYPT_SCHEME_1;
- crypt_data->key_id = key_id;
+ crypt_data->key_id = key_id;
crypt_data->min_key_version = encryption_key_get_latest_version(key_id);
}
mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK);
- crypt_data->iv_length = iv_length;
- my_random_bytes(crypt_data->iv, iv_length);
+ crypt_data->locker = crypt_data_scheme_locker;
+ my_random_bytes(crypt_data->iv, sizeof(crypt_data->iv));
crypt_data->encryption = FIL_SPACE_ENCRYPTION_DEFAULT;
return crypt_data;
}
@@ -317,12 +230,9 @@ fil_space_crypt_compare(
ut_a(crypt_data2->type == CRYPT_SCHEME_UNENCRYPTED ||
crypt_data2->type == CRYPT_SCHEME_1);
- ut_a(crypt_data1->iv_length == CRYPT_SCHEME_1_IV_LEN);
- ut_a(crypt_data2->iv_length == CRYPT_SCHEME_1_IV_LEN);
-
/* no support for changing iv (yet?) */
ut_a(memcmp(crypt_data1->iv, crypt_data2->iv,
- crypt_data1->iv_length) == 0);
+ sizeof(crypt_data1->iv)) == 0);
return 0;
}
@@ -378,9 +288,10 @@ fil_space_read_crypt_data(
ut_error;
}
+ fil_space_crypt_t* crypt_data;
ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1);
- if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
+ if (! (iv_length == sizeof(crypt_data->iv))) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Found non sensible iv length: %lu for space %lu "
" offset: %lu type: %lu bytes: "
@@ -405,8 +316,7 @@ fil_space_read_crypt_data(
page + offset + MAGIC_SZ + 2 + iv_length + 8);
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
- fil_space_crypt_t* crypt_data = static_cast<fil_space_crypt_t*>(
- malloc(sz));
+ crypt_data = static_cast<fil_space_crypt_t*>(malloc(sz));
memset(crypt_data, 0, sz);
crypt_data->type = type;
@@ -416,7 +326,7 @@ fil_space_read_crypt_data(
crypt_data->encryption = encryption;
mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK);
- crypt_data->iv_length = iv_length;
+ crypt_data->locker = crypt_data_scheme_locker;
memcpy(crypt_data->iv, page + offset + MAGIC_SZ + 2, iv_length);
return crypt_data;
@@ -453,7 +363,7 @@ fil_space_write_crypt_data_low(
ut_a(offset > 0 && offset < UNIV_PAGE_SIZE);
ulint space_id = mach_read_from_4(
page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- const uint len = crypt_data->iv_length;
+ const uint len = sizeof(crypt_data->iv);
const uint min_key_version = crypt_data->min_key_version;
const uint key_id = crypt_data->key_id;
const fil_encryption_t encryption = crypt_data->encryption;
@@ -662,9 +572,6 @@ fil_space_encrypt(
fil_space_crypt_t* crypt_data = NULL;
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
uint key_version;
- unsigned char key[MY_AES_MAX_KEY_LENGTH];
- uint key_length = MY_AES_MAX_KEY_LENGTH;
- unsigned char iv[MY_AES_BLOCK_SIZE];
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
@@ -686,12 +593,14 @@ fil_space_encrypt(
return;
}
- fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version);
+ key_version = fil_crypt_get_latest_key_version(crypt_data);
- /* create iv/counter */
- mach_write_to_4(iv + 0, space);
- mach_write_to_4(iv + 4, offset);
- mach_write_to_8(iv + 8, lsn);
+ if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Unknown key id %u. Can't continue!\n",
+ crypt_data->key_id);
+ ut_error;
+ }
ibool page_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
@@ -719,9 +628,9 @@ fil_space_encrypt(
dst+=2;
}
- int rc = encryption_encrypt(src, srclen, dst, &dstlen,
- key, key_length, iv, sizeof(iv), 1,
- crypt_data->key_id, key_version);
+ int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
ib_logf(IB_LOG_LEVEL_FATAL,
@@ -837,17 +746,6 @@ fil_space_decrypt(
/* Copy FIL page header, it is not encrypted */
memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
- /* Get key */
- byte key[MY_AES_MAX_KEY_LENGTH];
- uint key_length;
- unsigned char iv[MY_AES_BLOCK_SIZE];
- fil_crypt_get_key(key, &key_length, crypt_data, key_version);
-
- /* create iv/counter */
- mach_write_to_4(iv + 0, space);
- mach_write_to_4(iv + 4, offset);
- mach_write_to_8(iv + 8, lsn);
-
/* Calculate the offset where decryption starts */
const byte* src = src_frame + FIL_PAGE_DATA;
byte* dst = dst_frame + FIL_PAGE_DATA;
@@ -865,9 +763,9 @@ fil_space_decrypt(
srclen = compressed_len;
}
- int rc = encryption_decrypt(src, srclen, dst, &dstlen, key, key_length,
- iv, sizeof(iv), 1,
- crypt_data->key_id, key_version);
+ int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
ib_logf(IB_LOG_LEVEL_FATAL,
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index ded1680bfb2..b837ac43909 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -11729,8 +11729,7 @@ ha_innobase::create(
/* If there is old crypt data, copy IV */
if (old_crypt_data) {
- memcpy(crypt_data->iv, old_crypt_data->iv, old_crypt_data->iv_length);
- crypt_data->iv_length = old_crypt_data->iv_length;
+ memcpy(crypt_data->iv, old_crypt_data->iv, sizeof(crypt_data->iv));
}
mtr_t mtr;
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index 12f0946f28c..32d3c46585f 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -80,13 +80,8 @@ struct fil_space_rotate_state_t
} scrubbing;
};
-struct fil_space_crypt_struct
+struct fil_space_crypt_struct : st_encryption_scheme
{
- ulint type; // CRYPT_SCHEME
- uint keyserver_requests; // no of key requests to key server
- uint key_count; // No of initalized key-structs
- uint key_id; // Key id for this space
- key_struct keys[3]; // cached L = AES_ECB(KEY, IV)
uint min_key_version; // min key version for this space
ulint page0_offset; // byte offset on page 0 for crypt data
fil_encryption_t encryption; // Encryption setup
@@ -94,9 +89,6 @@ struct fil_space_crypt_struct
ib_mutex_t mutex; // mutex protecting following variables
bool closing; // is tablespace being closed
fil_space_rotate_state_t rotate_state;
-
- uint iv_length; // length of IV
- byte iv[1]; // IV-data
};
/* structure containing encryption specification */
diff --git a/storage/maria/ma_check_standalone.h b/storage/maria/ma_check_standalone.h
index 693de8a8a56..c240ca056e7 100644
--- a/storage/maria/ma_check_standalone.h
+++ b/storage/maria/ma_check_standalone.h
@@ -33,6 +33,33 @@ struct encryption_service_st encryption_handler=
no_key, 0, 0, 0, 0, 0
};
+int encryption_scheme_encrypt(const unsigned char* src __attribute__((unused)),
+ unsigned int slen __attribute__((unused)),
+ unsigned char* dst __attribute__((unused)),
+ unsigned int* dlen __attribute__((unused)),
+ struct st_encryption_scheme *scheme __attribute__((unused)),
+ unsigned int key_version __attribute__((unused)),
+ unsigned int i32_1 __attribute__((unused)),
+ unsigned int i32_2 __attribute__((unused)),
+ unsigned long long i64 __attribute__((unused)))
+{
+ return -1;
+}
+
+
+int encryption_scheme_decrypt(const unsigned char* src __attribute__((unused)),
+ unsigned int slen __attribute__((unused)),
+ unsigned char* dst __attribute__((unused)),
+ unsigned int* dlen __attribute__((unused)),
+ struct st_encryption_scheme *scheme __attribute__((unused)),
+ unsigned int key_version __attribute__((unused)),
+ unsigned int i32_1 __attribute__((unused)),
+ unsigned int i32_2 __attribute__((unused)),
+ unsigned long long i64 __attribute__((unused)))
+{
+ return -1;
+}
+
/* only those that included myisamchk.h may need and can use the below */
#ifdef _myisamchk_h
/*
diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c
index c0a260c405f..b327d528678 100644
--- a/storage/maria/ma_crypt.c
+++ b/storage/maria/ma_crypt.c
@@ -39,14 +39,9 @@ struct st_crypt_key
struct st_maria_crypt_data
{
- uchar type;
- uint keyid;
+ struct st_encryption_scheme scheme;
+ uint space;
mysql_mutex_t lock; /* protecting keys */
- uint keyserver_requests; /* # of key requests to key server */
- uint key_count; /* # of initalized key-structs */
- struct st_crypt_key keys[3]; /* cached L = AES_ECB(KEY, IV) */
- uchar iv_length;
- uchar iv[1]; /* variable size */
};
uint
@@ -77,19 +72,27 @@ ma_crypt_get_file_length()
return 2 + CRYPT_SCHEME_1_IV_LEN + CRYPT_SCHEME_1_ID_LEN;
}
+static void crypt_data_scheme_locker(struct st_encryption_scheme *scheme,
+ int unlock)
+{
+ MARIA_CRYPT_DATA *crypt_data = (MARIA_CRYPT_DATA*)scheme;
+ if (unlock)
+ mysql_mutex_unlock(&crypt_data->lock);
+ else
+ mysql_mutex_lock(&crypt_data->lock);
+}
+
int
ma_crypt_create(MARIA_SHARE* share)
{
- const uint iv_length= CRYPT_SCHEME_1_IV_LEN + CRYPT_SCHEME_1_ID_LEN;
- const uint sz= sizeof(MARIA_CRYPT_DATA) + iv_length;
- MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0));
- bzero(crypt_data, sz);
- crypt_data->type= CRYPT_SCHEME_1;
- crypt_data->key_count= 0;
+ MARIA_CRYPT_DATA *crypt_data=
+ (MARIA_CRYPT_DATA*)my_malloc(sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL));
+ crypt_data->scheme.type= CRYPT_SCHEME_1;
+ crypt_data->scheme.locker= crypt_data_scheme_locker;
mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock, MY_MUTEX_INIT_FAST);
- crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID;
- crypt_data->iv_length= iv_length;
- my_random_bytes(crypt_data->iv, iv_length);
+ crypt_data->scheme.key_id= HARD_CODED_ENCRYPTION_KEY_ID;
+ my_random_bytes(crypt_data->scheme.iv, sizeof(crypt_data->scheme.iv));
+ my_random_bytes((uchar*)&crypt_data->space, sizeof(crypt_data->space));
share->crypt_data= crypt_data;
share->crypt_page_header_space= CRYPT_SCHEME_1_KEY_VERSION_SIZE;
return 0;
@@ -109,19 +112,18 @@ ma_crypt_free(MARIA_SHARE* share)
int
ma_crypt_write(MARIA_SHARE* share, File file)
{
- uchar buff[2];
MARIA_CRYPT_DATA *crypt_data= share->crypt_data;
+ uchar buff[2 + 4 + sizeof(crypt_data->scheme.iv)];
if (crypt_data == 0)
return 0;
- buff[0]= crypt_data->type;
- buff[1]= crypt_data->iv_length;
+ buff[0]= crypt_data->scheme.type;
+ buff[1]= sizeof(buff) - 2;
- if (mysql_file_write(file, buff, 2, MYF(MY_NABP)))
- return 1;
+ int4store(buff + 2, crypt_data->space);
+ memcpy(buff + 6, crypt_data->scheme.iv, sizeof(crypt_data->scheme.iv));
- if (mysql_file_write(file, crypt_data->iv, crypt_data->iv_length,
- MYF(MY_NABP)))
+ if (mysql_file_write(file, buff, sizeof(buff), MYF(MY_NABP)))
return 1;
return 0;
@@ -132,29 +134,10 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff)
{
uchar type= buff[0];
uchar iv_length= buff[1];
- if (share->crypt_data == NULL)
- {
- /* opening a table */
- const uint sz= sizeof(MARIA_CRYPT_DATA) + iv_length;
- MARIA_CRYPT_DATA *crypt_data= (MARIA_CRYPT_DATA*)my_malloc(sz, MYF(0));
- crypt_data->type= type;
- crypt_data->key_count= 0;
- mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock,
- MY_MUTEX_INIT_FAST);
- crypt_data->keyid= HARD_CODED_ENCRYPTION_KEY_ID;
- crypt_data->iv_length= iv_length;
- memcpy(crypt_data->iv, buff + 2, iv_length);
- share->crypt_data= crypt_data;
- }
- else
- {
- /* creating a table */
- assert(type == share->crypt_data->type);
- assert(iv_length == share->crypt_data->iv_length);
- }
/* currently only supported type */
- if (type != CRYPT_SCHEME_1)
+ if (type != CRYPT_SCHEME_1 ||
+ iv_length != sizeof(((MARIA_CRYPT_DATA*)1)->scheme.iv) + 4)
{
my_printf_error(HA_ERR_UNSUPPORTED,
"Unsupported crypt scheme! type: %d iv_length: %d\n",
@@ -163,6 +146,22 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff)
return 0;
}
+ if (share->crypt_data == NULL)
+ {
+ /* opening a table */
+ MARIA_CRYPT_DATA *crypt_data=
+ (MARIA_CRYPT_DATA*)my_malloc(sizeof(MARIA_CRYPT_DATA), MYF(MY_ZEROFILL));
+
+ crypt_data->scheme.type= type;
+ mysql_mutex_init(key_CRYPT_DATA_lock, &crypt_data->lock,
+ MY_MUTEX_INIT_FAST);
+ crypt_data->scheme.locker= crypt_data_scheme_locker;
+ crypt_data->scheme.key_id= HARD_CODED_ENCRYPTION_KEY_ID;
+ crypt_data->space= uint4korr(buff + 2);
+ memcpy(crypt_data->scheme.iv, buff + 6, sizeof(crypt_data->scheme.iv));
+ share->crypt_data= crypt_data;
+ }
+
share->crypt_page_header_space= CRYPT_SCHEME_1_KEY_VERSION_SIZE;
return buff + 2 + iv_length;
}
@@ -425,100 +424,6 @@ void ma_crypt_set_index_pagecache_callbacks(PAGECACHE_FILE *file,
file->post_write_hook= ma_crypt_post_write_hook;
}
-/**
- get key bytes for a table and key-version
-*/
-static int ma_crypt_get_key(uchar *dst, uint dstlen,
- MARIA_CRYPT_DATA *crypt_data, uint version)
-{
- int rc;
- uint i;
- uchar keybuf[CRYPT_SCHEME_1_IV_LEN];
- uint keylen= sizeof(keybuf);
-
- DBUG_ASSERT(dstlen == sizeof(crypt_data->keys[0].key));
-
- mysql_mutex_lock(&crypt_data->lock);
-
- /* Check if we already have key */
- for (i= 0; i < crypt_data->key_count; i++)
- {
- if (crypt_data->keys[i].key_version == version)
- {
- memcpy(dst, crypt_data->keys[i].key, sizeof(crypt_data->keys[i].key));
- mysql_mutex_unlock(&crypt_data->lock);
- return 0;
- }
- }
-
- /* Not found! */
- crypt_data->keyserver_requests++;
-
- /* Rotate keys to make room for a new */
- for (i= 1; i < array_elements(crypt_data->keys); i++)
- crypt_data->keys[i]= crypt_data->keys[i - 1];
-
- /* Get new key from key server */
- rc= encryption_key_get(crypt_data->keyid, version, keybuf, &keylen);
- if (rc != 0)
- {
- my_printf_error(HA_ERR_GENERIC,
- "Key id %u version %u can not be found. Reason=%u",
- MYF(ME_FATALERROR|ME_NOREFRESH),
- crypt_data->keyid, version, rc );
- return 1;
- }
-
- /* Now compute L by encrypting IV using this key */
- {
- const uchar* src= crypt_data->iv;
- const int srclen= CRYPT_SCHEME_1_IV_LEN;
- uchar* buf= crypt_data->keys[0].key;
- uint buflen= sizeof(crypt_data->keys[0].key);
- rc = my_aes_encrypt_ecb(src, srclen, buf, &buflen,
- keybuf, keylen, NULL, 0, 1);
- if (rc != MY_AES_OK)
- {
- my_printf_error(HA_ERR_GENERIC,
- "Unable to encrypt key-block "
- " src: %p srclen: %d buf: %p buflen: %d."
- " return-code: %d. Can't continue!",
- MYF(ME_FATALERROR|ME_NOREFRESH),
- src, srclen, buf, buflen, rc);
- return 1;
- }
- }
-
- crypt_data->keys[0].key_version= version;
- crypt_data->key_count++;
-
- if (crypt_data->key_count > array_elements(crypt_data->keys))
- crypt_data->key_count= array_elements(crypt_data->keys);
-
- memcpy(dst, crypt_data->keys[0].key, sizeof(crypt_data->keys[0].key));
- mysql_mutex_unlock(&crypt_data->lock);
- return 0;
-}
-
-/******************************************************************
-Get key bytes for a table and latest key-version */
-static int ma_crypt_get_latest_key(uchar *dst, uint dstlen,
- MARIA_CRYPT_DATA* crypt_data, uint *version)
-{
- uint rc = *version = encryption_key_get_latest_version(crypt_data->keyid);
- if (rc == ENCRYPTION_KEY_VERSION_INVALID)
- {
- my_printf_error(HA_ERR_GENERIC,
- "Unknown key id %u. Can't continue!",
- MYF(ME_FATALERROR|ME_NOREFRESH),
- crypt_data->keyid);
- return 1;
- }
- return ma_crypt_get_key(dst, dstlen, crypt_data, *version);
-}
-
-#define COUNTER_LEN MY_AES_BLOCK_SIZE
-
static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data,
const uchar *src, uchar *dst, uint size,
uint pageno, LSN lsn,
@@ -526,22 +431,18 @@ static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data,
{
int rc;
uint32 dstlen;
- uchar counter[COUNTER_LEN];
- uchar key[CRYPT_SCHEME_1_IV_LEN];
- // get key (L) and key_version
- if (ma_crypt_get_latest_key(key, sizeof(key), crypt_data, key_version))
+ *key_version = encryption_key_get_latest_version(crypt_data->scheme.key_id);
+ if (*key_version == ENCRYPTION_KEY_VERSION_INVALID)
+ {
+ my_printf_error(HA_ERR_GENERIC, "Unknown key id %u. Can't continue!",
+ MYF(ME_FATALERROR|ME_NOREFRESH), crypt_data->scheme.key_id);
return 1;
+ }
- /* create counter block */
- memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4);
- int4store(counter + 4, pageno);
- int8store(counter + 8, lsn);
-
- rc= encryption_encrypt(src, size, dst, &dstlen,
- crypt_data->iv, CRYPT_SCHEME_1_IV_LEN,
- counter, sizeof(counter), 1,
- crypt_data->keyid, *key_version);
+ rc= encryption_scheme_encrypt(src, size, dst, &dstlen,
+ &crypt_data->scheme, *key_version,
+ crypt_data->space, pageno, lsn);
DBUG_ASSERT(rc == MY_AES_OK);
DBUG_ASSERT(dstlen == size);
@@ -564,22 +465,10 @@ static int ma_decrypt(MARIA_CRYPT_DATA *crypt_data,
{
int rc;
uint32 dstlen;
- uchar counter[COUNTER_LEN];
- uchar key[CRYPT_SCHEME_1_IV_LEN];
-
- // get key (L) and key_version
- if (ma_crypt_get_key(key, sizeof(key), crypt_data, key_version))
- return 1;
-
- /* create counter block */
- memcpy(counter + 0, crypt_data->iv + CRYPT_SCHEME_1_IV_LEN, 4);
- int4store(counter + 4, pageno);
- int8store(counter + 8, lsn);
- rc =encryption_decrypt(src, size, dst, &dstlen,
- crypt_data->iv, CRYPT_SCHEME_1_IV_LEN,
- counter, sizeof(counter), 1, crypt_data->keyid,
- key_version);
+ rc= encryption_scheme_decrypt(src, size, dst, &dstlen,
+ &crypt_data->scheme, key_version,
+ crypt_data->space, pageno, lsn);
DBUG_ASSERT(rc == MY_AES_OK);
DBUG_ASSERT(dstlen == size);
diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc
index 2d8ac3cef39..878c34a5091 100644
--- a/storage/xtradb/fil/fil0crypt.cc
+++ b/storage/xtradb/fil/fil0crypt.cc
@@ -150,82 +150,6 @@ fil_space_crypt_cleanup()
}
/******************************************************************
-Get key bytes for a space/key-version */
-static
-void
-fil_crypt_get_key(
-/*==============*/
- byte* dst, /*<! out: Key */
- uint* key_length, /*<! out: Key length */
- fil_space_crypt_t* crypt_data, /*<! in: crypt data */
- uint version) /*<! in: Key version */
-{
- unsigned char keybuf[MY_AES_MAX_KEY_LENGTH];
-
- mutex_enter(&crypt_data->mutex);
-
- // Check if we already have key
- for (uint i = 0; i < crypt_data->key_count; i++) {
- if (crypt_data->keys[i].key_version == version) {
- memcpy(dst, crypt_data->keys[i].key,
- crypt_data->keys[i].key_length);
- *key_length = crypt_data->keys[i].key_length;
- mutex_exit(&crypt_data->mutex);
- return;
- }
- }
-
- // Not found!
- crypt_data->keyserver_requests++;
-
- // Rotate keys to make room for a new
- for (uint i = 1; i < array_elements(crypt_data->keys); i++) {
- crypt_data->keys[i] = crypt_data->keys[i - 1];
- }
-
- *key_length = sizeof(keybuf);
- uint rc = encryption_key_get(crypt_data->key_id, version, keybuf, key_length);
- if (rc) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Key id %u version %u can not be found. Reason=%u",
- crypt_data->key_id, version, rc);
- ut_error;
- }
-
- /* Now compute L by encrypting IV using this key. Note
- that we use random IV from crypt data. */
- const unsigned char* src = crypt_data->iv;
- const int srclen = crypt_data->iv_length;
- unsigned char* buf = crypt_data->keys[0].key;
- uint32 buflen = CRYPT_SCHEME_1_IV_LEN;
-
- /* We use AES_ECB to encrypt IV */
- rc = my_aes_encrypt_ecb(src, srclen, buf, &buflen,
- keybuf, *key_length, NULL, 0, 1);
-
- if (rc != MY_AES_OK) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Unable to encrypt key-block "
- " src: %p srclen: %d buf: %p buflen: %d."
- " return-code: %d. Can't continue!\n",
- src, srclen, buf, buflen, rc);
- ut_error;
- }
-
- crypt_data->keys[0].key_version = version;
- crypt_data->key_count++;
- *key_length = buflen;
- crypt_data->keys[0].key_length = buflen;
-
- if (crypt_data->key_count > array_elements(crypt_data->keys)) {
- crypt_data->key_count = array_elements(crypt_data->keys);
- }
-
- memcpy(dst, buf, buflen);
- mutex_exit(&crypt_data->mutex);
-}
-
-/******************************************************************
Get the latest(key-version), waking the encrypt thread, if needed */
static inline
uint
@@ -244,27 +168,17 @@ fil_crypt_get_latest_key_version(
}
/******************************************************************
-Get key bytes for a space/latest(key-version) */
-static inline
-void
-fil_crypt_get_latest_key(
-/*=====================*/
- byte* dst, /*!< out: Key */
- uint* key_length, /*!< out: Key length */
- fil_space_crypt_t* crypt_data, /*!< in: crypt data */
- uint* version) /*!< in: Key version */
+Mutex helper for crypt_data->scheme */
+static void crypt_data_scheme_locker(st_encryption_scheme *scheme, int exit)
{
- // used for key rotation - get the next key id from the key provider
- uint rc = *version = fil_crypt_get_latest_key_version(crypt_data);
+ fil_space_crypt_t* crypt_data =
+ static_cast<fil_space_crypt_t*>(scheme);
- if (rc == ENCRYPTION_KEY_VERSION_INVALID) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Unknown key id %u. Can't continue!\n",
- crypt_data->key_id);
- ut_error;
+ if (exit) {
+ mutex_exit(&crypt_data->mutex);
+ } else {
+ mutex_enter(&crypt_data->mutex);
}
-
- return fil_crypt_get_key(dst, key_length, crypt_data, *version);
}
/******************************************************************
@@ -277,8 +191,7 @@ fil_space_create_crypt_data(
fil_encryption_t encrypt_mode, /*!< in: encryption mode */
uint key_id) /*!< in: encryption key id */
{
- const uint iv_length = CRYPT_SCHEME_1_IV_LEN;
- const uint sz = sizeof(fil_space_crypt_t) + iv_length;
+ const uint sz = sizeof(fil_space_crypt_t);
fil_space_crypt_t* crypt_data =
static_cast<fil_space_crypt_t*>(malloc(sz));
@@ -290,14 +203,14 @@ fil_space_create_crypt_data(
crypt_data->min_key_version = 0;
} else {
crypt_data->type = CRYPT_SCHEME_1;
- crypt_data->key_id = key_id;
+ crypt_data->key_id = key_id;
crypt_data->min_key_version = encryption_key_get_latest_version(key_id);
}
mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK);
- crypt_data->iv_length = iv_length;
- my_random_bytes(crypt_data->iv, iv_length);
+ crypt_data->locker = crypt_data_scheme_locker;
+ my_random_bytes(crypt_data->iv, sizeof(crypt_data->iv));
crypt_data->encryption = FIL_SPACE_ENCRYPTION_DEFAULT;
return crypt_data;
}
@@ -317,12 +230,9 @@ fil_space_crypt_compare(
ut_a(crypt_data2->type == CRYPT_SCHEME_UNENCRYPTED ||
crypt_data2->type == CRYPT_SCHEME_1);
- ut_a(crypt_data1->iv_length == CRYPT_SCHEME_1_IV_LEN);
- ut_a(crypt_data2->iv_length == CRYPT_SCHEME_1_IV_LEN);
-
/* no support for changing iv (yet?) */
ut_a(memcmp(crypt_data1->iv, crypt_data2->iv,
- crypt_data1->iv_length) == 0);
+ sizeof(crypt_data1->iv)) == 0);
return 0;
}
@@ -378,9 +288,10 @@ fil_space_read_crypt_data(
ut_error;
}
+ fil_space_crypt_t* crypt_data;
ulint iv_length = mach_read_from_1(page + offset + MAGIC_SZ + 1);
- if (! (iv_length == CRYPT_SCHEME_1_IV_LEN)) {
+ if (! (iv_length == sizeof(crypt_data->iv))) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Found non sensible iv length: %lu for space %lu "
" offset: %lu type: %lu bytes: "
@@ -405,8 +316,7 @@ fil_space_read_crypt_data(
page + offset + MAGIC_SZ + 2 + iv_length + 8);
const uint sz = sizeof(fil_space_crypt_t) + iv_length;
- fil_space_crypt_t* crypt_data = static_cast<fil_space_crypt_t*>(
- malloc(sz));
+ crypt_data = static_cast<fil_space_crypt_t*>(malloc(sz));
memset(crypt_data, 0, sz);
crypt_data->type = type;
@@ -416,7 +326,7 @@ fil_space_read_crypt_data(
crypt_data->encryption = encryption;
mutex_create(fil_crypt_data_mutex_key,
&crypt_data->mutex, SYNC_NO_ORDER_CHECK);
- crypt_data->iv_length = iv_length;
+ crypt_data->locker = crypt_data_scheme_locker;
memcpy(crypt_data->iv, page + offset + MAGIC_SZ + 2, iv_length);
return crypt_data;
@@ -453,7 +363,7 @@ fil_space_write_crypt_data_low(
ut_a(offset > 0 && offset < UNIV_PAGE_SIZE);
ulint space_id = mach_read_from_4(
page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- const uint len = crypt_data->iv_length;
+ const uint len = sizeof(crypt_data->iv);
const uint min_key_version = crypt_data->min_key_version;
const uint key_id = crypt_data->key_id;
const fil_encryption_t encryption = crypt_data->encryption;
@@ -662,9 +572,6 @@ fil_space_encrypt(
fil_space_crypt_t* crypt_data = NULL;
ulint page_size = (zip_size) ? zip_size : UNIV_PAGE_SIZE;
uint key_version;
- unsigned char key[MY_AES_MAX_KEY_LENGTH];
- uint key_length = MY_AES_MAX_KEY_LENGTH;
- unsigned char iv[MY_AES_BLOCK_SIZE];
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
@@ -686,12 +593,14 @@ fil_space_encrypt(
return;
}
- fil_crypt_get_latest_key(key, &key_length, crypt_data, &key_version);
+ key_version = fil_crypt_get_latest_key_version(crypt_data);
- /* create iv/counter */
- mach_write_to_4(iv + 0, space);
- mach_write_to_4(iv + 4, offset);
- mach_write_to_8(iv + 8, lsn);
+ if (key_version == ENCRYPTION_KEY_VERSION_INVALID) {
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Unknown key id %u. Can't continue!\n",
+ crypt_data->key_id);
+ ut_error;
+ }
ibool page_compressed = (mach_read_from_2(src_frame+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
@@ -719,9 +628,9 @@ fil_space_encrypt(
dst+=2;
}
- int rc = encryption_encrypt(src, srclen, dst, &dstlen,
- key, key_length, iv, sizeof(iv), 1,
- crypt_data->key_id, key_version);
+ int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
ib_logf(IB_LOG_LEVEL_FATAL,
@@ -837,17 +746,6 @@ fil_space_decrypt(
/* Copy FIL page header, it is not encrypted */
memcpy(dst_frame, src_frame, FIL_PAGE_DATA);
- /* Get key */
- byte key[MY_AES_MAX_KEY_LENGTH];
- uint key_length;
- unsigned char iv[MY_AES_BLOCK_SIZE];
- fil_crypt_get_key(key, &key_length, crypt_data, key_version);
-
- /* create iv/counter */
- mach_write_to_4(iv + 0, space);
- mach_write_to_4(iv + 4, offset);
- mach_write_to_8(iv + 8, lsn);
-
/* Calculate the offset where decryption starts */
const byte* src = src_frame + FIL_PAGE_DATA;
byte* dst = dst_frame + FIL_PAGE_DATA;
@@ -865,9 +763,9 @@ fil_space_decrypt(
srclen = compressed_len;
}
- int rc = encryption_decrypt(src, srclen, dst, &dstlen, key, key_length,
- iv, sizeof(iv), 1,
- crypt_data->key_id, key_version);
+ int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ space, offset, lsn);
if (! ((rc == MY_AES_OK) && ((ulint) dstlen == srclen))) {
ib_logf(IB_LOG_LEVEL_FATAL,
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 7097c72a721..ddcbc3f591d 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -12242,8 +12242,7 @@ ha_innobase::create(
/* If there is old crypt data, copy IV */
if (old_crypt_data) {
- memcpy(crypt_data->iv, old_crypt_data->iv, old_crypt_data->iv_length);
- crypt_data->iv_length = old_crypt_data->iv_length;
+ memcpy(crypt_data->iv, old_crypt_data->iv, sizeof(crypt_data->iv));
}
mtr_t mtr;
diff --git a/storage/xtradb/include/fil0crypt.h b/storage/xtradb/include/fil0crypt.h
index 12f0946f28c..32d3c46585f 100644
--- a/storage/xtradb/include/fil0crypt.h
+++ b/storage/xtradb/include/fil0crypt.h
@@ -80,13 +80,8 @@ struct fil_space_rotate_state_t
} scrubbing;
};
-struct fil_space_crypt_struct
+struct fil_space_crypt_struct : st_encryption_scheme
{
- ulint type; // CRYPT_SCHEME
- uint keyserver_requests; // no of key requests to key server
- uint key_count; // No of initalized key-structs
- uint key_id; // Key id for this space
- key_struct keys[3]; // cached L = AES_ECB(KEY, IV)
uint min_key_version; // min key version for this space
ulint page0_offset; // byte offset on page 0 for crypt data
fil_encryption_t encryption; // Encryption setup
@@ -94,9 +89,6 @@ struct fil_space_crypt_struct
ib_mutex_t mutex; // mutex protecting following variables
bool closing; // is tablespace being closed
fil_space_rotate_state_t rotate_state;
-
- uint iv_length; // length of IV
- byte iv[1]; // IV-data
};
/* structure containing encryption specification */