mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Identical key derivation code in XtraDB/InnoDB/Aria
* Extract it into the "encryption_scheme" service. * Make these engines to use the service, remove duplicate code. * Change MY_AES_xxx error codes, to return them safely from encryption_scheme_encrypt/decrypt without conflicting with ENCRYPTION_SCHEME_KEY_INVALID error
This commit is contained in:
parent
632f2307f7
commit
2300fe2e0e
26 changed files with 612 additions and 466 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
133
include/mysql/service_encryption_scheme.h
Normal file
133
include/mysql/service_encryption_scheme.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -36,4 +36,5 @@
|
|||
#define VERSION_thd_error_context 0x0100
|
||||
#define VERSION_thd_specifics 0x0100
|
||||
#define VERSION_encryption 0x0200
|
||||
#define VERSION_encryption_scheme 0x0100
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
17
libservices/encryption_scheme_service.c
Normal file
17
libservices/encryption_scheme_service.c
Normal file
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
|
|
@ -149,82 +149,6 @@ fil_space_crypt_cleanup()
|
|||
os_event_free(fil_crypt_throttle_sleep_event);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
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
|
||||
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -149,82 +149,6 @@ fil_space_crypt_cleanup()
|
|||
os_event_free(fil_crypt_throttle_sleep_event);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
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
|
||||
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue