mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
remove old my_aes_encrypt/decrypt
and simplify Item_func_aes_encrypt/decrypt
This commit is contained in:
parent
91f7363e4b
commit
b937574293
4 changed files with 52 additions and 331 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
String *Item_func_aes_encrypt::val_str(String *str)
|
||||
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_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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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_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_str_func(a,b) {}
|
||||
String *val_str(String *);
|
||||
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"; }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue