Browse Source
Further fixes (copied from
Further fixes (copied from d7d589dc
)
93 changed files with 953 additions and 1614 deletions
-
1CMakeLists.txt
-
50dbug/dbug.c
-
2include/my_aes.h
-
3include/my_crypt.h
-
10include/my_crypt_key_management.h
-
3include/mysql/plugin.h
-
1libmysqld/CMakeLists.txt
-
2mysql-test/include/bootstrap.cnf
-
7mysql-test/include/have_innodb_encryption.inc
-
4mysql-test/mysql-test-run.pl
-
2mysql-test/r/information_schema_all_engines.result
-
9mysql-test/r/mysqld--help.result
-
2mysql-test/suite/funcs_1/r/is_engines_innodb.result
-
3mysql-test/suite/innodb/r/innodb_monitor.result
-
5mysql-test/suite/innodb/t/innodb-page_encryption-32k-master.opt
-
4mysql-test/suite/innodb/t/innodb-page_encryption.opt
-
4mysql-test/suite/innodb/t/innodb-page_encryption_compression.opt
-
2mysql-test/suite/innodb/t/innodb_bug14147491-master.opt
-
1mysql-test/suite/innodb/t/innodb_bug60049.opt
-
9mysql-test/suite/innodb/t/innodb_encryption.opt
-
1mysql-test/suite/innodb/t/innodb_information_schema.opt
-
1mysql-test/suite/innodb/t/innodb_information_schema_buffer.opt
-
16mysql-test/suite/innodb/t/innodb_scrub.opt
-
16mysql-test/suite/innodb/t/innodb_scrub_background.opt
-
17mysql-test/suite/innodb/t/innodb_scrub_compressed.opt
-
2mysql-test/suite/innodb_zip/t/innodb_cmp_drop_table-master.opt
-
2mysql-test/suite/maria/maria3.result
-
1mysql-test/suite/sys_vars/r/all_vars.result
-
3mysql-test/suite/sys_vars/r/debug_use_static_encryption_keys_basic.result
-
7mysql-test/suite/sys_vars/r/encryption_algorithm_basic.result
-
28mysql-test/suite/sys_vars/r/sysvars_debug.result
-
58mysql-test/suite/sys_vars/r/sysvars_innodb.result
-
28mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
-
32mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
-
3mysql-test/suite/sys_vars/t/danger_danger_use_dbug_keys_basic.test
-
2mysql-test/suite/sys_vars/t/debug_encryption_key_version_basic.test
-
3mysql-test/suite/sys_vars/t/debug_use_static_encryption_keys_basic.test
-
13mysql-test/suite/sys_vars/t/encryption_algorithm_basic.test
-
1mysql-test/suite/sys_vars/t/innodb_checksum_algorithm_basic.opt
-
1mysql-test/suite/sys_vars/t/innodb_data_encryption_filekey_basic.test
-
4mysql-test/suite/sys_vars/t/innodb_data_encryption_providername_basic.test
-
1mysql-test/suite/sys_vars/t/innodb_data_encryption_providertype_basic.test
-
1mysql-test/suite/sys_vars/t/innodb_data_encryption_providerurl_basic.test
-
3mysql-test/t/mysqld--help.test
-
5mysys/my_default.c
-
6mysys/my_thr_init.c
-
27mysys_ssl/my_crypt_key_management.cc
-
5mysys_ssl/my_crypt_key_management_impl.cc
-
20plugin/example_key_management_plugin/example_key_management_plugin.cc
-
3plugin/file_key_management_plugin/CMakeLists.txt
-
271plugin/file_key_management_plugin/EncKeys.cc
-
2plugin/file_key_management_plugin/EncKeys.h
-
44plugin/file_key_management_plugin/KeySingleton.cc
-
2plugin/file_key_management_plugin/KeySingleton.h
-
39plugin/file_key_management_plugin/file_key_management_plugin.cc
-
6sql/mysqld.cc
-
4sql/mysqld.h
-
9sql/sql_acl.cc
-
85sql/sql_plugin.cc
-
4sql/sql_plugin.h
-
6sql/sql_select.cc
-
35sql/sys_vars.cc
-
1storage/innobase/CMakeLists.txt
-
46storage/innobase/buf/buf0buf.cc
-
2storage/innobase/buf/buf0rea.cc
-
433storage/innobase/enc/EncKeys.cc
-
68storage/innobase/enc/KeySingleton.cc
-
34storage/innobase/fil/fil0crypt.cc
-
13storage/innobase/fil/fil0pagecompress.cc
-
4storage/innobase/handler/ha_innodb.cc
-
2storage/innobase/handler/ha_innodb.h
-
3storage/innobase/include/buf0buf.h
-
2storage/innobase/include/fil0fil.h
-
6storage/innobase/log/log0crypt.cc
-
4storage/innobase/log/log0recv.cc
-
62storage/innobase/os/os0file.cc
-
8storage/maria/ma_bitmap.c
-
108storage/maria/ma_blockrec.c
-
2storage/maria/ma_create.c
-
6storage/maria/ma_crypt.c
-
2storage/maria/ma_crypt.h
-
2storage/maria/ma_write.c
-
1storage/maria/maria_def.h
-
2storage/xtradb/buf/buf0rea.cc
-
33storage/xtradb/fil/fil0crypt.cc
-
15storage/xtradb/fil/fil0pagecompress.cc
-
4storage/xtradb/handler/ha_innodb.cc
-
3storage/xtradb/include/buf0buf.h
-
2storage/xtradb/include/fil0fil.h
-
6storage/xtradb/log/log0crypt.cc
-
4storage/xtradb/log/log0recv.cc
-
140storage/xtradb/os/os0file.cc
-
24tests/test_innodb_log_encryption.sh
@ -1,2 +0,0 @@ |
|||
[mysqld] |
|||
loose-innodb-encrypt-tables=OFF |
@ -0,0 +1,7 @@ |
|||
# |
|||
# Ensure we have innodb encryption incompiled |
|||
|
|||
if (`select count(*)=0 from information_schema.global_variables where variable_name="innodb_data_encryption_providertype"`) |
|||
{ |
|||
--skip Test requires InnoDB encryption. |
|||
} |
@ -1 +1,4 @@ |
|||
--default_storage_engine=InnoDB --innodb-buffer-pool-size=24M --file_key_management_plugin_filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
|||
--default-storage-engine=InnoDB |
|||
--encryption-algorithm=aes_cbs |
|||
--file-key-management-plugin-filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
|||
--innodb-buffer-pool-size=24M |
@ -1 +1,3 @@ |
|||
--enable-file_key_management_plugin --file_key_management_plugin_filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
|||
--enable-file-key-management-plugin |
|||
--encryption-algorithm=aes_cbs |
|||
--file-key-management-plugin-filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
@ -1 +1,3 @@ |
|||
--enable-file_key_management_plugin --file_key_management_plugin_filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
|||
--enable-file-key-management-plugin |
|||
--encryption-algorithm=aes_cbs |
|||
--file-key-management-plugin-filename=$MYSQL_TEST_DIR/suite/innodb/include/keys.txt |
@ -1 +1 @@ |
|||
--innodb_file_per_table=1 --skip-stack-trace --skip-core-file --innodb-encrypt-tables=FALSE |
|||
--innodb_file_per_table=1 --skip-stack-trace --skip-core-file |
@ -1 +0,0 @@ |
|||
--innodb-encrypt-tables=FALSE |
@ -1 +1,8 @@ |
|||
--enable-example_key_management_plugin --loose-encrypt-tmp-disk-tables=ON --loose-aria-encrypt-tables=ON --loose-innodb-encryption-threads=4 --loose-innodb-encryption-rotate-key-age=15 --loose-innodb-encrypt-tables=ON --innodb_tablespaces_encryption |
|||
--enable-example-key-management-plugin |
|||
--encrypt-tmp-disk-tables=ON |
|||
--aria-encrypt-tables=ON |
|||
--innodb-encryption-threads=4 |
|||
--innodb-encryption-rotate-key-age=15 |
|||
--innodb-encrypt-tables=ON |
|||
--innodb-tablespaces-encryption |
|||
--encryption-algorithm=aes_ctr |
@ -1 +0,0 @@ |
|||
--innodb-encrypt-tables=FALSE |
@ -1,4 +1,3 @@ |
|||
--loose-innodb-buffer-pool-stats |
|||
--loose-innodb-buffer-page |
|||
--loose-innodb-buffer-page-lru |
|||
--loose-innodb-encrypt-tables=FALSE |
@ -1,2 +1,14 @@ |
|||
--innodb_file_per_table=1 --innodb_file_format=Barracuda --innodb_encrypt_tables=0 --innodb-encryption_threads=0 --innodb-immediate-scrub-data-uncompressed=ON --innodb-background-scrub-data-uncompressed=OFF --innodb-background-scrub-data-compressed=OFF --loose-innodb-scrub-force-testing=ON --enable-example_key_management_plugin --loose-encrypt-tmp-disk-tables=ON --loose-aria-encrypt-tables=ON --loose-innodb-encryption-threads=4 --loose-innodb-encryption-rotate-key-age=15 --loose-innodb-encrypt-tables=ON |
|||
|
|||
--enable-example-key-management-plugin |
|||
--innodb-background-scrub-data-compressed=OFF |
|||
--innodb-background-scrub-data-uncompressed=OFF |
|||
--innodb-encrypt-tables=0 |
|||
--innodb-encryption-threads=0 |
|||
--innodb-file-format=Barracuda |
|||
--innodb-file-per-table=1 |
|||
--innodb-immediate-scrub-data-uncompressed=ON |
|||
--loose-aria-encrypt-tables=ON |
|||
--loose-encrypt-tmp-disk-tables=ON |
|||
--loose-innodb-encrypt-tables=ON |
|||
--loose-innodb-encryption-rotate-key-age=15 |
|||
--loose-innodb-encryption-threads=4 |
|||
--loose-innodb-scrub-force-testing=ON |
@ -1 +1,15 @@ |
|||
--innodb_file_per_table=1 --innodb_file_format=Barracuda --innodb_encrypt_tables=0 --innodb-encryption_threads=0 --innodb-immediate-scrub-data-uncompressed=OFF --innodb-background-scrub-data-uncompressed=ON --innodb-background-scrub-data-compressed=ON --loose-innodb-scrub-force-testing=ON --enable-example_key_management_plugin --loose-encrypt-tmp-disk-tables=ON --loose-aria-encrypt-tables=ON --loose-innodb-encryption-threads=4 --loose-innodb-encryption-rotate-key-age=15 --loose-innodb-encrypt-tables=ON --innodb_tablespaces_scrubbing |
|||
--enable-example-key-management-plugin |
|||
--innodb-background-scrub-data-compressed=ON |
|||
--innodb-background-scrub-data-uncompressed=ON |
|||
--innodb-encrypt-tables=0 |
|||
--innodb-encryption-threads=0 |
|||
--innodb-file-format=Barracuda |
|||
--innodb-file-per-table=1 |
|||
--innodb-immediate-scrub-data-uncompressed=OFF |
|||
--innodb-tablespaces-scrubbing |
|||
--loose-aria-encrypt-tables=ON |
|||
--loose-encrypt-tmp-disk-tables=ON |
|||
--loose-innodb-encrypt-tables=ON |
|||
--loose-innodb-encryption-rotate-key-age=15 |
|||
--loose-innodb-encryption-threads=4 |
|||
--loose-innodb-scrub-force-testing=ON |
@ -1,2 +1,15 @@ |
|||
--innodb_file_per_table=1 --innodb_file_format=Barracuda --innodb_encrypt_tables=off --innodb-immediate-scrub-data-uncompressed=ON --innodb-background-scrub-data-uncompressed=ON --innodb-background-scrub-data-compressed=ON --loose-innodb-scrub-force-testing=ON --innodb-encryption-threads=0 --enable-example_key_management_plugin --loose-encrypt-tmp-disk-tables=ON --loose-aria-encrypt-tables=ON --loose-innodb-encryption-threads=4 --loose-innodb-encryption-rotate-key-age=15 --loose-innodb-encrypt-tables=ON --innodb_tablespaces_scrubbing |
|||
|
|||
--enable-example-key-management-plugin |
|||
--innodb-background-scrub-data-compressed=ON |
|||
--innodb-background-scrub-data-uncompressed=ON |
|||
--innodb-encrypt-tables=off |
|||
--innodb-encryption-threads=0 |
|||
--innodb-file-format=Barracuda |
|||
--innodb-file-per-table=1 |
|||
--innodb-immediate-scrub-data-uncompressed=ON |
|||
--innodb-tablespaces-scrubbing |
|||
--loose-aria-encrypt-tables=ON |
|||
--loose-encrypt-tmp-disk-tables=ON |
|||
--loose-innodb-encrypt-tables=ON |
|||
--loose-innodb-encryption-rotate-key-age=15 |
|||
--loose-innodb-encryption-threads=4 |
|||
--loose-innodb-scrub-force-testing=ON |
@ -1 +1 @@ |
|||
--innodb-buffer-pool-size=8M --innodb-encrypt-tables=FALSE |
|||
--innodb-buffer-pool-size=8M |
@ -0,0 +1,3 @@ |
|||
show global variables like "debug_use_static_encryption_keys"; |
|||
Variable_name Value |
|||
debug_use_static_encryption_keys OFF |
@ -0,0 +1,7 @@ |
|||
select @@global.encryption_algorithm; |
|||
@@global.encryption_algorithm |
|||
none |
|||
select @@session.encryption_algorithm; |
|||
ERROR HY000: Variable 'encryption_algorithm' is a GLOBAL variable |
|||
set global encryption_algorithm="none"; |
|||
ERROR HY000: Variable 'encryption_algorithm' is a read only variable |
@ -1,3 +0,0 @@ |
|||
|
|||
# This is just to satisfy all_vars |
|||
select 1; |
@ -1,3 +1,3 @@ |
|||
|
|||
--source include/have_debug.inc |
|||
# This is just to satisfy all_vars |
|||
select 1; |
@ -0,0 +1,3 @@ |
|||
# This is just to satisfy all_vars |
|||
--source include/have_debug.inc |
|||
show global variables like "debug_use_static_encryption_keys"; |
@ -0,0 +1,13 @@ |
|||
# bool global |
|||
|
|||
# exists as global only |
|||
# |
|||
select @@global.encryption_algorithm; |
|||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR |
|||
select @@session.encryption_algorithm; |
|||
|
|||
# |
|||
# show that it's not writable |
|||
# |
|||
--error 1238 |
|||
set global encryption_algorithm="none"; |
@ -1 +0,0 @@ |
|||
--innodb-encrypt-tables=FALSE --innodb-encryption-threads=0 |
@ -1,3 +1,4 @@ |
|||
SET(FILE_KEY_MANAGEMENT_PLUGIN_SOURCES file_key_management_plugin.cc EncKeys.cc KeySingleton.cc) |
|||
|
|||
MYSQL_ADD_PLUGIN(FILE_KEY_MANAGEMENT_PLUGIN ${FILE_KEY_MANAGEMENT_PLUGIN_SOURCES} DEFAULT) |
|||
MYSQL_ADD_PLUGIN(FILE_KEY_MANAGEMENT_PLUGIN ${FILE_KEY_MANAGEMENT_PLUGIN_SOURCES} DEFAULT |
|||
LINK_LIBRARIES pcre) |
@ -1,433 +0,0 @@ |
|||
/* Copyright (C) 2014 eperi GmbH. All Rights Reserved.
|
|||
|
|||
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 EncKeys.cc |
|||
A class to keep keys for encryption/decryption. |
|||
|
|||
How it works... |
|||
The location and usage can be configured via the configuration file. |
|||
Example |
|||
|
|||
[mysqld] |
|||
... |
|||
innodb_data_encryption_providertype = 1 |
|||
innodb_data_encryption_providername = keys.enc |
|||
innodb_data_encryption_providerurl = /home/mdb/ |
|||
innodb_data_encryption_filekey = secret |
|||
... |
|||
|
|||
As provider type currently only value 1 is supported, which means, the keys are read from a file. |
|||
The filename is set up via the innodb_data_encryption_providername configuration value. |
|||
innodb_data_encryption_providerurl is used to configure the path to this file. This is usually |
|||
a folder name. |
|||
Examples: |
|||
innodb_data_encryption_providerurl = \\\\unc (windows share) |
|||
innodb_data_encryption_providerurl = e:/tmp/ (windows path) |
|||
innodb_data_encryption_providerurl = /tmp (linux path) |
|||
|
|||
The key file contains AES keys and initialization vectors as hex-encoded Strings. |
|||
Supported are keys of size 128, 192 or 256 bits. IV consists of 16 bytes. |
|||
|
|||
The key file should be encrypted and the key to decrypt the file can be given with the |
|||
innodb_data_encryption_filekey parameter. |
|||
|
|||
The file key can also be located if FILE: is prepended to the key. Then the following part is interpreted |
|||
as absolut to the file containing the file key. This file can optionally be encrypted, currently with a fix key. |
|||
Example: |
|||
innodb_data_encryption_filekey = FILE:y:/secret256.enc |
|||
|
|||
If the key file can not be read at server startup, for example if the file key is not present, |
|||
page_encryption feature is not availabe and access to page_encryption tables is not possible. |
|||
|
|||
Example files can be found inside the unittest/eperi folder. |
|||
|
|||
Open SSL command line utility can be used to create an encrypted key file. |
|||
Examples: |
|||
openssl enc –aes-256-cbc –md sha1 –k secret –in keys.txt –out keys.enc |
|||
openssl enc –aes-256-cbc –md sha1 –k <initialPwd> –in secret –out secret.enc |
|||
|
|||
Created 09/15/2014 |
|||
***********************************************************************/ |
|||
#ifdef __WIN__
|
|||
#define PCRE_STATIC 1
|
|||
#endif
|
|||
|
|||
#include "EncKeys.h"
|
|||
#include <my_global.h>
|
|||
#include <my_aes.h>
|
|||
#include <memory.h>
|
|||
#include <my_sys.h>
|
|||
#include <pcre.h>
|
|||
#include <string.h>
|
|||
#include <my_sys.h>
|
|||
|
|||
|
|||
|
|||
|
|||
const char* EncKeys::strMAGIC = "Salted__"; |
|||
const int EncKeys::magicSize = 8;//strlen(strMAGIC); // 8 byte
|
|||
const char* EncKeys::newLine = "\n"; |
|||
|
|||
const char* EncKeys::errorNoKeyId = "KeyID = %u not found or with error. Check the key and the log file.\n"; |
|||
const char* EncKeys::errorInMatches = "Wrong match of the keyID in line %u, see the template.\n"; |
|||
const char* EncKeys::errorExceedKeyFileSize = "The size of the key file %s exceeds " |
|||
"the maximum allowed of %u bytes.\n"; |
|||
const char* EncKeys::errorExceedKeySize = "The key size exceeds the maximum allowed size of %u in line %u.\n"; |
|||
const char* EncKeys::errorEqualDoubleKey = "More than one identical key with keyID = %u found" |
|||
" in lines %u and %u.\nDelete one of them in the key file.\n"; |
|||
const char* EncKeys::errorUnequalDoubleKey = "More than one not identical key with keyID = %u found" |
|||
" in lines %u and %u.\nChoose the right one and delete the other in the key file.\n" |
|||
"I'll take the key from line %u\n"; |
|||
const char* EncKeys::errorNoInitializedKey = "The key could not be initialized.\n"; |
|||
const char* EncKeys::errorNotImplemented = "Initializing keys through key server is not" |
|||
" yet implemented.\nYou can not read encrypted tables or columns\n\n"; |
|||
const char* EncKeys::errorOpenFile = "Could not open %s for reading. You can not read encrypted tables or columns.\n\n"; |
|||
const char* EncKeys::errorReadingFile = "Could not read from %s. You can not read encrypted tables or columns\n\n"; |
|||
const char* EncKeys::errorFileSize = "Could not get the file size from %s. You can not read encrypted tables or columns\n\n"; |
|||
const char* EncKeys::errorFalseFileKey = "Wrong encryption / decryption key for keyfile '%s'.\n"; |
|||
|
|||
/* read this from a secret source in some later version */ |
|||
const char* EncKeys::initialPwd = "lg28s9ac5ffa537fd8798875c98e190df289da7e047c05"; |
|||
|
|||
EncKeys::EncKeys() { |
|||
countKeys = keyLineInKeyFile = 0; |
|||
for (int ii = 0; ii < MAX_KEYS; ii++) { |
|||
keys[ii].id = 0; |
|||
keys[ii].iv = keys[ii].key = NULL; |
|||
} |
|||
oneKey = NULL; |
|||
} |
|||
|
|||
EncKeys::~EncKeys() { |
|||
for (int ii = MAX_KEYS - 1; ii >= 0 ; ii--) { |
|||
delete[] keys[ii].iv; keys[ii].iv = NULL; |
|||
delete[] keys[ii].key; keys[ii].key = NULL; |
|||
|
|||
} |
|||
} |
|||
|
|||
bool EncKeys::initKeys(const char *name, const char *url, const int initType, const char *filekey) { |
|||
if (KEYINITTYPE_FILE == initType) |
|||
{ |
|||
int result = initKeysThroughFile(name, url, filekey); |
|||
return ERROR_FALSE_FILE_KEY != result && ERROR_OPEN_FILE != result && ERROR_READING_FILE != result; |
|||
} |
|||
else if (KEYINITTYPE_SERVER == initType) |
|||
{ |
|||
return NO_ERROR_KEY_FILE_PARSE_OK == initKeysThroughServer(name, url, filekey); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
int EncKeys::initKeysThroughFile(const char *name, const char *path, const char *filekey) { |
|||
if (path==NULL || name==NULL) return ERROR_OPEN_FILE; |
|||
size_t len1 = strlen(path); |
|||
size_t len2 = strlen(name); |
|||
const char *MAGIC = "FILE:"; |
|||
const short MAGIC_LEN = 5; |
|||
int ret = NO_ERROR_KEY_FILE_PARSE_OK; |
|||
bool isUncPath= (len1>2) ? ((strncmp("\\\\", path, 2)==0) ? TRUE : FALSE) : FALSE; |
|||
bool isSlash = ((isUncPath? '\\':'/') == path[len1 - 1]); |
|||
char *secret = (char*) malloc(MAX_SECRET_SIZE +1 * sizeof(char)); |
|||
char *filename = (char*) malloc((len1 + len2 + (isSlash ? 1 : 2)) * sizeof(char)); |
|||
if(filekey != NULL) |
|||
{ |
|||
//If secret starts with FILE: interpret the secret as filename.
|
|||
if(memcmp(MAGIC, filekey, MAGIC_LEN) == 0) { |
|||
int fk_len = strlen(filekey); |
|||
char *secretfile = (char*)malloc( (1 + fk_len - MAGIC_LEN)* sizeof(char)); |
|||
memcpy(secretfile, filekey+MAGIC_LEN, fk_len - MAGIC_LEN); |
|||
secretfile[fk_len-MAGIC_LEN] = '\0'; |
|||
parseSecret(secretfile, secret); |
|||
free(secretfile); |
|||
} else |
|||
{ |
|||
sprintf(secret, "%s", filekey); |
|||
} |
|||
} |
|||
sprintf(filename, "%s%s%s", path, isSlash ? "" : (isUncPath ? "\\":"/"), name); |
|||
ret = parseFile((const char *)filename, 254, secret); |
|||
free(filename); |
|||
free(secret); |
|||
return ret; |
|||
} |
|||
|
|||
int EncKeys::initKeysThroughServer( const char *name, const char *path, const char *filekey) |
|||
{ |
|||
//TODO
|
|||
#ifdef UNIV_DEBUG
|
|||
fprintf(stderr, errorNotImplemented); |
|||
#endif //UNIV_DEBUG
|
|||
return ERROR_KEYINITTYPE_SERVER_NOT_IMPLEMENTED; |
|||
} |
|||
|
|||
/*
|
|||
* secret is limited to MAX_SECRET_SIZE characters |
|||
*/ |
|||
void EncKeys::parseSecret( const char *secretfile, char *secret ) { |
|||
int maxSize = (MAX_SECRET_SIZE +16 + magicSize*2) ; |
|||
char* buf = (char*)malloc((maxSize) * sizeof(char)); |
|||
char* _initPwd = (char*)malloc((strlen(initialPwd)+1) * sizeof(char)); |
|||
|
|||
FILE *fp = fopen(secretfile, "rb"); |
|||
fseek(fp, 0L, SEEK_END); |
|||
long file_size = ftell(fp); |
|||
rewind(fp); |
|||
int bytes_to_read = (maxSize >= file_size)? file_size:(maxSize); |
|||
fread(buf, 1, bytes_to_read, fp); |
|||
if (memcmp(buf, strMAGIC, magicSize)) { |
|||
bytes_to_read = ((unsigned long) bytes_to_read>MAX_SECRET_SIZE) ? MAX_SECRET_SIZE : bytes_to_read; |
|||
memcpy(secret, buf, bytes_to_read); |
|||
secret[bytes_to_read] = '\0'; |
|||
} else { |
|||
unsigned char salt[magicSize]; |
|||
unsigned char *key = new unsigned char[keySize32]; |
|||
unsigned char *iv = new unsigned char[ivSize16]; |
|||
memcpy(&salt, buf + magicSize, magicSize); |
|||
memcpy(_initPwd, initialPwd, strlen(initialPwd)); |
|||
_initPwd[strlen(initialPwd)]= '\0'; |
|||
my_bytes_to_key((unsigned char *) salt, _initPwd, key, iv); |
|||
uint32 d_size = 0; |
|||
/* This should be checked! */ |
|||
(void) my_aes_decrypt_dynamic((const uchar*)buf + 2 * magicSize, |
|||
bytes_to_read - 2 * magicSize, |
|||
(uchar*)secret, &d_size, |
|||
(const uchar*)key, keySize32, |
|||
iv, ivSize16, 0); |
|||
if (d_size>EncKeys::MAX_SECRET_SIZE) { |
|||
d_size = EncKeys::MAX_SECRET_SIZE; |
|||
} |
|||
secret[d_size] = '\0'; |
|||
delete[] key; |
|||
delete[] iv; |
|||
} |
|||
free(buf); |
|||
free(_initPwd); |
|||
fclose(fp); |
|||
} |
|||
|
|||
/**
|
|||
* Returns a struct keyentry with the asked 'id' or NULL. |
|||
*/ |
|||
keyentry *EncKeys::getKeys(int id) { |
|||
if (KEY_MIN <= id && KEY_MAX >= id && (&keys[id - 1])->iv) |
|||
{ |
|||
return &keys[id - 1]; |
|||
} |
|||
#ifdef UNIV_DEBUG
|
|||
else { |
|||
|
|||
fprintf(stderr, errorNoKeyId, id); |
|||
return NULL; |
|||
} |
|||
#endif //UNIV_DEBUG
|
|||
} |
|||
|
|||
/**
|
|||
* Get the keys from the key file <filename> and decrypt it with the key <secret>. |
|||
* Store the keys with id smaller then <maxKeyId> in an array of structs keyentry. |
|||
* Returns NO_ERROR_PARSE_OK or an appropriate error code. |
|||
*/ |
|||
int EncKeys::parseFile(const char* filename, const ulint maxKeyId, const char *secret) { |
|||
int errorCode = 0; |
|||
char *buffer = decryptFile(filename, secret, &errorCode); |
|||
ulint id = 0; |
|||
|
|||
if (NO_ERROR_PARSE_OK != errorCode) return errorCode; |
|||
else errorCode = NO_ERROR_KEY_FILE_PARSE_OK; |
|||
|
|||
char *line = strtok(buffer, newLine); |
|||
while ( NULL != line) { |
|||
keyLineInKeyFile++; |
|||
switch (parseLine(line, maxKeyId)) { |
|||
case NO_ERROR_PARSE_OK: |
|||
id = oneKey->id; |
|||
keys[oneKey->id - 1] = *oneKey; |
|||
delete(oneKey); |
|||
countKeys++; |
|||
fprintf(stderr, "Line: %lu --> ", keyLineInKeyFile); printKeyEntry(id); |
|||
break; |
|||
case ERROR_ID_TOO_BIG: |
|||
fprintf(stderr, errorExceedKeySize, KEY_MAX, keyLineInKeyFile); |
|||
fprintf(stderr, " --> %s\n", line); |
|||
errorCode = ERROR_KEY_FILE_EXCEEDS_MAX_NUMBERS_OF_KEYS; |
|||
break; |
|||
case ERROR_NOINITIALIZEDKEY: |
|||
fprintf(stderr, errorNoInitializedKey); |
|||
fprintf(stderr, " --> %s\n", line); |
|||
errorCode = ERROR_KEY_FILE_PARSE_NULL; |
|||
break; |
|||
case ERROR_WRONG_NUMBER_OF_MATCHES: |
|||
fprintf(stderr, errorInMatches, keyLineInKeyFile); |
|||
fprintf(stderr, " --> %s\n", line); |
|||
errorCode = ERROR_KEY_FILE_PARSE_NULL; |
|||
break; |
|||
case NO_ERROR_KEY_GREATER_THAN_ASKED: |
|||
fprintf(stderr, "No asked key in line %lu: %s\n", keyLineInKeyFile, line); |
|||
break; |
|||
case NO_ERROR_ISCOMMENT: |
|||
fprintf(stderr, "Is comment in line %lu: %s\n", keyLineInKeyFile, line); |
|||
default: |
|||
break; |
|||
} |
|||
line = strtok(NULL, newLine); |
|||
} |
|||
|
|||
free(line); line = NULL; |
|||
delete[] buffer; buffer = NULL; |
|||
return errorCode; |
|||
} |
|||
|
|||
int EncKeys::parseLine(const char *line, const ulint maxKeyId) { |
|||
int ret = NO_ERROR_PARSE_OK; |
|||
if (isComment(line)) |
|||
ret = NO_ERROR_ISCOMMENT; |
|||
else { |
|||
const char *error_p = NULL; |
|||
int offset; |
|||
pcre *pattern = pcre_compile( |
|||
"([0-9]+);([0-9,a-f,A-F]{32});([0-9,a-f,A-F]{64}|[0-9,a-f,A-F]{48}|[0-9,a-f,A-F]{32})", |
|||
0, &error_p, &offset, NULL); |
|||
if ( NULL != error_p) |
|||
fprintf(stderr, "Error: %s\nOffset: %d\n", error_p, offset); |
|||
|
|||
int m_len = (int) strlen(line), ovector[MAX_OFFSETS_IN_PCRE_PATTERNS]; |
|||
int rc = pcre_exec(pattern, NULL, line, m_len, 0, 0, ovector, MAX_OFFSETS_IN_PCRE_PATTERNS); |
|||
pcre_free(pattern); |
|||
if (4 == rc) { |
|||
char lin[MAX_KEY_LINE_SIZE + 1]; |
|||
strncpy( lin, line, MAX_KEY_LINE_SIZE); |
|||
lin[MAX_KEY_LINE_SIZE] = '\0'; |
|||
char *substring_start = lin + ovector[2]; |
|||
int substr_length = ovector[3] - ovector[2]; |
|||
if (3 < substr_length) |
|||
ret = ERROR_ID_TOO_BIG; |
|||
else { |
|||
char buffer[4]; |
|||
sprintf(buffer, "%.*s", substr_length, substring_start); |
|||
ulint id = atoi(buffer); |
|||
if (0 == id) ret = ERROR_NOINITIALIZEDKEY; |
|||
else if (KEY_MAX < id) ret = ERROR_ID_TOO_BIG; |
|||
else if (maxKeyId < id) ret = NO_ERROR_KEY_GREATER_THAN_ASKED; |
|||
else { |
|||
oneKey = new keyentry; |
|||
oneKey->id = id; |
|||
substring_start = lin + ovector[4]; |
|||
substr_length = ovector[5] - ovector[4]; |
|||
oneKey->iv = new char[substr_length + 1]; |
|||
sprintf(oneKey->iv, "%.*s", substr_length, substring_start); |
|||
substring_start = lin + ovector[6]; |
|||
substr_length = ovector[7] - ovector[6]; |
|||
oneKey->key = new char[substr_length + 1]; |
|||
sprintf(oneKey->key, "%.*s", substr_length, substring_start); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
ret = ERROR_WRONG_NUMBER_OF_MATCHES; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
/**
|
|||
* Decrypt the key file 'filename' if it is encrypted with the key 'secret'. |
|||
* Store the content of the decrypted file in 'buffer'. The buffer has to be freed |
|||
* in the calling function. |
|||
*/ |
|||
char* EncKeys::decryptFile(const char* filename, const char *secret, int *errorCode) { |
|||
*errorCode = NO_ERROR_PARSE_OK; |
|||
fprintf(stderr, "Reading %s\n\n", filename); |
|||
FILE *fp = fopen(filename, "rb"); |
|||
if (NULL == fp) { |
|||
fprintf(stderr, errorOpenFile, filename); |
|||
*errorCode = ERROR_OPEN_FILE; |
|||
return NULL; |
|||
} |
|||
|
|||
if (fseek(fp, 0L, SEEK_END)) { |
|||
*errorCode = ERROR_READING_FILE; |
|||
return NULL; |
|||
} |
|||
long file_size = ftell(fp); // get the file size
|
|||
if (MAX_KEY_FILE_SIZE < file_size) { |
|||
fprintf(stderr, errorExceedKeyFileSize, filename, MAX_KEY_FILE_SIZE); |
|||
*errorCode = ERROR_KEY_FILE_TOO_BIG; |
|||
fclose(fp); |
|||
return NULL; |
|||
} |
|||
else if (-1L == file_size) { |
|||
fprintf(stderr, errorFileSize, filename); |
|||
*errorCode = ERROR_READING_FILE; |
|||
return NULL; |
|||
} |
|||
|
|||
rewind(fp); |
|||
//Read file into buffer
|
|||
uchar *buffer = new uchar[file_size + 1]; |
|||
file_size= fread(buffer, 1, file_size, fp); |
|||
buffer[file_size] = '\0'; |
|||
fclose(fp); |
|||
//Check for file encryption
|
|||
if (0 == memcmp(buffer, strMAGIC, magicSize)) { //If file is encrypted, decrypt it first.
|
|||
unsigned char salt[magicSize]; |
|||
unsigned char *key = new unsigned char[keySize32]; |
|||
unsigned char *iv = new unsigned char[ivSize16]; |
|||
uchar *decrypted = new uchar[file_size]; |
|||
memcpy(&salt, buffer + magicSize, magicSize); |
|||
my_bytes_to_key((unsigned char *) salt, secret, key, iv); |
|||
uint32 d_size = 0; |
|||
int res = my_aes_encrypt_dynamic((const uchar*)buffer + 2 * magicSize, file_size - 2 * magicSize, |
|||
decrypted, &d_size, (const uchar*) key, keySize32, iv, ivSize16, 0); |
|||
if(0 != res) { |
|||
*errorCode = ERROR_FALSE_FILE_KEY; |
|||
delete[] buffer; buffer = NULL; |
|||
fprintf(stderr, errorFalseFileKey, filename); |
|||
} |
|||
else { |
|||
memcpy(buffer, decrypted, d_size); |
|||
buffer[d_size] = '\0'; |
|||
} |
|||
|
|||
delete[] decrypted; decrypted = NULL; |
|||
delete[] key; key = NULL; |
|||
delete[] iv; iv = NULL; |
|||
} |
|||
return (char*) buffer; |
|||
} |
|||
|
|||
bool EncKeys::isComment(const char *line) { |
|||
const char *error_p; |
|||
int offset, m_len = (int) strlen(line), ovector[MAX_OFFSETS_IN_PCRE_PATTERNS]; |
|||
pcre *pattern = pcre_compile("\\s*#.*", 0, &error_p, &offset, NULL); |
|||
int rc = pcre_exec( pattern, NULL, line, m_len, 0, 0, ovector, MAX_OFFSETS_IN_PCRE_PATTERNS); |
|||
pcre_free(pattern); |
|||
if (0 > rc) return false; |
|||
else return true; |
|||
} |
|||
|
|||
|
|||
void EncKeys::printKeyEntry( ulint id) |
|||
{ |
|||
#ifdef UNIV_DEBUG
|
|||
keyentry *entry = getKeys(id); |
|||
if( NULL == entry) { |
|||
fprintf(stderr, "No such keyID=%lu\n",id); |
|||
} |
|||
else { |
|||
fprintf(stderr, "Key: id:%3lu \tiv:%lu bytes\tkey:%lu bytes\n", entry->id, strlen(entry->iv)/2, strlen(entry->key)/2); |
|||
} |
|||
#endif //UNIV_DEBUG
|
|||
} |
@ -1,68 +0,0 @@ |
|||
/* Copyright (C) 2014 eperi GmbH. All Rights Reserved.
|
|||
|
|||
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 KeySingleton.cc |
|||
Implementation of single pattern to keep keys for encrypting/decrypting pages. |
|||
|
|||
Created 09/13/2014 |
|||
***********************************************************************/ |
|||
|
|||
|
|||
#include "KeySingleton.h"
|
|||
#include <stdlib.h>
|
|||
#include <my_aes.h>
|
|||
|
|||
|
|||
bool KeySingleton::instanceInited = false; |
|||
KeySingleton KeySingleton::theInstance; |
|||
EncKeys KeySingleton::encKeys; |
|||
|
|||
|
|||
|
|||
KeySingleton & KeySingleton::getInstance() { |
|||
#ifdef UNIV_DEBUG
|
|||
if( !instanceInited) { |
|||
fprintf(stderr, "Encryption / decryption keys were not initialized. " |
|||
"You can not read encrypted tables or columns\n"); |
|||
} |
|||
#endif /* UNIV_DEBUG */
|
|||
return theInstance; |
|||
} |
|||
|
|||
KeySingleton & KeySingleton::getInstance(const char *name, const char *url, |
|||
const int initType, const char *filekey) { |
|||
|
|||
if(instanceInited) return theInstance; |
|||
instanceInited = encKeys.initKeys(name, url, initType, filekey); |
|||
if( !instanceInited) { |
|||
fprintf(stderr, "Could not initialize any of the encryption / decryption keys. " |
|||
"You can not read encrypted tables\n\n"); |
|||
fflush(stderr); |
|||
} else { |
|||
my_aes_init_dynamic_encrypt(MY_AES_ALGORITHM_CTR); |
|||
} |
|||
|
|||
return theInstance; |
|||
} |
|||
|
|||
keyentry *KeySingleton::getKeys(int id) { |
|||
return encKeys.getKeys(id); |
|||
} |
|||
|
|||
ibool KeySingleton::hasKey(int id) { |
|||
return encKeys.getKeys(id) != NULL; |
|||
} |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue