From 7e6bfc45c06f88e21a16926d2eb64076a0c2c169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 23 Jul 2026 17:05:12 +0200 Subject: [PATCH 1/2] Zephyr: wolfSSL module support for the wolfPSA provider and native RTOS use Extend the wolfSSL Zephyr module for the wolfPSA-provider and secure-sockets efforts: - Native RTOS threading: wolfCrypt's Zephyr port uses k_mutex/k_thread/ k_condvar directly (no CONFIG_POSIX_THREADS), with k_condvar gated on the kernel version, covered by a native-threading ztest wired into CI. - Config interface: a user-supplied CONFIG_WOLFSSL_SETTINGS_FILE is authoritative and the module never layers Kconfig #defines over it. The module-default block is shaped by build-profile knobs (WOLFSSL_CRYPTO_ONLY, WOLFSSL_SINGLE_THREADED, which now defaults from !MULTITHREADING) plus new classic-crypto/TLS/PQC feature knobs (RSA/ECC/ChaCha-Poly/Curve25519/SNI/ session-cache/session-ticket and ML-KEM/ML-DSA/LMS/XMSS/Falcon, each with its memory-reduction "small" options). A consumer such as wolfPSA validates its own requirements rather than the module injecting them. - DRBG seeding: wc_GenerateSeed() on Zephyr draws seed material from the hardware entropy driver when present (chunked to the entropy API's uint16_t length, DT_HAS_CHOSEN-guarded) and falls back to sys_rand_get() otherwise; HAVE_HASHDRBG stays guarded by WC_NO_HASHDRBG. - z_time(): read the native_sim simulator RTC for a real wall clock on the native targets regardless of libc. Verified on native_sim/native/64 and nucleo_h743zi. --- .github/scripts/zephyr-4.x/zephyr-test.sh | 19 ++- .github/workflows/zephyr-4.x.yml | 66 ++++++++++ .github/workflows/zephyr.yml | 9 +- .wolfssl_known_macro_extras | 28 +++- wolfcrypt/src/random.c | 43 +++++++ wolfcrypt/src/wc_port.c | 92 +++++++++++-- wolfssl/wolfcrypt/types.h | 13 ++ wolfssl/wolfcrypt/wc_port.h | 24 ++-- zephyr/CMakeLists.txt | 3 + zephyr/Kconfig | 124 +++++++++++++++++- zephyr/tests/wolfssl_condvar/CMakeLists.txt | 6 + zephyr/tests/wolfssl_condvar/prj.conf | 13 ++ zephyr/tests/wolfssl_condvar/src/main.c | 91 +++++++++++++ zephyr/tests/wolfssl_condvar/testcase.yaml | 32 +++++ zephyr/user_settings.h | 135 ++++++++++++++++---- zephyr/zephyr_init.c | 7 +- 16 files changed, 640 insertions(+), 65 deletions(-) create mode 100644 zephyr/tests/wolfssl_condvar/CMakeLists.txt create mode 100644 zephyr/tests/wolfssl_condvar/prj.conf create mode 100644 zephyr/tests/wolfssl_condvar/src/main.c create mode 100644 zephyr/tests/wolfssl_condvar/testcase.yaml diff --git a/.github/scripts/zephyr-4.x/zephyr-test.sh b/.github/scripts/zephyr-4.x/zephyr-test.sh index 9c31d0e767e..c225277cacc 100755 --- a/.github/scripts/zephyr-4.x/zephyr-test.sh +++ b/.github/scripts/zephyr-4.x/zephyr-test.sh @@ -10,7 +10,8 @@ # -b, --branch wolfSSL branch/revision # -z, --zephyr Zephyr version tag # -t, --target Board target -# -s, --sample Sample to build +# -s, --sample Sample/test app to build +# -d, --subdir App subdir under zephyr/ (samples or tests; default samples) # -v, --verbose Verbose compile output (show full compiler commands) # -W, --werror Build with -Werror (treat warnings as errors) # --commit Checkout specific commit after fetching branch @@ -49,6 +50,7 @@ WOLFSSL_BRANCH="master" ZEPHYR_VERSION="v4.1.0" BOARD_TARGET="native_sim" SAMPLE_NAME="wolfssl_tls_sock" +SUBDIR="samples" INTERACTIVE=0 VERBOSE=0 WERROR=0 @@ -92,6 +94,7 @@ while [[ $# -gt 0 ]]; do -z|--zephyr) ZEPHYR_VERSION="$2"; shift 2 ;; -t|--target) BOARD_TARGET="$2"; shift 2 ;; -s|--sample) SAMPLE_NAME="$2"; shift 2 ;; + -d|--subdir) SUBDIR="$2"; shift 2 ;; -v|--verbose) VERBOSE=1; shift ;; -W|--werror) WERROR=1; shift ;; --commit) WOLFSSL_COMMIT="$2"; shift 2 ;; @@ -123,7 +126,7 @@ echo "==> wolfSSL repo: ${WOLFSSL_REPO}" echo "==> wolfSSL branch: ${WOLFSSL_BRANCH}" echo "==> Zephyr version: ${ZEPHYR_VERSION}" echo "==> Board target: ${BOARD_TARGET}" -echo "==> Sample: ${SAMPLE_NAME}" +echo "==> Sample: ${SUBDIR}/${SAMPLE_NAME}" echo "==> Docker image: ${DOCKER_IMAGE}" [[ -n "$WOLFSSL_COMMIT" ]] && echo "==> Commit: ${WOLFSSL_COMMIT}" [[ "$WERROR" == "1" ]] && echo "==> Werror: enabled" @@ -144,6 +147,7 @@ set -euo pipefail ZEPHYR_VERSION="__ZEPHYR_VERSION__" BOARD_TARGET="__BOARD_TARGET__" SAMPLE_NAME="__SAMPLE_NAME__" +SUBDIR="__SUBDIR__" WOLFSSL_REPO="__WOLFSSL_REPO__" WOLFSSL_BRANCH="__WOLFSSL_BRANCH__" WOLFSSL_COMMIT="__WOLFSSL_COMMIT__" @@ -224,11 +228,11 @@ if [[ "$INTERACTIVE" == "1" ]]; then echo " wolfSSL: modules/crypto/wolfssl" echo "" echo " Example build commands:" - echo " west build -p always -b ${BOARD_TARGET} modules/crypto/wolfssl/zephyr/samples/${SAMPLE_NAME}" + echo " west build -p always -b ${BOARD_TARGET} modules/crypto/wolfssl/zephyr/${SUBDIR}/${SAMPLE_NAME}" echo " west build -t run" echo "" echo " To run twister tests:" - echo " ./zephyr/scripts/twister -T modules/crypto/wolfssl/zephyr/samples/${SAMPLE_NAME} -vvv" + echo " ./zephyr/scripts/twister -T modules/crypto/wolfssl/zephyr/${SUBDIR}/${SAMPLE_NAME} -vvv" echo "==========================================" echo "" exec /bin/bash @@ -256,7 +260,7 @@ else fi west build -p always -b "${BOARD_TARGET}" \ - "modules/crypto/wolfssl/zephyr/samples/${SAMPLE_NAME}" \ + "modules/crypto/wolfssl/zephyr/${SUBDIR}/${SAMPLE_NAME}" \ ${CMAKE_ARGS:+-- $CMAKE_ARGS} echo "" @@ -300,7 +304,7 @@ else exit 1 fi # Check for success strings - if grep -q "Benchmark complete\|Test complete\|Client Return: 0" "${RUN_LOG}" 2>/dev/null; then + if grep -q "Benchmark complete\|Test complete\|Client Return: 0\|PROJECT EXECUTION SUCCESSFUL" "${RUN_LOG}" 2>/dev/null; then echo "==> [container] App completed successfully!" APP_RC=0 kill "${RUN_PID}" 2>/dev/null || true @@ -315,7 +319,7 @@ else if [[ $APP_RC -ne 0 ]]; then # Process exited on its own - check if it printed a success string - if grep -q "Benchmark complete\|Test complete\|Client Return: 0" "${RUN_LOG}" 2>/dev/null; then + if grep -q "Benchmark complete\|Test complete\|Client Return: 0\|PROJECT EXECUTION SUCCESSFUL" "${RUN_LOG}" 2>/dev/null; then APP_RC=0 else echo "==> [container] App exited without a success string" @@ -336,6 +340,7 @@ INNER_SCRIPT BUILD_SCRIPT="${BUILD_SCRIPT//__ZEPHYR_VERSION__/$ZEPHYR_VERSION}" BUILD_SCRIPT="${BUILD_SCRIPT//__BOARD_TARGET__/$BOARD_TARGET}" BUILD_SCRIPT="${BUILD_SCRIPT//__SAMPLE_NAME__/$SAMPLE_NAME}" +BUILD_SCRIPT="${BUILD_SCRIPT//__SUBDIR__/$SUBDIR}" BUILD_SCRIPT="${BUILD_SCRIPT//__WOLFSSL_REPO__/$WOLFSSL_REPO}" BUILD_SCRIPT="${BUILD_SCRIPT//__WOLFSSL_BRANCH__/$WOLFSSL_BRANCH}" BUILD_SCRIPT="${BUILD_SCRIPT//__WOLFSSL_COMMIT__/$WOLFSSL_COMMIT}" diff --git a/.github/workflows/zephyr-4.x.yml b/.github/workflows/zephyr-4.x.yml index 757020a789f..f02bde0c9be 100644 --- a/.github/workflows/zephyr-4.x.yml +++ b/.github/workflows/zephyr-4.x.yml @@ -103,3 +103,69 @@ jobs: .github/scripts/zephyr-4.x/artifacts/${{ matrix.board == 'native_sim' && 'native_sim' || 'frdm_rw612-rw612' }}-wolfssl_test/zephyr.map if-no-files-found: warn retention-days: 1 + + # Native k_mutex/k_thread/k_condvar threading ztest (no POSIX). native_sim + # only - it reads the native_sim simulator RTC - so it lives on this 4.x + # matrix rather than the legacy zephyr.yml (v2.7.4/v3.4.0/v3.5.0), where + # native_sim is unavailable or its POSIX headers clash with ztest. + condvar: + name: ${{ matrix.zephyr-ref }} | native_sim | wolfssl_condvar${{ matrix.crypto-only == 'y' && ' | crypto-only' || '' }} + if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} + runs-on: ubuntu-22.04 + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + zephyr-ref: [ v4.1.0, v4.3.0, v4.4.0 ] + # Both build profiles the testcase.yaml exercises: default (TLS + crypto) + # and the WOLFCRYPT_ONLY build-profile knob. + crypto-only: [ 'n', 'y' ] + steps: + - name: Checkout test driver + uses: actions/checkout@v5 + with: + sparse-checkout: .github/scripts/zephyr-4.x + fetch-depth: 1 + + - name: Free disk space + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \ + /opt/hostedtoolcache/CodeQL "$AGENT_TOOLSDIRECTORY" || true + docker system prune -af || true + df -h / + + - name: Resolve wolfSSL repo and branch + id: src + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "repo=https://github.com/${{ github.repository }}" >> "$GITHUB_OUTPUT" + echo "branch=refs/pull/${{ github.event.pull_request.number }}/merge" >> "$GITHUB_OUTPUT" + else + echo "repo=https://github.com/${{ github.repository }}" >> "$GITHUB_OUTPUT" + echo "branch=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" + fi + + - name: Build and run condvar ztest + working-directory: .github/scripts/zephyr-4.x + run: | + CRYPTO_ONLY_ARG="" + if [[ "${{ matrix.crypto-only }}" == "y" ]]; then + CRYPTO_ONLY_ARG="--cmake-args -DCONFIG_WOLFSSL_CRYPTO_ONLY=y" + fi + bash ./zephyr-test.sh \ + -r "${{ steps.src.outputs.repo }}" \ + -b "${{ steps.src.outputs.branch }}" \ + -z "${{ matrix.zephyr-ref }}" \ + -t native_sim \ + -d tests \ + -s wolfssl_condvar \ + $CRYPTO_ONLY_ARG + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v6 + with: + name: zephyr-4.x-condvar-${{ matrix.zephyr-ref }}-${{ matrix.crypto-only }}-${{ strategy.job-index }} + path: .github/scripts/zephyr-4.x/logs/ + retention-days: 5 + if-no-files-found: ignore diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index c987502a842..571106494ab 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -92,10 +92,13 @@ jobs: - name: Run wolfssl test id: wolfssl-test working-directory: zephyr + # Scope -T to the sample directory (not the whole module) so twister does + # not load zephyr/tests/*/testcase.yaml. The condvar test's modern + # list-form platform_allow is rejected by the 2.7.4 twister schema, and + # this is the only sample step that runs on 2.7.4. Runs both scenarios + # (wolfssl_test and wolfssl_test_no_malloc). run: | - ./zephyr/scripts/twister -T modules/crypto/wolfssl --test zephyr/samples/wolfssl_test/sample.crypto.wolfssl_test -vvv - rm -rf zephyr/twister-out - ./zephyr/scripts/twister -T modules/crypto/wolfssl --test zephyr/samples/wolfssl_test/sample.crypto.wolfssl_test_no_malloc -vvv + ./zephyr/scripts/twister -T modules/crypto/wolfssl/zephyr/samples/wolfssl_test -vvv rm -rf zephyr/twister-out - name: Run wolfssl TLS sock test diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 9f3f45f24de..64bc3fd36f6 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -95,6 +95,7 @@ CONFIG_CRYPTO_SHA3 CONFIG_CRYPTO_SHA512 CONFIG_CRYPTO_XTS CONFIG_CSPRNG_ENABLED +CONFIG_ENTROPY_HAS_DRIVER CONFIG_ESP32C2_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32H2_DEFAULT_CPU_FREQ_MHZ @@ -154,6 +155,7 @@ CONFIG_POSIX_THREADS CONFIG_PREEMPT_COUNT CONFIG_PREEMPT_RT CONFIG_PTHREAD_IPC +CONFIG_RTC CONFIG_SCHED_INFO CONFIG_SMP CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH @@ -166,6 +168,11 @@ CONFIG_USE_WOLFSSL_ESP_SDK_TIME CONFIG_USE_WOLFSSL_ESP_SDK_WIFI CONFIG_WOLFCRYPT_ARMASM CONFIG_WOLFCRYPT_FIPS +CONFIG_WOLFCRYPT_FIPS_READY +CONFIG_WOLFCRYPT_FIPS_V2 +CONFIG_WOLFCRYPT_FIPS_V5 +CONFIG_WOLFCRYPT_FIPS_V6 +CONFIG_WOLFCRYPT_FIPS_V7 CONFIG_WOLFCRYPT_INTELASM CONFIG_WOLFSSL CONFIG_WOLFSSL_ALLOW_TLS13 @@ -176,7 +183,11 @@ CONFIG_WOLFSSL_APPLE_HOMEKIT CONFIG_WOLFSSL_ASN_ALLOW_0_SERIAL CONFIG_WOLFSSL_CERTIFICATE_BUNDLE CONFIG_WOLFSSL_CERTIFICATE_BUNDLE_DEFAULT_NONE +CONFIG_WOLFSSL_CHACHA_POLY +CONFIG_WOLFSSL_CRYPTO_ONLY +CONFIG_WOLFSSL_CURVE25519 CONFIG_WOLFSSL_DTLS +CONFIG_WOLFSSL_ECC CONFIG_WOLFSSL_ENABLE_KYBER CONFIG_WOLFSSL_EXAMPLE_NAME_ESP32_SSH_SERVER CONFIG_WOLFSSL_EXAMPLE_NAME_ESP8266_SSH_SERVER @@ -188,20 +199,30 @@ CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFMQTT_AWS_IOT_MQTT CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFMQTT_TEMPLATE CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFSSH_ECHOSERVER CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFSSH_TEMPLATE +CONFIG_WOLFSSL_FALCON CONFIG_WOLFSSL_HKDF CONFIG_WOLFSSL_KEEP_PEER_CERT +CONFIG_WOLFSSL_LMS CONFIG_WOLFSSL_MAX_FRAGMENT_LEN +CONFIG_WOLFSSL_MLDSA CONFIG_WOLFSSL_MLKEM CONFIG_WOLFSSL_NO_ASN_STRICT CONFIG_WOLFSSL_OPENSSL_EXTRA_X509_SMALL CONFIG_WOLFSSL_PSK +CONFIG_WOLFSSL_RSA CONFIG_WOLFSSL_RSA_PSS +CONFIG_WOLFSSL_SESSION_CACHE CONFIG_WOLFSSL_SESSION_EXPORT +CONFIG_WOLFSSL_SESSION_TICKET +CONFIG_WOLFSSL_SETTINGS_FILE +CONFIG_WOLFSSL_SINGLE_THREADED +CONFIG_WOLFSSL_SNI CONFIG_WOLFSSL_TARGET_HOST CONFIG_WOLFSSL_TARGET_PORT CONFIG_WOLFSSL_TLS13_ENABLED CONFIG_WOLFSSL_TLS_VERSION_1_2 CONFIG_WOLFSSL_TLS_VERSION_1_3 +CONFIG_WOLFSSL_XMSS CONFIG_WOLFTPM CONFIG_WOLFTPM_EXAMPLE_NAME_ESPRESSIF CONFIG_X86 @@ -840,15 +861,8 @@ WOLFSSL_EVP_PRINT WOLFSSL_EXPORT_INT WOLFSSL_EXPORT_SPC_SZ WOLFSSL_EXTRA -WOLFSSL_FALCON_FFT_AVX2 -WOLFSSL_FALCON_FFT_NEON -WOLFSSL_FALCON_FPR_ASM -WOLFSSL_FALCON_FPR_DOUBLE WOLFSSL_FALCON_NO_NTT_DSP -WOLFSSL_FALCON_NTT_DSP -WOLFSSL_FALCON_SIGN_SMALL_MEM WOLFSSL_FALCON_SIGN_STATS -WOLFSSL_FALCON_VERIFY_ONLY WOLFSSL_FORCE_OCSP_NONCE_CHECK WOLFSSL_FRDM_K64 WOLFSSL_FRDM_K64_JENKINS diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 01f0794b8bb..bad7eb30907 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -5328,10 +5328,53 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #include #endif + #if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy) + /* Match the zephyr/-prefixed include layout used above: it did not + * exist before Zephyr 3.1. */ + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #include + #else + #include + #include + #endif + #endif + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { + /* Seed the DRBG straight from the hardware entropy driver when the platform + * exposes one (a zephyr,entropy chosen node), so wolfCrypt gets + * cryptographic-quality seed material instead of the general-purpose + * sys_rand_get(). A dead source returns an error, which makes wc_InitRng() + * fail (RNG_FAILURE_E) rather than yield weak output. Boards that set + * CONFIG_ENTROPY_HAS_DRIVER without a chosen entropy node fall back to + * sys_rand_get() rather than failing the build. */ + #if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy) + const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); + word32 off = 0; + word32 rem; + uint16_t chunk; + + (void)os; + if (!device_is_ready(dev)) { + return RNG_FAILURE_E; + } + /* entropy_get_entropy() takes a uint16_t length; chunk the request so + * any word32 seed size is honored without silent truncation. */ + while (off < sz) { + rem = sz - off; + chunk = (rem > 0xFFFFU) ? (uint16_t)0xFFFFU : (uint16_t)rem; + if (entropy_get_entropy(dev, (uint8_t *)output + off, chunk) != 0) { + return RNG_FAILURE_E; + } + off += chunk; + } + return 0; + #else + (void)os; sys_rand_get(output, sz); return 0; + #endif } #elif defined(WOLFSSL_TELIT_M2MB) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 99be1cb3d96..687f2c5f7d4 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -238,7 +238,6 @@ Threading/Mutex options: #if defined(WOLFSSL_ZEPHYR) #if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM) #include "native_rtc.h" -#define CONFIG_RTC #endif #endif @@ -4439,16 +4438,13 @@ time_t xilinx_time(time_t * timer) time_t z_time(time_t * timer) { - struct timespec ts; - - #if defined(CONFIG_RTC) && \ - (defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC)) - #if defined(CONFIG_BOARD_NATIVE_POSIX) || defined(CONFIG_BOARD_NATIVE_SIM) - /* When using native sim, get time from simulator rtc */ + /* native_sim: read the simulator RTC for a real host wall-clock. The + * real-target RTC/libc gate below is compiled out under the host libc. */ uint32_t nsec = 0; uint64_t sec = 0; + native_rtc_gettime(RTC_CLOCK_PSEUDOHOSTREALTIME, &nsec, &sec); if (timer != NULL) @@ -4458,6 +4454,11 @@ time_t z_time(time_t * timer) #else + struct timespec ts = { 0 }; + + #if defined(CONFIG_RTC) && \ + (defined(CONFIG_PICOLIBC) || defined(CONFIG_NEWLIB_LIBC)) + /* Try to obtain the actual time from an RTC */ static const struct device *rtc = DEVICE_DT_GET(DT_NODELABEL(rtc)); @@ -4476,8 +4477,7 @@ time_t z_time(time_t * timer) return epochTime; } } - #endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */ - #endif + #endif /* CONFIG_RTC && (CONFIG_PICOLIBC || CONFIG_NEWLIB_LIBC) */ /* Fallback to uptime since boot. This works for relative times, but * not for ASN.1 date validation */ @@ -4486,6 +4486,8 @@ time_t z_time(time_t * timer) *timer = ts.tv_sec; return ts.tv_sec; + + #endif /* CONFIG_BOARD_NATIVE_POSIX || CONFIG_BOARD_NATIVE_SIM */ } #endif /* WOLFSSL_ZEPHYR */ @@ -5261,8 +5263,78 @@ char* wolfSSL_strnstr(const char* s1, const char* s2, size_t n) } #ifdef WOLFSSL_COND - /* Use the pthreads translation layer for signaling */ + /* Native Zephyr condition variables (k_condvar) over a k_mutex; no POSIX + * pthread layer required. Semantics mirror the pthread implementation. */ + int wolfSSL_CondInit(COND_TYPE* cond) + { + int ret; + if (cond == NULL) + return BAD_FUNC_ARG; + + ret = wc_InitMutex(&cond->mutex); + if (ret == 0) { + /* k_condvar_init always returns 0 on Zephyr. */ + (void)k_condvar_init(&cond->cond); + } + + return ret; + } + + int wolfSSL_CondFree(COND_TYPE* cond) + { + if (cond == NULL) + return BAD_FUNC_ARG; + + /* k_condvar has no destroy; just release the backing mutex. */ + return wc_FreeMutex(&cond->mutex); + } + + int wolfSSL_CondStart(COND_TYPE* cond) + { + if (cond == NULL) + return BAD_FUNC_ARG; + + if (wc_LockMutex(&cond->mutex) != 0) + return BAD_MUTEX_E; + + return 0; + } + + int wolfSSL_CondSignal(COND_TYPE* cond) + { + if (cond == NULL) + return BAD_FUNC_ARG; + + /* Caller holds cond->mutex; wake a single waiter. */ + (void)k_condvar_signal(&cond->cond); + + return 0; + } + + int wolfSSL_CondWait(COND_TYPE* cond) + { + if (cond == NULL) + return BAD_FUNC_ARG; + + /* Atomically releases the mutex, blocks, and re-acquires it on wake, + * matching pthread_cond_wait semantics. */ + if (k_condvar_wait(&cond->cond, &cond->mutex, K_FOREVER) != 0) + return BAD_MUTEX_E; + + return 0; + } + + int wolfSSL_CondEnd(COND_TYPE* cond) + { + if (cond == NULL) + return BAD_FUNC_ARG; + + if (wc_UnLockMutex(&cond->mutex) != 0) + return BAD_MUTEX_E; + + return 0; + } #endif /* WOLFSSL_COND */ #elif defined(WOLFSSL_PTHREADS) || \ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index af98e43ba30..0802044bc7b 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1958,6 +1958,19 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); } THREAD_TYPE; #define WOLFSSL_THREAD extern void* wolfsslThreadHeapHint; + /* Native Zephyr condition variable (k_condvar) built on a k_mutex; no + * POSIX pthread layer required. Only reached when !SINGLE_THREADED, so + * wolfSSL_Mutex is k_mutex and is already included. + * k_condvar was introduced in Zephyr 2.4, so gate the capability on the + * kernel version: an older target builds without condition-variable + * support (WOLFSSL_COND undefined), exactly as it did before. */ + #if KERNEL_VERSION_NUMBER >= 0x20400 + typedef struct COND_TYPE { + wolfSSL_Mutex mutex; + struct k_condvar cond; + } COND_TYPE; + #define WOLFSSL_COND + #endif #elif defined(NETOS) typedef UINT THREAD_RETURN; typedef struct { diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index e84b724ae0d..3d3faf24ac6 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -320,25 +320,23 @@ #else #include #endif - /* Include sys/types.h early so host libc sets __timer_t_defined - * before Zephyr's posix_types.h can define a conflicting timer_t */ + /* Include sys/types.h early so host libc sets __timer_t_defined before any + * later Zephyr posix_types.h (pulled in by an application POSIX layer, e.g. + * CONFIG_POSIX_API) can define a conflicting timer_t. wolfCrypt itself does + * not include posix_types.h on Zephyr; this include is purely defensive. */ #include #ifndef SINGLE_THREADED - #if !defined(CONFIG_PTHREAD_IPC) && !defined(CONFIG_POSIX_THREADS) - #error "Threading needs CONFIG_PTHREAD_IPC / CONFIG_POSIX_THREADS" - #endif + /* wolfCrypt's threading primitives on Zephyr are backed by native + * kernel objects: k_mutex for wolfSSL_Mutex, k_thread for thread + * creation, and k_condvar for condition variables. These all come from + * and do NOT require the POSIX compatibility layer, + * so a multi-threaded wolfCrypt build does not need + * CONFIG_POSIX_THREADS / CONFIG_PTHREAD_IPC and pulls in no pthread + * headers of its own. */ #if KERNEL_VERSION_NUMBER >= 0x30100 #include - #ifndef CONFIG_ARCH_POSIX - #include - #include - #endif #else #include - #ifndef CONFIG_ARCH_POSIX - #include - #include - #endif #endif #endif diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index f13d724a7a8..719c4098bda 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -56,6 +56,7 @@ if(CONFIG_WOLFSSL) endif() zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/arc4.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ascon.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/asm.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/asn.c) #zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/async.c) @@ -122,6 +123,8 @@ if(CONFIG_WOLFSSL) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_pkcs11.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_port.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_slhdsa.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_xmss.c) + zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_xmss_impl.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfevent.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wolfmath.c) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e6cb1cb0603..1e96b8bf46b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -67,8 +67,66 @@ config WOLFCRYPT_FIPS bool "wolfCrypt FIPS support" depends on WOLFSSL_BUILTIN help - Enables FIPS support in wolfCrypt. Requires the wolfSSL FIPS ready - download that includes fips.c/fips_test.c. + Enable the wolfCrypt FIPS 140-3 module boundary. Requires the wolfSSL + FIPS bundle (fips.c, fips_test.c, wolfcrypt_first.c, wolfcrypt_last.c) + dropped into wolfcrypt/src/ - the CMake FIPS-boundary block compiles them. + Select the version that matches the bundle under "wolfCrypt FIPS version". + +choice + prompt "wolfCrypt FIPS version" + depends on WOLFCRYPT_FIPS + default WOLFCRYPT_FIPS_V6 + help + Select the FIPS module version. It must match the dropped-in bundle: the + in-core integrity check and the in-boundary algorithm set are keyed to the + version, so a mismatch fails the power-on self test. Values mirror + configure.ac's --enable-fips=VERSION mapping. + +config WOLFCRYPT_FIPS_V2 + bool "FIPS 140-2 (Cert #3389)" + help + Legacy FIPS 140-2 validated module (HAVE_FIPS_VERSION 2.0.0). + +config WOLFCRYPT_FIPS_V5 + bool "FIPS 140-3 (Cert #4718)" + help + wolfCrypt FIPS 140-3 validated module, Certificate #4718 (version 5.2.1). + +config WOLFCRYPT_FIPS_V6 + bool "FIPS 140-3 (SRTP-KDF full submission)" + help + wolfCrypt FIPS 140-3 SRTP-KDF full submission (version 6.0.0). + +config WOLFCRYPT_FIPS_V7 + bool "FIPS 140-3 (v7 full submission)" + help + wolfCrypt FIPS 140-3 v7 full submission (version 7.0.0). + +config WOLFCRYPT_FIPS_READY + bool "FIPS Ready (in-tree, uncertified)" + help + FIPS-Ready in-tree sources, feature locked (version 8.0.0 - kept one ahead + of the latest submission). Carries the newest in-boundary algorithms but is + not yet NIST-certified; use it for pre-certification integration. + +endchoice + +config WOLFSSL_CRYPTO_ONLY + bool "Build wolfCrypt only (no TLS layer)" + depends on WOLFSSL_BUILTIN + help + Define WOLFCRYPT_ONLY: compile only the wolfCrypt crypto library and + leave the wolfSSL TLS layer out of the build. + +config WOLFSSL_SINGLE_THREADED + bool "wolfCrypt single-threaded" + depends on WOLFSSL_BUILTIN + default y if !MULTITHREADING + help + Define SINGLE_THREADED: build wolfCrypt without internal locking, for a + single-threaded system or when the caller serializes all access. Defaults + on when the kernel has no threading (!MULTITHREADING), so consumers such + as wolfPSA do not need to select it themselves. config WOLFSSL_DTLS bool "wolfSSL DTLS support" @@ -90,6 +148,68 @@ config WOLFSSL_MLKEM help Enable PQC ML-KEM support for Key Exchange +config WOLFSSL_MLDSA + bool "wolfSSL PQC ML-DSA support" + help + Enable PQC ML-DSA (Dilithium) signatures. + +config WOLFSSL_LMS + bool "wolfSSL LMS/HSS hash-based signatures" + help + Enable LMS/HSS stateful hash-based signature verification (verify-only). + +config WOLFSSL_XMSS + bool "wolfSSL XMSS/XMSS^MT hash-based signatures" + help + Enable XMSS/XMSS^MT stateful hash-based signature verification (verify-only). + +config WOLFSSL_FALCON + bool "wolfSSL PQC Falcon signatures" + help + Enable PQC Falcon (FN-DSA) signatures. + +config WOLFSSL_RSA + bool "wolfCrypt RSA support" + default y + help + Enable RSA (define RSA support; NO_RSA when off). + +config WOLFSSL_ECC + bool "wolfCrypt ECC support" + default y + help + Enable ECC (HAVE_ECC, SECP256R1). + +config WOLFSSL_CHACHA_POLY + bool "wolfCrypt ChaCha20-Poly1305 support" + default y + help + Enable ChaCha20 and Poly1305 (HAVE_CHACHA, HAVE_POLY1305). + +config WOLFSSL_CURVE25519 + bool "wolfCrypt Curve25519 / Ed25519 support" + default n + help + Enable Curve25519 and Ed25519 (HAVE_CURVE25519, HAVE_ED25519). + +config WOLFSSL_SNI + bool "wolfSSL Server Name Indication (SNI)" + default y + help + Enable TLS Server Name Indication (HAVE_SNI). + +config WOLFSSL_SESSION_CACHE + bool "wolfSSL TLS session cache" + default y + help + Enable the TLS session cache (SMALL_SESSION_CACHE; NO_SESSION_CACHE off). + +config WOLFSSL_SESSION_TICKET + bool "wolfSSL TLS session tickets" + default y + help + Enable TLS session tickets (HAVE_SESSION_TICKET, TLS 1.3 resumption). + config WOLFSSL_MAX_FRAGMENT_LEN int default 3 diff --git a/zephyr/tests/wolfssl_condvar/CMakeLists.txt b/zephyr/tests/wolfssl_condvar/CMakeLists.txt new file mode 100644 index 00000000000..cf26ca03b2c --- /dev/null +++ b/zephyr/tests/wolfssl_condvar/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(wolfssl_condvar) + +target_sources(app PRIVATE src/main.c) +add_definitions(-DWOLFSSL_USER_SETTINGS) diff --git a/zephyr/tests/wolfssl_condvar/prj.conf b/zephyr/tests/wolfssl_condvar/prj.conf new file mode 100644 index 00000000000..eba974c0b58 --- /dev/null +++ b/zephyr/tests/wolfssl_condvar/prj.conf @@ -0,0 +1,13 @@ +# wolfCrypt native Zephyr condition-variable / thread ztest. +# Multi-threaded (default, SINGLE_THREADED not set) so the k_condvar-backed +# wolfSSL_Cond* path is compiled, and DELIBERATELY no CONFIG_POSIX_API / +# CONFIG_POSIX_THREADS / CONFIG_PTHREAD_IPC: the whole point is that the native +# k_mutex/k_thread/k_condvar primitives work without the POSIX layer. +CONFIG_ZTEST=y +CONFIG_MAIN_STACK_SIZE=16384 +CONFIG_ZTEST_STACK_SIZE=16384 +# wolfSSL_NewThread allocates its ~48KB thread stack from the heap. +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=131072 + +CONFIG_WOLFSSL=y +CONFIG_WOLFSSL_BUILTIN=y diff --git a/zephyr/tests/wolfssl_condvar/src/main.c b/zephyr/tests/wolfssl_condvar/src/main.c new file mode 100644 index 00000000000..0cd5c8040c2 --- /dev/null +++ b/zephyr/tests/wolfssl_condvar/src/main.c @@ -0,0 +1,91 @@ +/* main.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* + * Exercises wolfCrypt's native Zephyr threading primitives -- the k_condvar + * backed wolfSSL_Cond* API and wolfSSL_NewThread/wolfSSL_JoinThread -- on a + * multi-threaded, POSIX-free build (see prj.conf: no CONFIG_POSIX_THREADS / + * CONFIG_PTHREAD_IPC). Covers the producer/consumer wakeup handshake (the + * atomic release/re-acquire semantics of wolfSSL_CondWait and signalling under + * the lock) and the NULL-pointer guards of all six condition-variable calls. + */ + +#include +#include + +#include +#include +#include +#include + +static COND_TYPE g_cond; +static volatile int g_predicate; + +/* Publish the predicate under the lock, then wake the waiter. */ +static THREAD_RETURN WOLFSSL_THREAD condvar_signaler(void* arg) +{ + (void)arg; + + /* Yield so the consumer generally reaches wolfSSL_CondWait() first. The + * handshake must still be correct if it does not, because the consumer + * re-checks the predicate under the lock before each wait. */ + k_msleep(50); + + (void)wolfSSL_CondStart(&g_cond); + g_predicate = 1; + (void)wolfSSL_CondSignal(&g_cond); + (void)wolfSSL_CondEnd(&g_cond); +} + +ZTEST(wolfssl_condvar, test_producer_consumer_wakeup) +{ + THREAD_TYPE thread; + + g_predicate = 0; + + zassert_equal(wolfSSL_CondInit(&g_cond), 0, "CondInit"); + zassert_equal(wolfSSL_NewThread(&thread, condvar_signaler, NULL), 0, + "NewThread"); + + /* wolfSSL_CondWait must atomically release the mutex, block, and + * re-acquire it on wake; loop guards against spurious wakeups. */ + zassert_equal(wolfSSL_CondStart(&g_cond), 0, "CondStart"); + while (!g_predicate) { + zassert_equal(wolfSSL_CondWait(&g_cond), 0, "CondWait"); + } + zassert_equal(g_predicate, 1, "predicate observed set after wake"); + zassert_equal(wolfSSL_CondEnd(&g_cond), 0, "CondEnd"); + + zassert_equal(wolfSSL_JoinThread(thread), 0, "JoinThread"); + zassert_equal(wolfSSL_CondFree(&g_cond), 0, "CondFree"); +} + +ZTEST(wolfssl_condvar, test_null_guards) +{ + zassert_equal(wolfSSL_CondInit(NULL), BAD_FUNC_ARG, "CondInit NULL"); + zassert_equal(wolfSSL_CondFree(NULL), BAD_FUNC_ARG, "CondFree NULL"); + zassert_equal(wolfSSL_CondStart(NULL), BAD_FUNC_ARG, "CondStart NULL"); + zassert_equal(wolfSSL_CondSignal(NULL), BAD_FUNC_ARG, "CondSignal NULL"); + zassert_equal(wolfSSL_CondWait(NULL), BAD_FUNC_ARG, "CondWait NULL"); + zassert_equal(wolfSSL_CondEnd(NULL), BAD_FUNC_ARG, "CondEnd NULL"); +} + +ZTEST_SUITE(wolfssl_condvar, NULL, NULL, NULL, NULL, NULL); diff --git a/zephyr/tests/wolfssl_condvar/testcase.yaml b/zephyr/tests/wolfssl_condvar/testcase.yaml new file mode 100644 index 00000000000..fb1092c2266 --- /dev/null +++ b/zephyr/tests/wolfssl_condvar/testcase.yaml @@ -0,0 +1,32 @@ +common: + tags: + - wolfssl + - threading + harness: ztest +tests: + crypto.wolfssl.condvar: + # native_sim only: the test builds wolfCrypt multi-threaded with no POSIX. + # wc_port.c's z_time() reads the native_sim simulator RTC (native_rtc_gettime) + # for a real wall clock; non-native boards would need the POSIX clock enabled, + # so restrict to native_sim rather than fail elsewhere. Allow both the plain + # board (older Zephyr / x86 CI, where native_sim/native/64 does not exist) and + # the hardware-model-v2 64-bit variant (aarch64 host). + platform_allow: + - native_sim + - native_sim/native/64 + integration_platforms: + - native_sim + - native_sim/native/64 + crypto.wolfssl.condvar_crypto_only: + # Same threaded condvar test with the WOLFSSL_CRYPTO_ONLY build-profile knob + # set (WOLFCRYPT_ONLY, no TLS layer), giving that knob explicit build+run + # coverage in the module: the native k_mutex/k_thread/k_condvar path must + # still work in a crypto-only image. + platform_allow: + - native_sim + - native_sim/native/64 + integration_platforms: + - native_sim + - native_sim/native/64 + extra_configs: + - CONFIG_WOLFSSL_CRYPTO_ONLY=y diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index 5198ad5eab8..1056d896de1 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -24,10 +24,17 @@ #ifdef CONFIG_WOLFSSL -/* If a custom user_settings file is provided use it instead. - * CONFIG_WOLFSSL_SETTINGS_FILE is always defined. If it is not explicitly set - * in prj.conf then it is auto-defined to "". This obviously causes issues here. - * That is why we define WOLFSSL_SETTINGS_FILE in CMakeLists.txt. */ +/* The wolfCrypt feature configuration comes from the user's own settings file + * if one was supplied (CONFIG_WOLFSSL_SETTINGS_FILE), otherwise from the module + * default below. CONFIG_WOLFSSL_SETTINGS_FILE is always defined; when it is not + * set in prj.conf it is auto-defined to "", so WOLFSSL_SETTINGS_FILE is only + * defined (in CMakeLists.txt) when a real path was given. A user-supplied + * settings file is authoritative: the build-profile Kconfig knobs + * (WOLFSSL_CRYPTO_ONLY, WOLFSSL_SINGLE_THREADED) shape ONLY the module default + * below and are NOT applied on top of a settings file, so the two config + * interfaces never mix. A consumer like wolfPSA that needs specific wolfCrypt + * options checks for them itself and fails the build if a settings file omits + * them, rather than injecting them here. */ #ifdef WOLFSSL_SETTINGS_FILE #include WOLFSSL_SETTINGS_FILE #else @@ -82,9 +89,38 @@ extern "C" { /* FIPS */ /* ------------------------------------------------------------------------- */ #ifdef CONFIG_WOLFCRYPT_FIPS - /* FIPS Ready */ - #define HAVE_FIPS_VERSION 5 - #define HAVE_FIPS_VERSION_MINOR 3 + /* HAVE_FIPS is the master switch that routes the wolfCrypt algorithms + * through the FIPS module boundary. The version macros below must match the + * dropped-in FIPS bundle (see the CMake FIPS-boundary block); settings.h + * folds them into WOLFSSL_FIPS_VERSION_CODE for the in-boundary gating. */ + #define HAVE_FIPS + /* Version triples mirror configure.ac's --enable-fips=VERSION mapping. */ + #if defined(CONFIG_WOLFCRYPT_FIPS_READY) + /* FIPS Ready: in-tree, feature locked, one ahead of the latest. */ + #define HAVE_FIPS_VERSION 8 + #define HAVE_FIPS_VERSION_MINOR 0 + #define HAVE_FIPS_VERSION_PATCH 0 + #elif defined(CONFIG_WOLFCRYPT_FIPS_V7) + /* FIPS 140-3 v7 full submission. */ + #define HAVE_FIPS_VERSION 7 + #define HAVE_FIPS_VERSION_MINOR 0 + #define HAVE_FIPS_VERSION_PATCH 0 + #elif defined(CONFIG_WOLFCRYPT_FIPS_V6) + /* FIPS 140-3 SRTP-KDF full submission. */ + #define HAVE_FIPS_VERSION 6 + #define HAVE_FIPS_VERSION_MINOR 0 + #define HAVE_FIPS_VERSION_PATCH 0 + #elif defined(CONFIG_WOLFCRYPT_FIPS_V5) + /* FIPS 140-3 Cert #4718 (wolfCrypt 5.2.1). */ + #define HAVE_FIPS_VERSION 5 + #define HAVE_FIPS_VERSION_MINOR 2 + #define HAVE_FIPS_VERSION_PATCH 1 + #elif defined(CONFIG_WOLFCRYPT_FIPS_V2) + /* FIPS 140-2 Cert #3389. */ + #define HAVE_FIPS_VERSION 2 + #define HAVE_FIPS_VERSION_MINOR 0 + #define HAVE_FIPS_VERSION_PATCH 0 + #endif #endif @@ -114,7 +150,9 @@ extern "C" { #define HAVE_EXTENDED_MASTER #define HAVE_ENCRYPT_THEN_MAC #define HAVE_SERVER_RENEGOTIATION_INFO -#define HAVE_SNI /* optional Server Name Indicator (SNI) */ +#if defined(CONFIG_WOLFSSL_SNI) + #define HAVE_SNI /* optional Server Name Indication (SNI) */ +#endif /* ASN */ #define WOLFSSL_ASN_TEMPLATE /* use newer ASN template asn.c code (default) */ @@ -124,14 +162,15 @@ extern "C" { #endif /* Session Cache */ -#if 1 +#if defined(CONFIG_WOLFSSL_SESSION_CACHE) #define SMALL_SESSION_CACHE - #ifdef WOLFSSL_TLS13 - #define HAVE_SESSION_TICKET /* session tickets required for resumption in TLS v1.3 */ - #endif #else #define NO_SESSION_CACHE /* disable session resumption */ #endif +/* TLS 1.3 stateless session tickets -- independent of the internal cache. */ +#if defined(CONFIG_WOLFSSL_SESSION_TICKET) && defined(WOLFSSL_TLS13) + #define HAVE_SESSION_TICKET +#endif /* Session export (external session cache) */ #if defined(CONFIG_WOLFSSL_SESSION_EXPORT) @@ -194,15 +233,27 @@ extern "C" { /* Algorithms */ /* ------------------------------------------------------------------------- */ /* RNG */ +/* wolfCrypt Hash-DRBG (SHA2-256). On Zephyr its seed comes from wc_GenerateSeed() + * (wolfcrypt/src/random.c), which draws from the hardware entropy driver when one + * is present and falls back to sys_rand_get() otherwise -- so no seed callback is + * registered. Guarded by WC_NO_HASHDRBG so a PSA-RNG build + * (CONFIG_MBEDTLS_PSA_CRYPTO_C above) can still disable the internal DRBG and + * route randomness through the PSA provider. */ #ifndef WC_NO_HASHDRBG - #define HAVE_HASHDRBG /* Use DRBG SHA2-256 and seed */ - #ifdef CONFIG_CSPRNG_ENABLED - #define WC_RNG_SEED_CB - #endif + #define HAVE_HASHDRBG +#endif + +/* Build-profile knobs for the module-default config only (a user-supplied + * settings file sets these itself). */ +#ifdef CONFIG_WOLFSSL_CRYPTO_ONLY + #define WOLFCRYPT_ONLY +#endif +#ifdef CONFIG_WOLFSSL_SINGLE_THREADED + #define SINGLE_THREADED #endif /* ECC */ -#if 1 +#if defined(CONFIG_WOLFSSL_ECC) #define HAVE_ECC #define ECC_USER_CURVES /* Enable only ECC curves specific */ #undef NO_ECC256 /* Enable SECP256R1 only (on by default) */ @@ -225,7 +276,7 @@ extern "C" { #define WOLFSSL_OLD_PRIME_CHECK /* Use faster DH prime checking */ /* RSA */ -#if 1 +#if defined(CONFIG_WOLFSSL_RSA) #undef NO_RSA #define WC_RSA_BLINDING //#define WC_RSA_NO_PADDING @@ -256,7 +307,7 @@ extern "C" { #endif /* ChaCha20 / Poly1305 */ -#if 1 +#if defined(CONFIG_WOLFSSL_CHACHA_POLY) #define HAVE_CHACHA #define HAVE_POLY1305 @@ -265,7 +316,7 @@ extern "C" { #endif /* Ed25519 / Curve25519 */ -#if 0 +#if defined(CONFIG_WOLFSSL_CURVE25519) #define HAVE_CURVE25519 #define HAVE_ED25519 /* ED25519 Requires SHA512 */ @@ -358,13 +409,52 @@ extern "C" { #define NO_MD5 //#define NO_DES3 /* Necessary for pkcs12 tests */ -/* PQC ML-KEM */ +/* PQC families -- each independently selectable so a Kconfig-driven build (no + * user-provided settings file) can include only what a consumer needs and keep + * the flash footprint down. All default off. */ #if defined(CONFIG_WOLFSSL_MLKEM) #define WOLFSSL_HAVE_MLKEM #define WOLFSSL_MLKEM_NO_LARGE_CODE #define WOLFSSL_MLKEM_SMALL #define WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM #define WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM + #define WOLFSSL_MLKEM_DYNAMIC_KEYS +#endif + +#if defined(CONFIG_WOLFSSL_MLDSA) + #define WOLFSSL_HAVE_MLDSA + #define WOLFSSL_MLDSA_NO_LARGE_CODE + #define WOLFSSL_MLDSA_SMALL + #define WOLFSSL_MLDSA_VERIFY_SMALL_MEM + #define WOLFSSL_MLDSA_DYNAMIC_KEYS + #define WOLFSSL_MLDSA_SIGN_SMALL_MEM + #define WOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM +#endif + +#if defined(CONFIG_WOLFSSL_LMS) + #define WOLFSSL_HAVE_LMS + #define WOLFSSL_LMS_VERIFY_ONLY +#endif + +#if defined(CONFIG_WOLFSSL_XMSS) + #define WOLFSSL_HAVE_XMSS + #define WOLFSSL_XMSS_VERIFY_ONLY +#endif + +#if defined(CONFIG_WOLFSSL_FALCON) + #define WOLFSSL_EXPERIMENTAL_SETTINGS /* HAVE_FALCON is gated experimental */ + #define HAVE_FALCON + /* Small-memory dynamic signer instead of the fast tree-signer (keeps full + * sign+verify); the default portable integer FPR backend needs no ASM. */ + #define WOLFSSL_FALCON_SIGN_SMALL_MEM +#endif + +/* SHA-3 / SHAKE are required by ML-KEM, ML-DSA, and Falcon; enable them (small + * variant) when any is on, and explicitly disable SHAKE otherwise to keep a + * non-PQC build lean. */ +#if defined(CONFIG_WOLFSSL_MLKEM) || defined(CONFIG_WOLFSSL_MLDSA) || \ + defined(CONFIG_WOLFSSL_FALCON) + #define WOLFSSL_SHA3_SMALL #define WOLFSSL_SHAKE128 #define WOLFSSL_SHAKE256 #else @@ -496,7 +586,8 @@ extern "C" { } #endif -#endif /* CONFIG_WOLFSSL_SETTINGS_FILE */ +#endif /* WOLFSSL_SETTINGS_FILE */ + #endif /* CONFIG_WOLFSSL */ #endif /* USER_SETTINGS_H */ diff --git a/zephyr/zephyr_init.c b/zephyr/zephyr_init.c index 1516264eb5f..033f436d41f 100644 --- a/zephyr/zephyr_init.c +++ b/zephyr/zephyr_init.c @@ -19,4 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* Not needed. Keeping file for backwards compatibility. */ +/* The wolfSSL Zephyr module needs no boot-time SYS_INIT hook. wolfCrypt's + * Hash-DRBG is seeded on demand by wc_GenerateSeed() -- which on Zephyr draws + * from the hardware entropy driver when one is present (see + * wolfcrypt/src/random.c) -- and wolfCrypt_Init()/wolfSSL_Init() run lazily + * from the first library call. This translation unit is kept (it is referenced + * by the module CMakeLists) as the place for any future module init. */ From ccfcf2d0010318b49a8d6d849d9450a2fbf0b74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Mon, 16 Mar 2026 17:52:21 +0100 Subject: [PATCH 2/2] Add stack tracking to zephyr benchmark --- wolfssl/wolfcrypt/mem_track.h | 111 +++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index be2a1c35292..88827336452 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -484,7 +484,7 @@ static WC_INLINE int CleanupMemoryTracker(void) #include #endif -typedef void* (*thread_func)(void* args); +typedef THREAD_RETURN (*thread_func)(void* args); #define STACK_CHECK_VAL 0x01 struct stack_size_debug_context { @@ -620,7 +620,7 @@ static WC_INLINE int StackSizeCheck_Rebaseline(void) * ./configure --enable-stacksize=verbose [...] */ -static void* debug_stack_size_verbose_shim( +static THREAD_RETURN debug_stack_size_verbose_shim( struct stack_size_debug_context *shim_args) { StackSizeCheck_myStack = shim_args->myStack; @@ -733,7 +733,112 @@ int StackSizeHWMReset(void) #endif /* HAVE_STACK_SIZE_VERBOSE */ -#ifdef HAVE_PTHREAD +#if defined(__ZEPHYR__) + +static WC_INLINE int StackSizeCheck(struct func_args* args, thread_func tf) +{ + size_t i; + int ret = 0; + int err; + struct k_thread* tid = NULL; + k_thread_stack_t* threadStack = NULL; + unsigned char* myStack = NULL; + +#ifdef HAVE_STACK_SIZE_VERBOSE + struct stack_size_debug_context shim_args; +#endif + + tid = (struct k_thread*)XMALLOC( + Z_KERNEL_STACK_SIZE_ADJUST(sizeof(struct k_thread)), + wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); + if (tid == NULL) { + printf("error: XMALLOC tid failed"); + ret = MEMORY_E; + goto out; + } + +#ifndef WOLFSSL_ZEPHYR_STACK_SZ + #define WOLFSSL_ZEPHYR_STACK_SZ (48*1024) +#endif + + threadStack = (void*)XMALLOC( + Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ), + wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); + if (threadStack == NULL) { + printf("error: k_thread_stack_alloc threadStack failed"); + ret = MEMORY_E; + goto out; + } + + myStack = K_THREAD_STACK_BUFFER(threadStack); + XMEMSET(myStack, STACK_CHECK_VAL, WOLFSSL_ZEPHYR_STACK_SZ); + +#ifdef HAVE_STACK_SIZE_VERBOSE + StackSizeCheck_stackSizeHWM = 0; + shim_args.myStack = myStack; + shim_args.stackSize = WOLFSSL_ZEPHYR_STACK_SZ; + shim_args.stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; + shim_args.fn = tf; + shim_args.args = args; + + /* k_thread_create does not return any error codes */ + /* Casting to k_thread_entry_t should be fine since we just ignore the + * extra arguments being passed in */ + k_thread_create(tid, threadStack, WOLFSSL_ZEPHYR_STACK_SZ, + (k_thread_entry_t)debug_stack_size_verbose_shim, (void *)&shim_args, + NULL, NULL, 5, 0, K_NO_WAIT); +#else + /* k_thread_create does not return any error codes */ + /* Casting to k_thread_entry_t should be fine since we just ignore the + * extra arguments being passed in */ + k_thread_create(tid, threadStack, WOLFSSL_ZEPHYR_STACK_SZ, + (k_thread_entry_t)tf, args, NULL, NULL, 5, 0, K_NO_WAIT); + +#endif + + err = k_thread_join(tid, K_FOREVER); + if (err != 0) { + printf("k_thread_join failed\n"); + ret = MEMORY_E; + goto out; + } + + + for (i = 0; i < WOLFSSL_ZEPHYR_STACK_SZ; i++) { + if (myStack[i] != STACK_CHECK_VAL) { + break; + } + } + +#ifdef HAVE_STACK_SIZE_VERBOSE + printf("stack used = %lu\n", StackSizeCheck_stackSizeHWM > (WOLFSSL_ZEPHYR_STACK_SZ - i) + ? (unsigned long)StackSizeCheck_stackSizeHWM + : (unsigned long)(WOLFSSL_ZEPHYR_STACK_SZ - i)); + StackSizeCheck_myStack = NULL; + StackSizeCheck_stackOffsetPointer = NULL; +#else + { + size_t used = WOLFSSL_ZEPHYR_STACK_SZ - i; + printf("stack used = %lu\n", (unsigned long)used); + } +#endif + +out: + XFREE(tid, wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(threadStack, wolfsslThreadHeapHint, + DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +#define StackSizeCheck_launch(args, tf, threadId, stack_context) \ + ((void)(args), (void)(tf), (void)(threadId), (void)(stack_context), \ + (NOT_COMPILED_IN)) + +#define StackSizeCheck_reap(threadId, stack_context) \ + ((void)(threadId), (void)(stack_context), (NOT_COMPILED_IN)) + +#elif defined(HAVE_PTHREAD) static WC_INLINE int StackSizeCheck(struct func_args* args, thread_func tf) {