diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /mysys_ssl | |
parent | Initial commit. (diff) | |
download | mariadb-upstream.tar.xz mariadb-upstream.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mysys_ssl')
-rw-r--r-- | mysys_ssl/CMakeLists.txt | 49 | ||||
-rw-r--r-- | mysys_ssl/my_crypt.cc | 369 | ||||
-rw-r--r-- | mysys_ssl/my_md5.cc | 152 | ||||
-rw-r--r-- | mysys_ssl/my_sha.inl | 203 | ||||
-rw-r--r-- | mysys_ssl/my_sha1.cc | 18 | ||||
-rw-r--r-- | mysys_ssl/my_sha224.cc | 18 | ||||
-rw-r--r-- | mysys_ssl/my_sha256.cc | 18 | ||||
-rw-r--r-- | mysys_ssl/my_sha384.cc | 18 | ||||
-rw-r--r-- | mysys_ssl/my_sha512.cc | 18 | ||||
-rw-r--r-- | mysys_ssl/openssl.c | 74 |
10 files changed, 937 insertions, 0 deletions
diff --git a/mysys_ssl/CMakeLists.txt b/mysys_ssl/CMakeLists.txt new file mode 100644 index 00000000..1c3f60b5 --- /dev/null +++ b/mysys_ssl/CMakeLists.txt @@ -0,0 +1,49 @@ +# 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-1335 USA + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/mysys_ssl + ${SSL_INCLUDE_DIRS}) + +IF(SSL_DEFINES) +ADD_DEFINITIONS(${SSL_DEFINES}) +ENDIF() + +SET(MYSYS_SSL_HIDDEN_SOURCES + my_sha1.cc + my_sha224.cc + my_sha256.cc + my_sha384.cc + my_sha512.cc + my_md5.cc + openssl.c + ) + +SET(MYSYS_SSL_SOURCES + ${MYSYS_SSL_HIDDEN_SOURCES} + my_crypt.cc + ) + +# 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( + ${MYSYS_SSL_HIDDEN_SOURCES} + PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") +ENDIF() + +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/my_crypt.cc b/mysys_ssl/my_crypt.cc new file mode 100644 index 00000000..00447e73 --- /dev/null +++ b/mysys_ssl/my_crypt.cc @@ -0,0 +1,369 @@ +/* + Copyright (c) 2014 Google Inc. + Copyright (c) 2014, 2019, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <string.h> + +#define template _template /* bug in WolfSSL 4.4.0, see also violite.h */ +#include <openssl/evp.h> +#undef template +#include <openssl/aes.h> +#include <openssl/err.h> +#include <openssl/rand.h> + +#include <my_crypt.h> +#include <ssl_compat.h> +#include <cstdint> + +#define CTX_ALIGN 16 + +class MyCTX +{ +public: + char ctx_buf[EVP_CIPHER_CTX_SIZE + CTX_ALIGN]; + EVP_CIPHER_CTX* ctx; + MyCTX() + { +#if CTX_ALIGN > 0 + uintptr_t p= ((uintptr_t)ctx_buf + (CTX_ALIGN - 1)) & ~(CTX_ALIGN - 1); + ctx = reinterpret_cast<EVP_CIPHER_CTX*>(p); +#else + ctx = (EVP_CIPHER_CTX*)ctx_buf; +#endif + + EVP_CIPHER_CTX_init(ctx); + } + virtual ~MyCTX() + { + EVP_CIPHER_CTX_reset(ctx); + ERR_remove_state(0); + } + + virtual int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, + uint klen, const uchar *iv, uint ivlen) + { + compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX)); + if (unlikely(!cipher)) + return MY_AES_BAD_KEYSIZE; + + if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, encrypt) != 1) + return MY_AES_OPENSSL_ERROR; + + DBUG_ASSERT(EVP_CIPHER_CTX_key_length(ctx) == (int)klen); + DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(ctx) <= (int)ivlen); + + return MY_AES_OK; + } + virtual int update(const uchar *src, uint slen, uchar *dst, uint *dlen) + { +#ifdef HAVE_WOLFSSL + // WolfSSL checks parameters and does not like NULL pointers to be passed to function below. + if (!src) + { + static uchar dummy[MY_AES_BLOCK_SIZE]; + DBUG_ASSERT(!slen); + src=dummy; + } +#endif + + if (EVP_CipherUpdate(ctx, dst, (int*)dlen, src, slen) != 1) + return MY_AES_OPENSSL_ERROR; + return MY_AES_OK; + } + virtual int finish(uchar *dst, uint *dlen) + { + if (EVP_CipherFinal_ex(ctx, dst, (int*)dlen) != 1) + return MY_AES_BAD_DATA; + return MY_AES_OK; + } +}; + +class MyCTX_nopad : public MyCTX +{ +public: + const uchar *key; + uint klen, source_tail_len; + uchar oiv[MY_AES_BLOCK_SIZE]; + uchar source_tail[MY_AES_BLOCK_SIZE]; + + MyCTX_nopad() : MyCTX() { } + ~MyCTX_nopad() = default; + + int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, uint klen, + const uchar *iv, uint ivlen) + { + compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_nopad)); + this->key= key; + this->klen= klen; + this->source_tail_len= 0; + if (ivlen) + memcpy(oiv, iv, ivlen); + DBUG_ASSERT(ivlen == 0 || ivlen == sizeof(oiv)); + + int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen); + + EVP_CIPHER_CTX_set_padding(ctx, 0); + return res; + } + + /** Update last partial source block, stored in source_tail array. */ + void update_source_tail(const uchar* src, uint slen) + { + if (!slen) + return; + uint new_tail_len= (source_tail_len + slen) % MY_AES_BLOCK_SIZE; + if (new_tail_len) + { + if (slen + source_tail_len < MY_AES_BLOCK_SIZE) + { + memcpy(source_tail + source_tail_len, src, slen); + } + else + { + DBUG_ASSERT(slen > new_tail_len); + memcpy(source_tail, src + slen - new_tail_len, new_tail_len); + } + } + source_tail_len= new_tail_len; + } + + int update(const uchar *src, uint slen, uchar *dst, uint *dlen) + { + update_source_tail(src, slen); + return MyCTX::update(src, slen, dst, dlen); + } + + int finish(uchar *dst, uint *dlen) + { + if (source_tail_len) + { + /* + Not much we can do, block ciphers cannot encrypt data that aren't + a multiple of the block length. At least not without padding. + Let's do something CTR-like for the last partial block. + */ + uchar mask[MY_AES_BLOCK_SIZE]; + uint mlen; + + int rc= my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD, + oiv, sizeof(mask), mask, &mlen, key, klen, 0, 0); + DBUG_ASSERT(rc == MY_AES_OK); + if (rc) + return rc; + DBUG_ASSERT(mlen == sizeof(mask)); + + for (uint i=0; i < source_tail_len; i++) + dst[i]= source_tail[i] ^ mask[i]; + } + *dlen= source_tail_len; + return MY_AES_OK; + } +}; + +#define make_aes_dispatcher(mode) \ + static inline const EVP_CIPHER *aes_ ## mode(uint klen) \ + { \ + switch (klen) { \ + case 16: return EVP_aes_128_ ## mode(); \ + case 24: return EVP_aes_192_ ## mode(); \ + case 32: return EVP_aes_256_ ## mode(); \ + default: return 0; \ + } \ + } + +make_aes_dispatcher(ecb) +make_aes_dispatcher(cbc) +#ifdef HAVE_EncryptAes128Ctr +make_aes_dispatcher(ctr) +#endif /* HAVE_EncryptAes128Ctr */ +#ifdef HAVE_EncryptAes128Gcm +make_aes_dispatcher(gcm) + +/* + special implementation for GCM; to fit OpenSSL AES-GCM into the + existing my_aes_* API it does the following: + - IV tail (over 12 bytes) goes to AAD + - the tag is appended to the ciphertext +*/ + +class MyCTX_gcm : public MyCTX +{ +public: + const uchar *aad; + int aadlen; + MyCTX_gcm() : MyCTX() { } + ~MyCTX_gcm() { } + + int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, uint klen, + const uchar *iv, uint ivlen) + { + compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_gcm)); + int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen); + int real_ivlen= EVP_CIPHER_CTX_iv_length(ctx); + aad= iv + real_ivlen; + aadlen= ivlen - real_ivlen; + return res; + } + + int update(const uchar *src, uint slen, uchar *dst, uint *dlen) + { + /* + note that this GCM class cannot do streaming decryption, because + it needs the tag (which is located at the end of encrypted data) + before decrypting the data. it can encrypt data piecewise, like, first + half, then the second half, but it must decrypt all at once + */ + if (!EVP_CIPHER_CTX_encrypting(ctx)) + { + /* encrypted string must contain authenticaton tag (see MDEV-11174) */ + if (slen < MY_AES_BLOCK_SIZE) + return MY_AES_BAD_DATA; + slen-= MY_AES_BLOCK_SIZE; + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE, + (void*)(src + slen))) + return MY_AES_OPENSSL_ERROR; + } + int unused; + if (aadlen && !EVP_CipherUpdate(ctx, NULL, &unused, aad, aadlen)) + return MY_AES_OPENSSL_ERROR; + aadlen= 0; + return MyCTX::update(src, slen, dst, dlen); + } + + int finish(uchar *dst, uint *dlen) + { + int fin; + if (!EVP_CipherFinal_ex(ctx, dst, &fin)) + return MY_AES_BAD_DATA; + DBUG_ASSERT(fin == 0); + + if (EVP_CIPHER_CTX_encrypting(ctx)) + { + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE, dst)) + return MY_AES_OPENSSL_ERROR; + *dlen= MY_AES_BLOCK_SIZE; + } + else + *dlen= 0; + return MY_AES_OK; + } +}; + +#endif + +const EVP_CIPHER *(*ciphers[])(uint)= { + aes_ecb, aes_cbc +#ifdef HAVE_EncryptAes128Ctr + , aes_ctr +#ifdef HAVE_EncryptAes128Gcm + , aes_gcm +#endif +#endif +}; + +extern "C" { + +int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags, + const unsigned char* key, unsigned int klen, + const unsigned char* iv, unsigned int ivlen) +{ +#ifdef HAVE_EncryptAes128Ctr +#ifdef HAVE_EncryptAes128Gcm + if (mode == MY_AES_GCM) + if (flags & ENCRYPTION_FLAG_NOPAD) + return MY_AES_OPENSSL_ERROR; + else + new (ctx) MyCTX_gcm(); + else +#endif + if (mode == MY_AES_CTR) + new (ctx) MyCTX(); + else +#endif + if (flags & ENCRYPTION_FLAG_NOPAD) + new (ctx) MyCTX_nopad(); + else + new (ctx) MyCTX(); + return ((MyCTX*)ctx)->init(ciphers[mode](klen), flags & 1, + key, klen, iv, ivlen); +} + +int my_aes_crypt_update(void *ctx, const uchar *src, uint slen, + uchar *dst, uint *dlen) +{ + return ((MyCTX*)ctx)->update(src, slen, dst, dlen); +} + +int my_aes_crypt_finish(void *ctx, uchar *dst, uint *dlen) +{ + int res= ((MyCTX*)ctx)->finish(dst, dlen); + ((MyCTX*)ctx)->~MyCTX(); + return res; +} + +int my_aes_crypt(enum my_aes_mode mode, int flags, + const uchar *src, uint slen, uchar *dst, uint *dlen, + const uchar *key, uint klen, const uchar *iv, uint ivlen) +{ + void *ctx= alloca(MY_AES_CTX_SIZE); + int res1, res2; + uint d1= 0, d2; + if ((res1= my_aes_crypt_init(ctx, mode, flags, key, klen, iv, ivlen))) + return res1; + res1= my_aes_crypt_update(ctx, src, slen, dst, &d1); + res2= my_aes_crypt_finish(ctx, dst + d1, &d2); + if (res1 || res2) + ERR_remove_state(0); /* in case of failure clear error queue */ + else + *dlen= d1 + d2; + return res1 ? res1 : res2; +} + + +/* + calculate the length of the cyphertext from the length of the plaintext + for different AES encryption modes with padding enabled. + Without padding (ENCRYPTION_FLAG_NOPAD) cyphertext has the same length + as the plaintext +*/ +unsigned int my_aes_get_size(enum my_aes_mode mode __attribute__((unused)), unsigned int source_length) +{ +#ifdef HAVE_EncryptAes128Ctr + if (mode == MY_AES_CTR) + return source_length; +#ifdef HAVE_EncryptAes128Gcm + if (mode == MY_AES_GCM) + return source_length + MY_AES_BLOCK_SIZE; +#endif +#endif + return (source_length / MY_AES_BLOCK_SIZE + 1) * MY_AES_BLOCK_SIZE; +} + + +unsigned int my_aes_ctx_size(enum my_aes_mode) +{ + return MY_AES_CTX_SIZE; +} + +int my_random_bytes(uchar *buf, int num) +{ + if (RAND_bytes(buf, num) != 1) + return MY_AES_OPENSSL_ERROR; + return MY_AES_OK; +} + +} diff --git a/mysys_ssl/my_md5.cc b/mysys_ssl/my_md5.cc new file mode 100644 index 00000000..75995bcc --- /dev/null +++ b/mysys_ssl/my_md5.cc @@ -0,0 +1,152 @@ +/* Copyright (c) 2012, Oracle and/or its affiliates. + Copyright (c) 2017, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, 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> +#include <stdarg.h> + +#if defined(HAVE_WOLFSSL) +#include <wolfssl/wolfcrypt/md5.h> +#include <ssl_compat.h> +typedef wc_Md5 EVP_MD_CTX; +static void md5_init(EVP_MD_CTX *context) +{ + wc_InitMd5(context);; +} + +static void md5_input(EVP_MD_CTX *context, const uchar *buf, unsigned len) +{ + wc_Md5Update(context, buf, len); +} + +static void md5_result(EVP_MD_CTX *context, uchar digest[MD5_HASH_SIZE]) +{ + wc_Md5Final(context,digest); +} + +#elif defined(HAVE_OPENSSL) +#include <openssl/evp.h> +#include <ssl_compat.h> + +static void md5_init(EVP_MD_CTX *context) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD *md5; + EVP_MD_CTX_init(context); + /* Ok to ignore FIPS: MD5 is not used for crypto here */ + /* In OpenSSL 3.0.0+ it is a different EVP_MD provider */ + md5 = EVP_MD_fetch(NULL, "MD5", "fips=no"); + EVP_DigestInit_ex(context, md5, NULL); + EVP_MD_free(md5); +#else + EVP_MD_CTX_init(context); +#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW + /* Ok to ignore FIPS: MD5 is not used for crypto here */ + /* In OpenSSL 1.1.1 the non FIPS allowed flag is context specific */ + EVP_MD_CTX_set_flags(context, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +#endif + EVP_DigestInit_ex(context, EVP_md5(), NULL); +#endif +} + +static void md5_input(EVP_MD_CTX *context, const uchar *buf, unsigned len) +{ + EVP_DigestUpdate(context, buf, len); +} + +static void md5_result(EVP_MD_CTX *context, uchar digest[MD5_HASH_SIZE]) +{ + EVP_DigestFinal_ex(context, digest, NULL); + EVP_MD_CTX_reset(context); +} + +#endif /* HAVE_WOLFSSL */ + +/** + 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 my_md5(uchar *digest, const char *buf, size_t len) +{ + char ctx_buf[EVP_MD_CTX_SIZE]; + EVP_MD_CTX * const ctx= (EVP_MD_CTX*)ctx_buf; + md5_init(ctx); + md5_input(ctx, (const uchar *)buf, (uint) len); + md5_result(ctx, digest); +} + + +/** + Wrapper function to compute MD5 message digest for + many messages, concatenated. + + @param digest [out] Computed MD5 digest + @param buf1 [in] First message + @param len1 [in] Length of first message + ... + @param bufN [in] NULL terminates the list of buf,len pairs. + + @return void +*/ +void my_md5_multi(uchar *digest, ...) +{ + va_list args; + const uchar *str; + char ctx_buf[EVP_MD_CTX_SIZE]; + EVP_MD_CTX * const ctx= (EVP_MD_CTX*)ctx_buf; + va_start(args, digest); + + md5_init(ctx); + for (str= va_arg(args, const uchar*); str; str= va_arg(args, const uchar*)) + md5_input(ctx, str, (uint) va_arg(args, size_t)); + + md5_result(ctx, digest); + va_end(args); +} + +size_t my_md5_context_size() +{ + return EVP_MD_CTX_SIZE; +} + +void my_md5_init(void *context) +{ + md5_init((EVP_MD_CTX *)context); +} + +void my_md5_input(void *context, const uchar *buf, size_t len) +{ + md5_input((EVP_MD_CTX *)context, buf, (uint) len); +} + +void my_md5_result(void *context, uchar *digest) +{ + md5_result((EVP_MD_CTX *)context, digest); +} diff --git a/mysys_ssl/my_sha.inl b/mysys_ssl/my_sha.inl new file mode 100644 index 00000000..6bba6147 --- /dev/null +++ b/mysys_ssl/my_sha.inl @@ -0,0 +1,203 @@ +/* Copyright (c) 2012, Oracle and/or its affiliates. + Copyright (c) 2014, 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + + +/** + @file + + @brief + Wrapper functions for OpenSSL, YaSSL implementations. Also provides a + Compatibility layer to make available YaSSL's SHAn implementation. +*/ + +#include <my_global.h> +#include <stdarg.h> + +#define HASH_SIZE (NUM > 1 ? NUM/8 : 20) + +#if defined(HAVE_WOLFSSL) +#define WOLFSSL_SHA512 +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA224 +#include <wolfcrypt/sha.h> +#include <wolfcrypt/sha256.h> +#include <wolfcrypt/sha512.h> +#define xCONTEXT(x) wc_Sha ## x +#define yCONTEXT(y) xCONTEXT(y) +#define CONTEXT yCONTEXT(NUM) +#define wc_InitSha1 wc_InitSha +#define wc_Sha1Final wc_ShaFinal +#define wc_Sha1Update wc_ShaUpdate +#define wc_Sha1 wc_Sha +#define SHA224_CTX SHA256_CTX +#define SHA384_CTX SHA512_CTX + +#define xSHA_Init(x) wc_InitSha ## x +#define xSHA_Update(x) wc_Sha ## x ## Update +#define xSHA_Final(x) wc_Sha ## x ## Final +#define ySHA_Init(y) xSHA_Init(y) +#define ySHA_Update(y) xSHA_Update(y) +#define ySHA_Final(y) xSHA_Final(y) +#define SHA_Init ySHA_Init(NUM) +#define SHA_Update ySHA_Update(NUM) +#define SHA_Final ySHA_Final(NUM) +static void sha_init(CONTEXT *context) +{ + SHA_Init(context); +} + +static void sha_init_fast(CONTEXT *context) +{ + sha_init(context); +} + +static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) +{ + SHA_Update(context, buf, len); +} + +static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) +{ + SHA_Final(context, digest); +} + +#elif defined(HAVE_OPENSSL) +#include <openssl/sha.h> + +#define xCONTEXT(x) SHA ## x ## _CTX +#define yCONTEXT(y) xCONTEXT(y) +#define CONTEXT yCONTEXT(NUM) +#define SHA1_CTX SHA_CTX +#define SHA224_CTX SHA256_CTX +#define SHA384_CTX SHA512_CTX + +#define xSHA_Init(x) SHA ## x ## _Init +#define xSHA_Update(x) SHA ## x ## _Update +#define xSHA_Final(x) SHA ## x ## _Final +#define ySHA_Init(y) xSHA_Init(y) +#define ySHA_Update(y) xSHA_Update(y) +#define ySHA_Final(y) xSHA_Final(y) +#define SHA_Init ySHA_Init(NUM) +#define SHA_Update ySHA_Update(NUM) +#define SHA_Final ySHA_Final(NUM) + +static void sha_init(CONTEXT *context) +{ + SHA_Init(context); +} + +static void sha_init_fast(CONTEXT *context) +{ + sha_init(context); +} + +static void sha_input(CONTEXT *context, const uchar *buf, unsigned len) +{ + SHA_Update(context, buf, len); +} + +static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE]) +{ + SHA_Final(digest, context); +} + +#endif /* HAVE_WOLFSSL */ + +#define xmy_sha_multi(x) my_sha ## x ## _multi +#define xmy_sha_context_size(x) my_sha ## x ## _context_size +#define xmy_sha_init(x) my_sha ## x ## _init +#define xmy_sha_input(x) my_sha ## x ## _input +#define xmy_sha_result(x) my_sha ## x ## _result +#define xmy_sha(x) my_sha ## x +#define ymy_sha_multi(y) xmy_sha_multi(y) +#define ymy_sha_context_size(y) xmy_sha_context_size(y) +#define ymy_sha_init(y) xmy_sha_init(y) +#define ymy_sha_input(y) xmy_sha_input(y) +#define ymy_sha_result(y) xmy_sha_result(y) +#define ymy_sha(y) xmy_sha(y) +#define my_sha_multi ymy_sha_multi(NUM) +#define my_sha_context_size ymy_sha_context_size(NUM) +#define my_sha_init ymy_sha_init(NUM) +#define my_sha_input ymy_sha_input(NUM) +#define my_sha_result ymy_sha_result(NUM) +#define my_sha ymy_sha(NUM) + +/** + Wrapper function to compute SHAn message digest. + + @param digest [out] Computed SHAn digest + @param buf [in] Message to be computed + @param len [in] Length of the message + + @return void +*/ +void my_sha(uchar *digest, const char *buf, size_t len) +{ + CONTEXT context; + + sha_init_fast(&context); + sha_input(&context, (const uchar *)buf, (unsigned int)len); + sha_result(&context, digest); +} + + +/** + Wrapper function to compute SHAn message digest for + two messages in order to emulate shaN(msg1, msg2). + + @param digest [out] Computed SHAn 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_sha_multi(uchar *digest, ...) +{ + va_list args; + va_start(args, digest); + + CONTEXT context; + const uchar *str; + + sha_init_fast(&context); + for (str= va_arg(args, const uchar*); str; str= va_arg(args, const uchar*)) + sha_input(&context, str, (uint) va_arg(args, size_t)); + + sha_result(&context, digest); + va_end(args); +} + +size_t my_sha_context_size() +{ + return sizeof(CONTEXT); +} + +void my_sha_init(void *context) +{ + sha_init((CONTEXT *)context); +} + +void my_sha_input(void *context, const uchar *buf, size_t len) +{ + sha_input((CONTEXT *)context, buf, (uint) len); +} + +void my_sha_result(void *context, uchar *digest) +{ + sha_result((CONTEXT *)context, digest); +} diff --git a/mysys_ssl/my_sha1.cc b/mysys_ssl/my_sha1.cc new file mode 100644 index 00000000..29563742 --- /dev/null +++ b/mysys_ssl/my_sha1.cc @@ -0,0 +1,18 @@ +/* Copyright (c) 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define NUM 1 + +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha224.cc b/mysys_ssl/my_sha224.cc new file mode 100644 index 00000000..5fffdce7 --- /dev/null +++ b/mysys_ssl/my_sha224.cc @@ -0,0 +1,18 @@ +/* Copyright (c) 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define NUM 224 + +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha256.cc b/mysys_ssl/my_sha256.cc new file mode 100644 index 00000000..59e871de --- /dev/null +++ b/mysys_ssl/my_sha256.cc @@ -0,0 +1,18 @@ +/* Copyright (c) 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define NUM 256 + +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha384.cc b/mysys_ssl/my_sha384.cc new file mode 100644 index 00000000..40707de0 --- /dev/null +++ b/mysys_ssl/my_sha384.cc @@ -0,0 +1,18 @@ +/* Copyright (c) 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define NUM 384 + +#include "my_sha.inl" diff --git a/mysys_ssl/my_sha512.cc b/mysys_ssl/my_sha512.cc new file mode 100644 index 00000000..6a5a04d7 --- /dev/null +++ b/mysys_ssl/my_sha512.cc @@ -0,0 +1,18 @@ +/* Copyright (c) 2017, MariaDB + + 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, Fifth Floor, Boston, MA 02110-1335 USA */ + +#define NUM 512 + +#include "my_sha.inl" diff --git a/mysys_ssl/openssl.c b/mysys_ssl/openssl.c new file mode 100644 index 00000000..8adaeae4 --- /dev/null +++ b/mysys_ssl/openssl.c @@ -0,0 +1,74 @@ +/* + Copyright (c) 2017, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include <my_global.h> +#include <openssl/evp.h> +#include <ssl_compat.h> + +/* + The check is only done for OpenSSL 1.1.x. + It could run for OpenSSL 1.0.x but it doesn't make much sense + and it hits this bug: + https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/1594748 +*/ + +#ifndef HAVE_OPENSSL11 +int check_openssl_compatibility() +{ + return 0; +} +#else +#include <openssl/evp.h> + +static uint testing; +static size_t alloc_size, alloc_count; + +static void *coc_malloc(size_t size, const char *f __attribute__((unused)), + int l __attribute__((unused))) +{ + if (unlikely(testing)) + { + alloc_size+= size; + alloc_count++; + } + return malloc(size); +} + +int check_openssl_compatibility() +{ + EVP_CIPHER_CTX *evp_ctx; + EVP_MD_CTX *md5_ctx; + + if (!CRYPTO_set_mem_functions(coc_malloc, NULL, NULL)) + return 0; + + testing= 1; + alloc_size= alloc_count= 0; + evp_ctx= EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_free(evp_ctx); + if (alloc_count != 1 || !alloc_size || alloc_size > EVP_CIPHER_CTX_SIZE) + return 1; + + alloc_size= alloc_count= 0; + md5_ctx= EVP_MD_CTX_new(); + EVP_MD_CTX_free(md5_ctx); + if (alloc_count != 1 || !alloc_size || alloc_size > EVP_MD_CTX_SIZE) + return 1; + + testing= 0; + return 0; +} +#endif |