diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 4c274d56235..d6cb7e39dc1 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -185,9 +185,11 @@ CONFIG_USE_WOLFSSL_ESP_SDK_WIFI CONFIG_WOLFCRYPT_ARM_SYMMETRIC_ASM CONFIG_WOLFCRYPT_ASM CONFIG_WOLFCRYPT_FIPS +CONFIG_WOLFCRYPT_FIPS_PRE_V7_ASM CONFIG_WOLFCRYPT_FIPS_READY CONFIG_WOLFCRYPT_FIPS_V2 CONFIG_WOLFCRYPT_FIPS_V5 +CONFIG_WOLFCRYPT_FIPS_V5_2_3 CONFIG_WOLFCRYPT_FIPS_V6 CONFIG_WOLFCRYPT_FIPS_V7 CONFIG_WOLFCRYPT_SP_SMALL diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index c7c9b327362..50466a5f30e 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -19,6 +19,16 @@ if(CONFIG_WOLFSSL) ) zephyr_library() + # Library sources only, never the application, as the top-level CMake does. + # The v5 kdf.c predates libwolfssl_sources.h: without this, types.h pulls + # in wc_compat.h, which reaches fips.h before kdf.c sets FIPS_NO_WRAPPERS, + # and kdf.c then defines the wc_*_fips wrappers a second time. + zephyr_library_compile_definitions(BUILDING_WOLFSSL) + # The v5 random.c predates the zephyr/ include prefix; map its + # and onto the current headers. + if(CONFIG_WOLFCRYPT_FIPS_V5) + zephyr_library_include_directories(${ZEPHYR_CURRENT_MODULE_DIR}/zephyr/fips-v5-compat) + endif() zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/zephyr/zephyr_init.c) zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/crl.c) @@ -96,16 +106,30 @@ if(CONFIG_WOLFSSL) # The integrity test hashes the boundary .text and .rodata as two ranges, so # keep each in one piece and in file order: no sorting, splitting or merging. - if(WOLF_BOUNDARY_ASM AND CONFIG_WOLFCRYPT_FIPS) + # v5 hashes the same wolfCrypt_FIPS_first..last and ro_start..ro_end pair as + # v7, so this holds for every boundary, not only the one with assembly. + if(CONFIG_WOLFCRYPT_FIPS) if(CONFIG_LINKER_SORT_BY_ALIGNMENT) message(FATAL_ERROR "wolfCrypt FIPS needs CONFIG_LINKER_SORT_BY_ALIGNMENT=n: " "sorting by alignment moves boundary code out of the hashed range") endif() + # The v5 seed callback in zephyr_init.c draws on the Zephyr CSPRNG, which + # must read the entropy driver itself rather than pass the seed through + # a DRBG outside the module, as the CTR-DRBG and PSA generators do. Only + # with an entropy driver, which sets CSPRNG_ENABLED: without one the + # callback uses the test generator or fails the build. The test CSPRNG is + # sys_rand_get() under a name Zephyr already flags as insecure. + if(CONFIG_WOLFCRYPT_FIPS_V5 AND CONFIG_CSPRNG_ENABLED + AND NOT CONFIG_HARDWARE_DEVICE_CS_GENERATOR + AND NOT CONFIG_TEST_CSPRNG_GENERATOR) + message(FATAL_ERROR "wolfCrypt FIPS v5 needs CONFIG_HARDWARE_DEVICE_CS_GENERATOR=y: " + "the DRBG seed must come straight from the entropy driver") + endif() set_source_files_properties(${WOLF_FIPS_SRCS} PROPERTIES COMPILE_OPTIONS "-fno-function-sections;-fno-data-sections;-fno-merge-constants") endif() # native_sim links like a host program and keeps file order without this. - if(WOLF_BOUNDARY_ASM AND CONFIG_WOLFCRYPT_FIPS AND NOT CONFIG_ARCH_POSIX) + if(CONFIG_WOLFCRYPT_FIPS AND NOT CONFIG_ARCH_POSIX) set(WOLF_FIPS_LD ${CMAKE_CURRENT_BINARY_DIR}/wolfcrypt_fips_rodata.ld) file(WRITE ${WOLF_FIPS_LD} "SECTION_PROLOGUE(wolfcrypt_fips_rodata,,)\n{\n") foreach(s ${WOLF_FIPS_SRCS}) @@ -211,7 +235,7 @@ if(CONFIG_WOLFSSL) if(CONFIG_ARM64 AND NOT WOLF_BOUNDARY_ASM) zephyr_library_sources(${WOLF_ARM_ASM_DIR}/armv8-sha1-asm_c.c) endif() - elseif(CONFIG_X86_64) + elseif(CONFIG_X86_64 AND NOT CONFIG_WOLFCRYPT_FIPS_PRE_V7_ASM) # fe_x25519_asm.S, wc_mlkem_asm.S and wc_mldsa_asm.S are here because # curve25519.c, wc_mlkem_poly.c and wc_mldsa.c all take the Intel path # whenever USE_INTEL_SPEEDUP is set, so leaving one out is a link error diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 18e24f6cd5c..33e6ea3fe18 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -79,6 +79,12 @@ config WOLFCRYPT_FIPS dropped into wolfcrypt/src/ - the CMake FIPS-boundary block compiles them. Select the version that matches the bundle under "wolfCrypt FIPS version". + Set CONFIG_LINKER_SORT_BY_ALIGNMENT=n, which Zephyr defaults on. The + integrity check hashes the boundary as two ranges, so its sections + must stay in file order; the build stops while sorting is on. + + Needs Zephyr 3.7 or later, for STATIC_INIT_GNU. + choice prompt "wolfCrypt FIPS version" depends on WOLFCRYPT_FIPS @@ -98,6 +104,15 @@ config WOLFCRYPT_FIPS_V5 bool "FIPS 140-3 (Cert #4718)" help wolfCrypt FIPS 140-3 validated module, Certificate #4718 (version 5.2.1). + A 5.2.3 bundle is selected under "wolfCrypt FIPS v5 bundle". + + The v5 random.c seeds from a bare sys_rand_get(), so the DRBG is + seeded through a callback instead (zephyr_init.c): the Zephyr CSPRNG, + which reads the zephyr,entropy device. A board without an entropy + driver fails the build unless CONFIG_TEST_RANDOM_GENERATOR is set, and + so does any CSPRNG but CONFIG_HARDWARE_DEVICE_CS_GENERATOR or the test + one: the seed must come straight from the driver, not through a DRBG + outside the module, as the CTR-DRBG and PSA generators route it. config WOLFCRYPT_FIPS_V6 bool "FIPS 140-3 (SRTP-KDF full submission)" @@ -119,6 +134,35 @@ config WOLFCRYPT_FIPS_READY endchoice +choice + prompt "wolfCrypt FIPS v5 bundle" + depends on WOLFCRYPT_FIPS_V5 + default WOLFCRYPT_FIPS_V5_2_1 + help + Select the v5 bundle dropped into the tree. Like the version above, + it must match the bundle. + +config WOLFCRYPT_FIPS_V5_2_1 + bool "5.2.1" + help + wolfCrypt 5.2.1. The algorithm set follows the Kconfig options. + +config WOLFCRYPT_FIPS_V5_2_3 + bool "5.2.3" + select WOLFSSL_RSA + select WOLFSSL_ECC + select WOLFSSL_ECC_256 + help + wolfCrypt 5.2.3. The algorithm set is that of + ./configure --enable-fips=v5.2.3, from user_settings-fips-v5.2.3.h. + RSA, ECC and P-256 are selected here because user_settings.h would + otherwise disable them after that file; the other algorithm options + cannot remove what it enables either, and WOLFSSL_ECC_384 and + WOLFSSL_ECC_521 only add the single-precision code for curves the set + already has. + +endchoice + config WOLFSSL_CRYPTO_CB bool "wolfCrypt crypto callbacks" depends on !WOLFSSL_HAS_SETTINGS_FILE @@ -225,14 +269,18 @@ config WOLFSSL_PSK config WOLFSSL_MLKEM bool "wolfSSL PQC ML-KEM support" depends on !WOLFSSL_HAS_SETTINGS_FILE + depends on !WOLFCRYPT_FIPS_V2 && !WOLFCRYPT_FIPS_V5 help - Enable PQC ML-KEM support for Key Exchange + Enable PQC ML-KEM support for Key Exchange. Needs SHAKE, which the + FIPS v2 and v5 boundaries do not build. config WOLFSSL_MLDSA bool "wolfSSL PQC ML-DSA support" depends on !WOLFSSL_HAS_SETTINGS_FILE + depends on !WOLFCRYPT_FIPS_V2 && !WOLFCRYPT_FIPS_V5 help - Enable PQC ML-DSA (Dilithium) signatures. + Enable PQC ML-DSA (Dilithium) signatures. Needs SHAKE, which the FIPS + v2 and v5 boundaries do not build. config WOLFSSL_LMS bool "wolfSSL LMS/HSS hash-based signatures" @@ -243,14 +291,19 @@ config WOLFSSL_LMS config WOLFSSL_XMSS bool "wolfSSL XMSS/XMSS^MT hash-based signatures" depends on !WOLFSSL_HAS_SETTINGS_FILE + depends on !WOLFCRYPT_FIPS_V2 && !WOLFCRYPT_FIPS_V5 help Enable XMSS/XMSS^MT stateful hash-based signature verification (verify-only). + Its SHAKE parameter sets need SHAKE, which the FIPS v2 and v5 boundaries + do not build. config WOLFSSL_FALCON bool "wolfSSL PQC Falcon signatures" depends on !WOLFSSL_HAS_SETTINGS_FILE + depends on !WOLFCRYPT_FIPS_V2 && !WOLFCRYPT_FIPS_V5 help - Enable PQC Falcon (FN-DSA) signatures. + Enable PQC Falcon (FN-DSA) signatures. Needs SHAKE, which the FIPS v2 + and v5 boundaries do not build. config WOLFSSL_RSA bool "wolfCrypt RSA support" @@ -327,12 +380,23 @@ endif # WOLFSSL_ECC config WOLFSSL_ECC_ALLOW_ZERO_HASH bool +# v2, v5 and v6 keep their symmetric assembly in the armv8-aes.c and +# armv8-sha256.c of their own boundary (src/include.am's LEGACY_ARMASM_*), +# which this module does not build: their aes.c and sha256.c compile the C +# code out under WOLFSSL_ARMASM, so the link fails, and on x86_64 their +# sha256.c would call the tree's sha256_asm.S from outside the boundary. v7 +# and FIPS Ready carry the asm_c form, which the CMake boundary block builds +# in place. +config WOLFCRYPT_FIPS_PRE_V7_ASM + bool + default y if WOLFCRYPT_FIPS && !WOLFCRYPT_FIPS_V7 && !WOLFCRYPT_FIPS_READY + # Thumb2 needs UBFX and LDRD, so ARMv6-M and ARMv8-M baseline keep the C code # and take only the SP speedup. config WOLFCRYPT_ARM_SYMMETRIC_ASM bool - default y if WOLFCRYPT_ASM && (ARM64 || ARMV7_M_ARMV8_M_MAINLINE || \ - (ARM && !CPU_CORTEX_M)) + default y if WOLFCRYPT_ASM && !WOLFCRYPT_FIPS_PRE_V7_ASM && \ + (ARM64 || ARMV7_M_ARMV8_M_MAINLINE || (ARM && !CPU_CORTEX_M)) # Not under FIPS v2 or v5, whose pinned aes.c has neither backend, nor with the # Arm assembly, which indexes its AES and GHASH tables with secret data. @@ -703,6 +767,10 @@ config WOLFCRYPT_ASM 32-bit x86 is not offered: only the AES sources have an implementation at that width, and the rest are guarded to x86_64. + Under FIPS v2, v5 and v6 only the single-precision math is + accelerated. Those modules carry their symmetric assembly inside the + boundary in a form this module does not build. + config WOLFCRYPT_SP_SMALL bool "Smaller single-precision math" depends on WOLFSSL_BUILTIN && !WOLFSSL_HAS_SETTINGS_FILE diff --git a/zephyr/README.md b/zephyr/README.md index ef0334d1171..a8c72b7d4b1 100644 --- a/zephyr/README.md +++ b/zephyr/README.md @@ -76,6 +76,46 @@ west build -p auto -b qemu_x86 modules/crypto/wolfssl/zephyr/samples/wolfssl_tes west build -t run ``` +## Build with a wolfCrypt FIPS v5 bundle + +In a tree holding a v5 FIPS bundle, select it in `prj.conf`: + +``` +CONFIG_WOLFCRYPT_FIPS=y +CONFIG_WOLFCRYPT_FIPS_V5=y +CONFIG_WOLFCRYPT_FIPS_V5_2_3=y +CONFIG_LINKER_SORT_BY_ALIGNMENT=n +``` + +Leave `CONFIG_WOLFCRYPT_FIPS_V5_2_3` out for a 5.2.1 bundle. Every FIPS +boundary needs `CONFIG_LINKER_SORT_BY_ALIGNMENT=n`, which Zephyr defaults on: +the integrity check hashes the boundary as two ranges, and sorting input +sections by alignment moves code out of them, so the build stops while it is +set. + +With 5.2.3, `user_settings.h` takes the algorithm set of +`--enable-fips=v5.2.3` from `user_settings-fips-v5.2.3.h`; the TLS and +certificate options still follow Kconfig. Both v5 bundles seed the DRBG from +the Zephyr CSPRNG, which has to be `CONFIG_HARDWARE_DEVICE_CS_GENERATOR`, the +default with an entropy driver, so that the seed comes straight from the +driver and not through a DRBG outside the module; a board with no entropy +driver fails the build unless `CONFIG_TEST_RANDOM_GENERATOR` is set. Under +FIPS v2, v5 and v6 `CONFIG_WOLFCRYPT_ASM` accelerates only the SP math: those +boundaries keep their AES and SHA assembly in a form this module does not +build. + +The `crypto_only` scenario of `tests/wolfssl_condvar` also calls +`wc_InitRng()`, which under v5 only works once the hook in `zephyr_init.c` +has registered the seed callback; `wolfcrypt_test()` registers it itself, so +the test sample cannot tell. CI runs it without a bundle. With one: + +``` +west build -p always -b native_sim modules/crypto/wolfssl/zephyr/tests/wolfssl_condvar -- -DCONFIG_WOLFSSL_CRYPTO_ONLY=y -DCONFIG_WOLFCRYPT_FIPS=y -DCONFIG_WOLFCRYPT_FIPS_V5=y -DCONFIG_LINKER_SORT_BY_ALIGNMENT=n +west build -t run +``` + +Add `-DCONFIG_WOLFCRYPT_FIPS_V5_2_3=y` for a 5.2.3 bundle. + ## Build and Run wolfCrypt Benchmark Application build and execute `wolfssl_benchmark` diff --git a/zephyr/fips-v5-compat/posix/time.h b/zephyr/fips-v5-compat/posix/time.h new file mode 100644 index 00000000000..4cb389e65b2 --- /dev/null +++ b/zephyr/fips-v5-compat/posix/time.h @@ -0,0 +1,36 @@ +/* time.h + * + * 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 + */ + +/* Shim for the FIPS v5 random.c, which includes from + * before Zephyr moved its headers under zephyr/. The module needs Zephyr 3.7 + * or later; 4.3 then dropped zephyr/posix/time.h for the libc header. */ +#ifndef WOLFSSL_ZEPHYR_COMPAT_POSIX_TIME_H +#define WOLFSSL_ZEPHYR_COMPAT_POSIX_TIME_H + +#include + +#if KERNEL_VERSION_NUMBER >= 0x40300 + #include +#else + #include +#endif + +#endif /* WOLFSSL_ZEPHYR_COMPAT_POSIX_TIME_H */ diff --git a/zephyr/fips-v5-compat/random/rand32.h b/zephyr/fips-v5-compat/random/rand32.h new file mode 100644 index 00000000000..af6a76661e0 --- /dev/null +++ b/zephyr/fips-v5-compat/random/rand32.h @@ -0,0 +1,30 @@ +/* rand32.h + * + * 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 + */ + +/* Shim for the FIPS v5 random.c, which includes from + * before Zephyr moved its headers under zephyr/ and renamed rand32.h. The + * module needs Zephyr 3.7 or later, which has only the new header. */ +#ifndef WOLFSSL_ZEPHYR_COMPAT_RAND32_H +#define WOLFSSL_ZEPHYR_COMPAT_RAND32_H + +#include + +#endif /* WOLFSSL_ZEPHYR_COMPAT_RAND32_H */ diff --git a/zephyr/include.am b/zephyr/include.am index 57fa67fd77c..e9d7606e104 100644 --- a/zephyr/include.am +++ b/zephyr/include.am @@ -9,6 +9,9 @@ EXTRA_DIST+= zephyr/module.yml EXTRA_DIST+= zephyr/wolfssl/options.h EXTRA_DIST+= zephyr/user_settings.h EXTRA_DIST+= zephyr/user_settings-fips-v7.h +EXTRA_DIST+= zephyr/user_settings-fips-v5.2.3.h +EXTRA_DIST+= zephyr/fips-v5-compat/posix/time.h +EXTRA_DIST+= zephyr/fips-v5-compat/random/rand32.h EXTRA_DIST+= zephyr/README.md EXTRA_DIST+= zephyr/samples/wolfssl_benchmark/ EXTRA_DIST+= zephyr/samples/wolfssl_benchmark/CMakeLists.txt diff --git a/zephyr/tests/wolfssl_condvar/prj.conf b/zephyr/tests/wolfssl_condvar/prj.conf index eba974c0b58..7debb2fc286 100644 --- a/zephyr/tests/wolfssl_condvar/prj.conf +++ b/zephyr/tests/wolfssl_condvar/prj.conf @@ -11,3 +11,8 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=131072 CONFIG_WOLFSSL=y CONFIG_WOLFSSL_BUILTIN=y + +# Seed source for the RNG test, as in samples/wolfssl_tls_sock: native_sim's +# fake entropy driver, with the test generator as the fallback. +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/zephyr/tests/wolfssl_condvar/src/main.c b/zephyr/tests/wolfssl_condvar/src/main.c index 0cd5c8040c2..a98b54be174 100644 --- a/zephyr/tests/wolfssl_condvar/src/main.c +++ b/zephyr/tests/wolfssl_condvar/src/main.c @@ -26,6 +26,13 @@ * 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. + * + * Also brings up the wolfCrypt DRBG. Nothing in this image calls wolfSSL_Init() + * or wolfcrypt_test(), both of which register the DRBG seed callback themselves + * and so would hide a port that fails to register it; under FIPS v5 the module + * refuses to seed until it is set, so wc_InitRng() fails unless the + * APPLICATION-level hook in zephyr_init.c ran. Without a bundle, which is how + * CI runs it, the same check covers the tree's Zephyr wc_GenerateSeed(). */ #include @@ -35,6 +42,7 @@ #include #include #include +#include static COND_TYPE g_cond; static volatile int g_predicate; @@ -88,4 +96,29 @@ ZTEST(wolfssl_condvar, test_null_guards) zassert_equal(wolfSSL_CondEnd(NULL), BAD_FUNC_ARG, "CondEnd NULL"); } +ZTEST(wolfssl_condvar, test_init_rng_at_boot) +{ + WC_RNG rng; + byte block[32]; + byte zero[32]; + int ret; + + zassert_equal(wolfCrypt_Init(), 0, "wolfCrypt_Init"); + + /* Nothing in this image calls wc_SetSeed_Cb(), so under FIPS v5 this is + * where a missing boot-time registration shows. */ + ret = wc_InitRng(&rng); + zassert_equal(ret, 0, "wc_InitRng: %d", ret); + + XMEMSET(block, 0, sizeof(block)); + XMEMSET(zero, 0, sizeof(zero)); + ret = wc_RNG_GenerateBlock(&rng, block, sizeof(block)); + zassert_equal(ret, 0, "wc_RNG_GenerateBlock: %d", ret); + zassert_true(XMEMCMP(block, zero, sizeof(block)) != 0, + "generated block is all zero"); + + zassert_equal(wc_FreeRng(&rng), 0, "wc_FreeRng"); + zassert_equal(wolfCrypt_Cleanup(), 0, "wolfCrypt_Cleanup"); +} + ZTEST_SUITE(wolfssl_condvar, NULL, NULL, NULL, NULL, NULL); diff --git a/zephyr/user_settings-fips-v5.2.3.h b/zephyr/user_settings-fips-v5.2.3.h new file mode 100644 index 00000000000..c64dc52ff1f --- /dev/null +++ b/zephyr/user_settings-fips-v5.2.3.h @@ -0,0 +1,102 @@ +/* user_settings-fips-v5.2.3.h + * + * 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 + */ + +/* Algorithm set of ./configure --enable-fips=v5.2.3, included by + * user_settings.h under CONFIG_WOLFCRYPT_FIPS_V5_2_3, which also selects the + * RSA, ECC and P-256 options so that file cannot disable them afterwards. + * TLS, certificate, platform and DRBG seeding options stay with + * user_settings.h and its Kconfig mapping. */ + +#ifndef WOLFSSL_ZEPHYR_FIPS_V5_H +#define WOLFSSL_ZEPHYR_FIPS_V5_H + +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING +#define WOLFSSL_USE_ALIGN + +/* Hashes and KDFs */ +#define WOLFSSL_SHA224 +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 +#define WOLFSSL_NOSHA512_224 +#define WOLFSSL_NOSHA512_256 +#define WOLFSSL_SHA3 +#define HAVE_HKDF +#define WOLFSSL_WOLFSSH + +/* AES. The GHASH method follows the Kconfig choice. */ +#define HAVE_AESGCM +#define HAVE_AESCCM +#define HAVE_AES_ECB +#define WOLFSSL_AES_DIRECT +#define WOLFSSL_AES_COUNTER +#define WOLFSSL_AES_OFB +#define WOLFSSL_CMAC + +/* RSA */ +#define WOLFSSL_KEY_GEN +#define WC_RSA_PSS +#define WC_RSA_NO_PADDING + +/* ECC */ +#define HAVE_ECC +#define ECC_SHAMIR +#define ECC_USER_CURVES +#define HAVE_ECC192 +#define HAVE_ECC224 +#define HAVE_ECC256 +#define HAVE_ECC384 +#define HAVE_ECC521 +#define HAVE_ECC_CDH +#define WOLFSSL_VALIDATE_ECC_IMPORT +#define WOLFSSL_VALIDATE_ECC_KEYGEN + +/* DH */ +#undef NO_DH +#define HAVE_FFDHE_Q +#define HAVE_FFDHE_2048 +#define HAVE_FFDHE_3072 +#define HAVE_FFDHE_4096 +#define HAVE_FFDHE_6144 +#define HAVE_FFDHE_8192 +#define HAVE_DH_DEFAULT_PARAMS +#define HAVE_PUBLIC_FFDHE +#define WOLFSSL_DH_EXTRA +#define WOLFSSL_VALIDATE_FFC_IMPORT + +/* Outside the module */ +#define NO_DSA +#define NO_MD4 +#define NO_MD5 +#define NO_RC4 +#define NO_DES3 +#define NO_DES3_TLS_SUITES + +/* Math. SP_SMALL_STACK moves the 4096-bit mod-exp temporaries (11-23 KB of + * stack on Cortex-M4) to the heap; it touches only the sp_*.c files, which + * sit outside the v5 boundary. */ +#define WOLFSSL_SP_MATH_ALL +#define SP_INT_BITS 8192 +#define WOLFSSL_SP_4096 +#define WOLFSSL_SP_SMALL_STACK + +#endif /* WOLFSSL_ZEPHYR_FIPS_V5_H */ diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index 3c58119e2e1..c92987f85e0 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -132,7 +132,7 @@ extern "C" { #define HAVE_FIPS_VERSION_PATCH 0 #endif #elif defined(CONFIG_WOLFCRYPT_FIPS_V5) - /* FIPS 140-3 Cert #4718 (wolfCrypt 5.2.1). */ + /* FIPS 140-3 Cert #4718 (wolfCrypt 5.2.1), or the 5.2.3 bundle. */ #ifndef HAVE_FIPS_VERSION #define HAVE_FIPS_VERSION 5 #endif @@ -140,7 +140,28 @@ extern "C" { #define HAVE_FIPS_VERSION_MINOR 2 #endif #ifndef HAVE_FIPS_VERSION_PATCH - #define HAVE_FIPS_VERSION_PATCH 1 + #ifdef CONFIG_WOLFCRYPT_FIPS_V5_2_3 + #define HAVE_FIPS_VERSION_PATCH 3 + #else + #define HAVE_FIPS_VERSION_PATCH 1 + #endif + #endif + /* fips.c needs a thread-local choice made. Not HAVE_THREAD_LS: + * THREAD_LS_T is empty on Zephyr, so it would only drop the ECC/SP + * cache locks and arm the shared wolfCrypt_Init() recursion guard. */ + #define NO_THREAD_LS + /* The ECDSA CAST in fips_test.c signs with wc_ecc_sign_set_k(). */ + #define WOLFSSL_ECDSA_SET_K + /* The v5 random.c seeds the DRBG from a bare sys_rand_get(), so seed + * through the callback in zephyr_init.c instead: wolfSSL_Init() + * registers WC_GENERATE_SEED_DEFAULT, and that file registers it for + * wolfCrypt-only builds. configure sets WC_RNG_SEED_CB for v5 too. */ + #define WC_RNG_SEED_CB + #define WC_GENERATE_SEED_DEFAULT wolfssl_zephyr_seed + #ifndef __ASSEMBLER__ + struct OS_Seed; + int wolfssl_zephyr_seed(struct OS_Seed* os, unsigned char* seed, + unsigned int sz); #endif #elif defined(CONFIG_WOLFCRYPT_FIPS_V2) /* FIPS 140-2 Cert #3389. */ @@ -160,6 +181,8 @@ extern "C" { #endif #if defined(CONFIG_WOLFCRYPT_FIPS_V7) || defined(CONFIG_WOLFCRYPT_FIPS_READY) #include "user_settings-fips-v7.h" + #elif defined(CONFIG_WOLFCRYPT_FIPS_V5_2_3) + #include "user_settings-fips-v5.2.3.h" #endif #endif @@ -301,9 +324,11 @@ extern "C" { /* 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. */ + * registered. The v5 bundles' random.c has only the fallback, so the FIPS block + * above registers the callback in zephyr_init.c for them instead. + * 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 #endif @@ -386,7 +411,9 @@ extern "C" { #endif /* DH */ -#if 0 +#if defined(WOLFSSL_ZEPHYR_FIPS_V5_H) + /* in the v5.2.3 set */ +#elif 0 #undef NO_DH /* on by default */ #define WOLFSSL_DH_CONST /* don't rely on pow/log */ #define HAVE_FFDHE_2048 @@ -766,7 +793,9 @@ extern "C" { #if defined(CONFIG_ARM64) && !defined(__ARM_FEATURE_QRDMX) #define WOLFSSL_AARCH64_NO_SQRDMLSH #endif -#elif defined(CONFIG_X86_64) +#elif defined(CONFIG_X86_64) && !defined(CONFIG_WOLFCRYPT_FIPS_PRE_V7_ASM) + /* Not under FIPS v2, v5 or v6: their sha256.c would call the AVX + * transforms in the tree's sha256_asm.S, outside the boundary. */ #define USE_INTEL_SPEEDUP #define WOLFSSL_X86_64_BUILD #endif diff --git a/zephyr/zephyr_init.c b/zephyr/zephyr_init.c index 77a8205806f..cd4393b8a80 100644 --- a/zephyr/zephyr_init.c +++ b/zephyr/zephyr_init.c @@ -19,24 +19,33 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* Only a port that brings up a peripheral needs a boot-time hook. */ +#include -#ifdef CONFIG_WOLFSSL_SYS_INIT +/* The port's log module, for the boot-time hooks below. Zephyr before 3.2 has + * no zephyr/ include prefix, so the headers stay out until one of them needs + * them. */ + +#if defined(CONFIG_WOLFSSL_SYS_INIT) || defined(CONFIG_WOLFCRYPT_FIPS_V5) #include #include #include -#include +LOG_MODULE_REGISTER(wolfssl, CONFIG_WOLFSSL_LOG_LEVEL); + +#endif + +/* Only a port that brings up a peripheral needs a boot-time hook. */ + +#ifdef CONFIG_WOLFSSL_SYS_INIT + #ifdef WOLFCRYPT_ONLY #include #else #include #endif -LOG_MODULE_REGISTER(wolfssl, CONFIG_WOLFSSL_LOG_LEVEL); - static int wolfssl_module_init(void) { int ret; @@ -65,3 +74,57 @@ static int wolfssl_module_init(void) SYS_INIT(wolfssl_module_init, POST_KERNEL, 99); #endif /* CONFIG_WOLFSSL_SYS_INIT */ + +/* DRBG seed source for the FIPS v5 bundles, whose wc_GenerateSeed() is a bare + * sys_rand_get() and so not a CSPRNG on the xoshiro or test generators. + * Outside the module boundary. The tree's Zephyr wc_GenerateSeed() in + * wolfcrypt/src/random.c reads the entropy device, but the bundle's random.c + * replaces that file, so Zephyr's CSPRNG, which reads the same device, stands + * in for it here. */ + +#ifdef CONFIG_WOLFCRYPT_FIPS_V5 + +#include +#include + +/* Zephyr 3.7 or later: CONFIG_WOLFCRYPT_FIPS selects STATIC_INIT_GNU. */ +#include + +/* CSPRNG_ENABLED follows ENTROPY_HAS_DRIVER, and CMakeLists.txt holds the + * generator to the hardware one, so the seed comes straight from the driver. */ +#if !defined(CONFIG_CSPRNG_ENABLED) && !defined(CONFIG_TEST_RANDOM_GENERATOR) + #error "FIPS v5 seeds its DRBG from the Zephyr CSPRNG: enable an entropy driver" +#endif + +int wolfssl_zephyr_seed(OS_Seed* os, byte* seed, word32 sz) +{ + (void)os; +#ifdef CONFIG_CSPRNG_ENABLED + return (sys_csrand_get(seed, sz) == 0) ? 0 : RNG_FAILURE_E; +#else + /* CONFIG_TEST_RANDOM_GENERATOR, which Zephyr already flags as insecure. */ + sys_rand_get(seed, sz); + return 0; +#endif +} + +/* wolfSSL_Init() registers WC_GENERATE_SEED_DEFAULT only on its first call, + * and wolfCrypt-only builds never call it. wc_SetSeed_Cb() is refused until + * the power-on self test has run, which is a C constructor, so register at + * APPLICATION level: Zephyr runs the constructors just before it. */ +static int wolfssl_zephyr_seed_init(void) +{ + int ret = wc_SetSeed_Cb(wolfssl_zephyr_seed); + + /* Zephyr hands this return only to a trace hook, and every later + * wc_InitRng() would fail with DRBG_NO_SEED_CB, so say why here. */ + if (ret != 0) { + LOG_ERR("wc_SetSeed_Cb failed: %d", ret); + return -EIO; + } + return 0; +} + +SYS_INIT(wolfssl_zephyr_seed_init, APPLICATION, 0); + +#endif /* CONFIG_WOLFCRYPT_FIPS_V5 */