From 6a7ee5a5a540f2c69c8b56448e06098d368ecdb4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 26 Mar 2015 17:16:37 +0100 Subject: [PATCH] encryption cleanup: small changes * comments * move my_bytes_to_key() and my_aes_hex2uint() into file_key_management_plugin * rename HA_INSERT_ORDER -> HA_PRESERVE_INSERT_ORDER * remove unused variables and declarations * fix casts * don't link innodb with pcre * remove redundant entries from aria's TARGET_LINK_LIBRARIES --- include/my_aes.h | 36 +------ include/my_base.h | 2 +- include/my_dbug.h | 3 - include/my_md5.h | 2 +- mysys_ssl/my_aes.cc | 95 ------------------- .../CMakeLists.txt | 6 +- .../example_key_management_plugin.cc | 29 +++++- plugin/file_key_management_plugin/EncKeys.cc | 2 - plugin/file_key_management_plugin/EncKeys.h | 27 +++++- .../file_key_management_plugin.cc | 95 +++++++++++++++++++ sql/sql_plugin.cc | 2 +- sql/sql_select.cc | 5 +- storage/innobase/CMakeLists.txt | 2 +- storage/maria/CMakeLists.txt | 2 +- storage/maria/ma_create.c | 2 +- storage/maria/ma_crypt.c | 33 ++++--- storage/maria/ma_crypt.h | 21 +++- 17 files changed, 200 insertions(+), 164 deletions(-) diff --git a/include/my_aes.h b/include/my_aes.h index 057fa1e9860..3d9c9c1a8c9 100644 --- a/include/my_aes.h +++ b/include/my_aes.h @@ -1,4 +1,5 @@ /* Copyright (c) 2002, 2006 MySQL AB, 2009 Sun Microsystems, Inc. + Copyright (c) 2014, 2015 MariaDB Corporation Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -21,7 +22,6 @@ #ifndef MY_AES_INCLUDED #define MY_AES_INCLUDED -/* We expect same result code from encryption functions as in my_aes.h */ typedef int Crypt_result; #define AES_OK 0 @@ -36,7 +36,7 @@ typedef int Crypt_result; #define CRYPT_BUFFER_TO_SMALL -11 #define CRYPT_KEY_UNKNOWN -48 -/* The max block sizes of all supported algorithms */ +/* The block size for all supported algorithms */ #define MY_AES_BLOCK_SIZE 16 /* The max key length of all supported algorithms */ @@ -127,38 +127,6 @@ my_bool my_aes_init_dynamic_encrypt(enum enum_my_aes_encryption_algorithm method extern MYSQL_PLUGIN_IMPORT enum enum_my_aes_encryption_algorithm current_aes_dynamic_method; - - -/** - Calculate key and iv from a given salt and secret as it is handled in openssl - encrypted files via console - - SYNOPSIS - my_bytes_to_key() - - @param salt [in] the given salt as extracted from the encrypted file - @param secret [in] the given secret as String, provided by the user - @param key [out] 32 Bytes of key are written to this pointer - @param iv [out] 16 Bytes of iv are written to this pointer - */ - -void my_bytes_to_key(const uchar *salt, - const char *secret, uchar *key, - uchar *iv); - -/** - Decode Hexencoded String to uint8[]. - - SYNOPSIS - my_aes_hex2uint() - @param iv [in] Pointer to hexadecimal encoded IV String - @param dest [out] Pointer to output uint8 array. Memory needs to be - allocated by caller - @param iv_length [in] Size of destination array. - */ - -void my_aes_hex2uint(const char *in, uchar *out, int dest_length); - /** Crypt buffer with AES encryption algorithm. diff --git a/include/my_base.h b/include/my_base.h index 3f34adcef6d..b0a15a11dc8 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -355,7 +355,7 @@ enum ha_base_keytype { #define HA_CREATE_RELIES_ON_SQL_LAYER 128 #define HA_CREATE_INTERNAL_TABLE 256 #define HA_CREATE_ENCRYPTED 512 -#define HA_INSERT_ORDER 1024 +#define HA_PRESERVE_INSERT_ORDER 1024 /* Flags used by start_bulk_insert */ diff --git a/include/my_dbug.h b/include/my_dbug.h index 8d8d4fabd6c..bcf2015466d 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -176,9 +176,6 @@ extern void _db_suicide_(); #define DBUG_SYNC_POINT(lock_name,lock_timeout) \ debug_sync_point(lock_name,lock_timeout) void debug_sync_point(const char* lock_name, uint lock_timeout); - -/* Extern function for debugging */ -extern void dump_buffer(FILE *stream, unsigned n, const unsigned char* buf); #else #define DBUG_SYNC_POINT(lock_name,lock_timeout) #endif /* EXTRA_DEBUG */ diff --git a/include/my_md5.h b/include/my_md5.h index 34d3e931811..141ea309cae 100644 --- a/include/my_md5.h +++ b/include/my_md5.h @@ -28,7 +28,7 @@ extern "C" { #endif -#define compute_md5_hash(A,B,C) my_md5((unsigned char *)A,B,C) +#define compute_md5_hash(A,B,C) my_md5(A,B,C) /* Convert an array of bytes to a hexadecimal representation. diff --git a/mysys_ssl/my_aes.cc b/mysys_ssl/my_aes.cc index 6486f7447c3..cd28d7ed49f 100644 --- a/mysys_ssl/my_aes.cc +++ b/mysys_ssl/my_aes.cc @@ -100,101 +100,6 @@ static int my_aes_create_key(const char *key, int key_length, uint8 *rkey) return 0; } -/** - Decode Hexencoded String to uint8[]. - - SYNOPSIS - my_aes_hex2uint() - @param iv [in] Pointer to hexadecimal encoded IV String - @param dest [out] Pointer to output uint8 array. Memory allocated by caller - @param iv_length [in] Size of destination array. - */ - -void my_aes_hex2uint(const char* in, unsigned char *out, int dest_length) -{ - const char *pos= in; - int count; - for (count = 0; count < dest_length; count++) - { - uchar res; - sscanf(pos, "%2hhx", &res); - out[count] = res; - pos += 2 * sizeof(char); - } -} - - -/** - Calculate key and iv from a given salt and secret as it is handled - in openssl encrypted files via console - - SYNOPSIS - my_bytes_to_key() - @param salt [in] the given salt as extracted from the encrypted file - @param secret [in] the given secret as String, provided by the user - @param key [out] 32 Bytes of key are written to this pointer - @param iv [out] 16 Bytes of iv are written to this pointer -*/ - -void my_bytes_to_key(const unsigned char *salt, const char *secret, unsigned char *key, - unsigned char *iv) -{ -#ifdef HAVE_YASSL - /* the yassl function has no support for SHA1. Reason unknown. */ - int keyLen = 32; - int ivLen = 16; - int EVP_SALT_SZ = 8; - const int SHA_LEN = 20; - yaSSL::SHA myMD; - uint digestSz = myMD.get_digestSize(); - unsigned char digest[SHA_LEN]; // max size - int sz = strlen(secret); - int count = 1; - int keyLeft = keyLen; - int ivLeft = ivLen; - int keyOutput = 0; - - while (keyOutput < (keyLen + ivLen)) - { - int digestLeft = digestSz; - if (keyOutput) // first time D_0 is empty - myMD.update(digest, digestSz); - myMD.update((yaSSL::byte* )secret, sz); - if (salt) - myMD.update(salt, EVP_SALT_SZ); - myMD.get_digest(digest); - for (int j = 1; j < count; j++) - { - myMD.update(digest, digestSz); - myMD.get_digest(digest); - } - - if (keyLeft) - { - int store = MY_MIN(keyLeft, static_cast(digestSz)); - memcpy(&key[keyLen - keyLeft], digest, store); - - keyOutput += store; - keyLeft -= store; - digestLeft -= store; - } - - if (ivLeft && digestLeft) - { - int store = MY_MIN(ivLeft, digestLeft); - memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store); - - keyOutput += store; - ivLeft -= store; - } - } -#elif defined(HAVE_OPENSSL) - const EVP_CIPHER *type = EVP_aes_256_cbc(); - const EVP_MD *digest = EVP_sha1(); - EVP_BytesToKey(type, digest, salt, (uchar*) secret, strlen(secret), 1, key, iv); -#endif -} - /** Crypt buffer with AES CBC encryption algorithm. diff --git a/plugin/example_key_management_plugin/CMakeLists.txt b/plugin/example_key_management_plugin/CMakeLists.txt index 250f77856c0..95ff433dc43 100644 --- a/plugin/example_key_management_plugin/CMakeLists.txt +++ b/plugin/example_key_management_plugin/CMakeLists.txt @@ -1,4 +1,2 @@ -IF(HAVE_EncryptAes128Ctr) - MYSQL_ADD_PLUGIN(EXAMPLE_KEY_MANAGEMENT_PLUGIN example_key_management_plugin.cc - MODULE_ONLY) -ENDIF() +MYSQL_ADD_PLUGIN(EXAMPLE_KEY_MANAGEMENT_PLUGIN example_key_management_plugin.cc + MODULE_ONLY) diff --git a/plugin/example_key_management_plugin/example_key_management_plugin.cc b/plugin/example_key_management_plugin/example_key_management_plugin.cc index 580e9ea7091..62050eb48f2 100644 --- a/plugin/example_key_management_plugin/example_key_management_plugin.cc +++ b/plugin/example_key_management_plugin/example_key_management_plugin.cc @@ -1,4 +1,29 @@ -// Copyright (C) 2014 Google Inc. +/* + Copyright (c) 2014 Google Inc. + Copyright (c) 2014, 2015 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** + Example key management plugin. It demonstrates how to return + keys on request, how to change them. That the engine can have + different pages in the same tablespace encrypted with different keys + and what the background re-encryption thread does. + + THIS IS AN EXAMPLE ONLY! ENCRYPTION KEYS ARE HARD-CODED AND *NOT* SECRET! + DO NOT USE THIS PLUGIN IN PRODUCTION! EVER! +*/ #include #include @@ -36,7 +61,7 @@ get_latest_key_version() static int get_key(unsigned int version, unsigned char* dstbuf, unsigned buflen) { - char *dst = (char*)dstbuf; // md5 function takes char* as argument... + unsigned char *dst = dstbuf; unsigned len = 0; for (; len + MD5_HASH_SIZE <= buflen; len += MD5_HASH_SIZE) { diff --git a/plugin/file_key_management_plugin/EncKeys.cc b/plugin/file_key_management_plugin/EncKeys.cc index 266a88d2c3f..77e28878832 100644 --- a/plugin/file_key_management_plugin/EncKeys.cc +++ b/plugin/file_key_management_plugin/EncKeys.cc @@ -259,7 +259,6 @@ int EncKeys::parseFile(const char* filename, const uint32 maxKeyId, { int errorCode= 0; char *buffer= decryptFile(filename, secret, &errorCode); - uint32 id= 0; if (errorCode != NO_ERROR_PARSE_OK) return errorCode; @@ -271,7 +270,6 @@ int EncKeys::parseFile(const char* filename, const uint32 maxKeyId, keyLineInKeyFile++; switch (parseLine(line, maxKeyId)) { case NO_ERROR_PARSE_OK: - id= oneKey->id; keys[oneKey->id - 1]= *oneKey; delete(oneKey); countKeys++; diff --git a/plugin/file_key_management_plugin/EncKeys.h b/plugin/file_key_management_plugin/EncKeys.h index c0ab98b8e9d..8d57237f375 100644 --- a/plugin/file_key_management_plugin/EncKeys.h +++ b/plugin/file_key_management_plugin/EncKeys.h @@ -27,9 +27,35 @@ Created 09/15/2014 #include #include +/** + Calculate key and iv from a given salt and secret as it is handled in openssl + encrypted files via console + SYNOPSIS + my_bytes_to_key() + @param salt [in] the given salt as extracted from the encrypted file + @param secret [in] the given secret as String, provided by the user + @param key [out] 32 Bytes of key are written to this pointer + @param iv [out] 16 Bytes of iv are written to this pointer + */ +void my_bytes_to_key(const uchar *salt, + const char *secret, uchar *key, + uchar *iv); + +/** + Decode Hexencoded String to uint8[]. + + SYNOPSIS + my_aes_hex2uint() + @param iv [in] Pointer to hexadecimal encoded IV String + @param dest [out] Pointer to output uint8 array. Memory needs to be + allocated by caller + @param iv_length [in] Size of destination array. + */ + +void my_aes_hex2uint(const char *in, uchar *out, int dest_length); struct keyentry { uint32 id; @@ -37,7 +63,6 @@ struct keyentry { char *key; }; - class EncKeys { private: diff --git a/plugin/file_key_management_plugin/file_key_management_plugin.cc b/plugin/file_key_management_plugin/file_key_management_plugin.cc index cb6485f8596..780aeb81f18 100644 --- a/plugin/file_key_management_plugin/file_key_management_plugin.cc +++ b/plugin/file_key_management_plugin/file_key_management_plugin.cc @@ -42,6 +42,101 @@ static struct st_mysql_sys_var* settings[] = { NULL }; +/** + Decode Hexencoded String to uint8[]. + + SYNOPSIS + my_aes_hex2uint() + @param iv [in] Pointer to hexadecimal encoded IV String + @param dest [out] Pointer to output uint8 array. Memory allocated by caller + @param iv_length [in] Size of destination array. + */ + +void my_aes_hex2uint(const char* in, unsigned char *out, int dest_length) +{ + const char *pos= in; + int count; + for (count = 0; count < dest_length; count++) + { + uchar res; + sscanf(pos, "%2hhx", &res); + out[count] = res; + pos += 2 * sizeof(char); + } +} + + +/** + Calculate key and iv from a given salt and secret as it is handled + in openssl encrypted files via console + + SYNOPSIS + my_bytes_to_key() + @param salt [in] the given salt as extracted from the encrypted file + @param secret [in] the given secret as String, provided by the user + @param key [out] 32 Bytes of key are written to this pointer + @param iv [out] 16 Bytes of iv are written to this pointer +*/ + +void my_bytes_to_key(const unsigned char *salt, const char *secret, unsigned char *key, + unsigned char *iv) +{ +#ifdef HAVE_YASSL + /* the yassl function has no support for SHA1. Reason unknown. */ + int keyLen = 32; + int ivLen = 16; + int EVP_SALT_SZ = 8; + const int SHA_LEN = 20; + yaSSL::SHA myMD; + uint digestSz = myMD.get_digestSize(); + unsigned char digest[SHA_LEN]; // max size + int sz = strlen(secret); + int count = 1; + int keyLeft = keyLen; + int ivLeft = ivLen; + int keyOutput = 0; + + while (keyOutput < (keyLen + ivLen)) + { + int digestLeft = digestSz; + if (keyOutput) // first time D_0 is empty + myMD.update(digest, digestSz); + myMD.update((yaSSL::byte* )secret, sz); + if (salt) + myMD.update(salt, EVP_SALT_SZ); + myMD.get_digest(digest); + for (int j = 1; j < count; j++) + { + myMD.update(digest, digestSz); + myMD.get_digest(digest); + } + + if (keyLeft) + { + int store = MY_MIN(keyLeft, static_cast(digestSz)); + memcpy(&key[keyLen - keyLeft], digest, store); + + keyOutput += store; + keyLeft -= store; + digestLeft -= store; + } + + if (ivLeft && digestLeft) + { + int store = MY_MIN(ivLeft, digestLeft); + memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store); + + keyOutput += store; + ivLeft -= store; + } + } +#elif defined(HAVE_OPENSSL) + const EVP_CIPHER *type = EVP_aes_256_cbc(); + const EVP_MD *digest = EVP_sha1(); + EVP_BytesToKey(type, digest, salt, (uchar*) secret, strlen(secret), 1, key, iv); +#endif +} + /** diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index fe020d36f93..30ab2531a1e 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1616,7 +1616,7 @@ int plugin_init(int *argc, char **argv, int flags) goto err_unlock; /* - initialize the global default storage engine so that it may + set the global default storage engine variable so that it will not be null in any child thread. */ global_system_variables.table_plugin= diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c087732bab1..7cf5f65c350 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16874,7 +16874,6 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, MARIA_UNIQUEDEF uniquedef; TABLE_SHARE *share= table->s; MARIA_CREATE_INFO create_info; - my_bool encrypt= encrypt_tmp_disk_tables; DBUG_ENTER("create_internal_tmp_table"); if (share->keys) @@ -16984,14 +16983,14 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, DYNAMIC_RECORD : BLOCK_RECORD); uint create_flags= HA_CREATE_TMP_TABLE | HA_CREATE_INTERNAL_TABLE; - if (file_type != NO_RECORD && MY_TEST(encrypt)) + if (file_type != NO_RECORD && encrypt_tmp_disk_tables) { /* encryption is only supported for BLOCK_RECORD */ file_type= BLOCK_RECORD; create_flags|= HA_CREATE_ENCRYPTED; if (table->keep_row_order) { - create_flags|= HA_INSERT_ORDER; + create_flags|= HA_PRESERVE_INSERT_ORDER; } if (table->used_for_duplicate_elimination) diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 87c6a1467e6..94a913cbe4c 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -474,5 +474,5 @@ ENDIF() MYSQL_ADD_PLUGIN(innobase ${INNOBASE_SOURCES} STORAGE_ENGINE MODULE_ONLY MODULE_OUTPUT_NAME ha_innodb - LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT} pcre pcreposix) + LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT}) diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index 09c816aee4e..b8e3350ca76 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -64,7 +64,7 @@ IF(NOT WITH_ARIA_STORAGE_ENGINE) ENDIF() TARGET_LINK_LIBRARIES(aria myisam - mysys mysys_ssl ${LIBCRYPT} ${LIBDL} ${SSL_LIBRARIES}) + mysys mysys_ssl) MYSQL_ADD_EXECUTABLE(aria_ftdump maria_ftdump.c COMPONENT Server) TARGET_LINK_LIBRARIES(aria_ftdump aria) diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index b7fcb6b7058..35491b1d31d 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -74,7 +74,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, myf sync_dir= 0; uchar *log_data= NULL; my_bool encrypted= MY_TEST(flags & HA_CREATE_ENCRYPTED); - my_bool insert_order= MY_TEST(flags & HA_INSERT_ORDER); + my_bool insert_order= MY_TEST(flags & HA_PRESERVE_INSERT_ORDER); uint crypt_page_header_space= 0; DBUG_ENTER("maria_create"); DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index 89defe8cec9..f21f2c4d964 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -1,4 +1,19 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. */ +/* + Copyright (c) 2013 Google Inc. + Copyright (c) 2014, 2015 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "ma_crypt.h" @@ -136,12 +151,10 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) return buff + 2 + iv_length; } -static void ma_encrypt(MARIA_CRYPT_DATA *crypt_data, - const uchar *src, uchar *dst, uint size, - uint pageno, LSN lsn, uint *key_version); -static void ma_decrypt(MARIA_CRYPT_DATA *crypt_data, - const uchar *src, uchar *dst, uint size, - uint pageno, LSN lsn, uint key_version); +static void ma_encrypt(MARIA_CRYPT_DATA *, const uchar *, uchar *, uint, + uint, LSN, uint *); +static void ma_decrypt(MARIA_CRYPT_DATA *, const uchar *, uchar *, uint, + uint, LSN, uint); static my_bool ma_crypt_pre_read_hook(PAGECACHE_IO_HOOK_ARGS *args) { @@ -249,7 +262,7 @@ static my_bool ma_crypt_data_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) /* 1 - copy head */ memcpy(dst, src, head); - /* 2 - decrypt page */ + /* 2 - encrypt page */ ma_encrypt(share->crypt_data, src + head, dst + head, size - (head + tail), pageno, lsn, &key_version); @@ -368,7 +381,7 @@ static my_bool ma_crypt_index_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) /* 1 - copy head */ memcpy(dst, src, head); - /* 2 - decrypt page */ + /* 2 - encrypt page */ ma_encrypt(share->crypt_data, src + head, dst + head, size, pageno, lsn, &key_version); /* 3 - copy tail */ @@ -456,6 +469,4 @@ static void ma_decrypt(MARIA_CRYPT_DATA *crypt_data, fatal("failed to decrypt! rc: %d, dstlen: %d size: %d\n", rc, dstlen, (int)size); } - - (void)key_version; } diff --git a/storage/maria/ma_crypt.h b/storage/maria/ma_crypt.h index 76752e19449..309a8300eb8 100644 --- a/storage/maria/ma_crypt.h +++ b/storage/maria/ma_crypt.h @@ -1,7 +1,22 @@ -/* Copyright 2013 Google Inc. All Rights Reserved. */ +/* + Copyright (c) 2013 Google Inc. + Copyright (c) 2014, 2015 MariaDB Corporation -#ifndef _ma_crypt_h -#define _ma_crypt_h + 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 */ + +#ifndef STORAGE_MARIA_MA_CRYPT_INCLUDED +#define STORAGE_MARIA_MA_CRYPT_INCLUDED #include