summaryrefslogtreecommitdiff
path: root/mysys_ssl
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-03-24 20:43:20 +0100
committerSergei Golubchik <serg@mariadb.org>2015-04-05 13:14:37 +0200
commit2f8d101f9eb5193a8a1d5ab5cc8e52d7b52007a4 (patch)
tree5dbab28b47eb9055efeec9a3b2c3cb9fb6bc711e /mysys_ssl
parent27cc252bb73436957120a964734a794ab3fd64ef (diff)
downloadmariadb-git-2f8d101f9eb5193a8a1d5ab5cc8e52d7b52007a4.tar.gz
unify my_{en|de}crypt_{cbc|ecb|ctr}. no yassl support yet.
Diffstat (limited to 'mysys_ssl')
-rw-r--r--mysys_ssl/my_aes.cc530
-rw-r--r--mysys_ssl/my_crypt.cc125
2 files changed, 96 insertions, 559 deletions
diff --git a/mysys_ssl/my_aes.cc b/mysys_ssl/my_aes.cc
index cd28d7ed49f..0a81cef9ab1 100644
--- a/mysys_ssl/my_aes.cc
+++ b/mysys_ssl/my_aes.cc
@@ -101,536 +101,6 @@ static int my_aes_create_key(const char *key, int key_length, uint8 *rkey)
}
/**
- Crypt buffer with AES CBC encryption algorithm.
-
- SYNOPSIS
- my_aes_encrypt_cbc()
- @param source [in] Pointer to data for encryption
- @param source_length [in] Size of encryption data
- @param dest [out] Buffer to place encrypted data (must be large enough)
- @param dest_length [out] Pointer to size of encrypted data
- @param key [in] Key to be used for encryption
- @param key_length [in] Length of the key. 16, 24 or 32
- @param iv [in] Iv to be used for encryption
- @param iv_length [in] Length of the iv. should be 16.
- @param noPadding [in] if set to true, no padding is used. if the input length is not a
- multiple of the AES block size, trailing bytes are only copied to destination buffer.
- This allows currently the same interface for CBC, ECB and CTR encryption.
- @return
- != 0 error
- 0 no error
-*/
-
-static int my_aes_encrypt_cbc(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
-{
- uint8 remaining_bytes = (noPadding == 0) ? 0 : source_length % MY_AES_BLOCK_SIZE;
- source_length = source_length - remaining_bytes;
-
-#ifdef HAVE_YASSL
- TaoCrypt::AES_CBC_Encryption enc;
- /* 128 bit block used for padding */
- uint8 block[MY_AES_BLOCK_SIZE];
- int num_blocks; /* number of complete blocks */
- int i;
- switch(key_length) {
- case 16:
- break;
- case 24:
- break;
- case 32:
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
-
- enc.SetKey((const TaoCrypt::byte *) key, key_length, (const TaoCrypt::byte *) iv);
-
- 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;
- }
-
- if (noPadding) {
- if (remaining_bytes!=0) {
- /* Note that we moved the original pointers above */
- memcpy(dest, source, remaining_bytes);
- }
- *dest_length = MY_AES_BLOCK_SIZE * (num_blocks) + remaining_bytes;
- return AES_OK;
- }
-
- /* 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);
-
- *dest_length = MY_AES_BLOCK_SIZE * (num_blocks + 1);
- return AES_OK;
-#elif defined(HAVE_OPENSSL)
- MyCipherCtx ctx;
- int u_len, f_len;
- /* The real key to be used for encryption */
- const EVP_CIPHER* cipher;
- switch(key_length) {
- case 16:
- cipher = EVP_aes_128_cbc();
- break;
- case 24:
- cipher = EVP_aes_192_cbc();
- break;
- case 32:
- cipher = EVP_aes_256_cbc();
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
- //Initialize Encryption Engine here, default software Engine is default
- ENGINE *engine = NULL;
-
- if (! EVP_EncryptInit_ex(&ctx.ctx, cipher, engine, key, iv))
- return AES_BAD_DATA; /* Error */
- if (noPadding) {
- EVP_CIPHER_CTX_set_padding(&ctx.ctx, 0);
- }
- EVP_CIPHER_CTX_key_length(&ctx.ctx);
- OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx.ctx) == key_length);
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx.ctx) == iv_length);
- OPENSSL_assert(EVP_CIPHER_CTX_block_size(&ctx.ctx) == 16);
- if (! EVP_EncryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len,
- (unsigned const char *) source, source_length))
- return AES_BAD_DATA; /* Error */
- if (! EVP_EncryptFinal_ex(&ctx.ctx, (unsigned char *) dest + u_len, &f_len))
- return AES_BAD_DATA; /* Error */
-
- if (remaining_bytes!=0) {
- memcpy(dest + source_length, source + source_length, remaining_bytes);
- }
- *dest_length = (unsigned long int) (u_len + f_len + remaining_bytes);
-
- return AES_OK;
-#else
- /* currently Open SSL is required */
- return AES_BAD_DATA;
-#endif
-}
-
-
-/**
- Crypt buffer with AES ECB encryption algorithm.
-
- SYNOPSIS
- my_aes_encrypt_ecb()
- @param source [in] Pointer to data for encryption
- @param source_length [in] Size of encryption data
- @param dest [out] Buffer to place encrypted data (must be large enough)
- @param dest_length [out] Pointer to size of encrypted data
- @param key [in] Key to be used for encryption
- @param key_length [in] Length of the key. 16, 24 or 32
- @param iv [in] Iv to be used for encryption
- @param iv_length [in] Length of the iv. should be 16.
- @param noPadding [in] if set to true, no padding is used. if the input length is not a
- multiple of the AES block size, trailing bytes are only copied to destination buffer.
- This allows currently the same interface for CBC, ECB and CTR encryption.
- @return
- != 0 error
- 0 no error
-*/
-
-static int my_aes_encrypt_ecb(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
-{
- uint8 remaining_bytes = (noPadding == 0) ? 0 : source_length % MY_AES_BLOCK_SIZE;
- source_length = source_length - remaining_bytes;
-
-#ifdef 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;
- switch(key_length) {
- case 16:
- break;
- case 24:
- break;
- case 32:
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
-
- enc.SetKey((const TaoCrypt::byte *) key, key_length, (const TaoCrypt::byte *) iv);
-
- 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;
- }
-
- if (noPadding) {
- if (remaining_bytes!=0) {
- /* Note that we moved the original pointers above */
- memcpy(dest, source, remaining_bytes);
- }
- *dest_length = MY_AES_BLOCK_SIZE * (num_blocks) + remaining_bytes;
- return AES_OK;
- }
-
- /* 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);
-
- *dest_length = MY_AES_BLOCK_SIZE * (num_blocks + 1);
- return AES_OK;
-#elif defined(HAVE_OPENSSL)
- MyCipherCtx ctx;
- int u_len, f_len;
- /* The real key to be used for encryption */
- const EVP_CIPHER* cipher;
- switch(key_length) {
- case 16:
- cipher = EVP_aes_128_ecb();
- break;
- case 24:
- cipher = EVP_aes_192_ecb();
- break;
- case 32:
- cipher = EVP_aes_256_ecb();
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
- //Initialize Encryption Engine here, default software Engine is default
- ENGINE *engine = NULL;
-
- if (! EVP_EncryptInit_ex(&ctx.ctx, cipher, engine, key, iv))
- return AES_BAD_DATA; /* Error */
- if (noPadding) {
- EVP_CIPHER_CTX_set_padding(&ctx.ctx, 0);
- }
- EVP_CIPHER_CTX_key_length(&ctx.ctx);
- OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx.ctx) == key_length);
- // ECB does not use IV
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx.ctx) == 0);
- OPENSSL_assert(EVP_CIPHER_CTX_block_size(&ctx.ctx) == 16);
- if (! EVP_EncryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len,
- (unsigned const char *) source, source_length))
- return AES_BAD_DATA; /* Error */
- if (! EVP_EncryptFinal_ex(&ctx.ctx, (unsigned char *) dest + u_len, &f_len))
- return AES_BAD_DATA; /* Error */
-
- if (remaining_bytes!=0)
- memcpy(dest + source_length, source + source_length, remaining_bytes);
-
- *dest_length = (unsigned long int) (u_len + f_len + remaining_bytes);
-
- return AES_OK;
-#else
- /* currently Open SSL is required */
- return AES_BAD_DATA;
-#endif
-}
-
-
-
-/**
- AES decryption - CBC mode
-
- SYNOPSIS
- my_aes_decrypt_cbc()
- @param source [in] Pointer to data to decrypt
- @param source_length [in] Size of data
- @param dest [out] Buffer to place decrypted data (must be large enough)
- @param dest_length [out] Pointer to size of decrypted data
- @param key [in] Key to be used for decryption
- @param key_length [in] Length of the key. 16, 24 or 32
- @param iv [in] Iv to be used for encryption
- @param iv_length [in] Length of the iv. should be 16.
- @param noPadding [in] if set to true, no padding is used. if the input length is not a
- multiple of the AES block size, trailing bytes are only copied to destination buffer.
- This allows currently the same interface for CBC, ECB and CTR encryption.
-
- @return
- != 0 error
- 0 no error
-*/
-
-static int my_aes_decrypt_cbc(const uchar* source, uint32 source_length,
- uchar* dest, uint32 *dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
-{
- uint8 remaining_bytes = (noPadding == 0) ? 0 : source_length % MY_AES_BLOCK_SIZE;
- source_length = source_length - remaining_bytes;
-
-
-#ifdef HAVE_YASSL
- TaoCrypt::AES_CBC_Decryption dec;
- /* 128 bit block used for padding */
- uint8 block[MY_AES_BLOCK_SIZE];
- uint num_blocks; /* Number of complete blocks */
- int i;
- switch(key_length) {
- case 16:
- break;
- case 24:
- break;
- case 32:
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
-
- dec.SetKey((const TaoCrypt::byte *) key, key_length, iv);
-
- 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);
-
- if (noPadding) {
- memcpy(dest, block, MY_AES_BLOCK_SIZE);
- if (remaining_bytes!=0) {
- /* Note that we have moved dest and source */
- memcpy(dest + MY_AES_BLOCK_SIZE, source + MY_AES_BLOCK_SIZE, remaining_bytes);
- }
- *dest_length = MY_AES_BLOCK_SIZE * num_blocks + remaining_bytes;
- return AES_OK;
- }
-
- /* 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);
- *dest_length = MY_AES_BLOCK_SIZE * num_blocks - pad_len;
- return AES_OK;
-#elif defined(HAVE_OPENSSL)
- MyCipherCtx ctx;
- int u_len, f_len;
-
- const EVP_CIPHER* cipher;
- switch(key_length) {
- case 16:
- cipher = EVP_aes_128_cbc();
- break;
- case 24:
- cipher = EVP_aes_192_cbc();
- break;
- case 32:
- cipher = EVP_aes_256_cbc();
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
- //Initialize Encryption Engine here, default software Engine is default
- ENGINE *engine = NULL;
-
- if (! EVP_DecryptInit_ex(&ctx.ctx, cipher, engine, key, iv))
- return AES_BAD_DATA; /* Error */
- if (noPadding) {
- EVP_CIPHER_CTX_set_padding(&ctx.ctx, 0);
- }
- OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx.ctx) == key_length);
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx.ctx) == iv_length);
- OPENSSL_assert(EVP_CIPHER_CTX_block_size(&ctx.ctx) == 16);
- if (! EVP_DecryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len,
- (unsigned char *)source, source_length))
- return AES_BAD_DATA; /* Error */
- if (! EVP_DecryptFinal_ex(&ctx.ctx, (unsigned char *) dest + u_len, &f_len)) {
- *dest_length = (unsigned long int) u_len;
- return AES_BAD_DATA;
- }
- if (remaining_bytes!=0) {
- memcpy(dest + source_length, source + source_length, remaining_bytes);
- }
- *dest_length = (unsigned long int) (u_len + f_len) + remaining_bytes;
-#endif
- return AES_OK;
-}
-
-/**
- AES decryption - ECB mode
-
- SYNOPSIS
- my_aes_decrypt_ecb()
- @param source [in] Pointer to data to decrypt
- @param source_length [in] Size of data
- @param dest [out] Buffer to place decrypted data (must be large enough)
- @param dest_length [out] Pointer to size of decrypted data
- @param key [in] Key to be used for decryption
- @param key_length [in] Length of the key. 16, 24 or 32
- @param iv [in] Iv to be used for encryption
- @param iv_length [in] Length of the iv. should be 16.
- @param noPadding [in] if set to true, no padding is used. if the input length is not a
- multiple of the AES block size, trailing bytes are only copied to destination buffer.
- This allows currently the same interface for CBC, ECB and CTR encryption.
-
- @return
- != 0 error
- 0 no error
-*/
-
-static int my_aes_decrypt_ecb(const uchar* source, uint32 source_length,
- uchar* dest, uint32 *dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
-{
- uint8 remaining_bytes = (noPadding == 0) ? 0 : source_length % MY_AES_BLOCK_SIZE;
- source_length = source_length - remaining_bytes;
-
-
-#ifdef HAVE_YASSL
- TaoCrypt::AES_ECB_Decryption dec;
- /* 128 bit block used for padding */
- uint8 block[MY_AES_BLOCK_SIZE];
- uint num_blocks; /* Number of complete blocks */
- int i;
- switch(key_length) {
- case 16:
- break;
- case 24:
- break;
- case 32:
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
-
- dec.SetKey((const TaoCrypt::byte *) key, key_length, iv);
-
- 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);
-
- if (noPadding) {
- memcpy(dest, block, MY_AES_BLOCK_SIZE);
- if (remaining_bytes!=0) {
- /* Note that we have moved dest and source */
- memcpy(dest + MY_AES_BLOCK_SIZE, source + MY_AES_BLOCK_SIZE, remaining_bytes);
- }
- *dest_length = MY_AES_BLOCK_SIZE * num_blocks + remaining_bytes;
- return AES_OK;
- }
-
- /* 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);
- *dest_length = MY_AES_BLOCK_SIZE * num_blocks - pad_len;
- return AES_OK;
-#elif defined(HAVE_OPENSSL)
- MyCipherCtx ctx;
- int u_len, f_len;
-
- const EVP_CIPHER* cipher;
- switch(key_length) {
- case 16:
- cipher = EVP_aes_128_ecb();
- break;
- case 24:
- cipher = EVP_aes_192_ecb();
- break;
- case 32:
- cipher = EVP_aes_256_ecb();
- break;
- default:
- return AES_BAD_KEYSIZE;
- }
- //Initialize Encryption Engine here, default software Engine is default
- ENGINE *engine = NULL;
-
- if (! EVP_DecryptInit_ex(&ctx.ctx, cipher, engine, key, iv))
- return AES_BAD_DATA; /* Error */
- if (noPadding) {
- EVP_CIPHER_CTX_set_padding(&ctx.ctx, 0);
- }
- OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx.ctx) == key_length);
- // ECB does not use IV
- OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx.ctx) == 0);
- OPENSSL_assert(EVP_CIPHER_CTX_block_size(&ctx.ctx) == 16);
- if (! EVP_DecryptUpdate(&ctx.ctx, (unsigned char *) dest, &u_len,
- (unsigned char *)source, source_length))
- return AES_BAD_DATA; /* Error */
- if (! EVP_DecryptFinal_ex(&ctx.ctx, (unsigned char *) dest + u_len, &f_len)) {
- *dest_length = (unsigned long int) u_len;
- return AES_BAD_DATA;
- }
- if (remaining_bytes!=0) {
- memcpy(dest + source_length, source + source_length, remaining_bytes);
- }
- *dest_length = (unsigned long int) (u_len + f_len) + remaining_bytes;
-
-#endif
- return AES_OK;
-}
-
-
-
-
-
-/**
Encryption interface that doesn't do anything (for testing)
SYNOPSIS
diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
index f1356523f90..2b9bfedb08c 100644
--- a/mysys_ssl/my_crypt.cc
+++ b/mysys_ssl/my_crypt.cc
@@ -1,14 +1,29 @@
/*
+ 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 */
+
+/*
TODO: add support for YASSL
*/
#include <my_global.h>
#include <my_crypt.h>
-/* YASSL doesn't support EVP_CIPHER_CTX */
#ifdef HAVE_EncryptAes128Ctr
-#include "mysql.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
@@ -17,67 +32,119 @@ static const int CRYPT_DECRYPT = 0;
C_MODE_START
-static int do_crypt(const EVP_CIPHER *cipher, int mode,
+static int do_crypt(const EVP_CIPHER *cipher, int encrypt,
const uchar* source, uint32 source_length,
uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length, int no_padding)
{
- int res= AES_OPENSSL_ERROR;
+ int res= AES_OPENSSL_ERROR, fin;
+ int tail= no_padding ? source_length % MY_AES_BLOCK_SIZE : 0;
+
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, mode))
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, encrypt))
goto err;
- if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length))
+
+ EVP_CIPHER_CTX_set_padding(&ctx, !no_padding);
+
+ DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == key_length);
+ DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) == iv_length || !EVP_CIPHER_CTX_iv_length(&ctx));
+ DBUG_ASSERT(EVP_CIPHER_CTX_block_size(&ctx) == MY_AES_BLOCK_SIZE || !no_padding);
+
+ if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length - tail))
goto err;
+ if (!EVP_CipherFinal_ex(&ctx, dest + *dest_length, &fin))
+ goto err;
+ *dest_length += fin;
+
+ if (tail)
+ {
+ /*
+ Not much we can do here, block cyphers cannot encrypt data that aren't
+ a multiple of the block length. At least not without padding.
+ What we do here, we XOR the tail with the previous encrypted block.
+ */
+
+ DBUG_ASSERT(source_length - tail == *dest_length);
+ DBUG_ASSERT(source_length - tail > MY_AES_BLOCK_SIZE);
+ const uchar *s= source + source_length - tail;
+ const uchar *e= source + source_length;
+ uchar *d= dest + source_length - tail;
+ const uchar *m= (encrypt ? d : s) - MY_AES_BLOCK_SIZE;
+ while (s < e)
+ *d++ = *s++ ^ *m++;
+ *dest_length= source_length;
+ }
+
res= AES_OK;
err:
EVP_CIPHER_CTX_cleanup(&ctx);
return res;
}
+/* CTR is a stream cypher mode, it needs no special padding code */
int my_aes_encrypt_ctr(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
{
return do_crypt(EVP_aes_128_ctr(), CRYPT_ENCRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, noPadding);
+ dest, dest_length, key, key_length, iv, iv_length, 0);
}
int my_aes_decrypt_ctr(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
{
return do_crypt(EVP_aes_128_ctr(), CRYPT_DECRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, noPadding);
+ dest, dest_length, key, key_length, iv, iv_length, 0);
}
int my_aes_encrypt_ecb(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
{
return do_crypt(EVP_aes_128_ecb(), CRYPT_ENCRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, noPadding);
+ dest, dest_length, key, key_length, iv, iv_length, no_padding);
}
int my_aes_decrypt_ecb(const uchar* source, uint32 source_length,
- uchar* dest, uint32* dest_length,
- const unsigned char* key, uint8 key_length,
- const unsigned char* iv, uint8 iv_length,
- uint noPadding)
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
{
return do_crypt(EVP_aes_128_ecb(), CRYPT_DECRYPT, source, source_length,
- dest, dest_length, key, key_length, iv, iv_length, noPadding);
+ dest, dest_length, key, key_length, iv, iv_length, no_padding);
+}
+
+int my_aes_encrypt_cbc(const uchar* source, uint32 source_length,
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
+{
+ return do_crypt(EVP_aes_128_cbc(), CRYPT_ENCRYPT, source, source_length,
+ dest, dest_length, key, key_length, iv, iv_length, no_padding);
+}
+
+int my_aes_decrypt_cbc(const uchar* source, uint32 source_length,
+ uchar* dest, uint32* dest_length,
+ const uchar* key, uint8 key_length,
+ const uchar* iv, uint8 iv_length,
+ uint no_padding)
+{
+ return do_crypt(EVP_aes_128_cbc(), CRYPT_DECRYPT, source, source_length,
+ dest, dest_length, key, key_length, iv, iv_length, no_padding);
}
C_MODE_END