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
+