diff --git a/.github/workflows/replace-default.yml b/.github/workflows/replace-default.yml
new file mode 100644
index 00000000..4a9860e8
--- /dev/null
+++ b/.github/workflows/replace-default.yml
@@ -0,0 +1,66 @@
+name: Replace Default Tests
+
+# START OF COMMON SECTION
+on:
+ push:
+ branches: [ 'master', 'main', 'release/**' ]
+ pull_request:
+ branches: [ '*' ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+# END OF COMMON SECTION
+
+jobs:
+ replace_default_test:
+ name: Replace Default Test
+ runs-on: ubuntu-22.04
+ timeout-minutes: 30
+ strategy:
+ matrix:
+ # Test both standard and replace-default builds
+ replace_default: ['', '--replace-default']
+ # Test with stable versions
+ wolfssl_ref: ['v5.8.0-stable']
+ openssl_ref: ['openssl-3.5.0']
+ steps:
+ - name: Checkout wolfProvider
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Build wolfProvider ${{ matrix.replace_default && 'with replace-default' || 'standard' }}
+ run: |
+ OPENSSL_TAG=${{ matrix.openssl_ref }} \
+ WOLFSSL_TAG=${{ matrix.wolfssl_ref }} \
+ ./scripts/build-wolfprovider.sh ${{ matrix.replace_default }}
+
+ - name: Run standalone test suite
+ run: |
+ ./test/standalone/runners/run_standalone_tests.sh
+
+ - name: Print errors on failure
+ if: ${{ failure() }}
+ run: |
+ # Build failure log
+ if [ -f scripts/build-release.log ]; then
+ echo "=== Build log (last 50 lines) ==="
+ tail -n 50 scripts/build-release.log
+ fi
+
+ # Test suite failure log
+ if [ -f test-suite.log ]; then
+ echo "=== Test suite log ==="
+ cat test-suite.log
+ fi
+
+ # Standalone test failures
+ if [ -d test/standalone/runners/test_results ]; then
+ for log in test/standalone/runners/test_results/*.log; do
+ if [ -f "$log" ]; then
+ echo "=== $log ==="
+ cat "$log"
+ fi
+ done
+ fi
diff --git a/.gitignore b/.gitignore
index 6c79bf33..483d9a6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,30 @@
/wolfprov-install/
/artifacts
+# Default stub autotools files
+default_stub/ar-lib
+default_stub/compile
+default_stub/config.guess
+default_stub/config.sub
+default_stub/depcomp
+default_stub/install-sh
+default_stub/ltmain.sh
+default_stub/missing
+
+# Build install directories
+*-install/
+
+# Libtool archive files
+*.la
+
+# Test artifacts in subdirectories
+test/**/*.log
+test/**/*.test
+test/**/*.trs
+test/**/*.o
+test/**/.deps/
+test/**/.dirstamp
+
IDE/Android/android-ndk-r26b/
IDE/Android/openssl-source/
IDE/Android/openssl-install/
diff --git a/Makefile.am b/Makefile.am
index 69ad2f6a..6d3e43af 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
-SUFFIXES =
+SUFFIXES =
TESTS =
noinst_PROGRAMS =
noinst_HEADERS =
@@ -14,6 +14,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = libwolfprov.la
+# Conditionally build libdefault.so when --replace-default is enabled
+if BUILD_REPLACE_DEFAULT
+# Install libdefault.la directly to OpenSSL lib directory
+openssldir = $(OPENSSL_LIB_DIR)
+openssl_LTLIBRARIES = libdefault.la
+libdefault_la_SOURCES = src/wp_default_replace.c
+libdefault_la_LIBADD = libwolfprov.la
+endif
+
EXTRA_DIST+=ChangeLog.md
EXTRA_DIST+=README.md
EXTRA_DIST+=IDE
diff --git a/configure.ac b/configure.ac
index d1962b1b..17e31303 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,8 +123,26 @@ AS_IF([ test "x$ENABLED_SINGLETHREADED" = "xno" ],[
])
])
+# Replace default provider
+AC_ARG_ENABLE([replace-default],
+ [AS_HELP_STRING([--enable-replace-default],[Build real libdefault.so from wp_default_replace.c (default: disabled).])],
+ [ ENABLED_REPLACE_DEFAULT=$enableval ],
+ [ ENABLED_REPLACE_DEFAULT=no ]
+ )
-
+AM_CONDITIONAL([BUILD_REPLACE_DEFAULT], [test "x$ENABLED_REPLACE_DEFAULT" = "xyes"])
+
+# Set OpenSSL lib directory for installing libdefault.so
+if test "x$ENABLED_REPLACE_DEFAULT" = "xyes"; then
+ if test -d "$OPENSSL_INSTALL_DIR/lib64"; then
+ OPENSSL_LIB_DIR="$OPENSSL_INSTALL_DIR/lib64"
+ elif test -d "$OPENSSL_INSTALL_DIR/lib"; then
+ OPENSSL_LIB_DIR="$OPENSSL_INSTALL_DIR/lib"
+ else
+ OPENSSL_LIB_DIR="$OPENSSL_INSTALL_DIR/lib"
+ fi
+fi
+AC_SUBST([OPENSSL_LIB_DIR])
AX_HARDEN_CC_COMPILER_FLAGS
@@ -170,6 +188,7 @@ echo
echo " Features "
echo " * User settings: $ENABLED_USERSETTINGS"
echo " * Dynamic provider: $ENABLED_DYNAMIC_PROVIDER"
+echo " * Replace default: $ENABLED_REPLACE_DEFAULT"
echo ""
echo "---"
diff --git a/default_stub/.gitignore b/default_stub/.gitignore
new file mode 100644
index 00000000..f13db083
--- /dev/null
+++ b/default_stub/.gitignore
@@ -0,0 +1,15 @@
+Makefile
+Makefile.in
+.deps/
+.libs/
+*.la
+*.lo
+*.o
+aclocal.m4
+autom4te.cache/
+config.log
+config.status
+configure
+libtool
+*.so
+*.so.*
diff --git a/default_stub/Makefile.am b/default_stub/Makefile.am
new file mode 100644
index 00000000..e31303de
--- /dev/null
+++ b/default_stub/Makefile.am
@@ -0,0 +1,2 @@
+lib_LTLIBRARIES = libdefault.la
+libdefault_la_SOURCES = wp_default_stub.c
diff --git a/default_stub/README.md b/default_stub/README.md
new file mode 100644
index 00000000..3bf15917
--- /dev/null
+++ b/default_stub/README.md
@@ -0,0 +1,21 @@
+# libdefault - Default Provider Stub Library
+
+Minimal autotools build for a stub version of the default provider.
+
+## Building
+
+```bash
+# Generate build system
+./autogen.sh
+
+# Configure and build
+./configure
+make
+
+# Clean build artifacts
+make clean
+```
+
+## Output
+
+The build produces `libdefault.so` in the `.libs/` directory.
diff --git a/default_stub/autogen.sh b/default_stub/autogen.sh
new file mode 100755
index 00000000..c350c05b
--- /dev/null
+++ b/default_stub/autogen.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -e
+
+autoreconf -fiv
diff --git a/default_stub/configure.ac b/default_stub/configure.ac
new file mode 100644
index 00000000..5c44872c
--- /dev/null
+++ b/default_stub/configure.ac
@@ -0,0 +1,7 @@
+AC_INIT([libdefault], [1.0], [support@wolfssl.com])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_PROG_CC
+AM_PROG_AR
+LT_INIT
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/default_stub/wp_default_stub.c b/default_stub/wp_default_stub.c
new file mode 100644
index 00000000..52d9ea28
--- /dev/null
+++ b/default_stub/wp_default_stub.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006-2024 wolfSSL Inc.
+ *
+ * This file is part of wolfProvider.
+ *
+ * wolfProvider is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfProvider is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wolfProvider. If not, see .
+ */
+
+#include
+
+/* Prototype of public function that initializes the wolfSSL provider. */
+OSSL_provider_init_fn wolfssl_provider_init;
+
+/* Prototype for the wolfprov_provider_init function */
+int wolfprov_provider_init(const OSSL_CORE_HANDLE* handle,
+ const OSSL_DISPATCH* in,
+ const OSSL_DISPATCH** out,
+ void** provCtx);
+
+/*
+ * Provider implementation stub
+ */
+int wolfprov_provider_init(const OSSL_CORE_HANDLE* handle,
+ const OSSL_DISPATCH* in,
+ const OSSL_DISPATCH** out,
+ void** provCtx)
+{
+ return 0;
+}
diff --git a/patches/README.md b/patches/README.md
new file mode 100644
index 00000000..abfcd2cb
--- /dev/null
+++ b/patches/README.md
@@ -0,0 +1,16 @@
+# OpenSSL Default Provider Replacement Patch
+
+> **Note**: For comprehensive Open Source Project (OSP) patches and integration work, visit the main wolfSSL OSP repository: **https://github.com/wolfSSL/osp/tree/master/wolfProvider**
+
+This directory contains the patch for replacing OpenSSL's default provider with wolfProvider.
+
+## Purpose
+
+The patch modifies OpenSSL's provider registration to substitute wolfProvider as the "default" provider, ensuring that all default provider operations are handled by wolfProvider instead of OpenSSL's built-in implementation.
+
+## Compatibility
+
+- **Supported Versions**: OpenSSL 3.0 and later
+- **Patch Target**: `crypto/provider_predefined.c`
+
+This directory contains only the OpenSSL default provider replacement functionality.
\ No newline at end of file
diff --git a/patches/openssl3-replace-default.patch b/patches/openssl3-replace-default.patch
new file mode 100644
index 00000000..37aa2578
--- /dev/null
+++ b/patches/openssl3-replace-default.patch
@@ -0,0 +1,30 @@
+diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c
+index 068e0b7..499a9ca 100644
+--- a/crypto/provider_predefined.c
++++ b/crypto/provider_predefined.c
+@@ -10,21 +10,15 @@
+ #include
+ #include "provider_local.h"
+
+-OSSL_provider_init_fn ossl_default_provider_init;
++OSSL_provider_init_fn wolfprov_provider_init;
+ OSSL_provider_init_fn ossl_base_provider_init;
+ OSSL_provider_init_fn ossl_null_provider_init;
+-OSSL_provider_init_fn ossl_fips_intern_provider_init;
+-#ifdef STATIC_LEGACY
+-OSSL_provider_init_fn ossl_legacy_provider_init;
+-#endif
+ const OSSL_PROVIDER_INFO ossl_predefined_providers[] = {
+ #ifdef FIPS_MODULE
+- { "fips", NULL, ossl_fips_intern_provider_init, NULL, 1 },
++ { "fips", NULL, wolfprov_provider_init, NULL, 1 },
+ #else
+- { "default", NULL, ossl_default_provider_init, NULL, 1 },
+-# ifdef STATIC_LEGACY
+- { "legacy", NULL, ossl_legacy_provider_init, NULL, 0 },
+-# endif
++ { "default", NULL, wolfprov_provider_init, NULL, 1 },
++ { "legacy", NULL, wolfprov_provider_init, NULL, 0 },
+ { "base", NULL, ossl_base_provider_init, NULL, 0 },
+ { "null", NULL, ossl_null_provider_init, NULL, 0 },
+ #endif
diff --git a/scripts/build-wolfprovider.sh b/scripts/build-wolfprovider.sh
index 9aa46e7b..16f2584d 100755
--- a/scripts/build-wolfprovider.sh
+++ b/scripts/build-wolfprovider.sh
@@ -8,7 +8,7 @@ show_help() {
echo "Script Arguments:"
echo " --help, -help, -h Display this help menu and exit"
echo " --clean Run make clean in OpenSSL, wolfSSL, and wolfProvider"
- echo " --distclean Remove source directories of OpenSSL and wolfSSL"
+ echo " --distclean Remove source and install directories of OpenSSL, wolfSSL, and wolfProvider"
echo " --debug Builds OpenSSL, wolfSSL, and WolfProvider with debugging enabled. This is the same as setting WOLFPROV_DEBUG=1"
echo " --debug-asn-template Enable debug information for asn within wolfSSL"
echo " --disable-err-trace No debug trace messages from library errors in wolfSSL"
@@ -21,6 +21,7 @@ show_help() {
echo " --debian Build a Debian package"
echo " --debian --enable-fips Build a Debian package with FIPS support"
echo " --quicktest Disable some tests for a faster testing suite"
+ echo " --replace-default Patch OpenSSL and build it so that wolfProvider is the default provider"
echo ""
echo "Environment Variables:"
echo " OPENSSL_TAG OpenSSL tag to use (e.g., openssl-3.5.0)"
@@ -30,7 +31,7 @@ show_help() {
echo " WOLFSSL_FIPS_VERSION Version of wolfSSL FIPS bundle (v5, v6, ready), used as an argument for --enable-fips when configuring wolfSSL"
echo " WOLFSSL_FIPS_CHECK_TAG Tag for wolfSSL FIPS bundle (linuxv5.2.1, v6.0.0, etc), used as an argument for fips-check.sh when cloning a wolfSSL FIPS version"
echo " WOLFPROV_CLEAN If set to 1, run make clean in OpenSSL, wolfSSL, and wolfProvider"
- echo " WOLFPROV_DISTCLEAN If set to 1, remove the source directories of OpenSSL and wolfSSL"
+ echo " WOLFPROV_DISTCLEAN If set to 1, remove the source and install directories of OpenSSL, wolfSSL, and wolfProvider"
echo " WOLFPROV_DEBUG If set to 1, builds OpenSSL, wolfSSL, and wolfProvider with debug options enabled"
echo " WOLFPROV_QUICKTEST If set to 1, disables some tests in the test suite to increase test speed"
echo " WOLFPROV_DISABLE_ERR_TRACE If set to 1, wolfSSL will not be configured with --enable-debug-trace-errcodes=backtrace"
@@ -82,7 +83,6 @@ for arg in "$@"; do
WOLFSSL_ISFIPS=1
;;
--fips-bundle=*)
- unset WOLFSSL_ISFIPS
unset WOLFSSL_FIPS_CHECK_TAG
IFS='=' read -r trash fips_bun <<< "$arg"
if [ -z "$fips_bun" ]; then
@@ -114,6 +114,9 @@ for arg in "$@"; do
--quicktest)
WOLFPROV_QUICKTEST=1
;;
+ --replace-default)
+ WOLFPROV_REPLACE_DEFAULT=1
+ ;;
*)
args_wrong+="$arg, "
;;
@@ -145,6 +148,10 @@ source ${SCRIPT_DIR}/utils-wolfprovider.sh
echo "Using openssl: $OPENSSL_TAG, wolfssl: $WOLFSSL_TAG"
+if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ build_default_stub
+fi
+
init_wolfprov
exit $?
diff --git a/scripts/env-setup b/scripts/env-setup
index 4077cdff..46ca81ba 100755
--- a/scripts/env-setup
+++ b/scripts/env-setup
@@ -33,9 +33,9 @@ echo "PWD: $PWD"
# Detect the openssl library path
if [ -d $REPO_ROOT/openssl-install/lib ]; then
- OPENSSL_LIB_PATH=$REPO_ROOT/openssl-install/lib
+ export OPENSSL_LIB_PATH=$REPO_ROOT/openssl-install/lib
elif [ -d $REPO_ROOT/openssl-install/lib64 ]; then
- OPENSSL_LIB_PATH=$REPO_ROOT/openssl-install/lib64
+ export OPENSSL_LIB_PATH=$REPO_ROOT/openssl-install/lib64
else
echo "Error: Could not find OpenSSL lib directory in $REPO_ROOT/openssl-install"
exit 1
@@ -44,8 +44,9 @@ fi
WOLFSSL_LIB_PATH="$REPO_ROOT/wolfssl-install/lib"
WOLFPROV_LIB_PATH="$REPO_ROOT/wolfprov-install/lib"
-# Set variables with default values if not already set
-export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:=$WOLFSSL_LIB_PATH:$OPENSSL_LIB_PATH}"
+# Always reconstruct LD_LIBRARY_PATH with correctly detected OPENSSL_LIB_PATH
+# ${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} expands to :$LD_LIBRARY_PATH only if LD_LIBRARY_PATH was already set
+export LD_LIBRARY_PATH="$WOLFSSL_LIB_PATH:$OPENSSL_LIB_PATH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
# Auto-detect FIPS mode and use appropriate config
if [ "${WOLFSSL_ISFIPS:-0}" = "1" ]; then
diff --git a/scripts/utils-openssl.sh b/scripts/utils-openssl.sh
index 2fd908e7..ca320667 100755
--- a/scripts/utils-openssl.sh
+++ b/scripts/utils-openssl.sh
@@ -50,6 +50,8 @@ clean_openssl() {
if [ "$WOLFPROV_DISTCLEAN" -eq "1" ]; then
printf "Removing OpenSSL source ...\n"
rm -rf "${OPENSSL_SOURCE_DIR}"
+ printf "Removing OpenSSL install ...\n"
+ rm -rf "${OPENSSL_INSTALL_DIR}"
fi
}
@@ -93,19 +95,113 @@ clone_openssl() {
fi
}
+check_openssl_replace_default_mismatch() {
+ local openssl_is_patched=0
+
+ # Check if the source was patched for --replace-default
+ if [ -f "${OPENSSL_SOURCE_DIR}/crypto/provider_predefined.c" ]; then
+ if grep -q "wolfprov_provider_init" "${OPENSSL_SOURCE_DIR}/crypto/provider_predefined.c" 2>/dev/null; then
+ openssl_is_patched=1
+ printf "INFO: OpenSSL source modified - wolfProvider integrated as default provider (non-stock build).\n"
+ fi
+ fi
+
+ # Check for mismatch
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ] && [ "$openssl_is_patched" = "0" ]; then
+ printf "ERROR: --replace-default build mode mismatch!\n"
+ printf "Existing OpenSSL was built WITHOUT --replace-default patch\n"
+ printf "Current request: --replace-default build\n\n"
+ printf "Fix: ./scripts/build-wolfprovider.sh --distclean\n"
+ printf "Then rebuild with desired configuration.\n"
+ exit 1
+ elif [ "$WOLFPROV_REPLACE_DEFAULT" != "1" ] && [ "$openssl_is_patched" = "1" ]; then
+ printf "ERROR: Standard build mode mismatch!\n"
+ printf "Existing OpenSSL was built WITH --replace-default patch\n"
+ printf "Current request: standard build\n\n"
+ printf "Fix: ./scripts/build-wolfprovider.sh --distclean\n"
+ printf "Then rebuild with desired configuration.\n"
+ exit 1
+ fi
+}
+
+patch_openssl() {
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+
+ if [ -d "${OPENSSL_INSTALL_DIR}" ]; then
+ # If openssl is already installed, patching makes no sense as
+ # it will not be rebuilt. It may already be built as patched,
+ # just return and let check_openssl_replace_default_mismatch
+ # check for the mismatch.
+ return 0
+ fi
+
+ printf "\tApplying OpenSSL default provider patch ... "
+ cd ${OPENSSL_SOURCE_DIR}
+
+ # Check if patch is already applied
+ if grep -q "wolfprov_provider_init" crypto/provider_predefined.c 2>/dev/null; then
+ printf "Already applied.\n"
+ return 0
+ fi
+
+ # Apply the patch
+ patch -p1 < ${SCRIPT_DIR}/../patches/openssl3-replace-default.patch >>$LOG_FILE 2>&1
+ if [ $? != 0 ]; then
+ printf "ERROR.\n"
+ printf "\n\nPatch application failed. Last 40 lines of log:\n"
+ tail -n 40 $LOG_FILE
+ do_cleanup
+ exit 1
+ fi
+ printf "Done.\n"
+
+ cd ${SCRIPT_DIR}/..
+ fi
+}
+
install_openssl() {
printf "\nInstalling OpenSSL ${OPENSSL_TAG} ...\n"
clone_openssl
+ patch_openssl
+ check_openssl_replace_default_mismatch
cd ${OPENSSL_SOURCE_DIR}
if [ ! -d ${OPENSSL_INSTALL_DIR} ]; then
printf "\tConfigure OpenSSL ${OPENSSL_TAG} ... "
+
+ # Build configure command
+ CONFIG_CMD="./config shared --prefix=${OPENSSL_INSTALL_DIR}"
if [ "$WOLFPROV_DEBUG" = "1" ]; then
- ./config shared enable-trace --prefix=${OPENSSL_INSTALL_DIR} --debug >>$LOG_FILE 2>&1
- RET=$?
+ CONFIG_CMD+=" enable-trace --debug"
+ fi
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ CONFIG_CMD+=" no-external-tests no-tests"
+
+ # Set up library paths to find the stub libdefault
+ STUB_LIB_DIR=${SCRIPT_DIR}/../libdefault-stub-install/lib
+ if [ -d "${STUB_LIB_DIR}" ]; then
+ export PKG_CONFIG_PATH="${STUB_LIB_DIR}/pkgconfig:${PKG_CONFIG_PATH}"
+ # Link the stub library directly into libcrypto using LDFLAGS and LDLIBS
+ CONFIGURE_LDFLAGS="-L${STUB_LIB_DIR}"
+ CONFIGURE_LDLIBS="-ldefault"
+ else
+ printf "ERROR - stub libdefault not found in: ${STUB_LIB_DIR}\n"
+ do_cleanup
+ exit 1
+ fi
+ fi
+
+ # Execute configure
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ $CONFIG_CMD LDFLAGS="${CONFIGURE_LDFLAGS}" LDLIBS="${CONFIGURE_LDLIBS}" >>$LOG_FILE 2>&1
else
- ./config shared --prefix=${OPENSSL_INSTALL_DIR} >>$LOG_FILE 2>&1
- RET=$?
+ $CONFIG_CMD >>$LOG_FILE 2>&1
+ fi
+ RET=$?
+
+ # Clean up environment
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ unset LDFLAGS
fi
if [ $RET != 0 ]; then
printf "ERROR.\n"
@@ -143,15 +239,18 @@ init_openssl() {
install_openssl
printf "\tOpenSSL ${OPENSSL_TAG} installed in: ${OPENSSL_INSTALL_DIR}\n"
- OSSL_VER=`LD_LIBRARY_PATH=${OPENSSL_LIB_DIRS} $OPENSSL_BIN version | tail -n1`
- case $OSSL_VER in
- OpenSSL\ 3.*) ;;
- *)
- echo "OpenSSL ($OPENSSL_BIN) has wrong version: $OSSL_VER"
- echo "Set: OPENSSL_DIR"
- exit 1
- ;;
- esac
+ # Skip version check for replace-default mode since we only build libraries
+ if [ "$WOLFPROV_REPLACE_DEFAULT" != "1" ]; then
+ OSSL_VER=`LD_LIBRARY_PATH=${OPENSSL_LIB_DIRS} $OPENSSL_BIN version | tail -n1`
+ case $OSSL_VER in
+ OpenSSL\ 3.*) ;;
+ *)
+ echo "OpenSSL ($OPENSSL_BIN) has wrong version: $OSSL_VER"
+ echo "Set: OPENSSL_DIR"
+ exit 1
+ ;;
+ esac
+ fi
if [ -z $LD_LIBRARY_PATH ]; then
export LD_LIBRARY_PATH=${OPENSSL_LIB_DIRS}
diff --git a/scripts/utils-wolfprovider.sh b/scripts/utils-wolfprovider.sh
index 8b00f00c..f3d11481 100644
--- a/scripts/utils-wolfprovider.sh
+++ b/scripts/utils-wolfprovider.sh
@@ -25,6 +25,7 @@ source ${SCRIPT_DIR}/utils-general.sh
WOLFPROV_SOURCE_DIR=${SCRIPT_DIR}/..
WOLFPROV_INSTALL_DIR=${SCRIPT_DIR}/../wolfprov-install
+LIBDEFAULT_STUB_INSTALL_DIR=${SCRIPT_DIR}/../libdefault-stub-install
WOLFPROV_WITH_WOLFSSL=--with-wolfssl=${WOLFSSL_INSTALL_DIR}
# Check if using system wolfSSL installation
@@ -57,6 +58,55 @@ WOLFPROV_DEBUG=${WOLFPROV_DEBUG:-0}
WOLFPROV_CLEAN=${WOLFPROV_CLEAN:-0}
WOLFPROV_DISTCLEAN=${WOLFPROV_DISTCLEAN:-0}
+build_default_stub() {
+ printf "\nBuilding default stub library ...\n"
+ cd ${SCRIPT_DIR}/../default_stub
+
+ printf "\tGenerate build system ... "
+ if [ ! -e "configure" ]; then
+ ./autogen.sh >>$LOG_FILE 2>&1
+ if [ $? != 0 ]; then
+ printf "\n\n...\n"
+ tail -n 40 $LOG_FILE
+ do_cleanup
+ exit 1
+ fi
+ fi
+ printf "Done.\n"
+
+ printf "\tConfigure default stub ... "
+ ./configure --prefix=${LIBDEFAULT_STUB_INSTALL_DIR} >>$LOG_FILE 2>&1
+ if [ $? != 0 ]; then
+ printf "\n\n...\n"
+ tail -n 40 $LOG_FILE
+ do_cleanup
+ exit 1
+ fi
+ printf "Done.\n"
+
+ printf "\tBuild default stub ... "
+ make >>$LOG_FILE 2>&1
+ if [ $? != 0 ]; then
+ printf "\n\n...\n"
+ tail -n 40 $LOG_FILE
+ do_cleanup
+ exit 1
+ fi
+ printf "Done.\n"
+
+ printf "\tInstall default stub ... "
+ make install >>$LOG_FILE 2>&1
+ if [ $? != 0 ]; then
+ printf "\n\n...\n"
+ tail -n 40 $LOG_FILE
+ do_cleanup
+ exit 1
+ fi
+ printf "Done.\n"
+
+ cd ${SCRIPT_DIR}/..
+}
+
clean_wolfprov() {
printf "\n"
@@ -65,19 +115,41 @@ clean_wolfprov() {
if [ -f "Makefile" ]; then
make clean >>$LOG_FILE 2>&1
fi
+ # Clean default_stub build artifacts
+ if [ -f "default_stub/Makefile" ]; then
+ printf "Cleaning default stub ...\n"
+ make -C default_stub clean >>$LOG_FILE 2>&1
+ fi
+ # Remove root libdefault.la file
+ rm -f libdefault.la
+ rm -rf ${WOLFPROV_INSTALL_DIR}
+ fi
+ if [ "$WOLFPROV_DISTCLEAN" -eq "1" ]; then
+ printf "Removing wolfProvider install ...\n"
rm -rf ${WOLFPROV_INSTALL_DIR}
+ rm -rf ${LIBDEFAULT_STUB_INSTALL_DIR}
fi
}
install_wolfprov() {
cd ${WOLFPROV_SOURCE_DIR}
+ # Add stub library path for replace-default functionality after dependencies are installed
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ if [ -z "$LD_LIBRARY_PATH" ]; then
+ export LD_LIBRARY_PATH="${LIBDEFAULT_STUB_INSTALL_DIR}/lib"
+ else
+ export LD_LIBRARY_PATH="${LIBDEFAULT_STUB_INSTALL_DIR}/lib:$LD_LIBRARY_PATH"
+ fi
+ fi
+
init_openssl
init_wolfssl
printf "\nConsolidating wolfProvider ...\n"
unset OPENSSL_MODULES
unset OPENSSL_CONF
+
printf "LD_LIBRARY_PATH: $LD_LIBRARY_PATH\n"
printf "\tConfigure wolfProvider ... "
@@ -89,6 +161,10 @@ install_wolfprov() {
WOLFPROV_CONFIG_OPTS+=" --enable-debug"
fi
+ if [ "$WOLFPROV_REPLACE_DEFAULT" = "1" ]; then
+ WOLFPROV_CONFIG_OPTS+=" --enable-replace-default"
+ fi
+
./configure ${WOLFPROV_CONFIG_OPTS} CFLAGS="${WOLFPROV_CONFIG_CFLAGS}" >>$LOG_FILE 2>&1
RET=$?
diff --git a/scripts/utils-wolfssl.sh b/scripts/utils-wolfssl.sh
index 45ac9cda..481929d9 100644
--- a/scripts/utils-wolfssl.sh
+++ b/scripts/utils-wolfssl.sh
@@ -49,6 +49,8 @@ clean_wolfssl() {
if [ "$WOLFPROV_DISTCLEAN" -eq "1" ]; then
printf "Removing wolfSSL source ...\n"
rm -rf "${WOLFSSL_SOURCE_DIR}"
+ printf "Removing wolfSSL install ...\n"
+ rm -rf "${WOLFSSL_INSTALL_DIR}"
fi
}
@@ -72,7 +74,10 @@ clone_wolfssl() {
DEPTH_ARG=${WOLFPROV_DEBUG:+""}
DEPTH_ARG=${DEPTH_ARG:---depth=1}
- git clone ${DEPTH_ARG} -b ${CLONE_TAG} ${WOLFSSL_GIT} ${WOLFSSL_SOURCE_DIR} >>$LOG_FILE 2>&1
+ # If we are replacing default provider, our current built openssl still
+ # links to the default stub and is non-functional. Run the clone with
+ # no explicitly LD_LIBRARY_PATH to ensure use of global openssl for clone
+ LD_LIBRARY_PATH="" git clone ${DEPTH_ARG} -b ${CLONE_TAG} ${WOLFSSL_GIT} ${WOLFSSL_SOURCE_DIR} >>$LOG_FILE 2>&1
RET=$?
if [ $RET != 0 ]; then
diff --git a/src/wp_default_replace.c b/src/wp_default_replace.c
new file mode 100644
index 00000000..046a48ec
--- /dev/null
+++ b/src/wp_default_replace.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006-2024 wolfSSL Inc.
+ *
+ * This file is part of wolfProvider.
+ *
+ * wolfProvider is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfProvider is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wolfProvider. If not, see .
+ */
+
+/*
+ * wolfProvider Real Implementation for libdefault.so
+ *
+ * This is the real implementation of wolfprov_provider_init that bridges
+ * OpenSSL's default provider interface to wolfProvider by dynamically
+ * loading libwolfprov.so and calling wolfssl_provider_init.
+ *
+ * This replaces the stub implementation after wolfProvider is fully built.
+ */
+
+#include
+
+/* Prototype of public function that initializes the wolfSSL provider. */
+OSSL_provider_init_fn wolfssl_provider_init;
+
+/* Prototype for the wolfprov_provider_init function */
+int wolfprov_provider_init(const OSSL_CORE_HANDLE* handle,
+ const OSSL_DISPATCH* in,
+ const OSSL_DISPATCH** out,
+ void** provCtx);
+
+/*
+ * Real implementation of wolfprov_provider_init.
+ *
+ * This function dynamically loads libwolfprov.so and calls its
+ * wolfssl_provider_init function to provide full wolfProvider functionality.
+ *
+ * @param [in] handle Handle to the core.
+ * @param [in] in Dispatch table from previous provider.
+ * @param [out] out Dispatch table of wolfSSL provider.
+ * @param [out] provCtx New provider context.
+ * @return 1 on success, 0 on failure.
+ */
+int wolfprov_provider_init(const OSSL_CORE_HANDLE* handle,
+ const OSSL_DISPATCH* in,
+ const OSSL_DISPATCH** out,
+ void** provCtx)
+{
+ return wolfssl_provider_init(handle, in, out, provCtx);
+}
diff --git a/test/include.am b/test/include.am
index a2eed11c..6dbad0cc 100644
--- a/test/include.am
+++ b/test/include.am
@@ -35,3 +35,5 @@ test_unit_test_SOURCES = \
test_unit_test_LDADD = libwolfprov.la
noinst_HEADERS += test/unit.h
+# Include standalone binary tests
+include test/standalone/include.am
diff --git a/test/standalone/include.am b/test/standalone/include.am
new file mode 100644
index 00000000..f61b2dba
--- /dev/null
+++ b/test/standalone/include.am
@@ -0,0 +1,35 @@
+# vim:ft=automake
+# included from test/include.am
+# All paths should be given relative to the root
+
+# Standalone test programs use no extension - simple and clean!
+
+# Common standalone test headers
+noinst_HEADERS += test/standalone/test_common.h
+
+# Standalone test programs
+# Each test compiles to its own binary for isolated execution
+# Note: These are NOT in check_PROGRAMS because they must be run through scripts, not directly
+noinst_PROGRAMS += test/sha256_simple.test test/hardload.test
+DISTCLEANFILES += test/.libs/sha256_simple.test test/.libs/hardload.test
+
+# Common flags for all standalone tests
+STANDALONE_COMMON_CPPFLAGS = -DCERTS_DIR='"$(abs_top_srcdir)/certs"' \
+ -I$(srcdir)/test/standalone
+STANDALONE_COMMON_LDADD = libwolfprov.la
+
+# Individual test configurations
+test_sha256_simple_test_CPPFLAGS = $(STANDALONE_COMMON_CPPFLAGS)
+test_sha256_simple_test_SOURCES = test/standalone/tests/sha256_simple/test_sha256_simple.c
+test_sha256_simple_test_LDADD = $(STANDALONE_COMMON_LDADD)
+
+test_hardload_test_CPPFLAGS = $(STANDALONE_COMMON_CPPFLAGS)
+test_hardload_test_SOURCES = test/standalone/tests/hardload/test_hardload.c
+test_hardload_test_LDADD = $(STANDALONE_COMMON_LDADD)
+
+# Common test utilities are built automatically by automake
+
+# Standalone tests are available for manual execution but not part of make check
+# Run manually with: ./test/standalone/runners/run_standalone_tests.sh
+
+# Note: test results are cleaned by the test runner automatically
diff --git a/test/standalone/provider-default.conf b/test/standalone/provider-default.conf
new file mode 100644
index 00000000..12da8cb5
--- /dev/null
+++ b/test/standalone/provider-default.conf
@@ -0,0 +1,10 @@
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = provider_sect
+
+[provider_sect]
+default = default_sect
+
+[default_sect]
+activate = 1
diff --git a/test/standalone/runners/run_standalone_tests.sh b/test/standalone/runners/run_standalone_tests.sh
new file mode 100755
index 00000000..9fcf6c01
--- /dev/null
+++ b/test/standalone/runners/run_standalone_tests.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# run_standalone_tests.sh - Master runner for all standalone tests
+
+set -e
+
+# Get the directory of this script and find the root
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)"
+
+echo "Running all standalone tests..."
+echo "================================"
+
+TOTAL_FAILURES=0
+
+# Run SHA256 simple test
+echo ""
+echo "Running SHA256 simple test..."
+set +e
+"$ROOT_DIR/test/standalone/tests/sha256_simple/run.sh"
+if [ $? -eq 0 ]; then
+ echo "SHA256 simple test: PASSED"
+else
+ echo "SHA256 simple test: FAILED"
+ TOTAL_FAILURES=$((TOTAL_FAILURES + 1))
+fi
+set -e
+
+# Run hardload test
+echo ""
+echo "Running hardload test..."
+set +e
+"$ROOT_DIR/test/standalone/tests/hardload/run.sh"
+if [ $? -eq 0 ]; then
+ echo "Hardload test: PASSED"
+else
+ echo "Hardload test: FAILED"
+ TOTAL_FAILURES=$((TOTAL_FAILURES + 1))
+fi
+set -e
+
+echo ""
+echo "================================"
+if [ $TOTAL_FAILURES -eq 0 ]; then
+ echo "All standalone tests passed!"
+ exit 0
+else
+ echo "$TOTAL_FAILURES standalone test(s) failed"
+ exit 1
+fi
\ No newline at end of file
diff --git a/test/standalone/test_common.h b/test/standalone/test_common.h
new file mode 100644
index 00000000..9cff9cd6
--- /dev/null
+++ b/test/standalone/test_common.h
@@ -0,0 +1,89 @@
+/* test_common.h
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfProvider.
+ *
+ * wolfProvider is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfProvider is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wolfProvider. If not, see .
+ */
+
+#ifndef TEST_COMMON_H
+#define TEST_COMMON_H
+
+#include
+#include
+
+#ifdef WOLFPROV_USER_SETTINGS
+#include
+#endif
+#include
+#include
+
+#include
+#include
+
+/* Test result codes */
+#define TEST_SUCCESS 0
+#define TEST_FAILURE 1
+
+/* Debug printing macros */
+#define TEST_INFO(fmt, ...) printf("[INFO] " fmt "\n", ##__VA_ARGS__)
+#define TEST_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
+#define TEST_DEBUG(fmt, ...) do { \
+ if (getenv("TEST_DEBUG")) { \
+ printf("[DEBUG] " fmt "\n", ##__VA_ARGS__); \
+ } \
+} while(0)
+
+/* Buffer printing for debugging */
+#ifdef WOLFPROV_DEBUG
+#define TEST_PRINT_BUFFER(desc, buf, len) test_print_buffer(desc, buf, len)
+static inline void test_print_buffer(const char *desc, const unsigned char *buffer, size_t len)
+{
+ size_t i;
+ printf("[BUFFER] %s (%zu bytes):\n", desc, len);
+ for (i = 0; i < len; i++) {
+ printf("%02x ", buffer[i]);
+ if ((i % 16) == 15) {
+ printf("\n");
+ }
+ }
+ if ((i % 16) != 0) {
+ printf("\n");
+ }
+ printf("\n");
+}
+#else
+#define TEST_PRINT_BUFFER(desc, buf, len)
+#endif
+
+/* Utility functions */
+static inline int test_bytes_to_hex(const unsigned char *bytes, size_t len, char *hex, size_t hex_size)
+{
+ size_t i;
+
+ if (hex_size < (len * 2 + 1)) {
+ TEST_ERROR("Hex buffer too small");
+ return TEST_FAILURE;
+ }
+
+ for (i = 0; i < len; i++) {
+ sprintf(hex + (i * 2), "%02x", bytes[i]);
+ }
+ hex[len * 2] = '\0';
+
+ return TEST_SUCCESS;
+}
+
+#endif /* TEST_COMMON_H */
diff --git a/test/standalone/tests/.libs/test_sha256_simple.standalone b/test/standalone/tests/.libs/test_sha256_simple.standalone
new file mode 100755
index 00000000..e47d2b43
Binary files /dev/null and b/test/standalone/tests/.libs/test_sha256_simple.standalone differ
diff --git a/test/standalone/tests/hardload/run.sh b/test/standalone/tests/hardload/run.sh
new file mode 100755
index 00000000..17326bea
--- /dev/null
+++ b/test/standalone/tests/hardload/run.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+# Hardload test runner
+
+set -e
+
+# Get the directory of this script and find the root
+TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$TEST_DIR/../../../.." && pwd)"
+
+# Binary should be in the test/.libs/ directory
+BINARY="hardload.test"
+BINARY_PATH="$ROOT_DIR/test/.libs/$BINARY"
+
+# Make sure we can find the binary
+if [ ! -f "$BINARY_PATH" ]; then
+ echo "Error: Cannot find binary $BINARY_PATH"
+ echo "Make sure you've built the test with: make test/hardload.test"
+ exit 1
+fi
+
+# Source env-setup
+if ! source "$ROOT_DIR/scripts/env-setup" >/dev/null; then
+ echo "Error: env-setup failed"
+ exit 1
+fi
+
+WP_USING_REPLACE_DEFAULT="0"
+if [ -f "$OPENSSL_LIB_PATH/libcrypto.so" ]; then
+ # Check for wolfProvider symbols in libcrypto
+ if nm -D "$OPENSSL_LIB_PATH/libcrypto.so" 2>/dev/null | grep -q "wolfprov_provider_init"; then
+ WP_USING_REPLACE_DEFAULT="1"
+ fi
+fi
+
+# Configure environment based on build type
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ echo "Detected: --replace-default build"
+ unset OPENSSL_CONF
+ EXPECTED_PROVIDER_NAME="wolfSSL Provider"
+else
+ EXPECTED_PROVIDER_NAME="OpenSSL Default Provider"
+fi
+
+echo "Expected provider name: $EXPECTED_PROVIDER_NAME"
+
+echo "Using environment:"
+echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
+echo "OPENSSL_CONF: $OPENSSL_CONF"
+echo "OPENSSL_BIN: $OPENSSL_BIN"
+
+# Check that wolfProvider is loaded in place of default
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ if ! ${OPENSSL_BIN} list -providers | grep -q "wolf"; then
+ echo "Error: wolfProvider is not loaded in place of default"
+ exit 1
+ fi
+fi
+
+# Function to run a test scenario
+run_test() {
+ local test_name="$1"
+ local should_fail="$2"
+ local set_force_fail="$3"
+ local output_file
+
+ echo "=== $test_name ==="
+
+ if [ "$set_force_fail" = "true" ]; then
+ export WOLFPROV_FORCE_FAIL=1
+ echo "Setting WOLFPROV_FORCE_FAIL=1"
+ else
+ unset WOLFPROV_FORCE_FAIL
+ echo "WOLFPROV_FORCE_FAIL not set"
+ fi
+
+ if [ "$should_fail" = "true" ]; then
+ expected="FAIL"
+ else
+ expected="PASS"
+ fi
+
+ # Create temporary file for test output
+ output_file=$(mktemp)
+
+ if "$BINARY_PATH" "$EXPECTED_PROVIDER_NAME" >"$output_file" 2>&1; then
+ result="PASS"
+ else
+ result="FAIL"
+ fi
+
+ echo "Expected: $expected, Got: $result"
+
+ if [ "$result" = "$expected" ]; then
+ echo "PASS"
+ rm -f "$output_file"
+ return 0
+ else
+ echo "FAILED"
+ echo "Test output:"
+ cat "$output_file"
+ rm -f "$output_file"
+ return 1
+ fi
+}
+
+echo "Running hardload test: $BINARY_PATH"
+echo ""
+
+FAILURES=0
+
+# Run normal scenario - should always pass
+if ! run_test "Normal operation" false false; then
+ FAILURES=$((FAILURES + 1))
+fi
+echo ""
+
+# Run force-fail scenario - success criteria depends on build type
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ # Replace-default: force-fail should actually fail (can't escape wolfProvider)
+ if ! run_test "Force fail test (should fail)" true true; then
+ FAILURES=$((FAILURES + 1))
+ fi
+else
+ # Normal build: force-fail should pass (hardload bypasses wolfProvider)
+ if ! run_test "Force fail test (should pass)" false true; then
+ FAILURES=$((FAILURES + 1))
+ fi
+fi
+
+echo ""
+if [ $FAILURES -gt 0 ]; then
+ echo "$FAILURES scenarios failed"
+ exit 1
+else
+ echo "All scenarios passed"
+ exit 0
+fi
diff --git a/test/standalone/tests/hardload/test_hardload.c b/test/standalone/tests/hardload/test_hardload.c
new file mode 100644
index 00000000..db79f832
--- /dev/null
+++ b/test/standalone/tests/hardload/test_hardload.c
@@ -0,0 +1,200 @@
+/* test_hardload.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfProvider.
+ *
+ * wolfProvider is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfProvider is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wolfProvider. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#ifdef WOLFPROV_USER_SETTINGS
+#include
+#endif
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "../../test_common.h"
+
+/* Test data and expected results */
+static const char test_data[] = "Hello, hardload test!";
+
+int main(int argc, char *argv[])
+{
+ OSSL_LIB_CTX *libctx = NULL;
+ OSSL_PROVIDER *default_prov = NULL;
+ EVP_MD_CTX *mdctx = NULL;
+ const EVP_MD *sha256 = NULL;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_len = 0;
+ char digest_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ const char *expected_provider_name = "default";
+ int ret = TEST_FAILURE;
+ const char *wpProviderName = NULL;
+ OSSL_PARAM wpParams[] = {
+ { OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, &wpProviderName, 0, 0 },
+ { NULL, 0, NULL, 0, 0 }
+ };
+
+ /* Parse command line arguments */
+ if (argc > 1) {
+ expected_provider_name = argv[1];
+ }
+
+ TEST_INFO("Expected provider name: %s", expected_provider_name);
+
+ /* Initialize OpenSSL */
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
+ /* Create library context */
+ libctx = OSSL_LIB_CTX_new();
+ if (libctx == NULL) {
+ TEST_ERROR("Failed to create OpenSSL library context");
+ goto cleanup;
+ }
+
+ /* Hard load the default provider - ignore environment variables */
+ TEST_DEBUG("Hard loading default provider (ignoring environment)");
+ default_prov = OSSL_PROVIDER_load(libctx, "default");
+ if (default_prov == NULL) {
+ TEST_ERROR("Failed to hard load default provider");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Verify the default provider is loaded */
+ if (!OSSL_PROVIDER_available(libctx, "default")) {
+ TEST_ERROR("Default provider is not available after loading");
+ goto cleanup;
+ }
+
+ TEST_INFO("Default provider hard loaded successfully");
+
+ /* Validate the provider name matches expected using OSSL_PROVIDER_get_params */
+ if (OSSL_PROVIDER_get_params(default_prov, wpParams) != 1) {
+ TEST_ERROR("Failed to get provider parameters");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ if (wpProviderName == NULL) {
+ TEST_ERROR("Provider name parameter returned NULL");
+ goto cleanup;
+ }
+
+ TEST_INFO("Actual provider name: %s", wpProviderName);
+
+ if (strcmp(wpProviderName, expected_provider_name) != 0) {
+ TEST_ERROR("Provider name mismatch - Expected: '%s', Got: '%s'",
+ expected_provider_name, wpProviderName);
+ goto cleanup;
+ }
+
+ TEST_INFO("Provider name validation passed: %s", wpProviderName);
+
+ /* Get SHA256 algorithm from the explicitly loaded default provider */
+ sha256 = EVP_MD_fetch(libctx, "SHA256", NULL);
+ if (sha256 == NULL) {
+ TEST_ERROR("Failed to fetch SHA256 algorithm from default provider");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Create message digest context */
+ mdctx = EVP_MD_CTX_new();
+ if (mdctx == NULL) {
+ TEST_ERROR("Failed to create MD context");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Initialize digest operation */
+ if (EVP_DigestInit_ex(mdctx, sha256, NULL) != 1) {
+ TEST_ERROR("Failed to initialize digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ TEST_DEBUG("Computing SHA256 of: \"%s\" (%zu bytes)", test_data, strlen(test_data));
+
+ /* Update digest with test data */
+ if (EVP_DigestUpdate(mdctx, test_data, strlen(test_data)) != 1) {
+ TEST_ERROR("Failed to update digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Finalize digest */
+ if (EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) {
+ TEST_ERROR("Failed to finalize digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Convert to hex string for logging */
+ if (test_bytes_to_hex(digest, digest_len, digest_hex, sizeof(digest_hex)) != TEST_SUCCESS) {
+ TEST_ERROR("Failed to convert digest to hex");
+ goto cleanup;
+ }
+
+ TEST_INFO("Computed SHA256: %s", digest_hex);
+
+ /* Verify we got a 32-byte SHA256 result */
+ if (digest_len != 32) {
+ TEST_ERROR("Invalid SHA256 digest length: %u (expected 32)", digest_len);
+ goto cleanup;
+ }
+
+ TEST_PRINT_BUFFER("SHA256 digest", digest, digest_len);
+
+ TEST_INFO("SHA256 computation successful using hard loaded default provider - got %u byte digest", digest_len);
+
+ /* Test passed */
+ ret = TEST_SUCCESS;
+
+cleanup:
+ if (mdctx != NULL) {
+ EVP_MD_CTX_free(mdctx);
+ }
+ if (sha256 != NULL) {
+ EVP_MD_free((EVP_MD*)sha256);
+ }
+ if (default_prov != NULL) {
+ OSSL_PROVIDER_unload(default_prov);
+ }
+ if (libctx != NULL) {
+ OSSL_LIB_CTX_free(libctx);
+ }
+
+ if (ret == TEST_SUCCESS) {
+ TEST_INFO("Test PASSED");
+ } else {
+ TEST_ERROR("Test FAILED");
+ }
+
+ return ret;
+}
diff --git a/test/standalone/tests/sha256_simple/run.sh b/test/standalone/tests/sha256_simple/run.sh
new file mode 100755
index 00000000..3062b99d
--- /dev/null
+++ b/test/standalone/tests/sha256_simple/run.sh
@@ -0,0 +1,159 @@
+#!/bin/bash
+# SHA256 simple test runner
+
+set -e
+
+# Get the directory of this script and find the root
+TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "$TEST_DIR/../../../.." && pwd)"
+
+# Binary should be in the test/.libs/ directory
+BINARY="sha256_simple.test"
+BINARY_PATH="$ROOT_DIR/test/.libs/$BINARY"
+
+# Make sure we can find the binary
+if [ ! -f "$BINARY_PATH" ]; then
+ echo "Error: Cannot find binary $BINARY_PATH"
+ echo "Make sure you've built the test with: make test/sha256_simple.test"
+ exit 1
+fi
+
+# Source env-setup
+if ! source "$ROOT_DIR/scripts/env-setup" >/dev/null; then
+ echo "Error: env-setup failed"
+ exit 1
+fi
+
+WP_USING_REPLACE_DEFAULT="0"
+if [ -f "$OPENSSL_LIB_PATH/libcrypto.so" ]; then
+ # Check for wolfProvider symbols in libcrypto
+ if nm -D "$OPENSSL_LIB_PATH/libcrypto.so" 2>/dev/null | grep -q "wolfprov_provider_init"; then
+ WP_USING_REPLACE_DEFAULT="1"
+ fi
+fi
+
+# Configure environment based on build type
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ echo "Detected: --replace-default build"
+ unset OPENSSL_CONF
+fi
+
+echo "Using environment:"
+echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
+echo "OPENSSL_CONF: $OPENSSL_CONF"
+echo "OPENSSL_BIN: $OPENSSL_BIN"
+
+# Check that wolfProvider is loaded in place of default
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ if ! ${OPENSSL_BIN} list -providers | grep -q "wolf"; then
+ echo "Error: wolfProvider is not loaded in place of default"
+ exit 1
+ fi
+fi
+
+# Function to run a test scenario
+run_test() {
+ local test_name="$1"
+ local should_fail="$2"
+ local custom_conf="$3"
+ local output_file
+
+ echo "=== $test_name ==="
+
+ if [ "$should_fail" = "true" ]; then
+ export WOLFPROV_FORCE_FAIL=1
+ expected="FAIL"
+ else
+ unset WOLFPROV_FORCE_FAIL
+ expected="PASS"
+ fi
+
+ # Set custom config if provided
+ local original_openssl_conf="$OPENSSL_CONF"
+ if [ -n "$custom_conf" ]; then
+ export OPENSSL_CONF="$custom_conf"
+ echo "Using custom config: $OPENSSL_CONF"
+ fi
+
+ # Create temporary file for test output
+ output_file=$(mktemp)
+
+ if "$BINARY_PATH" >"$output_file" 2>&1; then
+ result="PASS"
+ else
+ result="FAIL"
+ fi
+
+ # Restore original config
+ if [ -n "$custom_conf" ]; then
+ if [ -n "$original_openssl_conf" ]; then
+ export OPENSSL_CONF="$original_openssl_conf"
+ else
+ unset OPENSSL_CONF
+ fi
+ fi
+
+ echo "Expected: $expected, Got: $result"
+
+ if [ "$result" = "$expected" ]; then
+ echo "PASS"
+ rm -f "$output_file"
+ return 0
+ else
+ echo "FAILED"
+ echo "Test output:"
+ cat "$output_file"
+ rm -f "$output_file"
+ return 1
+ fi
+}
+
+echo "Running SHA256 test: $BINARY_PATH"
+echo ""
+
+FAILURES=0
+
+if [ "$WP_USING_REPLACE_DEFAULT" = "1" ]; then
+ echo "Replace-default build detected - running 4 test scenarios"
+
+ if ! run_test "No config, normal operation" false; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+
+ if ! run_test "No config, force fail" true; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+
+ if ! run_test "Explicit default config, normal operation" false "$ROOT_DIR/test/standalone/provider-default.conf"; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+
+ if ! run_test "Explicit default config, force fail" true "$ROOT_DIR/test/standalone/provider-default.conf"; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+else
+ echo "Standard build - running 2 test scenarios"
+
+ if ! run_test "Normal operation" false; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+
+ if ! run_test "Force fail test" true; then
+ FAILURES=$((FAILURES + 1))
+ fi
+ echo ""
+fi
+
+echo ""
+if [ $FAILURES -gt 0 ]; then
+ echo "$FAILURES scenarios failed"
+ exit 1
+else
+ echo "All scenarios passed"
+ exit 0
+fi
diff --git a/test/standalone/tests/sha256_simple/test_sha256_simple.c b/test/standalone/tests/sha256_simple/test_sha256_simple.c
new file mode 100644
index 00000000..1168b807
--- /dev/null
+++ b/test/standalone/tests/sha256_simple/test_sha256_simple.c
@@ -0,0 +1,143 @@
+/* test_sha256_simple.c
+ *
+ * Copyright (C) 2006-2025 wolfSSL Inc.
+ *
+ * This file is part of wolfProvider.
+ *
+ * wolfProvider is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfProvider is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wolfProvider. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#ifdef WOLFPROV_USER_SETTINGS
+#include
+#endif
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "../../test_common.h"
+
+/* Test data and expected results */
+static const char test_data[] = "Hello, wolfProvider!";
+static const char expected_sha256_hex[] = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+
+int main(int argc, char *argv[])
+{
+ EVP_MD_CTX *mdctx = NULL;
+ const EVP_MD *sha256 = NULL;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int digest_len = 0;
+ char digest_hex[EVP_MAX_MD_SIZE * 2 + 1];
+ int ret = TEST_FAILURE;
+
+ (void)argc;
+ (void)argv;
+
+ TEST_INFO("Starting SHA256 simple test");
+
+ /* Get SHA256 algorithm */
+ sha256 = EVP_MD_fetch(NULL, "SHA256", NULL);
+ if (sha256 == NULL) {
+ TEST_ERROR("Failed to fetch SHA256 algorithm");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Create message digest context */
+ mdctx = EVP_MD_CTX_new();
+ if (mdctx == NULL) {
+ TEST_ERROR("Failed to create MD context");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Initialize digest operation */
+ if (EVP_DigestInit_ex(mdctx, sha256, NULL) != 1) {
+ TEST_ERROR("Failed to initialize digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ TEST_DEBUG("Computing SHA256 of: \"%s\" (%zu bytes)", test_data, strlen(test_data));
+
+ /* Update digest with test data */
+ if (EVP_DigestUpdate(mdctx, test_data, strlen(test_data)) != 1) {
+ TEST_ERROR("Failed to update digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Finalize digest */
+ if (EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) {
+ TEST_ERROR("Failed to finalize digest");
+ ERR_print_errors_fp(stderr);
+ goto cleanup;
+ }
+
+ /* Convert to hex string for comparison */
+ if (test_bytes_to_hex(digest, digest_len, digest_hex, sizeof(digest_hex)) != TEST_SUCCESS) {
+ TEST_ERROR("Failed to convert digest to hex");
+ goto cleanup;
+ }
+
+ TEST_INFO("Computed SHA256: %s", digest_hex);
+ TEST_DEBUG("Expected SHA256: %s", expected_sha256_hex);
+
+ /* Verify the result */
+ if (strlen(expected_sha256_hex) != digest_len * 2) {
+ TEST_ERROR("Digest length mismatch (expected %zu, got %u)",
+ strlen(expected_sha256_hex) / 2, digest_len);
+ goto cleanup;
+ }
+
+ TEST_PRINT_BUFFER("SHA256 digest", digest, digest_len);
+
+ /* For now, just verify we got a 32-byte SHA256 result */
+ if (digest_len != 32) {
+ TEST_ERROR("Invalid SHA256 digest length: %u (expected 32)", digest_len);
+ goto cleanup;
+ }
+
+ TEST_INFO("SHA256 computation successful - got %u byte digest", digest_len);
+
+ ret = TEST_SUCCESS;
+
+cleanup:
+ if (mdctx != NULL) {
+ EVP_MD_CTX_free(mdctx);
+ }
+ if (sha256 != NULL) {
+ EVP_MD_free((EVP_MD*)sha256);
+ }
+
+ if (ret == TEST_SUCCESS) {
+ TEST_INFO("Test PASSED");
+ } else {
+ TEST_ERROR("Test FAILED");
+ }
+
+ return ret;
+}