diff options
Diffstat (limited to 'mysys_ssl')
-rw-r--r-- | mysys_ssl/CMakeLists.txt | 48 | ||||
-rw-r--r-- | mysys_ssl/crypt_genhash_impl.cc | 454 | ||||
-rw-r--r-- | mysys_ssl/my_aes.cc | 278 | ||||
-rw-r--r-- | mysys_ssl/my_md5.cc | 68 | ||||
-rw-r--r-- | mysys_ssl/my_rnd.cc | 103 | ||||
-rw-r--r-- | mysys_ssl/my_sha1.cc | 151 | ||||
-rw-r--r-- | mysys_ssl/my_sha2.cc | 68 |
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 */ |