summaryrefslogtreecommitdiff
path: root/mysys_ssl
diff options
context:
space:
mode:
Diffstat (limited to 'mysys_ssl')
-rw-r--r--mysys_ssl/CMakeLists.txt48
-rw-r--r--mysys_ssl/crypt_genhash_impl.cc454
-rw-r--r--mysys_ssl/my_aes.cc278
-rw-r--r--mysys_ssl/my_md5.cc68
-rw-r--r--mysys_ssl/my_rnd.cc103
-rw-r--r--mysys_ssl/my_sha1.cc151
-rw-r--r--mysys_ssl/my_sha2.cc68
7 files changed, 1170 insertions, 0 deletions
diff --git a/mysys_ssl/CMakeLists.txt b/mysys_ssl/CMakeLists.txt
new file mode 100644
index 00000000000..b91988d1c8b
--- /dev/null
+++ b/mysys_ssl/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#
+# 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
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/mysys_ssl
+ ${SSL_INCLUDE_DIRS})
+
+IF(SSL_DEFINES)
+ADD_DEFINITIONS(${SSL_DEFINES})
+ENDIF()
+
+# We do RESTRICT_SYMBOL_EXPORTS(yassl) elsewhere.
+# In order to get correct symbol visibility, these files
+# must be compiled with "-fvisibility=hidden"
+IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN)
+ SET_SOURCE_FILES_PROPERTIES(
+ crypt_genhash_impl.cc
+ my_aes.cc
+ my_md5.cc
+ my_sha1.cc
+ my_sha2.cc
+ PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
+ENDIF()
+
+SET(MYSYS_SSL_SOURCES
+ crypt_genhash_impl.cc
+ my_aes.cc
+ my_sha1.cc
+ my_sha2.cc
+ my_md5.cc
+ my_rnd.cc
+ )
+
+ADD_CONVENIENCE_LIBRARY(mysys_ssl ${MYSYS_SSL_SOURCES})
+TARGET_LINK_LIBRARIES(mysys_ssl dbug strings ${SSL_LIBRARIES})
+DTRACE_INSTRUMENT(mysys_ssl)
diff --git a/mysys_ssl/crypt_genhash_impl.cc b/mysys_ssl/crypt_genhash_impl.cc
new file mode 100644
index 00000000000..ab7fdec46b9
--- /dev/null
+++ b/mysys_ssl/crypt_genhash_impl.cc
@@ -0,0 +1,454 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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 02111-1307 USA */
+
+/* We always should include my_global first */
+
+#include <my_global.h>
+
+#ifdef HAVE_OPENSSL
+
+#ifdef HAVE_YASSL
+#include <sha.hpp>
+#include <openssl/ssl.h>
+#else
+#include <openssl/sha.h>
+#include <openssl/rand.h>
+#endif
+#include "crypt_genhash_impl.h"
+#include <string.h>
+
+#ifndef HAVE_YASSL
+#define DIGEST_CTX SHA256_CTX
+#define DIGESTInit SHA256_Init
+#define DIGESTUpdate SHA256_Update
+#define DIGESTFinal SHA256_Final
+#define DIGEST_LEN SHA256_DIGEST_LENGTH
+#else
+#define DIGEST_CTX TaoCrypt::SHA256
+#define DIGEST_LEN 32
+void DIGESTInit(DIGEST_CTX *ctx)
+{
+ ctx->Init();
+}
+
+void DIGESTUpdate(DIGEST_CTX *ctx, const void *plaintext, int len)
+{
+ ctx->Update((const TaoCrypt::byte *)plaintext, len);
+}
+
+void DIGESTFinal(void *txt, DIGEST_CTX *ctx)
+{
+ ctx->Final((TaoCrypt::byte *)txt);
+}
+
+#endif // HAVE_YASSL
+
+static const char crypt_alg_magic[] = "$5";
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+
+/**
+ Size-bounded string copying and concatenation
+ This is a replacement for STRLCPY(3)
+*/
+
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d= dst;
+ const char *s= src;
+ size_t n= siz;
+ size_t dlen;
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen= d - dst;
+ n= siz - dlen;
+ if (n == 0)
+ return(dlen + siz);
+ while (*s != '\0')
+ {
+ if (n != 1)
+ {
+ *d++= *s;
+ n--;
+ }
+ s++;
+ }
+ *d= '\0';
+ return(dlen + (s - src)); /* count does not include NUL */
+}
+
+static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1;
+
+static unsigned char b64t[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+#define b64_from_24bit(B2, B1, B0, N) \
+{ \
+ uint32 w = ((B2) << 16) | ((B1) << 8) | (B0); \
+ int n = (N); \
+ while (--n >= 0 && ctbufflen > 0) { \
+ *p++ = b64t[w & 0x3f]; \
+ w >>= 6; \
+ ctbufflen--; \
+} \
+}
+
+#define ROUNDS "rounds="
+#define ROUNDSLEN (sizeof (ROUNDS) - 1)
+
+/**
+ Get the integer value after rounds= where ever it occurs in the string.
+ if the last char after the int is a , or $ that is fine anything else is an
+ error.
+*/
+static uint32 getrounds(const char *s)
+{
+ const char *r;
+ const char *p;
+ char *e;
+ long val;
+
+ if (s == NULL)
+ return (0);
+
+ if ((r = strstr(s, ROUNDS)) == NULL)
+ {
+ return (0);
+ }
+
+ if (strncmp(r, ROUNDS, ROUNDSLEN) != 0)
+ {
+ return (0);
+ }
+
+ p= r + ROUNDSLEN;
+ errno= 0;
+ val= strtol(p, &e, 10);
+ /*
+ An error occurred or there is non-numeric stuff at the end
+ which isn't one of the crypt(3c) special chars ',' or '$'
+ */
+ if (errno != 0 || val < 0 || !(*e == '\0' || *e == ',' || *e == '$'))
+ {
+ return (0);
+ }
+
+ return ((uint32) val);
+}
+
+/**
+ Finds the interval which envelopes the user salt in a crypt password
+ The crypt format is assumed to be $a$bbbb$cccccc\0 and the salt is found
+ by counting the delimiters and marking begin and end.
+
+ @param salt_being[in] Pointer to start of crypt passwd
+ @param salt_being[out] Pointer to first byte of the salt
+ @param salt_end[in] Pointer to the last byte in passwd
+ @param salt_end[out] Pointer to the byte immediatly following the salt ($)
+
+ @return The size of the salt identified
+*/
+
+int extract_user_salt(char **salt_begin,
+ char **salt_end)
+{
+ char *it= *salt_begin;
+ int delimiter_count= 0;
+ while(it != *salt_end)
+ {
+ if (*it == '$')
+ {
+ ++delimiter_count;
+ if (delimiter_count == 2)
+ {
+ *salt_begin= it + 1;
+ }
+ if (delimiter_count == 3)
+ break;
+ }
+ ++it;
+ }
+ *salt_end= it;
+ return *salt_end - *salt_begin;
+}
+
+const char *sha256_find_digest(char *pass)
+{
+ int sz= strlen(pass);
+ return pass + sz - SHA256_HASH_LENGTH;
+}
+
+/*
+ * Portions of the below code come from crypt_bsdmd5.so (bsdmd5.c) :
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
+ *
+ */
+
+/*
+ * The below code implements the specification from:
+ *
+ * From http://people.redhat.com/drepper/SHA-crypt.txt
+ *
+ * Portions of the code taken from inspired by or verified against the
+ * source in the above document which is licensed as:
+ *
+ * "Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>."
+ */
+
+/*
+ Due to a Solaris namespace bug DS is a reserved word. To work around this
+ DS is undefined.
+*/
+#undef DS
+
+/* ARGSUSED4 */
+extern "C"
+char *
+my_crypt_genhash(char *ctbuffer,
+ size_t ctbufflen,
+ const char *plaintext,
+ int plaintext_len,
+ const char *switchsalt,
+ const char **params)
+{
+ int salt_len, i;
+ char *salt;
+ unsigned char A[DIGEST_LEN];
+ unsigned char B[DIGEST_LEN];
+ unsigned char DP[DIGEST_LEN];
+ unsigned char DS[DIGEST_LEN];
+ DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS;
+ int rounds = ROUNDS_DEFAULT;
+ int srounds = 0;
+ bool custom_rounds= false;
+ char *p;
+ char *P, *Pp;
+ char *S, *Sp;
+
+ /* Refine the salt */
+ salt = (char *)switchsalt;
+
+ /* skip our magic string */
+ if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0)
+ {
+ salt += crypt_alg_magic_len + 1;
+ }
+
+ srounds = getrounds(salt);
+ if (srounds != 0) {
+ rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
+ custom_rounds= true;
+ p = strchr(salt, '$');
+ if (p != NULL)
+ salt = p + 1;
+ }
+
+ salt_len = MIN(strcspn(salt, "$"), CRYPT_SALT_LENGTH);
+ //plaintext_len = strlen(plaintext);
+
+ /* 1. */
+ DIGESTInit(&ctxA);
+
+ /* 2. The password first, since that is what is most unknown */
+ DIGESTUpdate(&ctxA, plaintext, plaintext_len);
+
+ /* 3. Then the raw salt */
+ DIGESTUpdate(&ctxA, salt, salt_len);
+
+ /* 4. - 8. */
+ DIGESTInit(&ctxB);
+ DIGESTUpdate(&ctxB, plaintext, plaintext_len);
+ DIGESTUpdate(&ctxB, salt, salt_len);
+ DIGESTUpdate(&ctxB, plaintext, plaintext_len);
+ DIGESTFinal(B, &ctxB);
+
+ /* 9. - 10. */
+ for (i= plaintext_len; i > MIXCHARS; i -= MIXCHARS)
+ DIGESTUpdate(&ctxA, B, MIXCHARS);
+ DIGESTUpdate(&ctxA, B, i);
+
+ /* 11. */
+ for (i= plaintext_len; i > 0; i >>= 1) {
+ if ((i & 1) != 0)
+ {
+ DIGESTUpdate(&ctxA, B, MIXCHARS);
+ }
+ else
+ {
+ DIGESTUpdate(&ctxA, plaintext, plaintext_len);
+ }
+ }
+
+ /* 12. */
+ DIGESTFinal(A, &ctxA);
+
+ /* 13. - 15. */
+ DIGESTInit(&ctxDP);
+ for (i= 0; i < plaintext_len; i++)
+ DIGESTUpdate(&ctxDP, plaintext, plaintext_len);
+ DIGESTFinal(DP, &ctxDP);
+
+ /* 16. */
+ Pp= P= (char *)alloca(plaintext_len);
+ for (i= plaintext_len; i >= MIXCHARS; i -= MIXCHARS)
+ {
+ Pp= (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS;
+ }
+ (void) memcpy(Pp, DP, i);
+
+ /* 17. - 19. */
+ DIGESTInit(&ctxDS);
+ for (i= 0; i < 16 + (uint8)A[0]; i++)
+ DIGESTUpdate(&ctxDS, salt, salt_len);
+ DIGESTFinal(DS, &ctxDS);
+
+ /* 20. */
+ Sp= S= (char *)alloca(salt_len);
+ for (i= salt_len; i >= MIXCHARS; i -= MIXCHARS)
+ {
+ Sp= (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS;
+ }
+ (void) memcpy(Sp, DS, i);
+
+ /* 21. */
+ for (i= 0; i < rounds; i++)
+ {
+ DIGESTInit(&ctxC);
+
+ if ((i & 1) != 0)
+ {
+ DIGESTUpdate(&ctxC, P, plaintext_len);
+ }
+ else
+ {
+ if (i == 0)
+ DIGESTUpdate(&ctxC, A, MIXCHARS);
+ else
+ DIGESTUpdate(&ctxC, DP, MIXCHARS);
+ }
+
+ if (i % 3 != 0) {
+ DIGESTUpdate(&ctxC, S, salt_len);
+ }
+
+ if (i % 7 != 0) {
+ DIGESTUpdate(&ctxC, P, plaintext_len);
+ }
+
+ if ((i & 1) != 0)
+ {
+ if (i == 0)
+ DIGESTUpdate(&ctxC, A, MIXCHARS);
+ else
+ DIGESTUpdate(&ctxC, DP, MIXCHARS);
+ }
+ else
+ {
+ DIGESTUpdate(&ctxC, P, plaintext_len);
+ }
+ DIGESTFinal(DP, &ctxC);
+ }
+
+ /* 22. Now make the output string */
+ if (custom_rounds)
+ {
+ (void) snprintf(ctbuffer, ctbufflen,
+ "%s$rounds=%zu$", crypt_alg_magic, (size_t)rounds);
+ }
+ else
+ {
+ (void) snprintf(ctbuffer, ctbufflen,
+ "%s$", crypt_alg_magic);
+ }
+ (void) strncat(ctbuffer, (const char *)salt, salt_len);
+ (void) strlcat(ctbuffer, "$", ctbufflen);
+
+ p= ctbuffer + strlen(ctbuffer);
+ ctbufflen -= strlen(ctbuffer);
+
+ b64_from_24bit(DP[ 0], DP[10], DP[20], 4);
+ b64_from_24bit(DP[21], DP[ 1], DP[11], 4);
+ b64_from_24bit(DP[12], DP[22], DP[ 2], 4);
+ b64_from_24bit(DP[ 3], DP[13], DP[23], 4);
+ b64_from_24bit(DP[24], DP[ 4], DP[14], 4);
+ b64_from_24bit(DP[15], DP[25], DP[ 5], 4);
+ b64_from_24bit(DP[ 6], DP[16], DP[26], 4);
+ b64_from_24bit(DP[27], DP[ 7], DP[17], 4);
+ b64_from_24bit(DP[18], DP[28], DP[ 8], 4);
+ b64_from_24bit(DP[ 9], DP[19], DP[29], 4);
+ b64_from_24bit(0, DP[31], DP[30], 3);
+ *p= '\0';
+
+ (void) memset(A, 0, sizeof (A));
+ (void) memset(B, 0, sizeof (B));
+ (void) memset(DP, 0, sizeof (DP));
+ (void) memset(DS, 0, sizeof (DS));
+
+ return (ctbuffer);
+}
+
+
+/**
+ Generate a random string using ASCII characters but avoid seperator character.
+ Stdlib rand and srand are used to produce pseudo random numbers between
+ with about 7 bit worth of entropty between 1-127.
+*/
+extern "C"
+void generate_user_salt(char *buffer, int buffer_len)
+{
+ char *end= buffer + buffer_len - 1;
+#ifdef HAVE_YASSL
+ yaSSL::RAND_bytes((unsigned char *) buffer, buffer_len);
+#else
+ RAND_bytes((unsigned char *) buffer, buffer_len);
+#endif
+
+ /* Sequence must be a legal UTF8 string */
+ for (; buffer < end; buffer++)
+ {
+ *buffer &= 0x7f;
+ if (*buffer == '\0' || *buffer == '$')
+ *buffer= *buffer + 1;
+ }
+ /* Make sure the buffer is terminated properly */
+ *end= '\0';
+}
+
+void xor_string(char *to, int to_len, char *pattern, int pattern_len)
+{
+ int loop= 0;
+ while(loop <= to_len)
+ {
+ *(to + loop) ^= *(pattern + loop % pattern_len);
+ ++loop;
+ }
+}
+
+#endif // HAVE_OPENSSL
diff --git a/mysys_ssl/my_aes.cc b/mysys_ssl/my_aes.cc
new file mode 100644
index 00000000000..9327bc32a3b
--- /dev/null
+++ b/mysys_ssl/my_aes.cc
@@ -0,0 +1,278 @@
+/* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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 */
+
+
+#include <my_global.h>
+#include <m_string.h>
+#include <my_aes.h>
+
+#if defined(HAVE_YASSL)
+#include "aes.hpp"
+#include "openssl/ssl.h"
+#elif defined(HAVE_OPENSSL)
+#include <openssl/aes.h>
+#include <openssl/evp.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 };
+
+#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
+
+ 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;
+}
+
+
+/**
+ Crypt buffer with AES encryption algorithm.
+
+ SYNOPSIS
+ my_aes_encrypt()
+ @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 key [in] Key to be used for encryption
+ @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_encrypt(const char* source, int source_length, char* 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 char *source, int source_length, char *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
+
+ SYNOPSIS
+ my_aes_get_size()
+ @param source_length [in] Length of data to be encrypted
+
+ @return
+ Size of buffer required to store encrypted data
+*/
+
+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_md5.cc b/mysys_ssl/my_md5.cc
new file mode 100644
index 00000000000..4c14366a4e3
--- /dev/null
+++ b/mysys_ssl/my_md5.cc
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+
+/**
+ @file
+
+ @brief
+ Wrapper functions for OpenSSL and YaSSL. Also provides a Compatibility layer
+ to make available YaSSL's MD5 implementation.
+*/
+
+#include <my_global.h>
+#include <my_md5.h>
+
+#if defined(HAVE_YASSL)
+#include "my_config.h"
+#include "md5.hpp"
+
+static void my_md5_hash(char *digest, const char *buf, int len)
+{
+ TaoCrypt::MD5 hasher;
+ hasher.Update((TaoCrypt::byte *) buf, len);
+ hasher.Final((TaoCrypt::byte *) digest);
+}
+
+#elif defined(HAVE_OPENSSL)
+#include <openssl/md5.h>
+
+static void my_md5_hash(unsigned char* digest, unsigned const char *buf, int len)
+{
+ MD5_CTX ctx;
+ MD5_Init (&ctx);
+ MD5_Update (&ctx, buf, len);
+ MD5_Final (digest, &ctx);
+}
+
+#endif /* HAVE_YASSL */
+
+/**
+ Wrapper function to compute MD5 message digest.
+
+ @param digest [out] Computed MD5 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void compute_md5_hash(char *digest, const char *buf, int len)
+{
+#if defined(HAVE_YASSL)
+ my_md5_hash(digest, buf, len);
+#elif defined(HAVE_OPENSSL)
+ my_md5_hash((unsigned char*)digest, (unsigned const char*)buf, len);
+#endif /* HAVE_YASSL */
+}
diff --git a/mysys_ssl/my_rnd.cc b/mysys_ssl/my_rnd.cc
new file mode 100644
index 00000000000..aa8fb63cd4d
--- /dev/null
+++ b/mysys_ssl/my_rnd.cc
@@ -0,0 +1,103 @@
+/*
+ Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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 */
+
+#include <my_global.h>
+#include <my_rnd.h>
+#include <m_string.h>
+
+#if defined(HAVE_YASSL)
+#if defined(YASSL_PREFIX)
+#define RAND_bytes yaRAND_bytes
+#endif /* YASSL_PREFIX */
+
+#include <openssl/ssl.h>
+
+#elif defined(HAVE_OPENSSL)
+#include <openssl/rand.h>
+#endif /* HAVE_YASSL */
+
+
+/*
+ A wrapper to use OpenSSL/yaSSL PRNGs.
+*/
+
+extern "C" {
+
+/*
+ Initialize random generator
+
+ NOTES
+ MySQL's password checks depends on this, so don't do any changes
+ that changes the random numbers that are generated!
+*/
+
+void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2)
+{
+#ifdef HAVE_valgrind
+ bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */
+#endif
+ rand_st->max_value= 0x3FFFFFFFL;
+ rand_st->max_value_dbl=(double) rand_st->max_value;
+ rand_st->seed1=seed1%rand_st->max_value ;
+ rand_st->seed2=seed2%rand_st->max_value;
+}
+
+/**
+ Generate random number.
+
+ @param rand_st [INOUT] Structure used for number generation.
+
+ @retval Generated pseudo random number.
+*/
+
+double my_rnd(struct my_rnd_struct *rand_st)
+{
+ rand_st->seed1= (rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
+ rand_st->seed2= (rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
+ return (((double) rand_st->seed1) / rand_st->max_value_dbl);
+}
+
+/**
+ Generate a random number using the OpenSSL/yaSSL supplied
+ random number generator if available.
+
+ @param rand_st [INOUT] Structure used for number generation
+ only if none of the SSL libraries are
+ available.
+
+ @retval Generated random number.
+*/
+
+double my_rnd_ssl(struct my_rnd_struct *rand_st)
+{
+
+#if defined(HAVE_YASSL) || defined(HAVE_OPENSSL)
+ int rc;
+ unsigned int res;
+
+#if defined(HAVE_YASSL)
+ rc= yaSSL::RAND_bytes((unsigned char *) &res, sizeof (unsigned int));
+#else
+ rc= RAND_bytes((unsigned char *) &res, sizeof (unsigned int));
+#endif /* HAVE_YASSL */
+ if (rc)
+ return (double)res / (double)UINT_MAX;
+
+#endif /* defined(HAVE_YASSL) || defined(HAVE_OPENSSL) */
+ return my_rnd(rand_st);
+}
+
+}
diff --git a/mysys_ssl/my_sha1.cc b/mysys_ssl/my_sha1.cc
new file mode 100644
index 00000000000..fc8f88856bb
--- /dev/null
+++ b/mysys_ssl/my_sha1.cc
@@ -0,0 +1,151 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+
+/**
+ @file
+
+ @brief
+ Wrapper functions for OpenSSL, YaSSL implementations. Also provides a
+ Compatibility layer to make available YaSSL's SHA1 implementation.
+*/
+
+#include <my_global.h>
+#include <sha1.h>
+#include <stdarg.h>
+
+#if defined(HAVE_YASSL)
+#include "sha.hpp"
+
+/**
+ Compute SHA1 message digest using YaSSL.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void mysql_sha1_yassl(uint8 *digest, const char *buf, int len)
+{
+ TaoCrypt::SHA hasher;
+ hasher.Update((const TaoCrypt::byte *) buf, len);
+ hasher.Final ((TaoCrypt::byte *) digest);
+}
+
+/**
+ Compute SHA1 message digest for two messages in order to
+ emulate sha1(msg1, msg2) using YaSSL.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf1 [in] First message
+ @param len1 [in] Length of first message
+ @param buf2 [in] Second message
+ @param len2 [in] Length of second message
+
+ @return void
+*/
+void mysql_sha1_multi_yassl(uint8 *digest, va_list args)
+{
+ const char *str;
+ TaoCrypt::SHA hasher;
+
+ for (str= va_arg(args, const char*); str; str= va_arg(args, const char*))
+ {
+ hasher.Update((const TaoCrypt::byte *) str, va_arg(args, size_t));
+ }
+ hasher.Final((TaoCrypt::byte *) digest);
+}
+
+#elif defined(HAVE_OPENSSL)
+#include <openssl/sha.h>
+
+int mysql_sha1_reset(SHA_CTX *context)
+{
+ return SHA1_Init(context);
+}
+
+
+int mysql_sha1_input(SHA_CTX *context, const uint8 *message_array,
+ unsigned length)
+{
+ return SHA1_Update(context, message_array, length);
+}
+
+
+int mysql_sha1_result(SHA_CTX *context,
+ uint8 Message_Digest[SHA1_HASH_SIZE])
+{
+ return SHA1_Final(Message_Digest, context);
+}
+
+#endif /* HAVE_YASSL */
+
+/**
+ Wrapper function to compute SHA1 message digest.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void my_sha1(uint8 *digest, const char *buf, size_t len)
+{
+#if defined(HAVE_YASSL)
+ mysql_sha1_yassl(digest, buf, len);
+#elif defined(HAVE_OPENSSL)
+ SHA_CTX sha1_context;
+
+ mysql_sha1_reset(&sha1_context);
+ mysql_sha1_input(&sha1_context, (const uint8 *) buf, len);
+ mysql_sha1_result(&sha1_context, digest);
+#endif /* HAVE_YASSL */
+}
+
+
+/**
+ Wrapper function to compute SHA1 message digest for
+ two messages in order to emulate sha1(msg1, msg2).
+
+ @param digest [out] Computed SHA1 digest
+ @param buf1 [in] First message
+ @param len1 [in] Length of first message
+ @param buf2 [in] Second message
+ @param len2 [in] Length of second message
+
+ @return void
+*/
+void my_sha1_multi(uint8 *digest, ...)
+{
+ va_list args;
+ va_start(args, digest);
+
+#if defined(HAVE_YASSL)
+ mysql_sha1_multi_yassl(digest, args);
+#elif defined(HAVE_OPENSSL)
+ SHA_CTX sha1_context;
+ const char *str;
+
+ mysql_sha1_reset(&sha1_context);
+ for (str= va_arg(args, const char*); str; str= va_arg(args, const char*))
+ {
+ mysql_sha1_input(&sha1_context, (const uint8 *) str, va_arg(args, size_t));
+ }
+ mysql_sha1_result(&sha1_context, digest);
+#endif /* HAVE_YASSL */
+ va_end(args);
+}
+
diff --git a/mysys_ssl/my_sha2.cc b/mysys_ssl/my_sha2.cc
new file mode 100644
index 00000000000..00200337f08
--- /dev/null
+++ b/mysys_ssl/my_sha2.cc
@@ -0,0 +1,68 @@
+/* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+
+/**
+ @file
+ A compatibility layer to our built-in SSL implementation, to mimic the
+ oft-used external library, OpenSSL.
+*/
+
+#include <my_global.h>
+#include <sha2.h>
+
+#ifdef HAVE_YASSL
+
+/*
+ If TaoCrypt::SHA512 or ::SHA384 are not defined (but ::SHA256 is), it's
+ probably that neither of config.h's SIZEOF_LONG or SIZEOF_LONG_LONG are
+ 64 bits long. At present, both OpenSSL and YaSSL require 64-bit integers
+ for SHA-512. (The SIZEOF_* definitions come from autoconf's config.h .)
+*/
+
+# define GEN_YASSL_SHA2_BRIDGE(size) \
+unsigned char* SHA##size(const unsigned char *input_ptr, size_t input_length, \
+ char unsigned *output_ptr) { \
+ TaoCrypt::SHA##size hasher; \
+ \
+ hasher.Update(input_ptr, input_length); \
+ hasher.Final(output_ptr); \
+ return(output_ptr); \
+}
+
+
+/**
+ @fn SHA512
+ @fn SHA384
+ @fn SHA256
+ @fn SHA224
+
+ Instantiate an hash object, fill in the cleartext value, compute the digest,
+ and extract the result from the object.
+
+ (Generate the functions. See similar .h code for the prototypes.)
+*/
+# ifndef OPENSSL_NO_SHA512
+GEN_YASSL_SHA2_BRIDGE(512);
+GEN_YASSL_SHA2_BRIDGE(384);
+# else
+# warning Some SHA2 functionality is missing. See OPENSSL_NO_SHA512.
+# endif
+GEN_YASSL_SHA2_BRIDGE(256);
+GEN_YASSL_SHA2_BRIDGE(224);
+
+# undef GEN_YASSL_SHA2_BRIDGE
+
+#endif /* HAVE_YASSL */