The NXP CAAM (Cryptographic Accelerator and Assurance Module) supports offloading cryptographic operations for acceleration along with heightened security. wolfSSL supports accessing the hardware acceleration in many different operating environments, such as with QNX or NXP’s Yocto Linux builds. For QNX builds wolfSSL has targeted specific i.MX devices, check with our manual or support channel to verify your build. For NXP Yocto builds we acces the CAAM driver through the use of cryptodev-linux. The following shows how to go about building and using cryptodev.ko and some comparisons of three wolfCrypt builds on the same board (i.MX7D SABRE, kernel 6.6, wolfSSL 5.9.2): a pure-software build, an ARM assembly (NEON) build, and a CAAM hardware-offload build via cryptodev//dev/crypto. Each build was run at two benchmark block sizes, 1 MB and 4 KB.
Adding cryptodev.ko to the kernel
cryptodev-linux is an out-of-tree module. It is never part of the kernel tree, and its vermagic (kernel version plus config plus compiler) must match the kernel running on the board, or insmod fails with invalid module format. There are two ways to produce a matching cryptodev.ko.
A. Yocto standalone .ko (build it, insmod it yourself)
Builds cryptodev.ko against the exact kernel baked into your image, then you copy it to the board and load it manually. Inside the build container:
# 1. Set up the BSP build environment cd /workdir/imx-bsp DISTRO=fsl-imx-fb MACHINE=imx7dsabresd source ./imx-setup-release.sh -b build # 2. Build just the module (vermagic guaranteed to match the image kernel) bitbake cryptodev-module # 3. Locate the produced .ko and copy it out find /yocto-tmp/tmp/work -name cryptodev.ko # .../cryptodev-module/1.14-r0/.../lib/modules/6.6.52+g/extra/cryptodev.ko
On the booted board:
insmod ./cryptodev.ko # or place under /lib/modules/$(uname -r) + depmod && modprobe cryptodev lsmod | grep cryptodev # confirm it loaded dmesg | grep -i cryptodev # "cryptodev: driver ... loaded." ls -l /dev/crypto # the char device must now exist
Ensure the kernel is not built with CONFIG_MODULE_SIG_FORCE, or a hand-loaded .ko is rejected.
B. Add it to the image recipes (baked in, auto-loaded at boot)
For production images, install the module and auto-load it. In conf/local.conf (or your image recipe):
IMAGE_INSTALL:append = " cryptodev-module cryptodev-linux" KERNEL_MODULE_AUTOLOAD += "cryptodev"
- cryptodev-module builds and packages cryptodev.ko against this kernel (correct vermagic guaranteed); cryptodev-linux provides the
userspace header wolfSSL needs at compile time. - KERNEL_MODULE_AUTOLOAD += “cryptodev” writes /etc/modules-load.d/cryptodev.conf so the module loads at every boot, and the build runs depmod.
- After changing KERNEL_MODULE_AUTOLOAD, force a rebuild: bitbake -c cleansstate cryptodev-module && bitbake core-image-minimal.
To make wolfSSL itself devcrypto-enabled in a production recipe:
EXTRA_OECONF:append:pn-wolfssl = " --enable-devcrypto" DEPENDS:append:pn-wolfssl = " cryptodev-linux"
The kernel side must expose CAAM to the Crypto API for any of this to offload. Set CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y and …_AHASH_API=y (see the caam.cfg fragment). Check on target with cat /proc/crypto | grep -i caam.
Build configuration
All three variants are wolfSSL v5.9.2 (commit 38a4143a4), statically linked, and share one common feature set so the comparison is fair. Only the acceleration flags differ. The shared base is:
./configure \
--enable-static --disable-shared \
--enable-crypttests --disable-examples \
--enable-aesctr --enable-aesgcm \
--enable-reproducible-build
Each variant then adds its distinguishing flags:
| Variant | Extra configure flags | Notes |
|---|---|---|
| SW | –disable-asm –disable-armasm |
Pure C reference, every acceleration path off. |
| ASM | –enable-armasm –host=armv7a-poky-linux-gnueabi |
ARMv7 NEON assembly. The –host override forces the ARMv7 NEON code path; without it configure can emit ARMv8 crypto-extension instructions the Cortex-A7 cannot run (SIGILL). |
| CAAM | –enable-devcrypto=all –disable-sha224 |
CAAM offload via /dev/crypto. =all routes AES (CBC/CTR/ECB/GCM), SHA, and HMAC through the device. –disable-sha224 is required (SHA-224 is incompatible with –enable-devcrypto). |
| Also needs the cryptodev-linux userspace header at compile time. |
Results at 1 MB blocks (MB/s, higher is better)
| Algorithm | SW | ASM (NEON) | CAAM | Fastest |
|---|---|---|---|---|
| AES-128-CBC-enc | 19.85 | 26.72 | 45.76 | CAAM |
| AES-128-CBC-dec | 19.45 | 25.98 | 44.82 | CAAM |
| AES-192-CBC-enc | 17.02 | 22.78 | 38.90 | CAAM |
| AES-192-CBC-dec | 16.97 | 22.33 | 38.18 | CAAM |
| AES-256-CBC-enc | 15.07 | 19.76 | 33.79 | CAAM |
| AES-256-CBC-dec | 14.88 | 19.40 | 33.25 | CAAM |
| AES-128-GCM-enc | 10.06 | 13.56 | 45.82 | CAAM |
| AES-128-GCM-dec | 6.57 | 13.57 | 45.80 | CAAM |
| AES-192-GCM-enc | 9.27 | 12.43 | 38.89 | CAAM |
| AES-192-GCM-dec | 6.20 | 12.44 | 38.88 | CAAM |
| AES-256-GCM-enc | 8.65 | 11.43 | 33.78 | CAAM |
| AES-256-GCM-dec | 5.94 | 11.49 | 33.78 | CAAM |
| GMAC | 20.42 | 27.31 | 28.70 | CAAM |
| SHA-256 | 25.02 | 24.28 | 63.36 | CAAM |
Results at 4 KB blocks (MB/s, higher is better)
| Algorithm | SW | ASM (NEON) | CAAM | Fastest |
|---|---|---|---|---|
| AES-128-CBC-enc | 20.38 | 27.50 | 25.43 | ASM |
| AES-128-CBC-dec | 19.95 | 26.99 | 20.67 | ASM |
| AES-192-CBC-enc | 17.43 | 23.42 | 19.65 | ASM |
| AES-192-CBC-dec | 17.37 | 22.96 | 19.67 | ASM |
| AES-256-CBC-enc | 15.40 | 20.26 | 18.39 | ASM |
| AES-256-CBC-dec | 15.21 | 19.89 | 17.12 | ASM |
| AES-128-GCM-enc | 10.24 | 13.77 | 21.38 | CAAM |
| AES-128-GCM-dec | 6.63 | 13.77 | 21.07 | CAAM |
| AES-192-GCM-enc | 9.41 | 12.61 | 19.87 | CAAM |
| AES-192-GCM-dec | 6.27 | 12.61 | 19.92 | CAAM |
| AES-256-GCM-enc | 8.77 | 11.63 | 17.18 | CAAM |
| AES-256-GCM-dec | 5.99 | 11.63 | 17.15 | CAAM |
| GMAC | 20.47 | 27.63 | 28.68 | CAAM |
| SHA-256 | 25.40 | 24.75 | 59.25 | CAAM |
(GMAC: SW/CAAM use the 4-bit table path; ASM uses the ARM-ASM GMAC path.)
CPU Usage
In addition to higher throughput, CAAM offloads the work from the application core. The wall-clock breakdown of the 1 MB runs shows this clearly:
| Build | real | user | sys |
|---|---|---|---|
| SW | 17.71s | 17.66s | 0.01s |
| ASM | 15.93s | 15.86s | 0.02s |
| CAAM | 14.62s | 0.13s | 1.06s |
For the SW and ASM builds, user time is approximately equal to real time, indicating that the core is occupied performing the cipher for the full duration of the run. The CAAM build completes in comparable wall-clock time but consumes only about 1.2s of CPU time (user plus sys) over a 14.6s run. During the remaining time the calling thread is blocked on the ioctl(CIOCCRYPT) while the CAAM engine performs the operation, leaving the core available to the rest of the system.
This result also distinguishes a correctly bound CAAM path from a software fallback. When cryptodev binds to a kernel software cipher, the run instead consumes sys time for its full duration, since the crypto executes in kernel context. A low sys figure such as 1.06s indicates that the operation was serviced by the CAAM hardware and that the thread was suspended rather than busy-waiting. The binding can be confirmed directly with cat /proc/crypto | grep -i caam, which should list entries such as cbc-aes-caam and sha256-caam.
If you have questions about any of the above, please contact us at facts@wolfssl.com or call us at +1 425 245 8247.
Download wolfSSL now

