remove old my_aes_encrypt/decrypt
and simplify Item_func_aes_encrypt/decrypt
This commit is contained in:
parent
91f7363e4b
commit
b937574293
@ -47,8 +47,6 @@ typedef int Crypt_result;
|
|||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
|
|
||||||
#define AES_KEY_LENGTH 128 /* Must be 128 192 or 256 */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Crypt buffer with AES dynamic (defined at startup) encryption algorithm.
|
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;
|
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);
|
int my_aes_get_size(int source_length);
|
||||||
|
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
@ -13,93 +13,11 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
|
||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <my_aes.h>
|
#include <my_aes.h>
|
||||||
#include <my_crypt.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)
|
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;
|
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
|
Get size of buffer which will be large enough for encrypted data
|
||||||
|
|
||||||
|
@ -366,27 +366,46 @@ void Item_func_sha2::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Implementation of AES encryption routines */
|
/* 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);
|
DBUG_ASSERT(fixed == 1);
|
||||||
char key_buff[80];
|
StringBuffer<80> user_key_buf;
|
||||||
String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
|
String *sptr= args[0]->val_str(str);
|
||||||
String *sptr= args[0]->val_str(str); // String to encrypt
|
String *user_key= args[1]->val_str(&user_key_buf);
|
||||||
String *key= args[1]->val_str(&tmp_key_value); // key
|
uint32 aes_length;
|
||||||
int aes_length;
|
|
||||||
if (sptr && key) // we need both arguments to be not NULL
|
if (sptr && user_key) // we need both arguments to be not NULL
|
||||||
{
|
{
|
||||||
null_value=0;
|
null_value=0;
|
||||||
aes_length=my_aes_get_size(sptr->length()); // Calculate result length
|
aes_length=my_aes_get_size(sptr->length()); // Calculate result length
|
||||||
|
|
||||||
if (!str_value.alloc(aes_length)) // Ensure that memory is free
|
if (!str_value.alloc(aes_length)) // Ensure that memory is free
|
||||||
{
|
{
|
||||||
// finally encrypt directly to allocated buffer.
|
uchar rkey[AES_KEY_LENGTH / 8];
|
||||||
if (my_aes_encrypt((const uchar*) sptr->ptr(), sptr->length(), (uchar*) str_value.ptr(),
|
create_key(user_key, rkey);
|
||||||
key->ptr(), key->length()) == aes_length)
|
|
||||||
|
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);
|
str_value.length((uint) aes_length);
|
||||||
return &str_value;
|
return &str_value;
|
||||||
}
|
}
|
||||||
@ -396,43 +415,10 @@ String *Item_func_aes_encrypt::val_str(String *str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_aes_encrypt::fix_length_and_dec()
|
void Item_func_aes_encrypt::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
max_length=my_aes_get_size(args[0]->max_length);
|
max_length=my_aes_get_size(args[0]->max_length);
|
||||||
}
|
crypt= my_aes_encrypt_ecb;
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -440,6 +426,7 @@ void Item_func_aes_decrypt::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
max_length=args[0]->max_length;
|
max_length=args[0]->max_length;
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
|
crypt= my_aes_decrypt_ecb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,21 +134,33 @@ public:
|
|||||||
const char *func_name() const { return "from_base64"; }
|
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:
|
public:
|
||||||
Item_func_aes_encrypt(Item *a, Item *b) :Item_str_func(a,b) {}
|
Item_func_aes_encrypt(Item *a, Item *b) :Item_aes_crypt(a,b) {}
|
||||||
String *val_str(String *);
|
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
const char *func_name() const { return "aes_encrypt"; }
|
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:
|
public:
|
||||||
Item_func_aes_decrypt(Item *a, Item *b) :Item_str_func(a,b) {}
|
Item_func_aes_decrypt(Item *a, Item *b) :Item_aes_crypt(a,b) {}
|
||||||
String *val_str(String *);
|
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
const char *func_name() const { return "aes_decrypt"; }
|
const char *func_name() const { return "aes_decrypt"; }
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user