diff --git a/README.md b/README.md index 2ca5be6d..cd6bde3e 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Each project port included in this repository is contained in its own subdirecto | Python | Python language and interpreter | [Link](https://www.python.org/) | | [README](./Python/README.txt) | | qt | Qt | [Link](https://www.qt.io/) | [Link](https://www.wolfssl.com/building-qt-with-wolfssl/) | [README](./qt/README.md) | | rsyslog | rocket-fast Syslog Server | [Link](https://www.rsyslog.com/) | [Link](https://www.wolfssl.com/wolfssl-ported-rsyslog-8-2106-0/) | [README](./rsyslog/8.2106.0/README.md) | +| realm-core | Database that runs on phones, tablets or wearables | [Link](https://github.com/realm/realm-core/) | | [README](./realm/README.md) | | sblim-sfcb | SBLIM Small-footprint CIM Broker | [Link](http://sblim.sourceforge.net/wiki/index.php/Sfcb) | | [README](./sblim-sfcb/1.4.9/README.md) | | socat | socat Multipurpose relay | [Link](http://www.dest-unreach.org/socat/) | [Link](https://www.wolfssl.com/open-source-project-ports-socat/) | 1.7.3.4 [README](./socat/1.7.3.4/README.md)
1.7.4.1 [README](./socat/1.7.4.1/README.md) | | stunnel | stunnel Proxy | [Link](https://www.stunnel.org/) | [Link](https://www.wolfssl.com/securing-stunnel-tls-1-3/) | 5.57 Unix [README](./stunnel/5.57/README_UNIX.md)
5.57 Windows [README](./stunnel/5.57/README_WIN.md) | diff --git a/realm/README.md b/realm/README.md new file mode 100644 index 00000000..8b2e9b40 --- /dev/null +++ b/realm/README.md @@ -0,0 +1,31 @@ +To configure wolfSSL, use the following command: + +``` +./configure --enable-static --enable-opensslall --enable-enckeys --enable-certgen --enable-context-extra-user-data +sudo make install +``` + +Configuring wolfSSL for local installation can be specified with `--prefix=/path/to/install` + +Downloading and applying the patch for realm-core git commit a5e87a39: + +``` +git clone https://github.com/realm/realm-core.git +cd realm-core +git reset --hard HEAD +git checkout a5e87a39 +git submodule update --init --recursive +git apply ../realm-v13.26.0.patch +``` + +Building realm-core: + +``` +mkdir build +cmake -B build -DREALM_ENABLE_ENCRYPTION=1 -DREALM_ENABLE_SYNC=1 -DREALM_USE_WOLFSSL=1 -DREALM_WOLFSSL_ROOT_DIR=/usr/local/lib +cmake --build build +./build/test/realm-tests +``` + +You can also use the build_wolfssl_with_realm.sh script after adjusting the global variables as needed. + diff --git a/realm/build_wolfssl_with_realm.sh b/realm/build_wolfssl_with_realm.sh new file mode 100755 index 00000000..de210573 --- /dev/null +++ b/realm/build_wolfssl_with_realm.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +#bash -x ./build_wolfssl_with_realm.sh + + + # While the support to build from a tarball is included, + # Please note that to successfully build, + # you will need to manually download and set up Catch2 to match the Git + # repository structure when using the tarball. For example, + # mkdir -p test/external/generated/catch2 + # curl -L -O + # https://github.com/catchorg/Catch2/archive/refs/tags/v2.13.9.tar.gz + # tar -xvf v2.13.9.tar.gz --strip-components=1 -C + # test/external/generated/catch2 + + +# Commit hashes for specific versions when using git +WOLFSSL_COMMIT="e814d1ba" +#REALM_CORE_COMMIT="c729fc80" +REALM_CORE_COMMIT="a5e87a39" # Adjust if necessary + +# Variables +WOLFSSL_VERSION="v5.7.2-stable" +REALM_CORE_VERSION="v13.26.0" +WOLFSSL_TAR="${WOLFSSL_VERSION}.tar.gz" +REALM_TAR="${REALM_CORE_VERSION}.tar.gz" +WOLFSSL_URL="https://github.com/wolfSSL/wolfssl/archive/refs/tags/${WOLFSSL_TAR}" +REALM_URL="https://github.com/realm/realm-core/archive/refs/tags/${REALM_TAR}" +OSP_REALM_DIR="realm" +WOLFSSL_DIR="wolfssl" +REALM_CORE_DIR="realm-core" +BUILD_DIR="build" +TEST_EXECUTABLE="$BUILD_DIR/test/realm-tests" +WOLFSSL_INSTALL_DIR="$HOME/wolfssl-install-dir" +USE_SYSTEM_INSTALL=true # Change this to true if you want to use system-wide wolfSSL installation +USE_GIT=true # Default method is using git, set this to false to use curl for tarball + +# Patch file based on REALM_CORE_COMMIT or REALM_CORE_VERSION +PATCH_FILE="" + +# Check if user wants to use git +while getopts ":t" opt; do + case $opt in + t) + USE_GIT=false + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +# Step 2: Download or clone wolfSSL +if [ "$USE_GIT" = true ]; then + if [ ! -d "$WOLFSSL_DIR" ]; then + echo "Cloning the wolfSSL repository..." + git clone https://github.com/wolfSSL/wolfssl.git "$WOLFSSL_DIR" + cd "$WOLFSSL_DIR" || exit + echo "Checking out commit $WOLFSSL_COMMIT..." + git checkout "$WOLFSSL_COMMIT" + else + cd "$WOLFSSL_DIR" || exit + git fetch + echo "Checking out commit $WOLFSSL_COMMIT..." + git checkout "$WOLFSSL_COMMIT" + fi +else + if [ ! -d "$WOLFSSL_DIR" ]; then + echo "Downloading wolfSSL..." + curl -L -O "$WOLFSSL_URL" + echo "Extracting wolfSSL..." + tar -xvf "$WOLFSSL_TAR" + + EXTRACTED_WOLFSSL_DIR=$(tar -tzf "$WOLFSSL_TAR" | head -1 | cut -f1 -d"/") + if [ -d "$EXTRACTED_WOLFSSL_DIR" ]; then + mv "$EXTRACTED_WOLFSSL_DIR" "$WOLFSSL_DIR" + else + echo "Error: Failed to extract or find the wolfSSL directory." + exit 1 + fi + fi + cd "$WOLFSSL_DIR" || exit +fi + +# Step 3: Build and install wolfSSL +if [ "$USE_SYSTEM_INSTALL" = true ]; then + echo "Configuring wolfSSL for system-wide installation..." + ./autogen.sh + ./configure --enable-static --enable-opensslall --enable-enckeys --enable-certgen --enable-context-extra-user-data +else + ./autogen.sh + echo "Configuring wolfSSL for local installation at $WOLFSSL_INSTALL_DIR..." + ./configure --enable-static --enable-opensslall --enable-enckeys --enable-certgen --enable-context-extra-user-data --prefix="$WOLFSSL_INSTALL_DIR" +fi + +echo "Building and installing wolfSSL..." +make -j$(nproc) +sudo make install + +# Step 4: Download or clone realm-core +cd .. +if [ "$USE_GIT" = true ]; then + PATCH_FILE="realm-commit-${REALM_CORE_COMMIT}.patch" + if [ ! -d "$REALM_CORE_DIR" ]; then + echo "Cloning the realm-core repository..." + git clone https://github.com/realm/realm-core.git "$REALM_CORE_DIR" + cd "$REALM_CORE_DIR" || exit + else + cd "$REALM_CORE_DIR" || exit + fi + # Reset the branch before checking out the specific commit and applying patch + git reset --hard HEAD + git checkout "$REALM_CORE_COMMIT" + git submodule update --init --recursive +else + PATCH_FILE="realm-${REALM_CORE_VERSION}.patch" + if [ ! -d "$REALM_CORE_DIR" ]; then + echo "Downloading realm-core..." + curl -L -O "$REALM_URL" + echo "Extracting realm-core..." + tar -xvf "$REALM_TAR" + + EXTRACTED_REALM_DIR=$(tar -tzf "$REALM_TAR" | head -1 | cut -f1 -d"/") + if [ -d "$EXTRACTED_REALM_DIR" ]; then + mv "$EXTRACTED_REALM_DIR" "$REALM_CORE_DIR" + else + echo "Error: Failed to extract or find the realm-core directory." + exit 1 + fi + + cd "$REALM_CORE_DIR" || exit + else + cd "$REALM_CORE_DIR" || exit + fi +fi + +# Step 5: Apply patch if patch file exists for realm-core +if [ -f "$PATCH_FILE" ]; then + echo "Applying patch to realm-core..." + git apply "$PATCH_FILE" +fi + +# Step 6: Build realm-core +if [ ! -d "$BUILD_DIR" ]; then + mkdir "$BUILD_DIR" +fi + +if [ "$USE_SYSTEM_INSTALL" = true ]; then + echo "Configuring realm-core to use system-wide wolfSSL installation..." + cmake -B "$BUILD_DIR" -DREALM_ENABLE_ENCRYPTION=1 -DREALM_ENABLE_SYNC=1 -DREALM_USE_WOLFSSL=1 -DREALM_WOLFSSL_ROOT_DIR=/usr/local/lib +else + echo "Configuring realm-core to use local wolfSSL installation from $WOLFSSL_INSTALL_DIR..." + cmake -B "$BUILD_DIR" -DREALM_ENABLE_ENCRYPTION=1 -DREALM_ENABLE_SYNC=1 -DREALM_USE_WOLFSSL=1 -DREALM_WOLFSSL_ROOT_DIR="$WOLFSSL_INSTALL_DIR" +fi + +echo "Building realm-core..." +cmake --build "$BUILD_DIR" + +# Step 7: Run the tests +if [ -f "$TEST_EXECUTABLE" ]; then + echo "Running the test: $TEST_EXECUTABLE" + "$TEST_EXECUTABLE" +else + echo "Test executable not found. Make sure the build was successful." +fi diff --git a/realm/options.h b/realm/options.h new file mode 100644 index 00000000..763c83bd --- /dev/null +++ b/realm/options.h @@ -0,0 +1,241 @@ +/* wolfssl options.h + * generated from configure options + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + */ + +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#undef WOLFSSL_HAVE_ATOMIC_H +#define WOLFSSL_HAVE_ATOMIC_H + +#undef HAVE_C___ATOMIC +#define HAVE_C___ATOMIC 1 + +#undef HAVE_THREAD_LS +#define HAVE_THREAD_LS + +#undef NO_DO178 +#define NO_DO178 + +#undef WOLFSSL_X86_64_BUILD +#define WOLFSSL_X86_64_BUILD + +#undef WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_ASN_TEMPLATE + +#undef ERROR_QUEUE_PER_THREAD +#define ERROR_QUEUE_PER_THREAD + +#undef TFM_TIMING_RESISTANT +#define TFM_TIMING_RESISTANT + +#undef ECC_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT + +#undef WC_RSA_BLINDING +#define WC_RSA_BLINDING + +#undef WOLFSSL_USE_ALIGN +#define WOLFSSL_USE_ALIGN + +#undef WOLFSSL_SHA224 +#define WOLFSSL_SHA224 + +#undef WOLFSSL_SHA512 +#define WOLFSSL_SHA512 + +#undef WOLFSSL_SHA384 +#define WOLFSSL_SHA384 + +#undef HAVE_HKDF +#define HAVE_HKDF + +#undef NO_DSA +#define NO_DSA + +#undef HAVE_ECC +#define HAVE_ECC + +#undef TFM_ECC256 +#define TFM_ECC256 + +#undef ECC_SHAMIR +#define ECC_SHAMIR + +#undef ECC_MIN_KEY_SZ +#define ECC_MIN_KEY_SZ 224 + +#undef NO_OLD_TLS +#define NO_OLD_TLS + +#undef WC_RSA_PSS +#define WC_RSA_PSS + +#undef WOLFSSL_PSS_LONG_SALT +#define WOLFSSL_PSS_LONG_SALT + +#undef WOLFSSL_ASN_PRINT +#define WOLFSSL_ASN_PRINT + +#undef WOLFSSL_BASE64_ENCODE +#define WOLFSSL_BASE64_ENCODE + +#undef WOLFSSL_SHA3 +#define WOLFSSL_SHA3 + +#undef WOLFSSL_NO_SHAKE128 +#define WOLFSSL_NO_SHAKE128 + +#undef WOLFSSL_NO_SHAKE256 +#define WOLFSSL_NO_SHAKE256 + +#undef HAVE_POLY1305 +#define HAVE_POLY1305 + +#undef HAVE_CHACHA +#define HAVE_CHACHA + +#undef HAVE_HASHDRBG +#define HAVE_HASHDRBG + +#undef HAVE_OPENSSL_CMD +#define HAVE_OPENSSL_CMD + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SNI +#define HAVE_SNI + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef HAVE_FFDHE_2048 +#define HAVE_FFDHE_2048 + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef WOLFSSL_TLS13 +#define WOLFSSL_TLS13 + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_EXTENDED_MASTER +#define HAVE_EXTENDED_MASTER + +#undef NO_RC4 +#define NO_RC4 + +#undef HAVE_ENCRYPT_THEN_MAC +#define HAVE_ENCRYPT_THEN_MAC + +#undef NO_PSK +#define NO_PSK + +#undef NO_MD4 +#define NO_MD4 + +#undef WOLFSSL_ENCRYPTED_KEYS +#define WOLFSSL_ENCRYPTED_KEYS + +#undef WOLFSSL_SP_MATH_ALL +#define WOLFSSL_SP_MATH_ALL + +#undef WOLFSSL_SP_X86_64 +#define WOLFSSL_SP_X86_64 + +#undef WC_NO_ASYNC_THREADING +#define WC_NO_ASYNC_THREADING + +#undef HAVE_DH_DEFAULT_PARAMS +#define HAVE_DH_DEFAULT_PARAMS + +#undef HAVE_EX_DATA +#define HAVE_EX_DATA + +#undef WOLFSSL_SYS_CA_CERTS +#define WOLFSSL_SYS_CA_CERTS + +#undef WOLFSSL_CERT_GEN +#define WOLFSSL_CERT_GEN + +#undef HAVE_OCSP +#define HAVE_OCSP + +#undef OPENSSL_ALL +#define OPENSSL_ALL + +#undef WOLFSSL_EITHER_SIDE +#define WOLFSSL_EITHER_SIDE + +#undef WC_RSA_NO_PADDING +#define WC_RSA_NO_PADDING + +#undef WC_RSA_PSS +#define WC_RSA_PSS + +#undef WOLFSSL_PSS_LONG_SALT +#define WOLFSSL_PSS_LONG_SALT + +#undef WOLFSSL_TICKET_HAVE_ID +#define WOLFSSL_TICKET_HAVE_ID + +#undef WOLFSSL_ERROR_CODE_OPENSSL +#define WOLFSSL_ERROR_CODE_OPENSSL + +#undef WOLFSSL_CERT_NAME_ALL +#define WOLFSSL_CERT_NAME_ALL + +#undef OPENSSL_EXTRA +#define OPENSSL_EXTRA + +#undef NO_DES3 +#define NO_DES3 + +#undef NO_DES3_TLS_SUITES +#define NO_DES3_TLS_SUITES + +#undef GCM_TABLE_4BIT +#define GCM_TABLE_4BIT + +#undef HAVE_AESGCM +#define HAVE_AESGCM + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SERVER_RENEGOTIATION_INFO +#define HAVE_SERVER_RENEGOTIATION_INFO + +#undef HAVE_COMP_KEY +#define HAVE_COMP_KEY + +#undef HAVE___UINT128_T +#define HAVE___UINT128_T 1 + +#undef HAVE_WC_INTROSPECTION +#define HAVE_WC_INTROSPECTION + + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_OPTIONS_H */ + diff --git a/realm/realm-commit-a5e87a39.patch b/realm/realm-commit-a5e87a39.patch new file mode 100644 index 00000000..5da04cc5 --- /dev/null +++ b/realm/realm-commit-a5e87a39.patch @@ -0,0 +1,391 @@ +From 3ece43c30f46b56993867577ccec7c578e7f2356 Mon Sep 17 00:00:00 2001 +From: Tesfa Mael +Date: Tue, 8 Oct 2024 18:15:57 -0700 +Subject: [PATCH] Add support for wolfSSL + +--- + src/realm/CMakeLists.txt | 10 +++- + src/realm/sync/CMakeLists.txt | 2 + + src/realm/sync/network/network_ssl.cpp | 48 ++++++++++++--- + src/realm/sync/network/network_ssl.hpp | 60 ++++++++++++++++++- + src/realm/sync/noinst/server/CMakeLists.txt | 2 +- + .../noinst/server/crypto_server_openssl.cpp | 11 ++++ + src/realm/util/aes_cryptor.hpp | 11 ++++ + src/realm/util/config.h.in | 1 + + src/realm/util/sha_crypto.cpp | 11 ++++ + 9 files changed, 142 insertions(+), 14 deletions(-) + +diff --git a/src/realm/CMakeLists.txt b/src/realm/CMakeLists.txt +index c991e8dfe..12c981ab7 100644 +--- a/src/realm/CMakeLists.txt ++++ b/src/realm/CMakeLists.txt +@@ -337,7 +337,7 @@ target_include_directories(Storage INTERFACE + + # On systems without a built-in SHA-1 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. +-if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL) ++if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL) + add_library(sha1 OBJECT ../external/sha-1/sha1.c) + target_include_directories(Storage PRIVATE ../external/sha-1) + target_sources(Storage PRIVATE $) +@@ -346,7 +346,7 @@ endif() + # On systems without a built-in SHA-2 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. + # Note: This is also used on Windows because Windows lacks a native SHA224 hash needed for realm encryption +-if(NOT APPLE AND NOT REALM_HAVE_OPENSSL OR WIN32) ++if(NOT APPLE AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL OR WIN32) + add_library(sha2 OBJECT ../external/sha-2/sha224.cpp ../external/sha-2/sha256.cpp) + target_include_directories(Storage PRIVATE ../external/sha-2) + target_sources(Storage PRIVATE $) +@@ -376,7 +376,11 @@ if(TARGET Backtrace::Backtrace) + endif() + + if(REALM_ENABLE_ENCRYPTION AND UNIX AND NOT APPLE AND REALM_HAVE_OPENSSL) +- target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ if (REALM_HAVE_WOLFSSL) ++ target_link_libraries(Storage PUBLIC WolfSSL) ++ elseif (REALM_HAVE_OPENSSL) ++ target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ endif() + endif() + + # Use Zlib if the imported target is defined, otherise use -lz on Apple platforms +diff --git a/src/realm/sync/CMakeLists.txt b/src/realm/sync/CMakeLists.txt +index afa711d9e..abf682ef5 100644 +--- a/src/realm/sync/CMakeLists.txt ++++ b/src/realm/sync/CMakeLists.txt +@@ -103,6 +103,8 @@ target_link_libraries(Sync PUBLIC Storage) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_link_options(Sync INTERFACE "SHELL:-framework Security") ++elseif(REALM_HAVE_WOLFSSL) ++ target_link_libraries(Sync PUBLIC WolfSSL) + elseif(REALM_HAVE_OPENSSL) + target_link_libraries(Sync PUBLIC OpenSSL::SSL) + endif() +diff --git a/src/realm/sync/network/network_ssl.cpp b/src/realm/sync/network/network_ssl.cpp +index 58c2fcd96..86e989b57 100644 +--- a/src/realm/sync/network/network_ssl.cpp ++++ b/src/realm/sync/network/network_ssl.cpp +@@ -6,7 +6,7 @@ + #include + #include + +-#if REALM_HAVE_OPENSSL ++#if REALM_HAVE_OPENSSL || REALM_HAVE_WOLFSSL + #ifdef _WIN32 + #include + #else +@@ -14,6 +14,9 @@ + #endif + #include + #include ++#if REALM_HAVE_WOLFSSL ++ #include ++#endif + #elif REALM_HAVE_SECURE_TRANSPORT + #include + #include +@@ -65,7 +68,8 @@ void populate_cert_store_with_included_certs(X509_STORE* store, std::error_code& + #endif // REALM_INCLUDE_CERTS + + +-#if REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#if REALM_HAVE_WOLFSSL || \ ++ (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER))) + + // These must be made to execute before main() is called, i.e., before there is + // any chance of threads being spawned. +@@ -122,9 +126,13 @@ OpensslInit::~OpensslInit() + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + CONF_modules_unload(1); ++#if REALM_HAVE_WOLFSSL ++ wolfSSL_Cleanup(); ++#endif + } + +-#endif // REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#endif // REALM_HAVE_WOLFSSL || (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || ++ // defined(LIBRESSL_VERSION_NUMBER))) + + } // unnamed namespace + +@@ -276,6 +284,11 @@ void Context::ssl_init() + options |= SSL_OP_NO_COMPRESSION; + SSL_CTX_set_options(ssl_ctx, options); + ++#if REALM_HAVE_WOLFSSL ++ // mimic default OpenSSL behavior ++ SSL_CTX_set_verify(ssl_ctx, static_cast(VerifyMode::none), nullptr); ++#endif ++ + m_ssl_ctx = ssl_ctx; + } + +@@ -390,6 +403,16 @@ public: + + BioMethod() + { ++#if REALM_HAVE_WOLFSSL ++ bio_method = new BIO_METHOD(); ++ bio_method->type = WOLFSSL_BIO_UNDEF; // byte type ++ bio_method->writeCb = &Stream::bio_write; // int (*writeCb)(BIO*, const char*, int) ++ bio_method->readCb = &Stream::bio_read; // int (*readCb)(BIO*, char*, int) ++ bio_method->putsCb = &Stream::bio_puts; // int (*putsCb)(BIO*, const char*) ++ bio_method->ctrlCb = &Stream::bio_ctrl; // long (*ctrlCb)(BIO*, int, long, void*) ++ bio_method->createCb = &Stream::bio_create; // int (*createCb)(BIO*) ++ bio_method->freeCb = &Stream::bio_destroy; // int (*freeCb)(BIO*) ++#else + bio_method = new BIO_METHOD{ + BIO_TYPE_SOCKET, // int type + nullptr, // const char* name +@@ -402,6 +425,7 @@ public: + &Stream::bio_destroy, // int (*destroy)(BIO*) + nullptr // long (*callback_ctrl)(BIO*, int, bio_info_cb*) + }; ++#endif + } + + ~BioMethod() +@@ -475,7 +499,7 @@ bool check_san(X509* server_cert, const std::string& host_name) + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name +- char* dns_name = static_cast(ASN1_STRING_data(current_name->d.dNSName)); ++ char* dns_name = reinterpret_cast(ASN1_STRING_data(current_name->d.dNSName)); + + // Make sure there isn't an embedded NUL character in the DNS name + if (static_cast(ASN1_STRING_length(current_name->d.dNSName)) != std::strlen(dns_name)) +@@ -682,7 +706,9 @@ void Stream::ssl_init() + throw std::system_error(ec); + } + +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_data(bio, this); + #else + bio->ptr = this; +@@ -701,7 +727,9 @@ void Stream::ssl_destroy() noexcept + + int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -725,7 +753,9 @@ int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + + int Stream::bio_read(BIO* bio, char* buffer, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -784,7 +814,9 @@ long Stream::bio_ctrl(BIO*, int cmd, long, void*) noexcept + + int Stream::bio_create(BIO* bio) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_init(bio, 1); + BIO_set_data(bio, nullptr); + BIO_clear_flags(bio, 0); +diff --git a/src/realm/sync/network/network_ssl.hpp b/src/realm/sync/network/network_ssl.hpp +index abdd84311..d5f115357 100644 +--- a/src/realm/sync/network/network_ssl.hpp ++++ b/src/realm/sync/network/network_ssl.hpp +@@ -15,6 +15,17 @@ + #include + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #if REALM_HAVE_OPENSSL + #include + #include +@@ -479,6 +490,10 @@ private: + template + std::size_t ssl_perform(Oper oper, std::error_code& ec, Want& want) noexcept; + ++#if REALM_HAVE_WOLFSSL ++ static void ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept; ++#endif ++ + int do_ssl_accept() noexcept; + int do_ssl_connect() noexcept; + int do_ssl_shutdown() noexcept; +@@ -1141,11 +1156,15 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + int ssl_error = SSL_get_error(m_ssl, ret); + int sys_error = int(ERR_peek_last_error()); + ++#if REALM_HAVE_WOLFSSL ++ REALM_ASSERT(!m_bio_error_code || ssl_error == SOCKET_ERROR_E || ssl_error == SOCKET_PEER_CLOSED_E); ++ ++ ssl_map_wolfssl_error_codes(ret, ssl_error, sys_error); ++#else + // Guaranteed by the documentation of SSL_get_error() + REALM_ASSERT((ret > 0) == (ssl_error == SSL_ERROR_NONE)); +- + REALM_ASSERT(!m_bio_error_code || ssl_error == SSL_ERROR_SYSCALL); +- ++#endif + // Judging from various comments in the man pages, and from experience with + // the API, it seems that, + // +@@ -1233,6 +1252,43 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + return 0; + } + ++#if REALM_HAVE_WOLFSSL ++inline void Stream::ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept ++{ ++ // Map some common wolfSSL error codes to OpenSSL ones ++ // wolfSSL returns a more specific error codes for issues than openSSL's simple ++ // "ssl error" and "syscall error", however realm's tests and some business logic ++ // are written with OpenSSLs errors in mind, so we map them here to be non-intrusive ++ if (ret == WOLFSSL_FATAL_ERROR) { ++ switch (ssl_error) { ++ case SOCKET_ERROR_E: ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ case VERIFY_CERT_ERROR: ++ case FATAL_ERROR: ++ case ASN_NO_SIGNER_E: ++ ssl_error = SSL_ERROR_SSL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ else if (ret == WOLFSSL_ERROR_NONE && ssl_error != WOLFSSL_ERROR_NONE) { ++ switch (ssl_error) { ++ case SOCKET_PEER_CLOSED_E: ++ ret = WOLFSSL_FATAL_ERROR; ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++} ++#endif ++ + inline int Stream::do_ssl_accept() noexcept + { + int ret = SSL_accept(m_ssl); +diff --git a/src/realm/sync/noinst/server/CMakeLists.txt b/src/realm/sync/noinst/server/CMakeLists.txt +index a650c4840..f0fc05eaa 100644 +--- a/src/realm/sync/noinst/server/CMakeLists.txt ++++ b/src/realm/sync/noinst/server/CMakeLists.txt +@@ -31,7 +31,7 @@ target_link_libraries(SyncServer PUBLIC Sync QueryParser) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_sources(SyncServer PRIVATE crypto_server_apple.mm) +-elseif(REALM_HAVE_OPENSSL) ++elseif(REALM_HAVE_OPENSSL OR REALM_HAVE_WOLFSSL) + target_sources(SyncServer PRIVATE crypto_server_openssl.cpp) + else() + target_sources(SyncServer PRIVATE crypto_server_stub.cpp) +diff --git a/src/realm/sync/noinst/server/crypto_server_openssl.cpp b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +index 559e11cbe..efb802608 100644 +--- a/src/realm/sync/noinst/server/crypto_server_openssl.cpp ++++ b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +@@ -1,5 +1,16 @@ + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #include +diff --git a/src/realm/util/aes_cryptor.hpp b/src/realm/util/aes_cryptor.hpp +index d9f8da87f..0a1231669 100644 +--- a/src/realm/util/aes_cryptor.hpp ++++ b/src/realm/util/aes_cryptor.hpp +@@ -54,6 +54,17 @@ public: + #include + #pragma comment(lib, "bcrypt.lib") + #else ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #endif +diff --git a/src/realm/util/config.h.in b/src/realm/util/config.h.in +index 36a7e0990..a1dd8d44d 100644 +--- a/src/realm/util/config.h.in ++++ b/src/realm/util/config.h.in +@@ -5,6 +5,7 @@ + #cmakedefine01 REALM_HAVE_READDIR64 + #cmakedefine01 REALM_HAVE_POSIX_FALLOCATE + #cmakedefine01 REALM_HAVE_OPENSSL ++#cmakedefine01 REALM_HAVE_WOLFSSL + #cmakedefine01 REALM_HAVE_SECURE_TRANSPORT + #cmakedefine01 REALM_HAVE_PTHREAD_GETNAME + #cmakedefine01 REALM_HAVE_PTHREAD_SETNAME +diff --git a/src/realm/util/sha_crypto.cpp b/src/realm/util/sha_crypto.cpp +index e73fcad98..51530ebe9 100644 +--- a/src/realm/util/sha_crypto.cpp ++++ b/src/realm/util/sha_crypto.cpp +@@ -37,6 +37,17 @@ + #define REALM_USE_BUNDLED_SHA2 1 + #endif + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #ifdef REALM_USE_BUNDLED_SHA2 + #include + #include +-- +2.34.1 + diff --git a/realm/realm-commit-c729fc80.patch b/realm/realm-commit-c729fc80.patch new file mode 100644 index 00000000..7721ecaf --- /dev/null +++ b/realm/realm-commit-c729fc80.patch @@ -0,0 +1,554 @@ +From 03c2732f5c34bbb96eb2bdbc946a28d42bbff6f2 Mon Sep 17 00:00:00 2001 +From: Brett Nicholas +Date: Thu, 6 Apr 2023 15:27:15 -0600 +Subject: [PATCH] Add support for wolfSSL crypto + +--- + CMakeLists.txt | 45 ++++++++- + src/realm/CMakeLists.txt | 10 +- + src/realm/sync/CMakeLists.txt | 2 + + src/realm/sync/network/network_ssl.cpp | 52 ++++++++-- + src/realm/sync/network/network_ssl.hpp | 60 +++++++++++- + src/realm/sync/noinst/server/CMakeLists.txt | 2 +- + .../noinst/server/crypto_server_openssl.cpp | 11 +++ + src/realm/util/aes_cryptor.hpp | 11 +++ + src/realm/util/config.h.in | 1 + + src/realm/util/sha_crypto.cpp | 11 ++- + tools/cmake/FindWolfSSL.cmake | 96 +++++++++++++++++++ + 11 files changed, 282 insertions(+), 19 deletions(-) + create mode 100644 tools/cmake/FindWolfSSL.cmake + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a693f1c85..f16e5e42c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -299,13 +299,54 @@ elseif(REALM_ENABLE_ENCRYPTION AND CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + set(REALM_NEEDS_OPENSSL TRUE) + endif() + +-if(REALM_NEEDS_OPENSSL OR REALM_FORCE_OPENSSL) ++# If the system determines we should use openSSL, and the user wants to substitute wolfSSL ++# we allow this combination for only Linux builds ++if(REALM_USE_WOLFSSL) ++ if(REALM_FORCE_OPENSSL) ++ message(FATAL_ERROR "option \"REALM_FORCE_OPENSSL\" incompatible with option \"REALM_USE_WOLFSSL\"") ++ endif() ++ ++ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") ++ message(FATAL_ERROR "WolfSSL support only available on Linux, for now...") ++ endif() ++ ++ if(NOT REALM_NEEDS_OPENSSL) ++ message(FATAL_ERROR "WolfSSL support only available for builds that would otherwise use OpenSSL") ++ endif() ++ ++ set(REALM_NEEDS_WOLFSSL TRUE) ++ message(STATUS "Using wolfSSL compatibility layer over OpenSSL") ++endif() ++ ++ ++if(REALM_NEEDS_WOLFSSL AND REALM_NEEDS_OPENSSL) ++ # NOTE: this logic should eventually be changed to point to realm's self-hosted prebuilt WolfSSL ++ # and grab it using realm_aquire_dependency. For now we just allow pointing to an install directory ++ if (NOT REALM_USE_SYSTEM_WOLFSSL) ++ if(NOT DEFINED REALM_WOLFSSL_ROOT_DIR) ++ message(FATAL_ERROR "REALM_WOLFSSL_ROOT_DIR undefined. If you wish to build against the wolfSSL compatibility layer, define this variable \ ++ to hold the path to your wolfSSL installation directory using -DREALM_WOLFSSL_ROOT_DIR=/path/to/wolfssl/install/dir") ++ endif() ++ set(WOLFSSL_ROOT_DIR ${REALM_WOLFSSL_ROOT_DIR}) ++ else() ++ if(DEFINED REALM_WOLFSSL_ROOT_DIR) ++ message(FATAL_ERROR "option \"REALM_WOLFSSL_ROOT_DIR\" incompatible with option \"REALM_USE_SYSTEM_WOLFSSL\"") ++ endif() ++ endif() ++ ++ set(WOLFSSL_USE_STATIC_LIBS ON) ++ find_package(WolfSSL REQUIRED) ++ ++ set(REALM_HAVE_WOLFSSL ON) ++ # We also need to set REALM_HAVE_OPENSSL to enable the standard OpenSSL code paths ++ set(REALM_HAVE_OPENSSL ON) ++elseif(REALM_NEEDS_OPENSSL OR REALM_FORCE_OPENSSL) ++ message(STATUS "using OpenSSL") + option(REALM_USE_SYSTEM_OPENSSL "Look for an external OpenSSL installation instead of using prebuilt one." OFF) + set(_REALM_USE_OPENSSL_DEFAULT_VERIFY_PATHS ON) + if(NOT REALM_USE_SYSTEM_OPENSSL AND (ANDROID OR WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")) + # Use our own prebuilt OpenSSL + realm_acquire_dependency(openssl ${DEP_OPENSSL_VERSION} OPENSSL_CMAKE_INCLUDE_FILE) +- + include(${OPENSSL_CMAKE_INCLUDE_FILE}) + set(_REALM_USE_OPENSSL_DEFAULT_VERIFY_PATHS OFF) + endif() +diff --git a/src/realm/CMakeLists.txt b/src/realm/CMakeLists.txt +index 3cb6304a0..1c882105c 100644 +--- a/src/realm/CMakeLists.txt ++++ b/src/realm/CMakeLists.txt +@@ -347,7 +347,7 @@ target_include_directories(Storage INTERFACE + + # On systems without a built-in SHA-1 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. +-if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL) ++if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL) + add_library(sha1 OBJECT ../external/sha-1/sha1.c) + target_include_directories(Storage PRIVATE ../external/sha-1) + target_sources(Storage PRIVATE $) +@@ -356,7 +356,7 @@ endif() + # On systems without a built-in SHA-2 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. + # Note: This is also used on Windows because Windows lacks a native SHA224 hash needed for realm encryption +-if(NOT APPLE AND NOT REALM_HAVE_OPENSSL) ++if(NOT APPLE AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL) + add_library(sha2 OBJECT ../external/sha-2/sha224.cpp ../external/sha-2/sha256.cpp) + target_include_directories(Storage PRIVATE ../external/sha-2) + target_sources(Storage PRIVATE $) +@@ -392,7 +392,11 @@ if(REALM_HAVE_BACKTRACE AND NOT CMAKE_GENERATOR STREQUAL Xcode) + endif() + + if(REALM_HAVE_OPENSSL AND (UNIX OR WIN32)) +- target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ if (REALM_HAVE_WOLFSSL) ++ target_link_libraries(Storage PUBLIC WolfSSL) ++ elseif (REALM_HAVE_OPENSSL) ++ target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ endif() + endif() + + # Use Zlib if the imported target is defined, otherise use -lz on Apple platforms +diff --git a/src/realm/sync/CMakeLists.txt b/src/realm/sync/CMakeLists.txt +index 8896f15b5..5c1696286 100644 +--- a/src/realm/sync/CMakeLists.txt ++++ b/src/realm/sync/CMakeLists.txt +@@ -103,6 +103,8 @@ target_link_libraries(Sync PUBLIC Storage) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_link_options(Sync INTERFACE "SHELL:-framework Security") ++elseif(REALM_HAVE_WOLFSSL) ++ target_link_libraries(Sync PUBLIC WolfSSL) + elseif(REALM_HAVE_OPENSSL) + target_link_libraries(Sync PUBLIC OpenSSL::SSL) + endif() +diff --git a/src/realm/sync/network/network_ssl.cpp b/src/realm/sync/network/network_ssl.cpp +index d06d4a5c2..f46114279 100644 +--- a/src/realm/sync/network/network_ssl.cpp ++++ b/src/realm/sync/network/network_ssl.cpp +@@ -6,9 +6,12 @@ + #include + #include + +-#if REALM_HAVE_OPENSSL +-#include +-#include ++#if REALM_HAVE_OPENSSL || REALM_HAVE_WOLFSSL ++ #include ++ #include ++ #if REALM_HAVE_WOLFSSL ++ #include ++ #endif + #ifdef _WIN32 + using osslX509_NAME = X509_NAME; // alias this before including wincrypt.h because it gets clobbered + #include +@@ -183,7 +186,8 @@ void add_windows_certificate_store_lookup(X509_STORE* store) + + #endif // REALM_HAVE_OPENSSL && _WIN32 + +-#if REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#if REALM_HAVE_WOLFSSL || \ ++ (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER))) + + // These must be made to execute before main() is called, i.e., before there is + // any chance of threads being spawned. +@@ -240,9 +244,13 @@ OpensslInit::~OpensslInit() + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + CONF_modules_unload(1); ++#if REALM_HAVE_WOLFSSL ++ wolfSSL_Cleanup(); ++#endif + } + +-#endif // REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#endif // REALM_HAVE_WOLFSSL || (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || ++ // defined(LIBRESSL_VERSION_NUMBER))) + + } // unnamed namespace + +@@ -391,6 +399,11 @@ void Context::ssl_init() + options |= SSL_OP_NO_COMPRESSION; + SSL_CTX_set_options(ssl_ctx, options); + ++#if REALM_HAVE_WOLFSSL ++ // mimic default OpenSSL behavior ++ SSL_CTX_set_verify(ssl_ctx, static_cast(VerifyMode::none), nullptr); ++#endif ++ + m_ssl_ctx = ssl_ctx; + } + +@@ -510,6 +523,16 @@ public: + + BioMethod() + { ++#if REALM_HAVE_WOLFSSL ++ bio_method = new BIO_METHOD(); ++ bio_method->type = WOLFSSL_BIO_UNDEF; // byte type ++ bio_method->writeCb = &Stream::bio_write; // int (*writeCb)(BIO*, const char*, int) ++ bio_method->readCb = &Stream::bio_read; // int (*readCb)(BIO*, char*, int) ++ bio_method->putsCb = &Stream::bio_puts; // int (*putsCb)(BIO*, const char*) ++ bio_method->ctrlCb = &Stream::bio_ctrl; // long (*ctrlCb)(BIO*, int, long, void*) ++ bio_method->createCb = &Stream::bio_create; // int (*createCb)(BIO*) ++ bio_method->freeCb = &Stream::bio_destroy; // int (*freeCb)(BIO*) ++#else + bio_method = new BIO_METHOD{ + BIO_TYPE_SOCKET, // int type + nullptr, // const char* name +@@ -522,6 +545,7 @@ public: + &Stream::bio_destroy, // int (*destroy)(BIO*) + nullptr // long (*callback_ctrl)(BIO*, int, bio_info_cb*) + }; ++#endif + } + + ~BioMethod() +@@ -595,7 +619,7 @@ bool check_san(X509* server_cert, const std::string& host_name) + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name +- char* dns_name = static_cast(ASN1_STRING_data(current_name->d.dNSName)); ++ char* dns_name = reinterpret_cast(ASN1_STRING_data(current_name->d.dNSName)); + + // Make sure there isn't an embedded NUL character in the DNS name + if (static_cast(ASN1_STRING_length(current_name->d.dNSName)) != std::strlen(dns_name)) +@@ -802,7 +826,9 @@ void Stream::ssl_init() + throw std::system_error(ec); + } + +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_data(bio, this); + #else + bio->ptr = this; +@@ -821,7 +847,9 @@ void Stream::ssl_destroy() noexcept + + int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -845,7 +873,9 @@ int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + + int Stream::bio_read(BIO* bio, char* buffer, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -904,7 +934,9 @@ long Stream::bio_ctrl(BIO*, int cmd, long, void*) noexcept + + int Stream::bio_create(BIO* bio) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_init(bio, 1); + BIO_set_data(bio, nullptr); + BIO_clear_flags(bio, 0); +diff --git a/src/realm/sync/network/network_ssl.hpp b/src/realm/sync/network/network_ssl.hpp +index 07b607947..cc10ab356 100644 +--- a/src/realm/sync/network/network_ssl.hpp ++++ b/src/realm/sync/network/network_ssl.hpp +@@ -15,6 +15,17 @@ + #include + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #if REALM_HAVE_OPENSSL + #include + #include +@@ -472,6 +483,10 @@ private: + template + std::size_t ssl_perform(Oper oper, std::error_code& ec, Want& want) noexcept; + ++#if REALM_HAVE_WOLFSSL ++ static void ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept; ++#endif ++ + int do_ssl_accept() noexcept; + int do_ssl_connect() noexcept; + int do_ssl_shutdown() noexcept; +@@ -1174,11 +1189,15 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + int ssl_error = SSL_get_error(m_ssl, ret); + int sys_error = int(ERR_peek_last_error()); + ++#if REALM_HAVE_WOLFSSL ++ REALM_ASSERT(!m_bio_error_code || ssl_error == SOCKET_ERROR_E || ssl_error == SOCKET_PEER_CLOSED_E); ++ ++ ssl_map_wolfssl_error_codes(ret, ssl_error, sys_error); ++#else + // Guaranteed by the documentation of SSL_get_error() + REALM_ASSERT((ret > 0) == (ssl_error == SSL_ERROR_NONE)); +- + REALM_ASSERT(!m_bio_error_code || ssl_error == SSL_ERROR_SYSCALL); +- ++#endif + // Judging from various comments in the man pages, and from experience with + // the API, it seems that, + // +@@ -1266,6 +1285,43 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + return 0; + } + ++#if REALM_HAVE_WOLFSSL ++inline void Stream::ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept ++{ ++ // Map some common wolfSSL error codes to OpenSSL ones ++ // wolfSSL returns a more specific error codes for issues than openSSL's simple ++ // "ssl error" and "syscall error", however realm's tests and some business logic ++ // are written with OpenSSLs errors in mind, so we map them here to be non-intrusive ++ if (ret == WOLFSSL_FATAL_ERROR) { ++ switch (ssl_error) { ++ case SOCKET_ERROR_E: ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ case VERIFY_CERT_ERROR: ++ case FATAL_ERROR: ++ case ASN_NO_SIGNER_E: ++ ssl_error = SSL_ERROR_SSL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ else if (ret == WOLFSSL_ERROR_NONE && ssl_error != WOLFSSL_ERROR_NONE) { ++ switch (ssl_error) { ++ case SOCKET_PEER_CLOSED_E: ++ ret = WOLFSSL_FATAL_ERROR; ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++} ++#endif ++ + inline int Stream::do_ssl_accept() noexcept + { + int ret = SSL_accept(m_ssl); +diff --git a/src/realm/sync/noinst/server/CMakeLists.txt b/src/realm/sync/noinst/server/CMakeLists.txt +index a650c4840..f0fc05eaa 100644 +--- a/src/realm/sync/noinst/server/CMakeLists.txt ++++ b/src/realm/sync/noinst/server/CMakeLists.txt +@@ -31,7 +31,7 @@ target_link_libraries(SyncServer PUBLIC Sync QueryParser) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_sources(SyncServer PRIVATE crypto_server_apple.mm) +-elseif(REALM_HAVE_OPENSSL) ++elseif(REALM_HAVE_OPENSSL OR REALM_HAVE_WOLFSSL) + target_sources(SyncServer PRIVATE crypto_server_openssl.cpp) + else() + target_sources(SyncServer PRIVATE crypto_server_stub.cpp) +diff --git a/src/realm/sync/noinst/server/crypto_server_openssl.cpp b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +index 559e11cbe..efb802608 100644 +--- a/src/realm/sync/noinst/server/crypto_server_openssl.cpp ++++ b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +@@ -1,5 +1,16 @@ + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #include +diff --git a/src/realm/util/aes_cryptor.hpp b/src/realm/util/aes_cryptor.hpp +index b4e4d852a..8b3af095e 100644 +--- a/src/realm/util/aes_cryptor.hpp ++++ b/src/realm/util/aes_cryptor.hpp +@@ -57,6 +57,17 @@ protected: + #include + #pragma comment(lib, "bcrypt.lib") + #else ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #endif +diff --git a/src/realm/util/config.h.in b/src/realm/util/config.h.in +index 508dc064a..1b07c7602 100644 +--- a/src/realm/util/config.h.in ++++ b/src/realm/util/config.h.in +@@ -6,6 +6,7 @@ + #cmakedefine01 REALM_HAVE_POSIX_FALLOCATE + #cmakedefine01 REALM_USE_SYSTEM_OPENSSL_PATHS + #cmakedefine01 REALM_HAVE_OPENSSL ++#cmakedefine01 REALM_HAVE_WOLFSSL + #cmakedefine01 REALM_HAVE_SECURE_TRANSPORT + #cmakedefine01 REALM_HAVE_PTHREAD_GETNAME + #cmakedefine01 REALM_HAVE_PTHREAD_SETNAME +diff --git a/src/realm/util/sha_crypto.cpp b/src/realm/util/sha_crypto.cpp +index 6be0295c2..149ef4165 100644 +--- a/src/realm/util/sha_crypto.cpp ++++ b/src/realm/util/sha_crypto.cpp +@@ -32,7 +32,16 @@ + #include + #define REALM_USE_BUNDLED_SHA2 1 + #endif +- ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ + /* + * OpenSSL can be used with Windows. If this is the case: + * The Sha-1 & Sha-2 submodules are no longer needed, so the +diff --git a/tools/cmake/FindWolfSSL.cmake b/tools/cmake/FindWolfSSL.cmake +new file mode 100644 +index 000000000..c6c4b7e96 +--- /dev/null ++++ b/tools/cmake/FindWolfSSL.cmake +@@ -0,0 +1,96 @@ ++#[=======================================================================[.rst: ++FindWolfSSL ++--------- ++ ++Find WolfSSL includes and library. For now this only works when pointed to the output directory ++of a wolfSSL build that was configured using the following configure line: ++./configure --enable-static --enable-certgen --enable-opensslall --enable-opensslextra \ ++ --enable-context-extra-user-data --prefix=/path/to/output-dir ++ ++ ++Imported Targets ++^^^^^^^^^^^^^^^^ ++ ++An :ref:`imported target ` named ++``WolfSSL`` is provided if WolfSSL has been found. ++ ++Result Variables ++^^^^^^^^^^^^^^^^ ++ ++This module defines the following variables: ++ ++``WolfSSL_FOUND`` ++ True if WolfSSL was found, false otherwise. ++``WolfSSL_INCLUDE_DIRS`` ++ Include directories needed to include WolfSSL headers. ++``WolfSSL_LIBRARIES`` ++ Libraries needed to link to WolfSSL. ++ ++ ++Hints ++^^^^^ ++ ++The following variables may be set to control search behavior: ++ ++``WOLFSSL_ROOT_DIR`` ++ Set to the root directory of a wolfSSL installation. ++ ++``WOLFSSL_USE_STATIC_LIBS`` ++ Set to ``TRUE`` to look for static libraries. ++ ++ ++#]=======================================================================] ++ ++#----------------------------------------------------------------------------- ++if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") ++ message(FATAL_ERROR "FindWolfSSL.cmake only supports Linux, for now...") ++endif() ++ ++# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES ++if(WOLFSSL_USE_STATIC_LIBS) ++ # save the original find library ordering so we can restore it later ++ set(WOLFSSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) ++ # replace with our static lib suffix ++ set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) ++endif() ++ ++if(EXISTS ${WOLFSSL_ROOT_DIR}) ++ set(CMAKE_PREFIX_PATH ${WOLFSSL_ROOT_DIR}) ++endif() ++ ++find_library(WolfSSL_LIBRARY NAMES wolfssl libwolfssl HINTS ${WOLFSSL_ROOT_DIR}) ++mark_as_advanced(WolfSSL_LIBRARY) ++ ++find_path(WolfSSL_INCLUDE_DIR NAMES wolfssl/ssl.h HINTS ${WOLFSSL_ROOT_DIR}) ++mark_as_advanced(WolfSSL_INCLUDE_DIR) ++ ++# we need to add one additional include for the openssl compatibility layer ++find_path(WolfSSL_OpenSSL_Compat_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${WOLFSSL_ROOT_DIR} PATH_SUFFIXES "wolfssl") ++list(APPEND WolfSSL_INCLUDE_DIR ${WolfSSL_OpenSSL_Compat_INCLUDE_DIR}) ++ ++include(FindPackageHandleStandardArgs) ++FIND_PACKAGE_HANDLE_STANDARD_ARGS(WolfSSL ++ FOUND_VAR WolfSSL_FOUND ++ REQUIRED_VARS WolfSSL_LIBRARY WolfSSL_INCLUDE_DIR ++ ) ++set(WOLFSSL_FOUND ${WolfSSL_FOUND}) ++ ++#----------------------------------------------------------------------------- ++# Provide documented result variables and targets. ++if(WolfSSL_FOUND) ++ set(WolfSSL_INCLUDE_DIRS ${WolfSSL_INCLUDE_DIR}) ++ set(WolfSSL_LIBRARIES ${WolfSSL_LIBRARY}) ++ if(NOT TARGET WolfSSL) ++ add_library(WolfSSL UNKNOWN IMPORTED) ++ set_target_properties(WolfSSL PROPERTIES ++ IMPORTED_LOCATION "${WolfSSL_LIBRARY}" ++ INTERFACE_INCLUDE_DIRECTORIES "${WolfSSL_INCLUDE_DIRS}" ++ ) ++ endif() ++endif() ++ ++ ++if(WOLFSSL_USE_STATIC_LIBS) ++ set(CMAKE_FIND_LIBRARY_SUFFIXES ${WOLFSSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) ++endif() ++unset(CMAKE_PREFIX_PATH) +-- +2.34.1 + diff --git a/realm/realm-v13.26.0.patch b/realm/realm-v13.26.0.patch new file mode 100644 index 00000000..5da04cc5 --- /dev/null +++ b/realm/realm-v13.26.0.patch @@ -0,0 +1,391 @@ +From 3ece43c30f46b56993867577ccec7c578e7f2356 Mon Sep 17 00:00:00 2001 +From: Tesfa Mael +Date: Tue, 8 Oct 2024 18:15:57 -0700 +Subject: [PATCH] Add support for wolfSSL + +--- + src/realm/CMakeLists.txt | 10 +++- + src/realm/sync/CMakeLists.txt | 2 + + src/realm/sync/network/network_ssl.cpp | 48 ++++++++++++--- + src/realm/sync/network/network_ssl.hpp | 60 ++++++++++++++++++- + src/realm/sync/noinst/server/CMakeLists.txt | 2 +- + .../noinst/server/crypto_server_openssl.cpp | 11 ++++ + src/realm/util/aes_cryptor.hpp | 11 ++++ + src/realm/util/config.h.in | 1 + + src/realm/util/sha_crypto.cpp | 11 ++++ + 9 files changed, 142 insertions(+), 14 deletions(-) + +diff --git a/src/realm/CMakeLists.txt b/src/realm/CMakeLists.txt +index c991e8dfe..12c981ab7 100644 +--- a/src/realm/CMakeLists.txt ++++ b/src/realm/CMakeLists.txt +@@ -337,7 +337,7 @@ target_include_directories(Storage INTERFACE + + # On systems without a built-in SHA-1 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. +-if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL) ++if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES "^Windows" AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL) + add_library(sha1 OBJECT ../external/sha-1/sha1.c) + target_include_directories(Storage PRIVATE ../external/sha-1) + target_sources(Storage PRIVATE $) +@@ -346,7 +346,7 @@ endif() + # On systems without a built-in SHA-2 implementation (or one provided by a dependency) + # we need to bundle the public domain implementation. + # Note: This is also used on Windows because Windows lacks a native SHA224 hash needed for realm encryption +-if(NOT APPLE AND NOT REALM_HAVE_OPENSSL OR WIN32) ++if(NOT APPLE AND NOT REALM_HAVE_OPENSSL AND NOT REALM_HAVE_WOLFSSL OR WIN32) + add_library(sha2 OBJECT ../external/sha-2/sha224.cpp ../external/sha-2/sha256.cpp) + target_include_directories(Storage PRIVATE ../external/sha-2) + target_sources(Storage PRIVATE $) +@@ -376,7 +376,11 @@ if(TARGET Backtrace::Backtrace) + endif() + + if(REALM_ENABLE_ENCRYPTION AND UNIX AND NOT APPLE AND REALM_HAVE_OPENSSL) +- target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ if (REALM_HAVE_WOLFSSL) ++ target_link_libraries(Storage PUBLIC WolfSSL) ++ elseif (REALM_HAVE_OPENSSL) ++ target_link_libraries(Storage PUBLIC OpenSSL::Crypto) ++ endif() + endif() + + # Use Zlib if the imported target is defined, otherise use -lz on Apple platforms +diff --git a/src/realm/sync/CMakeLists.txt b/src/realm/sync/CMakeLists.txt +index afa711d9e..abf682ef5 100644 +--- a/src/realm/sync/CMakeLists.txt ++++ b/src/realm/sync/CMakeLists.txt +@@ -103,6 +103,8 @@ target_link_libraries(Sync PUBLIC Storage) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_link_options(Sync INTERFACE "SHELL:-framework Security") ++elseif(REALM_HAVE_WOLFSSL) ++ target_link_libraries(Sync PUBLIC WolfSSL) + elseif(REALM_HAVE_OPENSSL) + target_link_libraries(Sync PUBLIC OpenSSL::SSL) + endif() +diff --git a/src/realm/sync/network/network_ssl.cpp b/src/realm/sync/network/network_ssl.cpp +index 58c2fcd96..86e989b57 100644 +--- a/src/realm/sync/network/network_ssl.cpp ++++ b/src/realm/sync/network/network_ssl.cpp +@@ -6,7 +6,7 @@ + #include + #include + +-#if REALM_HAVE_OPENSSL ++#if REALM_HAVE_OPENSSL || REALM_HAVE_WOLFSSL + #ifdef _WIN32 + #include + #else +@@ -14,6 +14,9 @@ + #endif + #include + #include ++#if REALM_HAVE_WOLFSSL ++ #include ++#endif + #elif REALM_HAVE_SECURE_TRANSPORT + #include + #include +@@ -65,7 +68,8 @@ void populate_cert_store_with_included_certs(X509_STORE* store, std::error_code& + #endif // REALM_INCLUDE_CERTS + + +-#if REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#if REALM_HAVE_WOLFSSL || \ ++ (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER))) + + // These must be made to execute before main() is called, i.e., before there is + // any chance of threads being spawned. +@@ -122,9 +126,13 @@ OpensslInit::~OpensslInit() + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + CONF_modules_unload(1); ++#if REALM_HAVE_WOLFSSL ++ wolfSSL_Cleanup(); ++#endif + } + +-#endif // REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) ++#endif // REALM_HAVE_WOLFSSL || (REALM_HAVE_OPENSSL && (OPENSSL_VERSION_NUMBER < 0x10100000L || ++ // defined(LIBRESSL_VERSION_NUMBER))) + + } // unnamed namespace + +@@ -276,6 +284,11 @@ void Context::ssl_init() + options |= SSL_OP_NO_COMPRESSION; + SSL_CTX_set_options(ssl_ctx, options); + ++#if REALM_HAVE_WOLFSSL ++ // mimic default OpenSSL behavior ++ SSL_CTX_set_verify(ssl_ctx, static_cast(VerifyMode::none), nullptr); ++#endif ++ + m_ssl_ctx = ssl_ctx; + } + +@@ -390,6 +403,16 @@ public: + + BioMethod() + { ++#if REALM_HAVE_WOLFSSL ++ bio_method = new BIO_METHOD(); ++ bio_method->type = WOLFSSL_BIO_UNDEF; // byte type ++ bio_method->writeCb = &Stream::bio_write; // int (*writeCb)(BIO*, const char*, int) ++ bio_method->readCb = &Stream::bio_read; // int (*readCb)(BIO*, char*, int) ++ bio_method->putsCb = &Stream::bio_puts; // int (*putsCb)(BIO*, const char*) ++ bio_method->ctrlCb = &Stream::bio_ctrl; // long (*ctrlCb)(BIO*, int, long, void*) ++ bio_method->createCb = &Stream::bio_create; // int (*createCb)(BIO*) ++ bio_method->freeCb = &Stream::bio_destroy; // int (*freeCb)(BIO*) ++#else + bio_method = new BIO_METHOD{ + BIO_TYPE_SOCKET, // int type + nullptr, // const char* name +@@ -402,6 +425,7 @@ public: + &Stream::bio_destroy, // int (*destroy)(BIO*) + nullptr // long (*callback_ctrl)(BIO*, int, bio_info_cb*) + }; ++#endif + } + + ~BioMethod() +@@ -475,7 +499,7 @@ bool check_san(X509* server_cert, const std::string& host_name) + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name +- char* dns_name = static_cast(ASN1_STRING_data(current_name->d.dNSName)); ++ char* dns_name = reinterpret_cast(ASN1_STRING_data(current_name->d.dNSName)); + + // Make sure there isn't an embedded NUL character in the DNS name + if (static_cast(ASN1_STRING_length(current_name->d.dNSName)) != std::strlen(dns_name)) +@@ -682,7 +706,9 @@ void Stream::ssl_init() + throw std::system_error(ec); + } + +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_data(bio, this); + #else + bio->ptr = this; +@@ -701,7 +727,9 @@ void Stream::ssl_destroy() noexcept + + int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -725,7 +753,9 @@ int Stream::bio_write(BIO* bio, const char* data, int size) noexcept + + int Stream::bio_read(BIO* bio, char* buffer, int size) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + Stream& stream = *static_cast(BIO_get_data(bio)); + #else + Stream& stream = *static_cast(bio->ptr); +@@ -784,7 +814,9 @@ long Stream::bio_ctrl(BIO*, int cmd, long, void*) noexcept + + int Stream::bio_create(BIO* bio) noexcept + { +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++#if REALM_HAVE_WOLFSSL || \ ++ OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ + BIO_set_init(bio, 1); + BIO_set_data(bio, nullptr); + BIO_clear_flags(bio, 0); +diff --git a/src/realm/sync/network/network_ssl.hpp b/src/realm/sync/network/network_ssl.hpp +index abdd84311..d5f115357 100644 +--- a/src/realm/sync/network/network_ssl.hpp ++++ b/src/realm/sync/network/network_ssl.hpp +@@ -15,6 +15,17 @@ + #include + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #if REALM_HAVE_OPENSSL + #include + #include +@@ -479,6 +490,10 @@ private: + template + std::size_t ssl_perform(Oper oper, std::error_code& ec, Want& want) noexcept; + ++#if REALM_HAVE_WOLFSSL ++ static void ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept; ++#endif ++ + int do_ssl_accept() noexcept; + int do_ssl_connect() noexcept; + int do_ssl_shutdown() noexcept; +@@ -1141,11 +1156,15 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + int ssl_error = SSL_get_error(m_ssl, ret); + int sys_error = int(ERR_peek_last_error()); + ++#if REALM_HAVE_WOLFSSL ++ REALM_ASSERT(!m_bio_error_code || ssl_error == SOCKET_ERROR_E || ssl_error == SOCKET_PEER_CLOSED_E); ++ ++ ssl_map_wolfssl_error_codes(ret, ssl_error, sys_error); ++#else + // Guaranteed by the documentation of SSL_get_error() + REALM_ASSERT((ret > 0) == (ssl_error == SSL_ERROR_NONE)); +- + REALM_ASSERT(!m_bio_error_code || ssl_error == SSL_ERROR_SYSCALL); +- ++#endif + // Judging from various comments in the man pages, and from experience with + // the API, it seems that, + // +@@ -1233,6 +1252,43 @@ std::size_t Stream::ssl_perform(Oper oper, std::error_code& ec, Want& want) noex + return 0; + } + ++#if REALM_HAVE_WOLFSSL ++inline void Stream::ssl_map_wolfssl_error_codes(int& ret, int& ssl_error, int& sys_error) noexcept ++{ ++ // Map some common wolfSSL error codes to OpenSSL ones ++ // wolfSSL returns a more specific error codes for issues than openSSL's simple ++ // "ssl error" and "syscall error", however realm's tests and some business logic ++ // are written with OpenSSLs errors in mind, so we map them here to be non-intrusive ++ if (ret == WOLFSSL_FATAL_ERROR) { ++ switch (ssl_error) { ++ case SOCKET_ERROR_E: ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ case VERIFY_CERT_ERROR: ++ case FATAL_ERROR: ++ case ASN_NO_SIGNER_E: ++ ssl_error = SSL_ERROR_SSL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++ else if (ret == WOLFSSL_ERROR_NONE && ssl_error != WOLFSSL_ERROR_NONE) { ++ switch (ssl_error) { ++ case SOCKET_PEER_CLOSED_E: ++ ret = WOLFSSL_FATAL_ERROR; ++ ssl_error = SSL_ERROR_SYSCALL; ++ sys_error = 0; ++ break; ++ default: ++ break; ++ } ++ } ++} ++#endif ++ + inline int Stream::do_ssl_accept() noexcept + { + int ret = SSL_accept(m_ssl); +diff --git a/src/realm/sync/noinst/server/CMakeLists.txt b/src/realm/sync/noinst/server/CMakeLists.txt +index a650c4840..f0fc05eaa 100644 +--- a/src/realm/sync/noinst/server/CMakeLists.txt ++++ b/src/realm/sync/noinst/server/CMakeLists.txt +@@ -31,7 +31,7 @@ target_link_libraries(SyncServer PUBLIC Sync QueryParser) + + if(APPLE AND NOT REALM_FORCE_OPENSSL) + target_sources(SyncServer PRIVATE crypto_server_apple.mm) +-elseif(REALM_HAVE_OPENSSL) ++elseif(REALM_HAVE_OPENSSL OR REALM_HAVE_WOLFSSL) + target_sources(SyncServer PRIVATE crypto_server_openssl.cpp) + else() + target_sources(SyncServer PRIVATE crypto_server_stub.cpp) +diff --git a/src/realm/sync/noinst/server/crypto_server_openssl.cpp b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +index 559e11cbe..efb802608 100644 +--- a/src/realm/sync/noinst/server/crypto_server_openssl.cpp ++++ b/src/realm/sync/noinst/server/crypto_server_openssl.cpp +@@ -1,5 +1,16 @@ + #include + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #include +diff --git a/src/realm/util/aes_cryptor.hpp b/src/realm/util/aes_cryptor.hpp +index d9f8da87f..0a1231669 100644 +--- a/src/realm/util/aes_cryptor.hpp ++++ b/src/realm/util/aes_cryptor.hpp +@@ -54,6 +54,17 @@ public: + #include + #pragma comment(lib, "bcrypt.lib") + #else ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #include + #include + #endif +diff --git a/src/realm/util/config.h.in b/src/realm/util/config.h.in +index 36a7e0990..a1dd8d44d 100644 +--- a/src/realm/util/config.h.in ++++ b/src/realm/util/config.h.in +@@ -5,6 +5,7 @@ + #cmakedefine01 REALM_HAVE_READDIR64 + #cmakedefine01 REALM_HAVE_POSIX_FALLOCATE + #cmakedefine01 REALM_HAVE_OPENSSL ++#cmakedefine01 REALM_HAVE_WOLFSSL + #cmakedefine01 REALM_HAVE_SECURE_TRANSPORT + #cmakedefine01 REALM_HAVE_PTHREAD_GETNAME + #cmakedefine01 REALM_HAVE_PTHREAD_SETNAME +diff --git a/src/realm/util/sha_crypto.cpp b/src/realm/util/sha_crypto.cpp +index e73fcad98..51530ebe9 100644 +--- a/src/realm/util/sha_crypto.cpp ++++ b/src/realm/util/sha_crypto.cpp +@@ -37,6 +37,17 @@ + #define REALM_USE_BUNDLED_SHA2 1 + #endif + ++#if REALM_HAVE_WOLFSSL ++ #ifdef HAVE_CONFIG_H ++ #include ++ #endif ++ #ifndef WOLFSSL_USER_SETTINGS ++ #include ++ #else ++ #include ++ #endif ++#endif /* REALM_HAVE_WOLFSSL */ ++ + #ifdef REALM_USE_BUNDLED_SHA2 + #include + #include +-- +2.34.1 +