wc_swdev is a test-only software backend used to exercise builds
that strip a wolfCrypt algorithm in favor of CryptoCb dispatch. It is
compiled separately from the main library, linked into the test
programs only, and exposes exactly two C symbols. It is not a
production component and must not be linked into shipping binaries.
The switches it supports are:
| Macro | Strips | Test target |
|---|---|---|
WOLF_CRYPTO_CB_ONLY_RSA |
software RSA | RSA via CryptoCb |
WOLF_CRYPTO_CB_ONLY_ECC |
software ECC | ECC via CryptoCb |
WOLF_CRYPTO_CB_ONLY_SHA256 |
software SHA-256 | SHA-256 via CryptoCb |
WOLF_CRYPTO_CB_ONLY_SHA512 |
software SHA-512 | SHA-512 via CryptoCb |
WOLF_CRYPTO_CB_ONLY_AES |
software AES | AES via CryptoCb |
WOLF_CRYPTO_CB_ONLY_ED25519 |
software Ed25519 | Ed25519 via CryptoCb |
When a test program calls e.g. wc_AesCbcEncrypt() against a libwolfssl
built with -DWOLF_CRYPTO_CB_ONLY_AES, the software AES path is gone;
the call routes through the CryptoCb dispatch layer. swdev registers
itself as that callback, executes the operation against its own
internal copy of the AES code, and returns the result.
+-----------------------------------------------------------+
| TEST PROGRAM (testwolfcrypt, unit.test, examples/...) |
| |
| wolfCrypt_Init() |
| wc_SwDev_Init() -- registers swdev device + a |
| WOLF_CRYPTO_CB_FIND hook |
| ... wc_AesCbcEncrypt(), wc_Sha256Update(), etc. ... |
| wc_SwDev_Cleanup() |
| wolfCrypt_Cleanup() |
+-----------------------------------------------------------+
| ^
| call into LIBWOLFSSL | result
v |
+-----------------------------------------------------------+
| LIBWOLFSSL (compiled with -DWOLF_CRYPTO_CB_ONLY_AES, |
| -DWOLF_CRYPTO_CB_ONLY_SHA256, ...) |
| |
| wc_AesCbcEncrypt() |
| - software AES is #ifdef'd out |
| - dispatch via wc_CryptoCb_AesCbc...() |
+-----------------------------------------------------------+
| ^
| CryptoCb dispatch |
v |
+-----------------------------------------------------------+
| tests/swdev/build/swdev.o |
| (single relocatable .o, only 2 visible symbols) |
| |
| wc_SwDev_Callback(devId, info, ctx) |
| - swdev_ensure_init() lazy wolfCrypt_Init |
| - switch (info->algo_type): |
| PK -> RSA / ECC / Ed25519 software impl |
| HASH -> SHA-256 software impl |
| CIPHER -> AES (CBC/CTR/ECB/GCM/CCM) software impl |
| |
| swdev was compiled WITHOUT the WOLF_CRYPTO_CB_ONLY_* |
| gates, so its private copy of wolfcrypt still has the |
| full software implementations. |
+-----------------------------------------------------------+
The whole mechanism rests on compiling the wolfcrypt sources twice:
- libwolfssl is built normally with the user's
_ONLY_*flags set, so its software RSA/ECC/SHA-256/SHA-512/AES/Ed25519 paths are gone. - swdev recompiles the same source set under
tests/swdev/user_settings.h, which#undefs every_ONLY_*macro. swdev therefore contains the full software implementations.
To prevent symbol collisions when both are linked into the same test
binary, tests/swdev/Makefile does the following:
- Compiles every swdev TU with
-fvisibility=hidden -fno-common. - Drops
-DBUILDING_WOLFSSLsoWOLFSSL_APIdoes not re-promote symbols to default visibility. - Links all swdev objects with
ld -rinto a single relocatableswdev.partial.o. - Runs
objcopy --keep-global-symbol=wc_SwDev_Callback --keep-global-symbol=wc_SwDev_InternalCleanupto localize every remaining global except the two intended exports.
The Makefile then enforces the invariant directly:
nm --extern-only --defined-only build/swdev.omust list only wc_SwDev_Callback and wc_SwDev_InternalCleanup.
The build fails loudly otherwise (see tests/swdev/Makefile:122-129).
If you add a third WC_SWDEV_EXPORT API, update the keep-list in the
Makefile too.
swdev and libwolfssl share C structs across the CryptoCb boundary
(wc_Sha256, Aes, RsaKey, ecc_key, ...). One compilation
allocates them, the other operates on them. They must therefore be
ABI-identical. The _ONLY_* macros only gate function bodies, not
struct layouts, so flipping them between the two compiles is safe.
Do not introduce other macros that change struct layout into
tests/swdev/user_settings.h.
wc_swdev is enabled with the --enable-swdev configure flag.
./autogen.sh
./configure --enable-swdev --enable-cryptocb \
<other flags> \
CPPFLAGS="-DWOLF_CRYPTO_CB_ONLY_ECC \
-DWOLF_CRYPTO_CB_ONLY_RSA \
-DWOLF_CRYPTO_CB_ONLY_SHA256 \
-DWOLF_CRYPTO_CB_ONLY_AES"
make
make checkNotes:
--enable-swdevrequires--enable-cryptocb, or--enable-usersettingswithWOLF_CRYPTO_CBdefined in the user'suser_settings.h.--enable-swdevdefinesWOLFSSL_SWDEVandWOLF_CRYPTO_CB_FINDautomatically; seeconfigure.ac.- swdev is built from
wolfcrypt/test/include.amand inheritsPARENT_SRCS,PARENT_BUILD_CFLAGS, etc., from the parent build. Out-of-tree (VPATH) builds work:WOLFBUILDpoints the sub-make at the build tree for the configure-generated headers (wolfssl/options.h,wolfssl/version.h).
For the full CI matrix that exercises each _ONLY_* macro, see
.github/workflows/cryptocb-only.yml.
| File | Role |
|---|---|
swdev.h |
Public swdev interface (the two exported symbols) |
swdev.c |
CryptoCb dispatcher: PK / HASH / CIPHER algorithms |
swdev_loader.h |
Test-harness API: wc_SwDev_Init, wc_SwDev_Cleanup |
swdev_loader.c |
Refcounted Init/Cleanup; registers the callback + Find hook |
user_settings.h |
#undefs the WOLF_CRYPTO_CB_ONLY_* gates for swdev's TU |
Makefile |
Two-compile + objcopy + symbol-invariant check |
None. swdev exists only to make the WOLF_CRYPTO_CB_ONLY_* builds
testable on a generic Linux runner. Real deployments are expected to
provide their own CryptoCb backed by a hardware engine (TPM, HSM, SoC
crypto block, etc.). swdev is not API-stable, not benchmarked, and not
audited as a production cryptographic provider.