From 5a214e997070d37e07cecf738cbdd07eedebbaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 5 Nov 2026 12:11:09 +0100 Subject: [PATCH 1/8] zephyr: build with Zephyr 4.5 Zephyr 4.5 moved the lowercase min() and max() macros out of into , which has to be included explicitly. The module defines WOLFSSL_HAVE_MIN and WOLFSSL_HAVE_MAX for Zephyr 4.3 and later so that wolfSSL uses those macros, so every wolfSSL build on 4.5 fails with an implicit declaration of min(). Include where it exists, and only when wolfSSL defers to Zephyr's macros: CONFIG_WOLFSSL_NO_HAVE_MIN_MAX builds define their own min() function, which the macro would break. Zephyr 4.5 also removed cmake/app/boilerplate.cmake, which the wolfssl_tls_sock sample still included. Use find_package(Zephyr) as the other samples do. Add v4.5.0 to the Zephyr 4.x CI matrix. It needs the same SDK as 4.4. --- .github/workflows/zephyr-4.x.yml | 2 +- wolfssl/wolfcrypt/settings.h | 8 ++++++++ zephyr/samples/wolfssl_tls_sock/CMakeLists.txt | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zephyr-4.x.yml b/.github/workflows/zephyr-4.x.yml index c5f0f9bc62c..8429effeace 100644 --- a/.github/workflows/zephyr-4.x.yml +++ b/.github/workflows/zephyr-4.x.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - zephyr-ref: [ v4.1.0, v4.3.0, v4.4.0 ] + zephyr-ref: [ v4.1.0, v4.3.0, v4.4.0, v4.5.0 ] steps: - name: Checkout test driver uses: actions/checkout@v5 diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 6564f4aa52a..3a015ccb450 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -3176,6 +3176,14 @@ #include #include #include + #if defined(WOLFSSL_HAVE_MIN) || defined(WOLFSSL_HAVE_MAX) + /* Zephyr 4.5 moved the lowercase min() and max() out of util.h */ + #ifdef __has_include + #if __has_include() + #include + #endif + #endif + #endif #else #include #include diff --git a/zephyr/samples/wolfssl_tls_sock/CMakeLists.txt b/zephyr/samples/wolfssl_tls_sock/CMakeLists.txt index bdd894eda79..183170ed1ab 100644 --- a/zephyr/samples/wolfssl_tls_sock/CMakeLists.txt +++ b/zephyr/samples/wolfssl_tls_sock/CMakeLists.txt @@ -19,7 +19,7 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/zephyr_legacy.conf) endif() -include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(wolfssl_tls_sock) FILE(GLOB app_sources src/*.c) From 23c2bf9325badf3f60f2414cf18b4fef248968fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 5 Nov 2026 12:11:18 +0100 Subject: [PATCH 2/8] Report the rest of a DTLS datagram from wolfSSL_has_pending() A DTLS read takes a whole datagram, which can carry more than one record. Once the application has read the first record, the next one sits undecrypted in the input buffer while the socket has nothing left to report. wolfSSL_has_pending() looked at that buffer only with WOLFSSL_TLS_READ_AHEAD, so an application that polls the socket and asks wolfSSL_has_pending() before blocking waited for a datagram that never comes, with the record already in hand. Report the unprocessed rest of the input buffer for DTLS too. TLS without read-ahead never reads past the record it needs, so nothing changes there. The new test delivers two records in one datagram over DTLS 1.2, with an AEAD and a CBC suite, and over DTLS 1.3, and checks wolfSSL_has_pending() after the first read. It fails without this change. --- src/ssl_api_rw.c | 7 ++++ tests/api/test_ssl_rw.c | 82 +++++++++++++++++++++++++++++++++++++++++ tests/api/test_ssl_rw.h | 2 + 3 files changed, 91 insertions(+) diff --git a/src/ssl_api_rw.c b/src/ssl_api_rw.c index 8d9349f4724..99eede15a64 100644 --- a/src/ssl_api_rw.c +++ b/src/ssl_api_rw.c @@ -1284,6 +1284,13 @@ int wolfSSL_has_pending(const WOLFSSL* ssl) else if (ssl->buffers.inputBuffer.length > ssl->buffers.inputBuffer.idx) { ret = 1; } + #elif defined(WOLFSSL_DTLS) + /* A DTLS read takes a whole datagram, which can hold more records. They + * may carry no application data, so wolfSSL_read() can still WANT_READ. */ + else if (ssl->options.dtls && + ssl->buffers.inputBuffer.length > ssl->buffers.inputBuffer.idx) { + ret = 1; + } #endif return ret; diff --git a/tests/api/test_ssl_rw.c b/tests/api/test_ssl_rw.c index 4c992da4f74..b5bdf3ab63c 100644 --- a/tests/api/test_ssl_rw.c +++ b/tests/api/test_ssl_rw.c @@ -408,6 +408,88 @@ int test_wolfSSL_pending_api(void) return EXPECT_RESULT(); } +/* Test wolfSSL_has_pending() with two DTLS records in one datagram. + * + * A DTLS read takes the whole datagram, so the second record is still + * buffered, though not decrypted, after the first one is read. + * + * @return TEST_SUCCESS on success. + */ +int test_wolfSSL_has_pending_dtls_datagram(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ + (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_DTLS13)) + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + struct test_memio_ctx test_ctx; + byte reply[1]; + size_t i; + struct { + method_provider client_meth; + method_provider server_meth; + const char* cipher; + } params[] = { +#ifndef WOLFSSL_NO_TLS12 + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, NULL }, +#if !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_RSA) && !defined(NO_AES) && \ + defined(HAVE_AES_CBC) && !defined(NO_SHA256) && defined(HAVE_ECC) + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, + "ECDHE-RSA-AES128-SHA256" }, +#endif +#endif +#ifdef WOLFSSL_DTLS13 + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, NULL }, +#endif + }; + + for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) { + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, params[i].client_meth, params[i].server_meth), 0); + if (params[i].cipher != NULL) { + ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i].cipher), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i].cipher), + WOLFSSL_SUCCESS); + } + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + test_memio_clear_buffer(&test_ctx, 1); + + ExpectIntEQ(wolfSSL_write(ssl_s, "A", 1), 1); + ExpectIntEQ(wolfSSL_write(ssl_s, "B", 1), 1); + + /* Deliver both records in one datagram */ + ExpectIntEQ(test_ctx.c_msg_count, 2); + if (EXPECT_SUCCESS()) { + test_ctx.c_msg_sizes[0] += test_ctx.c_msg_sizes[1]; + test_ctx.c_msg_count = 1; + } + + ExpectIntEQ(wolfSSL_read(ssl_c, reply, sizeof(reply)), 1); + ExpectIntEQ(reply[0], 'A'); + ExpectIntEQ(wolfSSL_pending(ssl_c), 0); + ExpectIntEQ(wolfSSL_has_pending(ssl_c), 1); + + ExpectIntEQ(wolfSSL_read(ssl_c, reply, sizeof(reply)), 1); + ExpectIntEQ(reply[0], 'B'); + ExpectIntEQ(wolfSSL_has_pending(ssl_c), 0); + + wolfSSL_free(ssl_c); + ssl_c = NULL; + wolfSSL_free(ssl_s); + ssl_s = NULL; + wolfSSL_CTX_free(ctx_c); + ctx_c = NULL; + wolfSSL_CTX_free(ctx_s); + ctx_s = NULL; + } +#endif + return EXPECT_RESULT(); +} + /* Test parameter validation across the read/write APIs. * * Every entry point in ssl_api_rw.c rejects a NULL object, a NULL buffer or a diff --git a/tests/api/test_ssl_rw.h b/tests/api/test_ssl_rw.h index 822863c4515..f3b771d2873 100644 --- a/tests/api/test_ssl_rw.h +++ b/tests/api/test_ssl_rw.h @@ -29,6 +29,7 @@ int test_wolfSSL_writev(void); int test_wolfSSL_get_shutdown(void); int test_wolfSSL_want(void); int test_wolfSSL_pending_api(void); +int test_wolfSSL_has_pending_dtls_datagram(void); int test_wolfSSL_rw_bad_args(void); int test_wolfSSL_rw_info_callback(void); int test_wolfSSL_write_ex_partial(void); @@ -58,6 +59,7 @@ int test_wolfSSL_write_dup_max_fragment(void); TEST_DECL_GROUP("ssl_rw", test_wolfSSL_get_shutdown), \ TEST_DECL_GROUP("ssl_rw", test_wolfSSL_want), \ TEST_DECL_GROUP("ssl_rw", test_wolfSSL_pending_api), \ + TEST_DECL_GROUP("ssl_rw", test_wolfSSL_has_pending_dtls_datagram), \ TEST_DECL_GROUP("ssl_rw", test_wolfSSL_rw_bad_args), \ TEST_DECL_GROUP("ssl_rw", test_wolfSSL_rw_info_callback), \ TEST_DECL_GROUP("ssl_rw", test_wolfSSL_write_ex_partial), \ From 125fd742cc98fc0190e694544ef985545f980a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Fri, 6 Nov 2026 16:24:04 +0100 Subject: [PATCH 3/8] zephyr: keep big integers off the thread stack The TLS handshake runs on the stack of the thread that calls connect(), accept() or send(). With RSA enabled, the single-precision math sizes every big integer for the largest RSA key, so ECC code that keeps such integers on the stack needs over 12 KB on a Cortex-M7 for one P-256 chain. Turn on WOLFSSL_SP_SMALL_STACK by default through the new CONFIG_WOLFCRYPT_SP_SMALL_STACK option. It moves the RSA, DH and ECC temporaries of the SP routines to the heap; the rest of wolfSSL keeps its stack use, so WOLFSSL_SMALL_STACK stays off. Also define ALT_ECC_SIZE when RSA or DH is enabled, as configure does for low-resource builds, so ECC keys and points are sized for the largest curve. An ecc_key drops from 4160 to 352 bytes. Neither applies to a FIPS build, whose math comes from the module settings, or to a build without malloc. Measured on nucleo_h743zi with the Zephyr TLS socket tests, the peak stack of an RSA-2048 chain falls from 7.0 KB to 5.3 KB. Together with the ECC curve parameter change in ecc.c, a P-256 chain falls from 12.4 KB to 5.4 KB. The wolfssl_test sample gains a variant with the option off, and the Zephyr 4.x CI builds and runs it on native_sim. --- .github/scripts/zephyr-4.x/builds.txt | 1 + .github/scripts/zephyr-4.x/sp_stack.conf | 2 ++ .wolfssl_known_macro_extras | 1 + zephyr/Kconfig | 12 ++++++++++++ zephyr/samples/wolfssl_test/sample.yaml | 7 +++++++ zephyr/user_settings.h | 9 +++++++++ 6 files changed, 32 insertions(+) create mode 100644 .github/scripts/zephyr-4.x/sp_stack.conf diff --git a/.github/scripts/zephyr-4.x/builds.txt b/.github/scripts/zephyr-4.x/builds.txt index b1316f7b98c..d5c9f9410bf 100644 --- a/.github/scripts/zephyr-4.x/builds.txt +++ b/.github/scripts/zephyr-4.x/builds.txt @@ -11,6 +11,7 @@ native_sim samples/wolfssl_benchmark external_libc.conf native_sim samples/wolfssl_test prj-cert.conf native_sim samples/wolfssl_test prj-x25519-ed448.conf native_sim samples/wolfssl_test prj-ed25519-x448.conf +native_sim samples/wolfssl_test sp_stack.conf # external_libc overlay is native_sim-only in the original Jenkins matrix frdm_rw612/rw612 samples/wolfssl_tls_sock frdm_rw612/rw612 samples/wolfssl_test diff --git a/.github/scripts/zephyr-4.x/sp_stack.conf b/.github/scripts/zephyr-4.x/sp_stack.conf new file mode 100644 index 00000000000..e69c9e87ce5 --- /dev/null +++ b/.github/scripts/zephyr-4.x/sp_stack.conf @@ -0,0 +1,2 @@ +# SP math temporaries on the thread stack +CONFIG_WOLFCRYPT_SP_SMALL_STACK=n diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 36f3f3f5ede..a341f2a0bae 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -191,6 +191,7 @@ CONFIG_WOLFCRYPT_FIPS_V5 CONFIG_WOLFCRYPT_FIPS_V6 CONFIG_WOLFCRYPT_FIPS_V7 CONFIG_WOLFCRYPT_SP_SMALL +CONFIG_WOLFCRYPT_SP_SMALL_STACK CONFIG_WOLFSSL CONFIG_WOLFSSL_AES_BITSLICED CONFIG_WOLFSSL_AES_TOUCH_LINES diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 18e24f6cd5c..8d2e4cb307c 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -719,6 +719,18 @@ config WOLFCRYPT_SP_SMALL turning it off is what makes WOLFCRYPT_ASM pay off on a part with the flash to spare. +config WOLFCRYPT_SP_SMALL_STACK + bool "Single-precision math temporaries on the heap" + depends on WOLFSSL_BUILTIN && !WOLFSSL_HAS_SETTINGS_FILE && !WOLFCRYPT_FIPS + default y + help + Allocate the temporaries of the fixed-size single-precision RSA, DH + and ECC routines (sp_c32.c, sp_c64.c and the assembly sources) on + the heap (WOLFSSL_SP_SMALL_STACK) instead of the stack of the calling + thread. An RSA-3072 operation otherwise needs over 4 KB of stack. The + generic sp_int.c math and the rest of wolfSSL keep their stack use + unless WOLFSSL_SMALL_STACK is set in a settings file. + config WOLFSSL_NO_HAVE_MIN_MAX bool "Force wolfSSL to use its own min/max" help diff --git a/zephyr/samples/wolfssl_test/sample.yaml b/zephyr/samples/wolfssl_test/sample.yaml index 3698d56b184..05262139929 100644 --- a/zephyr/samples/wolfssl_test/sample.yaml +++ b/zephyr/samples/wolfssl_test/sample.yaml @@ -33,6 +33,13 @@ tests: extra_args: CONF_FILE="prj.conf;prj-ecc-custom.conf" integration_platforms: - qemu_x86 + sample.crypto.wolfssl_test_sp_stack: + timeout: 120 + platform_allow: qemu_x86 + extra_configs: + - CONFIG_WOLFCRYPT_SP_SMALL_STACK=n + integration_platforms: + - qemu_x86 sample.crypto.wolfssl_test_ghash_table_4bit: timeout: 120 platform_allow: qemu_x86 diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index 3c58119e2e1..0a986775de7 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -696,6 +696,11 @@ extern "C" { #if defined(HAVE_ECC521) #define WOLFSSL_SP_521 #endif + /* Sizes ECC keys and points for the largest curve */ + #if (!defined(NO_RSA) || !defined(NO_DH)) && !defined(WOLFSSL_NO_MALLOC) && \ + !defined(HAVE_FIPS) + #define ALT_ECC_SIZE + #endif #endif #ifndef NO_RSA #define WOLFSSL_HAVE_SP_RSA @@ -712,6 +717,10 @@ extern "C" { #endif //#define WOLFSSL_SP_NO_MALLOC /* disable heap in wolf/SP math */ //#define SP_DIV_WORD_USE_DIV /* no div64 */ + #if defined(CONFIG_WOLFCRYPT_SP_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) && \ + !defined(WOLFSSL_SP_NO_MALLOC) + #define WOLFSSL_SP_SMALL_STACK + #endif /* Assembly speedup, keyed on the CPU Zephyr reports. Anything not named * here keeps the C backend. Each pair is two separate backends: the _ASM From ad17c330085eae49a57bf8849fc6e6e992cdbd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Fri, 6 Nov 2026 16:24:04 +0100 Subject: [PATCH 4/8] zephyr: choose the largest RSA key size Add a Kconfig choice for the largest RSA modulus: 2048, 3072 or 4096 bits. It sets WOLFSSL_SP_NO_3072 or WOLFSSL_SP_4096, and with them SP_INT_BITS, which sizes the big integers of the RSA and DH math. With WOLFSSL_SP_MATH_ALL the choice also pins SP_INT_BITS, which settings.h otherwise raises to 4096 on 64-bit assembly builds. A FIPS build keeps the sizes its module settings define, so the choice is hidden there. The default is 4096, the limit mbedTLS applies to PSA RSA keys. The previous build could not verify a signature made with an RSA-4096 key, which many root certificates use. A board that only needs RSA-2048 can pick that and save about 4 KB of heap per handshake. The wolfssl_test sample gains variants for 2048 and 3072, each also with custom curves, and the Zephyr 4.x CI builds and runs the 2048, 3072 and 3072 custom curve ones on native_sim. --- .github/scripts/zephyr-4.x/builds.txt | 3 ++ .github/scripts/zephyr-4.x/rsa_2048.conf | 2 ++ .github/scripts/zephyr-4.x/rsa_3072.conf | 2 ++ .../zephyr-4.x/rsa_3072_ecc_custom.conf | 9 ++++++ .wolfssl_known_macro_extras | 3 ++ zephyr/Kconfig | 24 +++++++++++++++ zephyr/samples/wolfssl_test/sample.yaml | 30 +++++++++++++++++++ zephyr/user_settings.h | 14 +++++++-- 8 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 .github/scripts/zephyr-4.x/rsa_2048.conf create mode 100644 .github/scripts/zephyr-4.x/rsa_3072.conf create mode 100644 .github/scripts/zephyr-4.x/rsa_3072_ecc_custom.conf diff --git a/.github/scripts/zephyr-4.x/builds.txt b/.github/scripts/zephyr-4.x/builds.txt index d5c9f9410bf..b532ed6f004 100644 --- a/.github/scripts/zephyr-4.x/builds.txt +++ b/.github/scripts/zephyr-4.x/builds.txt @@ -12,6 +12,9 @@ native_sim samples/wolfssl_test prj-cert.conf native_sim samples/wolfssl_test prj-x25519-ed448.conf native_sim samples/wolfssl_test prj-ed25519-x448.conf native_sim samples/wolfssl_test sp_stack.conf +native_sim samples/wolfssl_test rsa_2048.conf +native_sim samples/wolfssl_test rsa_3072.conf +native_sim samples/wolfssl_test rsa_3072_ecc_custom.conf # external_libc overlay is native_sim-only in the original Jenkins matrix frdm_rw612/rw612 samples/wolfssl_tls_sock frdm_rw612/rw612 samples/wolfssl_test diff --git a/.github/scripts/zephyr-4.x/rsa_2048.conf b/.github/scripts/zephyr-4.x/rsa_2048.conf new file mode 100644 index 00000000000..9e5150a5728 --- /dev/null +++ b/.github/scripts/zephyr-4.x/rsa_2048.conf @@ -0,0 +1,2 @@ +# Largest RSA key 2048 bits +CONFIG_WOLFSSL_RSA_MAX_BITS_2048=y diff --git a/.github/scripts/zephyr-4.x/rsa_3072.conf b/.github/scripts/zephyr-4.x/rsa_3072.conf new file mode 100644 index 00000000000..8ad989e26eb --- /dev/null +++ b/.github/scripts/zephyr-4.x/rsa_3072.conf @@ -0,0 +1,2 @@ +# Largest RSA key 3072 bits +CONFIG_WOLFSSL_RSA_MAX_BITS_3072=y diff --git a/.github/scripts/zephyr-4.x/rsa_3072_ecc_custom.conf b/.github/scripts/zephyr-4.x/rsa_3072_ecc_custom.conf new file mode 100644 index 00000000000..4fe0eab1cac --- /dev/null +++ b/.github/scripts/zephyr-4.x/rsa_3072_ecc_custom.conf @@ -0,0 +1,9 @@ +# Custom curves (prj-ecc-custom.conf) with the largest RSA key 3072 bits +CONFIG_WOLFSSL_ECC=y +CONFIG_WOLFSSL_ECC_256=y +CONFIG_WOLFSSL_ECC_384=y +CONFIG_WOLFSSL_ECC_512=y +CONFIG_WOLFSSL_ECC_BRAINPOOL=y +CONFIG_MAIN_STACK_SIZE=65536 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=65536 +CONFIG_WOLFSSL_RSA_MAX_BITS_3072=y diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index a341f2a0bae..44d35938f0a 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -256,6 +256,9 @@ CONFIG_WOLFSSL_POST_HANDSHAKE_AUTH CONFIG_WOLFSSL_PSK CONFIG_WOLFSSL_PUBLIC_ASN CONFIG_WOLFSSL_RSA +CONFIG_WOLFSSL_RSA_MAX_BITS_2048 +CONFIG_WOLFSSL_RSA_MAX_BITS_3072 +CONFIG_WOLFSSL_RSA_MAX_BITS_4096 CONFIG_WOLFSSL_RSA_PSS CONFIG_WOLFSSL_SESSION_CACHE CONFIG_WOLFSSL_SESSION_EXPORT diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 8d2e4cb307c..3bf763f8a05 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -259,6 +259,30 @@ config WOLFSSL_RSA help Enable RSA (define RSA support; NO_RSA when off). +choice WOLFSSL_RSA_MAX_BITS + prompt "Largest RSA key size" + depends on WOLFSSL_RSA && !WOLFCRYPT_FIPS + default WOLFSSL_RSA_MAX_BITS_4096 + help + Largest RSA modulus wolfCrypt can sign, verify or decrypt with, so + also the largest RSA key a certificate chain may carry. The big + integers of the RSA and DH math are sized for this length, so a + smaller choice saves stack and heap in each handshake. The + single-precision math handles 2048, 3072 and 4096-bit keys up to the + chosen size; other sizes need WOLFSSL_SP_MATH_ALL. + A FIPS build takes its math sizes from the module settings instead. + +config WOLFSSL_RSA_MAX_BITS_2048 + bool "2048 bits" + +config WOLFSSL_RSA_MAX_BITS_3072 + bool "3072 bits" + +config WOLFSSL_RSA_MAX_BITS_4096 + bool "4096 bits" + +endchoice + config WOLFSSL_ECC bool "wolfCrypt ECC support" depends on !WOLFSSL_HAS_SETTINGS_FILE diff --git a/zephyr/samples/wolfssl_test/sample.yaml b/zephyr/samples/wolfssl_test/sample.yaml index 05262139929..e0261065079 100644 --- a/zephyr/samples/wolfssl_test/sample.yaml +++ b/zephyr/samples/wolfssl_test/sample.yaml @@ -33,6 +33,36 @@ tests: extra_args: CONF_FILE="prj.conf;prj-ecc-custom.conf" integration_platforms: - qemu_x86 + sample.crypto.wolfssl_test_rsa_2048: + timeout: 120 + platform_allow: qemu_x86 + extra_configs: + - CONFIG_WOLFSSL_RSA_MAX_BITS_2048=y + integration_platforms: + - qemu_x86 + sample.crypto.wolfssl_test_rsa_2048_ecc_custom: + timeout: 600 + platform_allow: qemu_x86 + extra_args: CONF_FILE="prj.conf;prj-ecc-custom.conf" + extra_configs: + - CONFIG_WOLFSSL_RSA_MAX_BITS_2048=y + integration_platforms: + - qemu_x86 + sample.crypto.wolfssl_test_rsa_3072: + timeout: 120 + platform_allow: qemu_x86 + extra_configs: + - CONFIG_WOLFSSL_RSA_MAX_BITS_3072=y + integration_platforms: + - qemu_x86 + sample.crypto.wolfssl_test_rsa_3072_ecc_custom: + timeout: 600 + platform_allow: qemu_x86 + extra_args: CONF_FILE="prj.conf;prj-ecc-custom.conf" + extra_configs: + - CONFIG_WOLFSSL_RSA_MAX_BITS_3072=y + integration_platforms: + - qemu_x86 sample.crypto.wolfssl_test_sp_stack: timeout: 120 platform_allow: qemu_x86 diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index 0a986775de7..d213f8b9126 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -705,8 +705,18 @@ extern "C" { #ifndef NO_RSA #define WOLFSSL_HAVE_SP_RSA //#define WOLFSSL_SP_NO_2048 - //#define WOLFSSL_SP_NO_3072 - //#define WOLFSSL_SP_4096 + #if defined(CONFIG_WOLFSSL_RSA_MAX_BITS_2048) + #define WOLFSSL_SP_NO_3072 + #ifdef WOLFSSL_SP_MATH_ALL + #define SP_INT_BITS 2048 + #endif + #elif defined(CONFIG_WOLFSSL_RSA_MAX_BITS_3072) + #ifdef WOLFSSL_SP_MATH_ALL + #define SP_INT_BITS 3072 + #endif + #elif defined(CONFIG_WOLFSSL_RSA_MAX_BITS_4096) + #define WOLFSSL_SP_4096 + #endif #endif #ifndef NO_DH #define WOLFSSL_HAVE_SP_DH From 614336fff28cf8d78c2c8e46e333ef26d713d2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Fri, 6 Nov 2026 16:24:04 +0100 Subject: [PATCH 5/8] zephyr: list the benchmark sample tags as a YAML list Twister in Zephyr 4.5 rejects a space-separated tags value and skips the whole sample. --- zephyr/samples/wolfssl_benchmark/sample.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zephyr/samples/wolfssl_benchmark/sample.yaml b/zephyr/samples/wolfssl_benchmark/sample.yaml index 525dfb2069a..bd5be5d1f24 100644 --- a/zephyr/samples/wolfssl_benchmark/sample.yaml +++ b/zephyr/samples/wolfssl_benchmark/sample.yaml @@ -2,7 +2,11 @@ sample: description: wolfCrypt benchmark sample app name: wolfCrypt benchmark common: - tags: crypto wolfssl userspace random + tags: + - crypto + - wolfssl + - userspace + - random harness: console harness_config: type: one_line From 357a91c546894189863173c0444419c6ab588402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Tue, 3 Nov 2026 13:42:56 +0100 Subject: [PATCH 6/8] zephyr: build without the old RNG type name The WOLFSSL_ZEPHYR block in settings.h includes . Through the arch and CMSIS headers that reaches the SoC's device header, and on an STM32 part with an RNG peripheral that header defines RNG as the peripheral pointer. random.h then redefines RNG as WC_RNG, the type name it keeps for old code, so every file that includes a wolfSSL header warns that RNG is redefined, and a build with -Werror, the twister default, fails. Any later use of the peripheral macro in such a file also gets the wolfSSL type. The STM32 port in settings.h defines NO_OLD_RNGNAME for this reason, but a Zephyr build does not use that port. Define NO_OLD_RNGNAME in zephyr/user_settings.h, outside the settings-file block, so it applies with CONFIG_WOLFSSL_SETTINGS_FILE as well and comes before the FIPS compatibility define in settings.h. Code that still names the type RNG has to use WC_RNG; nothing in wolfSSL or its Zephyr samples and tests does. --- zephyr/user_settings.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index d213f8b9126..bac85b9c2dc 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -820,6 +820,11 @@ extern "C" { #endif /* WOLFSSL_SETTINGS_FILE */ +/* pulls in SoC headers that define RNG, such as STM32's */ +#ifndef NO_OLD_RNGNAME +#define NO_OLD_RNGNAME +#endif + /* The port is silent when its define is missing: els_pkc_port.c compiles to * nothing and no crypto callback is ever registered. */ #if defined(CONFIG_WOLFSSL_ELS_PKC) && \ From 12a1f9c44cf2df16d23278ff475ad9a1c0d22556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Fri, 6 Nov 2026 16:58:40 +0100 Subject: [PATCH 7/8] zephyr: drop Zephyr 4.1 from CI Zephyr 4.1 is past its support window. Test 4.3, 4.4 and 4.5, and make 4.3 the default of the local test script. The script still selects the SDK image for 4.0 and 4.1, so those versions can be built by hand. --- .github/scripts/zephyr-4.x/zephyr-test.sh | 4 ++-- .github/workflows/zephyr-4.x.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/scripts/zephyr-4.x/zephyr-test.sh b/.github/scripts/zephyr-4.x/zephyr-test.sh index 1e894238109..968aae069ce 100755 --- a/.github/scripts/zephyr-4.x/zephyr-test.sh +++ b/.github/scripts/zephyr-4.x/zephyr-test.sh @@ -25,7 +25,7 @@ # -h, --help Show this help # # Examples: -# # Test master against Zephyr 4.1.0 for native_sim +# # Test master against Zephyr 4.3.0 for native_sim # ./zephyr-test.sh # # # Test a specific branch for frdm_rw612 on Zephyr 4.3.0 @@ -54,7 +54,7 @@ set -euo pipefail # Defaults WOLFSSL_REPO="https://github.com/wolfSSL/wolfssl" WOLFSSL_BRANCH="master" -ZEPHYR_VERSION="v4.1.0" +ZEPHYR_VERSION="v4.3.0" BOARD_TARGET="native_sim" SAMPLE_NAME="wolfssl_tls_sock" SUBDIR="samples" diff --git a/.github/workflows/zephyr-4.x.yml b/.github/workflows/zephyr-4.x.yml index 8429effeace..8b1b0db54db 100644 --- a/.github/workflows/zephyr-4.x.yml +++ b/.github/workflows/zephyr-4.x.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - zephyr-ref: [ v4.1.0, v4.3.0, v4.4.0, v4.5.0 ] + zephyr-ref: [ v4.3.0, v4.4.0, v4.5.0 ] steps: - name: Checkout test driver uses: actions/checkout@v5 From 281b7c9312ea3bb89da3cdd58756442ae678c0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Fri, 6 Nov 2026 16:58:40 +0100 Subject: [PATCH 8/8] zephyr: test the 3.7 LTS release instead of 3.4 and 3.5 Zephyr 3.4 and 3.5 were short-term releases and are long out of support, while 3.7, the current LTS release supported until July 2029, had no CI job. Run the zephyr.yml scenarios on v3.7.2 with SDK 0.16.8, the SDK that 3.7 documents. 2.7.4 stays for now. The comment on the twister step now names only the limits that still apply. --- .github/workflows/zephyr.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 770b811309a..1de6fe5f3a2 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -23,10 +23,8 @@ jobs: fail-fast: false matrix: config: - - zephyr-ref: v3.4.0 - zephyr-sdk: 0.16.1 - - zephyr-ref: v3.5.0 - zephyr-sdk: 0.16.3 + - zephyr-ref: v3.7.2 + zephyr-sdk: 0.16.8 - zephyr-ref: v2.7.4 zephyr-sdk: 0.16.3 if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} @@ -92,17 +90,8 @@ 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. - # - # Name the two scenarios rather than running the whole sample: the rest - # need a Zephyr these versions predate - hierarchical board names, - # COMMON_LIBC_MALLOC_ARENA_SIZE, and toolchains beyond the x86_64 one - # installed above. --test drops the others before their platform_allow - # is resolved, so an unrecognized board does not abort the run - but - # the yaml is still parsed, so a modern-only key would. + # 2.7.4's twister rejects the zephyr/tests yaml, so -T stays on the + # sample; the other scenarios need boards or toolchains not set up here. run: | ./zephyr/scripts/twister -T modules/crypto/wolfssl/zephyr/samples/wolfssl_test \ --test sample.crypto.wolfssl_test \