diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-03-25 19:36:10 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-04-08 10:58:46 +0200 |
commit | b937574293ee731dc7b5c949d27fede1f5d17db5 (patch) | |
tree | 3f75c7eb84197a885df6a2d16f453afe27dee1ba | |
parent | 91f7363e4baff9debe43cf039fe4525c43aee4cc (diff) | |
download | mariadb-git-b937574293ee731dc7b5c949d27fede1f5d17db5.tar.gz |
remove old my_aes_encrypt/decrypt
and simplify Item_func_aes_encrypt/decrypt
-rw-r--r-- | include/my_aes.h | 49 | ||||
-rw-r--r-- | mysys_ssl/my_aes.cc | 229 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 81 | ||||
-rw-r--r-- | sql/item_strfunc.h | 22 |
4 files changed, 51 insertions, 330 deletions
diff --git a/include/my_aes.h b/include/my_aes.h index 3d9c9c1a8c9..e7376a6b08e 100644 --- a/include/my_aes.h +++ b/include/my_aes.h @@ -47,8 +47,6 @@ typedef int Crypt_result; C_MODE_START -#define AES_KEY_LENGTH 128 /* Must be 128 192 or 256 */ - /** Crypt buffer with AES dynamic (defined at startup) encryption algorithm. @@ -127,53 +125,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; -/** - Crypt buffer with AES encryption algorithm. - - SYNOPSIS - my_aes_encrypt() - - @param source Pointer to data for encryption - @param source_length Size of encryption data - @param dest Buffer to place encrypted data (must be large enough) - @param key Key to be used for encryption - @param kel_length Length of the key. Will handle keys of any length - - @return Size of encrypted data, or negative in case of error. -*/ - -int my_aes_encrypt(const uchar *source, int source_length, uchar *dest, - const char *key, int key_length); - -/** - DeCrypt buffer with AES encryption algorithm. - - SYNOPSIS - my_aes_decrypt() - - @param source Pointer to data for decryption - @param source_length size of encrypted data - @param dest buffer to place decrypted data (must be large enough) - @param key Key to be used for decryption - @param kel_length Length of the key. Will handle keys of any length - - @return size of original data, or negative in case of error. -*/ - - -int my_aes_decrypt(const uchar *source, int source_length, uchar *dest, - const char *key, int key_length); - -/** - get size of buffer which will be large enough for encrypted data - - SYNOPSIS - my_aes_get_size() - @param source_length Length of data to be encrypted - - @return Size of buffer required to store encrypted data -*/ - int my_aes_get_size(int source_length); C_MODE_END diff --git a/mysys_ssl/my_aes.cc b/mysys_ssl/my_aes.cc index 0a81cef9ab1..97af3c39381 100644 --- a/mysys_ssl/my_aes.cc +++ b/mysys_ssl/my_aes.cc @@ -13,93 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include <my_global.h> #include <m_string.h> #include <my_aes.h> #include <my_crypt.h> -#if defined(HAVE_YASSL) -#include "aes.hpp" -#include "openssl/ssl.h" -#include "crypto_wrapper.hpp" -#elif defined(HAVE_OPENSSL) -#include <openssl/aes.h> -#include <openssl/evp.h> -#include <openssl/buffer.h> -#include <openssl/conf.h> - -// Wrap C struct, to ensure resources are released. -struct MyCipherCtx -{ - MyCipherCtx() { memset(&ctx, 0, sizeof(ctx)); } - ~MyCipherCtx() { EVP_CIPHER_CTX_cleanup(&ctx); } - - EVP_CIPHER_CTX ctx; -}; -#endif - -enum encrypt_dir { MY_AES_ENCRYPT, MY_AES_DECRYPT }; - -/** - This is internal function just keeps joint code of Key generation - - SYNOPSIS - my_aes_create_key() - @param key [in] Key to use for real key creation - @param key_length [in] Length of the key - @param rkey [out] Real key (used by OpenSSL/YaSSL) - - @return - 0 Ok - -1 Error; Note: The current impementation never returns this -*/ - -static int my_aes_create_key(const char *key, int key_length, uint8 *rkey) -{ - uint8 *rkey_end= rkey + AES_KEY_LENGTH / 8; /* Real key boundary */ - uint8 *ptr; /* Start of the real key*/ - const char *sptr; /* Start of the working key */ - const char *key_end= key + key_length; /* Working key boundary*/ - - memset(rkey, 0, AES_KEY_LENGTH / 8); /* Set initial key */ - - for (ptr= rkey, sptr= key; sptr < key_end; ptr ++, sptr ++) - { - if (ptr == rkey_end) - /* Just loop over tmp_key until we used all key */ - ptr= rkey; - *ptr ^= (uint8) *sptr; - } -#ifdef AES_USE_KEY_BITS - /* - This block is intended to allow more weak encryption if application - build with libmysqld needs to correspond to export regulations - It should be never used in normal distribution as does not give - any speed improvement. - To get worse security define AES_USE_KEY_BITS to number of bits - you want key to be. It should be divisible by 8 - - WARNING: Changing this value results in changing of enryption for - all key lengths so altering this value will result in impossibility - to decrypt data encrypted with previous value - */ -#define AES_USE_KEY_BYTES (AES_USE_KEY_BITS/8) - /* - To get weaker key we use first AES_USE_KEY_BYTES bytes of created key - and cyclically copy them until we created all required key length - */ - for (ptr= rkey+AES_USE_KEY_BYTES, sptr=rkey ; ptr < rkey_end; - ptr ++, sptr ++) - { - if (sptr == rkey + AES_USE_KEY_BYTES) - sptr= rkey; - *ptr= *sptr; - } -#endif - return 0; -} - /** Encryption interface that doesn't do anything (for testing) @@ -258,153 +176,6 @@ get_aes_encrypt_func(enum_my_aes_encryption_algorithm method) return NULL; } - -/**************************************************************** - Encryption function visible to MariaDB users -****************************************************************/ - -int my_aes_encrypt(const uchar* source, int source_length, uchar* dest, - const char* key, int key_length) -{ -#if defined(HAVE_YASSL) - TaoCrypt::AES_ECB_Encryption enc; - - /* 128 bit block used for padding */ - uint8 block[MY_AES_BLOCK_SIZE]; - int num_blocks; /* number of complete blocks */ - int i; -#elif defined(HAVE_OPENSSL) - MyCipherCtx ctx; - int u_len, f_len; -#endif - - /* The real key to be used for encryption */ - uint8 rkey[AES_KEY_LENGTH / 8]; - int rc; /* result codes */ - - if ((rc= my_aes_create_key(key, key_length, rkey))) - return rc; - -#if defined(HAVE_YASSL) - enc.SetKey((const TaoCrypt::byte *) rkey, MY_AES_BLOCK_SIZE); - - num_blocks = source_length / MY_AES_BLOCK_SIZE; - - for (i = num_blocks; i > 0; i--) /* Encode complete blocks */ - { - enc.Process((TaoCrypt::byte *) dest, (const TaoCrypt::byte *) source, - MY_AES_BLOCK_SIZE); - source += MY_AES_BLOCK_SIZE; - dest += MY_AES_BLOCK_SIZE; - } - - /* Encode the rest. We always have incomplete block */ - char pad_len = MY_AES_BLOCK_SIZE - (source_length - - MY_AES_BLOCK_SIZE * num_blocks); - memcpy(block, source, 16 - pad_len); - memset(block + MY_AES_BLOCK_SIZE - pad_len, pad_len, pad_len); - - enc.Process((TaoCrypt::byte *) dest, (const TaoCrypt::byte *) block, - MY_AES_BLOCK_SIZE); - - return MY_AES_BLOCK_SIZE * (num_blocks + 1); -#elif defined(HAVE_OPENSSL) - if (! EVP_EncryptInit(&ctx.ctx, EVP_aes_128_ecb(), - (const unsigned char *) rkey, NULL)) - return AES_BAD_DATA; /* Error */ - if (! EVP_EncryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len, - (unsigned const char *) source, source_length)) - return AES_BAD_DATA; /* Error */ - if (! EVP_EncryptFinal(&ctx.ctx, (unsigned char *) dest + u_len, &f_len)) - return AES_BAD_DATA; /* Error */ - - return u_len + f_len; -#endif -} - - -/** - DeCrypt buffer with AES encryption algorithm. - - SYNOPSIS - my_aes_decrypt() - @param source [in] Pointer to data for decryption - @param source_length [in] Size of encrypted data - @param dest [out] Buffer to place decrypted data (must - be large enough) - @param key [in] Key to be used for decryption - @param key_length [in] Length of the key. Will handle keys of any length - - @return - >= 0 Size of encrypted data - < 0 Error -*/ - -int my_aes_decrypt(const uchar *source, int source_length, uchar *dest, - const char *key, int key_length) -{ -#if defined(HAVE_YASSL) - TaoCrypt::AES_ECB_Decryption dec; - /* 128 bit block used for padding */ - uint8 block[MY_AES_BLOCK_SIZE]; - int num_blocks; /* Number of complete blocks */ - int i; -#elif defined(HAVE_OPENSSL) - MyCipherCtx ctx; - int u_len, f_len; -#endif - - /* The real key to be used for decryption */ - uint8 rkey[AES_KEY_LENGTH / 8]; - int rc; /* Result codes */ - - if ((rc= my_aes_create_key(key, key_length, rkey))) - return rc; - -#if defined(HAVE_YASSL) - dec.SetKey((const TaoCrypt::byte *) rkey, MY_AES_BLOCK_SIZE); - - num_blocks = source_length / MY_AES_BLOCK_SIZE; - - if ((source_length != num_blocks * MY_AES_BLOCK_SIZE) || num_blocks == 0 ) - /* Input size has to be even and at least one block */ - return AES_BAD_DATA; - - /* Decode all but last blocks */ - for (i = num_blocks - 1; i > 0; i--) - { - dec.Process((TaoCrypt::byte *) dest, (const TaoCrypt::byte *) source, - MY_AES_BLOCK_SIZE); - source += MY_AES_BLOCK_SIZE; - dest += MY_AES_BLOCK_SIZE; - } - - dec.Process((TaoCrypt::byte *) block, (const TaoCrypt::byte *) source, - MY_AES_BLOCK_SIZE); - - /* Use last char in the block as size */ - uint pad_len = (uint) (uchar) block[MY_AES_BLOCK_SIZE - 1]; - - if (pad_len > MY_AES_BLOCK_SIZE) - return AES_BAD_DATA; - /* We could also check whole padding but we do not really need this */ - - memcpy(dest, block, MY_AES_BLOCK_SIZE - pad_len); - return MY_AES_BLOCK_SIZE * num_blocks - pad_len; -#elif defined(HAVE_OPENSSL) - if (! EVP_DecryptInit(&ctx.ctx, EVP_aes_128_ecb(), - (const unsigned char *) rkey, NULL)) - return AES_BAD_DATA; /* Error */ - if (! EVP_DecryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len, - (unsigned const char *) source, source_length)) - return AES_BAD_DATA; /* Error */ - if (! EVP_DecryptFinal(&ctx.ctx, (unsigned char *) dest + u_len, &f_len)) - return AES_BAD_DATA; /* Error */ - return u_len + f_len; -#endif -} - - /** Get size of buffer which will be large enough for encrypted data diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 32b6d6348ac..544284b2c0b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -366,29 +366,48 @@ void Item_func_sha2::fix_length_and_dec() } /* Implementation of AES encryption routines */ +void Item_aes_crypt::create_key(String *user_key, uchar *real_key) +{ + uchar *real_key_end= real_key + AES_KEY_LENGTH / 8; + uchar *ptr; + const char *sptr= user_key->ptr(); + const char *key_end= sptr + user_key->length(); + + bzero(real_key, AES_KEY_LENGTH / 8); + + for (ptr= real_key; sptr < key_end; ptr++, sptr++) + { + if (ptr == real_key_end) + ptr= real_key; + *ptr ^= (uchar) *sptr; + } +} + -String *Item_func_aes_encrypt::val_str(String *str) +String *Item_aes_crypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); - char key_buff[80]; - String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info); - String *sptr= args[0]->val_str(str); // String to encrypt - String *key= args[1]->val_str(&tmp_key_value); // key - int aes_length; - if (sptr && key) // we need both arguments to be not NULL + StringBuffer<80> user_key_buf; + String *sptr= args[0]->val_str(str); + String *user_key= args[1]->val_str(&user_key_buf); + uint32 aes_length; + + if (sptr && user_key) // we need both arguments to be not NULL { null_value=0; aes_length=my_aes_get_size(sptr->length()); // Calculate result length if (!str_value.alloc(aes_length)) // Ensure that memory is free { - // finally encrypt directly to allocated buffer. - if (my_aes_encrypt((const uchar*) sptr->ptr(), sptr->length(), (uchar*) str_value.ptr(), - key->ptr(), key->length()) == aes_length) + uchar rkey[AES_KEY_LENGTH / 8]; + create_key(user_key, rkey); + + if (crypt((uchar*)sptr->ptr(), sptr->length(), + (uchar*)str_value.ptr(), &aes_length, + rkey, AES_KEY_LENGTH / 8, 0, 0, 0) == AES_OK) { - // We got the expected result length - str_value.length((uint) aes_length); - return &str_value; + str_value.length((uint) aes_length); + return &str_value; } } } @@ -396,43 +415,10 @@ String *Item_func_aes_encrypt::val_str(String *str) return 0; } - void Item_func_aes_encrypt::fix_length_and_dec() { max_length=my_aes_get_size(args[0]->max_length); -} - - -String *Item_func_aes_decrypt::val_str(String *str) -{ - DBUG_ASSERT(fixed == 1); - char key_buff[80]; - String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info); - String *sptr, *key; - DBUG_ENTER("Item_func_aes_decrypt::val_str"); - - sptr= args[0]->val_str(str); // String to decrypt - key= args[1]->val_str(&tmp_key_value); // Key - if (sptr && key) // Need to have both arguments not NULL - { - null_value=0; - if (!str_value.alloc(sptr->length())) // Ensure that memory is free - { - // finally decrypt directly to allocated buffer. - int length; - length=my_aes_decrypt((const uchar*)sptr->ptr(), sptr->length(), - (uchar*) str_value.ptr(), - key->ptr(), key->length()); - if (length >= 0) // if we got correct data data - { - str_value.length((uint) length); - DBUG_RETURN(&str_value); - } - } - } - // Bad parameters. No memory or bad data will all go here - null_value=1; - DBUG_RETURN(0); + crypt= my_aes_encrypt_ecb; } @@ -440,6 +426,7 @@ void Item_func_aes_decrypt::fix_length_and_dec() { max_length=args[0]->max_length; maybe_null= 1; + crypt= my_aes_decrypt_ecb; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index b79009c6778..e11d2c41bc6 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -134,21 +134,33 @@ public: const char *func_name() const { return "from_base64"; } }; +#include <my_crypt.h> -class Item_func_aes_encrypt :public Item_str_func +class Item_aes_crypt :public Item_str_func { + enum { AES_KEY_LENGTH = 128 }; + void create_key(String *user_key, uchar* key); + +protected: + my_aes_encrypt_dynamic_type crypt; + public: - Item_func_aes_encrypt(Item *a, Item *b) :Item_str_func(a,b) {} + Item_aes_crypt(Item *a, Item *b) :Item_str_func(a,b) {} String *val_str(String *); +}; + +class Item_func_aes_encrypt :public Item_aes_crypt +{ +public: + Item_func_aes_encrypt(Item *a, Item *b) :Item_aes_crypt(a,b) {} void fix_length_and_dec(); const char *func_name() const { return "aes_encrypt"; } }; -class Item_func_aes_decrypt :public Item_str_func +class Item_func_aes_decrypt :public Item_aes_crypt { public: - Item_func_aes_decrypt(Item *a, Item *b) :Item_str_func(a,b) {} - String *val_str(String *); + Item_func_aes_decrypt(Item *a, Item *b) :Item_aes_crypt(a,b) {} void fix_length_and_dec(); const char *func_name() const { return "aes_decrypt"; } }; |