summaryrefslogtreecommitdiff
path: root/mysys_ssl
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2014-12-22 16:53:17 +0200
committerSergei Golubchik <serg@mariadb.org>2015-02-10 10:21:17 +0100
commitd7d589dc01f6d70d1518b74d46fd3b75e76267f5 (patch)
treef9df59951453660f0038ed78cf5ceadc852bf74c /mysys_ssl
parent3a3ec744b5a31318a00821dc0ed6da8af49fda25 (diff)
downloadmariadb-git-d7d589dc01f6d70d1518b74d46fd3b75e76267f5.tar.gz
Push for testing of encryption
Diffstat (limited to 'mysys_ssl')
-rw-r--r--mysys_ssl/CMakeLists.txt3
-rw-r--r--mysys_ssl/my_aes.cc792
-rw-r--r--mysys_ssl/my_crypt.cc370
-rw-r--r--mysys_ssl/my_crypt_key_management.cc110
-rw-r--r--mysys_ssl/my_crypt_key_management_impl.cc34
5 files changed, 1296 insertions, 13 deletions
diff --git a/mysys_ssl/CMakeLists.txt b/mysys_ssl/CMakeLists.txt
index 45867095e4a..05b04b4d8cb 100644
--- a/mysys_ssl/CMakeLists.txt
+++ b/mysys_ssl/CMakeLists.txt
@@ -39,6 +39,9 @@ SET(MYSYS_SSL_SOURCES
my_sha2.cc
my_md5.cc
my_rnd.cc
+ my_crypt.cc
+ my_crypt_key_management.cc
+ my_crypt_key_management_impl.cc
)
ADD_CONVENIENCE_LIBRARY(mysys_ssl ${MYSYS_SSL_SOURCES})
diff --git a/mysys_ssl/my_aes.cc b/mysys_ssl/my_aes.cc
index 9327bc32a3b..20bd03551c2 100644
--- a/mysys_ssl/my_aes.cc
+++ b/mysys_ssl/my_aes.cc
@@ -17,13 +17,17 @@
#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
@@ -37,11 +41,6 @@ struct MyCipherCtx
enum encrypt_dir { MY_AES_ENCRYPT, MY_AES_DECRYPT };
-#define MY_AES_BLOCK_SIZE 16 /* Block size in bytes */
-
-/* If bad data discovered during decoding */
-#define AES_BAD_DATA -1
-
/**
This is internal function just keeps joint code of Key generation
@@ -101,28 +100,796 @@ 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<int>(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 encryption algorithm.
+ Crypt buffer with AES CBC encryption algorithm.
SYNOPSIS
- my_aes_encrypt()
+ 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. Will handle keys of any length
+ @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) {
+ memcpy(dest + source_length, source + source_length, 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 Size of encrypted data
- < 0 Error
+ != 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) {
+ memcpy(dest + source_length, source + source_length, 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);
+ 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
+}
+
+
+
+/**
+ 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) {
+ memcpy(dest + source_length, source + source_length, 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
*/
-int my_aes_encrypt(const char* source, int source_length, char* dest,
+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) {
+ memcpy(dest + source_length, source + source_length, 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);
+ 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;
+}
+
+
+
+
+
+/**
+ Encryption interface that doesn't do anything (for testing)
+
+ SYNOPSIS
+ my_aes_encrypt_none()
+ @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] unused
+ @return
+ != 0 error
+ 0 no error
+*/
+
+static int my_aes_encrypt_none(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)
+{
+ memcpy(dest, source, source_length);
+ *dest_length= source_length;
+ return 0;
+}
+
+
+/**
+ Decryption interface that doesn't do anything (for testing)
+
+ SYNOPSIS
+ my_aes_decrypt_none()
+ @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] unused
+
+ @return
+ != 0 error
+ 0 no error
+*/
+
+int my_aes_decrypt_none(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)
+{
+ memcpy(dest, source, source_length);
+ *dest_length= source_length;
+ return 0;
+}
+
+/**
+ Initialize encryption methods
+*/
+
+my_aes_decrypt_dynamic_type my_aes_decrypt_dynamic= my_aes_decrypt_none;
+my_aes_encrypt_dynamic_type my_aes_encrypt_dynamic= my_aes_encrypt_none;
+enum_my_aes_encryption_algorithm current_aes_dynamic_method= MY_AES_ALGORITHM_NONE;
+
+my_bool my_aes_init_dynamic_encrypt(enum_my_aes_encryption_algorithm method)
+{
+ switch (method)
+ {
+ /* used for encrypting tables */
+ case MY_AES_ALGORITHM_ECB:
+ my_aes_encrypt_dynamic= my_aes_encrypt_ecb;
+ my_aes_decrypt_dynamic= my_aes_decrypt_ecb;
+ break;
+ case MY_AES_ALGORITHM_CBC:
+ my_aes_encrypt_dynamic= my_aes_encrypt_cbc;
+ my_aes_decrypt_dynamic= my_aes_decrypt_cbc;
+ break;
+#ifdef HAVE_EncryptAes128Ctr
+ /* encrypt everything, with a set of keys */
+ case MY_AES_ALGORITHM_CTR:
+ my_aes_encrypt_dynamic= my_aes_encrypt_ctr;
+ my_aes_decrypt_dynamic= my_aes_decrypt_ctr;
+ break;
+#endif
+ /* Simulate encrypting interface */
+ case MY_AES_ALGORITHM_NONE:
+ my_aes_encrypt_dynamic= my_aes_encrypt_none;
+ my_aes_decrypt_dynamic= my_aes_decrypt_none;
+ break;
+ default:
+ return 1;
+ }
+ current_aes_dynamic_method= method;
+ return 0;
+}
+
+my_aes_decrypt_dynamic_type
+get_aes_decrypt_func(enum_my_aes_encryption_algorithm method)
+{
+ switch (method)
+ {
+ /* used for encrypting tables */
+ case MY_AES_ALGORITHM_ECB:
+ return my_aes_decrypt_ecb;
+ break;
+ case MY_AES_ALGORITHM_CBC:
+ return my_aes_decrypt_cbc;
+ break;
+#ifdef HAVE_EncryptAes128Ctr
+ /* encrypt everything, with a set of keys */
+ case MY_AES_ALGORITHM_CTR:
+ return my_aes_decrypt_ctr;
+ break;
+#endif
+ /* Simulate encrypting interface */
+ case MY_AES_ALGORITHM_NONE:
+ return my_aes_decrypt_none;
+ break;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+my_aes_encrypt_dynamic_type
+get_aes_encrypt_func(enum_my_aes_encryption_algorithm method)
+{
+ switch (method)
+ {
+ /* used for encrypting tables */
+ case MY_AES_ALGORITHM_ECB:
+ return my_aes_encrypt_ecb;
+ break;
+ case MY_AES_ALGORITHM_CBC:
+ return my_aes_encrypt_cbc;
+ break;
+#ifdef HAVE_EncryptAes128Ctr
+ /* encrypt everything, with a set of keys */
+ case MY_AES_ALGORITHM_CTR:
+ return my_aes_encrypt_ctr;
+ break;
+#endif
+ /* Simulate encrypting interface */
+ case MY_AES_ALGORITHM_NONE:
+ return my_aes_encrypt_none;
+ break;
+ default:
+ 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 */
@@ -194,7 +961,7 @@ int my_aes_encrypt(const char* source, int source_length, char* dest,
< 0 Error
*/
-int my_aes_decrypt(const char *source, int source_length, char *dest,
+int my_aes_decrypt(const uchar *source, int source_length, uchar *dest,
const char *key, int key_length)
{
#if defined(HAVE_YASSL)
@@ -275,4 +1042,3 @@ int my_aes_get_size(int source_length)
return MY_AES_BLOCK_SIZE * (source_length / MY_AES_BLOCK_SIZE)
+ MY_AES_BLOCK_SIZE;
}
-
diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
new file mode 100644
index 00000000000..0d49999fdfa
--- /dev/null
+++ b/mysys_ssl/my_crypt.cc
@@ -0,0 +1,370 @@
+/*
+ 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>
+#include <openssl/rand.h>
+
+static const int CRYPT_ENCRYPT = 1;
+static const int CRYPT_DECRYPT = 0;
+
+class Encrypter {
+ public:
+ virtual ~Encrypter() {}
+
+ virtual Crypt_result Encrypt(const uchar* plaintext,
+ int plaintext_size,
+ uchar* ciphertext,
+ int* ciphertext_used) = 0;
+ virtual Crypt_result GetTag(uchar* tag, int tag_size) = 0;
+};
+
+class Decrypter {
+ public:
+ virtual ~Decrypter() {}
+
+ virtual Crypt_result SetTag(const uchar* tag, int tag_size) = 0;
+ virtual Crypt_result Decrypt(const uchar* ciphertext,
+ int ciphertext_size,
+ uchar* plaintext,
+ int* plaintext_used) = 0;
+ virtual Crypt_result CheckTag() = 0;
+};
+
+class Crypto {
+ public:
+ virtual ~Crypto();
+
+ Crypt_result Crypt(const uchar* input, int input_size,
+ uchar* output, int* output_used);
+
+ protected:
+ Crypto();
+
+ EVP_CIPHER_CTX ctx;
+};
+
+
+/* Various crypto implementations */
+
+class Aes128CtrCrypto : public Crypto {
+ public:
+ virtual Crypt_result Init(const uchar* key, const uchar* iv,
+ int iv_size);
+
+ protected:
+ Aes128CtrCrypto() {}
+
+ virtual int mode() = 0;
+};
+
+class Aes128CtrEncrypter : public Aes128CtrCrypto, public Encrypter {
+ public:
+ Aes128CtrEncrypter() {}
+ virtual Crypt_result Encrypt(const uchar* plaintext,
+ int plaintext_size,
+ uchar* ciphertext,
+ int* ciphertext_used);
+
+ virtual Crypt_result GetTag(uchar* tag, int tag_size) {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ protected:
+ virtual int mode() {
+ return CRYPT_ENCRYPT;
+ }
+
+ private:
+ Aes128CtrEncrypter(const Aes128CtrEncrypter& o);
+ Aes128CtrEncrypter& operator=(const Aes128CtrEncrypter& o);
+};
+
+class Aes128CtrDecrypter : public Aes128CtrCrypto, public Decrypter {
+ public:
+ Aes128CtrDecrypter() {}
+ virtual Crypt_result Decrypt(const uchar* ciphertext,
+ int ciphertext_size,
+ uchar* plaintext,
+ int* plaintext_used);
+
+ virtual Crypt_result SetTag(const uchar* tag, int tag_size) {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ virtual Crypt_result CheckTag() {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ protected:
+ virtual int mode() {
+ return CRYPT_DECRYPT;
+ }
+
+ private:
+ Aes128CtrDecrypter(const Aes128CtrDecrypter& o);
+ Aes128CtrDecrypter& operator=(const Aes128CtrDecrypter& o);
+};
+
+class Aes128EcbCrypto : public Crypto {
+ public:
+ virtual Crypt_result Init(const unsigned char* key);
+
+ protected:
+ Aes128EcbCrypto() {}
+
+ virtual int mode() = 0;
+};
+
+class Aes128EcbEncrypter : public Aes128EcbCrypto, public Encrypter {
+ public:
+ Aes128EcbEncrypter() {}
+ virtual Crypt_result Encrypt(const unsigned char* plaintext,
+ int plaintext_size,
+ unsigned char* ciphertext,
+ int* ciphertext_used);
+
+ virtual Crypt_result GetTag(unsigned char* tag, int tag_size) {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ protected:
+ virtual int mode() {
+ return CRYPT_ENCRYPT;
+ }
+
+ private:
+ Aes128EcbEncrypter(const Aes128EcbEncrypter& o);
+ Aes128EcbEncrypter& operator=(const Aes128EcbEncrypter& o);
+};
+
+class Aes128EcbDecrypter : public Aes128EcbCrypto, public Decrypter {
+ public:
+ Aes128EcbDecrypter() {}
+ virtual Crypt_result Decrypt(const unsigned char* ciphertext,
+ int ciphertext_size,
+ unsigned char* plaintext,
+ int* plaintext_used);
+
+ virtual Crypt_result SetTag(const unsigned char* tag, int tag_size) {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ virtual Crypt_result CheckTag() {
+ DBUG_ASSERT(false);
+ return AES_INVALID;
+ }
+
+ protected:
+ virtual int mode() {
+ return CRYPT_DECRYPT;
+ }
+
+ private:
+ Aes128EcbDecrypter(const Aes128EcbDecrypter& o);
+ Aes128EcbDecrypter& operator=(const Aes128EcbDecrypter& o);
+};
+
+
+Crypto::~Crypto() {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+}
+
+Crypto::Crypto() {
+ EVP_CIPHER_CTX_init(&ctx);
+}
+
+/*
+ WARNING: It is allowed to have output == NULL, for special cases like AAD
+ support in AES GCM. output_used however must never be NULL.
+*/
+
+Crypt_result Crypto::Crypt(const uchar* input, int input_size,
+ uchar* output, int* output_used) {
+ DBUG_ASSERT(input != NULL);
+ DBUG_ASSERT(output_used != NULL);
+ if (!EVP_CipherUpdate(&ctx, output, output_used, input, input_size)) {
+ return AES_OPENSSL_ERROR;
+ }
+
+ return AES_OK;
+}
+
+Crypt_result Aes128CtrCrypto::Init(const uchar* key,
+ const uchar* iv,
+ int iv_size) {
+ if (iv_size != 16) {
+ DBUG_ASSERT(false);
+ return AES_BAD_IV;
+ }
+
+ if (!EVP_CipherInit_ex(&ctx, EVP_aes_128_ctr(), NULL, key, iv, mode())) {
+ return AES_OPENSSL_ERROR;
+ }
+
+ return AES_OK;
+}
+
+Crypt_result Aes128CtrEncrypter::Encrypt(const uchar* plaintext,
+ int plaintext_size,
+ uchar* ciphertext,
+ int* ciphertext_used) {
+ Crypt_result res = Crypt(plaintext, plaintext_size, ciphertext,
+ ciphertext_used);
+ DBUG_ASSERT(*ciphertext_used == plaintext_size);
+ return res;
+}
+
+Crypt_result Aes128CtrDecrypter::Decrypt(const uchar* ciphertext,
+ int ciphertext_size,
+ uchar* plaintext,
+ int* plaintext_used) {
+ Crypt_result res = Crypt(ciphertext, ciphertext_size, plaintext,
+ plaintext_used);
+ DBUG_ASSERT(*plaintext_used == ciphertext_size);
+ return res;
+}
+
+
+Crypt_result Aes128EcbCrypto::Init(const unsigned char* key) {
+ if (!EVP_CipherInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, NULL, mode())) {
+ return AES_OPENSSL_ERROR;
+ }
+
+ return AES_OK;
+}
+
+Crypt_result Aes128EcbEncrypter::Encrypt(const unsigned char* plaintext,
+ int plaintext_size,
+ unsigned char* ciphertext,
+ int* ciphertext_used) {
+ Crypt_result res = Crypt(plaintext, plaintext_size,
+ ciphertext, ciphertext_used);
+ DBUG_ASSERT(*ciphertext_used == plaintext_size);
+ return res;
+}
+
+Crypt_result Aes128EcbDecrypter::Decrypt(const unsigned char* ciphertext,
+ int ciphertext_size,
+ unsigned char* plaintext,
+ int* plaintext_used) {
+ Crypt_result res = Crypt(ciphertext, ciphertext_size,
+ plaintext, plaintext_used);
+ DBUG_ASSERT(*plaintext_used == ciphertext_size);
+ return res;
+}
+
+C_MODE_START
+
+
+ /* Encrypt and decrypt according to Aes128Ctr */
+
+Crypt_result 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)
+{
+ Aes128CtrEncrypter encrypter;
+ Crypt_result res = encrypter.Init(key, iv, iv_length);
+ if (res != AES_OK)
+ return res;
+ return encrypter.Encrypt(source, source_length, dest, (int*)dest_length);
+}
+
+
+Crypt_result 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)
+{
+ Aes128CtrDecrypter decrypter;
+
+ Crypt_result res = decrypter.Init(key, iv, iv_length);
+ if (res != AES_OK)
+ return res;
+ return decrypter.Decrypt(source, source_length, dest, (int*)dest_length);
+}
+
+
+Crypt_result 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)
+{
+ Aes128EcbEncrypter encrypter;
+ Crypt_result res = encrypter.Init(key);
+ if (res != AES_OK)
+ return res;
+ return encrypter.Encrypt(source, source_length, dest, (int*)dest_length);
+}
+
+Crypt_result 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)
+{
+ Aes128EcbDecrypter decrypter;
+
+ Crypt_result res = decrypter.Init(key);
+
+ if (res != AES_OK)
+ return res;
+ return decrypter.Decrypt(source, source_length, dest, (int*)dest_length);
+}
+
+C_MODE_END
+
+#endif /* HAVE_EncryptAes128Ctr */
+
+#if defined(HAVE_YASSL)
+
+#include <random.hpp>
+
+C_MODE_START
+
+Crypt_result my_random_bytes(uchar* buf, int num)
+{
+ TaoCrypt::RandomNumberGenerator rand;
+ rand.GenerateBlock((TaoCrypt::byte*) buf, num);
+ return AES_OK;
+}
+
+C_MODE_END
+
+#else /* OpenSSL */
+
+C_MODE_START
+
+Crypt_result my_random_bytes(uchar* buf, int num)
+{
+ /*
+ Unfortunately RAND_bytes manual page does not provide any guarantees
+ in relation to blocking behavior. Here we explicitly use SSLeay random
+ instead of whatever random engine is currently set in OpenSSL. That way
+ we are guaranteed to have a non-blocking random.
+ */
+ RAND_METHOD* rand = RAND_SSLeay();
+ if (rand == NULL || rand->bytes(buf, num) != 1)
+ return AES_OPENSSL_ERROR;
+ return AES_OK;
+}
+
+C_MODE_END
+#endif /* HAVE_YASSL */
diff --git a/mysys_ssl/my_crypt_key_management.cc b/mysys_ssl/my_crypt_key_management.cc
new file mode 100644
index 00000000000..69efed32567
--- /dev/null
+++ b/mysys_ssl/my_crypt_key_management.cc
@@ -0,0 +1,110 @@
+#include <my_global.h>
+#include <my_crypt_key_management.h>
+#include <cstring>
+
+#ifndef DBUG_OFF
+#include <myisampack.h>
+my_bool debug_use_static_encryption_keys = 0;
+
+#ifdef HAVE_PSI_INTERFACE
+PSI_rwlock_key key_LOCK_dbug_encryption_key_version;
+#endif
+mysql_rwlock_t LOCK_dbug_encryption_key_version;
+unsigned int opt_debug_encryption_key_version = 0;
+#endif
+
+/**
+ * Default functions
+ */
+int GetLatestCryptoKeyVersionImpl();
+unsigned int HasCryptoKeyImpl(unsigned int version);
+int GetCryptoKeySizeImpl(unsigned int version);
+int GetCryptoKeyImpl(unsigned int version, unsigned char* key_buffer,
+ unsigned int size);
+int GetCryptoIVImpl(unsigned int version, unsigned char* key_buffer,
+ unsigned int size);
+
+/**
+ * Function pointers for
+ * - GetLatestCryptoKeyVersion
+ * - GetCryptoKey
+ */
+static
+struct CryptoKeyFuncs_t cryptoKeyFuncs = {
+ GetLatestCryptoKeyVersionImpl,
+ HasCryptoKeyImpl,
+ GetCryptoKeySizeImpl,
+ GetCryptoKeyImpl,
+ GetCryptoIVImpl
+};
+
+extern "C"
+int GetLatestCryptoKeyVersion() {
+#ifndef DBUG_OFF
+ if (debug_use_static_encryption_keys) {
+ mysql_rwlock_rdlock(&LOCK_dbug_encryption_key_version);
+ unsigned int res = opt_debug_encryption_key_version;
+ mysql_rwlock_unlock(&LOCK_dbug_encryption_key_version);
+ return res;
+ }
+#endif
+
+ return (* cryptoKeyFuncs.getLatestCryptoKeyVersionFunc)();
+}
+
+extern "C"
+unsigned int HasCryptoKey(unsigned int version) {
+ return (* cryptoKeyFuncs.hasCryptoKeyFunc)(version);
+}
+
+extern "C"
+int GetCryptoKeySize(unsigned int version) {
+ return (* cryptoKeyFuncs.getCryptoKeySize)(version);
+}
+
+extern "C"
+int GetCryptoKey(unsigned int version, unsigned char* key, unsigned int size) {
+#ifndef DBUG_OFF
+ if (debug_use_static_encryption_keys) {
+ memset(key, 0, size);
+ // Just don't support tiny keys, no point anyway.
+ if (size < 4) {
+ return 1;
+ }
+
+ mi_int4store(key, version);
+ return 0;
+ }
+#endif
+
+ return (* cryptoKeyFuncs.getCryptoKeyFunc)(version, key, size);
+}
+
+extern "C"
+int GetCryptoIV(unsigned int version, unsigned char* key, unsigned int size) {
+ return (* cryptoKeyFuncs.getCryptoIVFunc)(version, key, size);
+}
+
+extern "C"
+void
+InstallCryptoKeyFunctions(const struct CryptoKeyFuncs_t* _cryptoKeyFuncs)
+{
+ if (_cryptoKeyFuncs == NULL)
+ {
+ /* restore defaults wHashhen called with NULL argument */
+ cryptoKeyFuncs.getLatestCryptoKeyVersionFunc =
+ GetLatestCryptoKeyVersionImpl;
+ cryptoKeyFuncs.hasCryptoKeyFunc =
+ HasCryptoKeyImpl;
+ cryptoKeyFuncs.getCryptoKeySize =
+ GetCryptoKeySizeImpl;
+ cryptoKeyFuncs.getCryptoKeyFunc =
+ GetCryptoKeyImpl;
+ cryptoKeyFuncs.getCryptoIVFunc =
+ GetCryptoIVImpl;
+ }
+ else
+ {
+ cryptoKeyFuncs = *_cryptoKeyFuncs;
+ }
+}
diff --git a/mysys_ssl/my_crypt_key_management_impl.cc b/mysys_ssl/my_crypt_key_management_impl.cc
new file mode 100644
index 00000000000..af2077d8d15
--- /dev/null
+++ b/mysys_ssl/my_crypt_key_management_impl.cc
@@ -0,0 +1,34 @@
+#include <my_global.h>
+
+// TODO Not yet implemented.
+int GetLatestCryptoKeyVersionImpl()
+{
+ abort();
+ return 0; /* Keep compiler happy */
+}
+
+unsigned int HasCryptoKeyImpl(unsigned int version)
+{
+ abort();
+ return 0; /* Keep compiler happy */
+}
+
+int GetCryptoKeySizeImpl(unsigned int version)
+{
+ abort();
+ return 0; /* Keep compiler happy */
+}
+
+int GetCryptoKeyImpl(unsigned int version, unsigned char* key,
+ unsigned int key_size)
+{
+ abort();
+ return 0; /* Keep compiler happy */
+}
+
+int GetCryptoIVImpl(unsigned int version, unsigned char* key,
+ unsigned int key_size)
+{
+ abort();
+ return 0; /* Keep compiler happy */
+}