Added documentation of the defines for algorithms and assembly code and math. user_settings_embedded.h has configuration defines at the top that are set to 0 for off and 1 for on. Setting these turns on the appropriate defines.
47 KiB
Assembly and Math Build Options
This guide is for developers building wolfSSL for a specific processor and
choosing how fast, how small, or how portable that build should be. It covers
the #defines that select the big-number math back end, the single-precision
(SP) implementations, and the assembly used by individual algorithms.
It is written for builds that configure wolfSSL through a hand-written
user_settings.h and WOLFSSL_USER_SETTINGS, which is the usual arrangement
for embedded targets, IDE projects and custom build systems. If you build with
./configure, you do not normally need to set any of these by hand — autotools
derives them from --enable-* options and writes them into
wolfssl/options.h. The tables below list the equivalent option in each case,
so you can reproduce an autotools build by hand or check what your current one
selected.
To get started quickly, copy examples/configs/user_settings_embedded.h into
your project. It implements everything described here through a short block of
on/off switches, so in most cases you can select your CPU and the level of
acceleration you want without setting individual defines at all.
For the options that select which algorithms are compiled and how each one
behaves, see the companion guide doc/ALGORITHM_DEFINES.md.
Contents
- The three independent axes
- Per-CPU quick reference
- Math back end
sp_int.c— generic multi-precision math- SP — specialised RSA/DH/ECC
- Per-algorithm assembly
- Hardware acceleration and offload
- FIPS builds
- Linux kernel modules
- Toolchains
- Recommended configurations
- Verifying and measuring the result
- Troubleshooting
1. The three independent axes
Three separate things are commonly all called "assembly". You select them independently, and enabling some but not others is perfectly normal.
| Axis | What it accelerates | Selected by | Code |
|---|---|---|---|
| A. Math back end | Which multi-precision integer implementation is compiled at all | WOLFSSL_SP_MATH_ALL, WOLFSSL_SP_MATH, USE_FAST_MATH, USE_INTEGER_HEAP_MATH |
sp_int.c, tfm.c, integer.c |
| B. SP big-number acceleration | RSA, DH, ECC, and generic mp_* operations |
WOLFSSL_SP_<arch> (inline) and WOLFSSL_SP_<arch>_ASM (specialised) |
sp_int.c, sp_<arch>.c (plus sp_x86_64_asm.S on x86_64 — see § 5) |
| C. Per-algorithm assembly | AES, SHA-2, SHA-3, ChaCha20, Poly1305, X25519, ML-KEM, ML-DSA, SM3/SM4 | WOLFSSL_AESNI, USE_INTEL_SPEEDUP, WOLFSSL_ARMASM, WOLFSSL_RISCV_ASM, WOLFSSL_PPC32_ASM, WOLFSSL_PPC64_ASM |
*_asm.S, port/<arch>/* |
Axis B has two tiers. The distinction matters when you are choosing what to enable, so it is worth reading before you pick your defines:
WOLFSSL_SP_<arch>(no_ASMsuffix) — inline assembly macros insidesp_int.cfor the word-level primitives (multiply-accumulate, divide). Speeds up all multi-precision work, including key sizes and curves that have no specialised implementation. Available for many CPUs. Sets the internalSP_INT_ASM_AVAILABLE.WOLFSSL_SP_<arch>_ASM— the specialised fixed-size implementations insp_<arch>.c. Only x86_64 adds a separatesp_x86_64_asm.S; the ARM files carry their assembly inline (§ 5). Much faster, but only for the specific key sizes and curves compiled in (RSA/DH 2048/3072/4096, P-256/P-384/P-521, SM2, SAKKE). Only available for x86_64, Aarch64, ARM32, ARM Thumb and Cortex-M.
Defining any WOLFSSL_SP_<arch>_ASM implies WOLFSSL_SP_ASM. You will normally
want both tiers together, which is what the per-CPU table in the next section
recommends: the specialised code handles the common key sizes and curves, and
the inline code covers everything else.
Both tiers are independent switches in your own build: turning off the
specialised WOLFSSL_SP_<arch>_ASM does not turn off the inline
WOLFSSL_SP_<arch>, and on RISC-V, PowerPC, MIPS and s390x the inline tier is
the only SP assembly there is. To turn all assembly off, define WOLFSSL_NO_ASM (and TFM_NO_ASM if you
use the legacy tfm.c back end). SP_INT_NO_ASM disables only the axis B
inline assembly and leaves axis C alone, which is useful when narrowing down a
problem.
2. Per-CPU quick reference
Find your processor and use the column that matches what you need. "With
assembly" is the fastest supported combination for that CPU; "without
assembly" is the portable C build, which is the right starting point when
bringing up a new target. Both assume the recommended WOLFSSL_SP_MATH_ALL
back end.
| CPU | Without assembly | With assembly |
|---|---|---|
| x86_64 / amd64 | WOLFSSL_SP_MATH_ALL, WOLFSSL_X86_64_BUILD |
add WOLFSSL_SP_X86_64, WOLFSSL_SP_X86_64_ASM, WOLFSSL_AESNI, USE_INTEL_SPEEDUP |
| x86 (32-bit) | WOLFSSL_SP_MATH_ALL, WOLFSSL_X86_BUILD |
add WOLFSSL_SP_X86, WOLFSSL_AESNI (no specialised SP asm) |
| Aarch64 / ARMv8-A | WOLFSSL_SP_MATH_ALL, WOLFSSL_AARCH64_BUILD |
add WOLFSSL_SP_ARM64, WOLFSSL_SP_ARM64_ASM, WOLFSSL_ARMASM |
| ARM32 (Cortex-A, Cortex-R, ARM11 and earlier) | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_ARM32, WOLFSSL_SP_ARM32_ASM, WOLFSSL_ARMASM, WOLFSSL_ARM_ARCH=<n> |
| ARM Thumb (Cortex-M0/M0+/M1) | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_ARM_THUMB, WOLFSSL_SP_ARM_THUMB_ASM |
| Cortex-M3/M4/M7/M33 (Thumb-2) | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_ARM_CORTEX_M, WOLFSSL_SP_ARM_CORTEX_M_ASM, WOLFSSL_ARMASM, WOLFSSL_ARMASM_THUMB2, WOLFSSL_ARM_ARCH=7 |
| RISC-V 64 | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_RISCV64, WOLFSSL_RISCV_ASM (+ extension defines) |
| RISC-V 32 | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_RISCV32 (inline SP only) |
| PowerPC 64 | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_PPC64, WOLFSSL_PPC64_ASM |
| PowerPC 32 | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_PPC, WOLFSSL_PPC32_ASM |
| MIPS64 / MIPS | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_MIPS64 / WOLFSSL_SP_MIPS (inline SP only) |
| s390x | WOLFSSL_SP_MATH_ALL |
add WOLFSSL_SP_S390X (inline SP only) |
| Anything else | WOLFSSL_SP_MATH_ALL |
— |
Notes:
- Specialised SP assembly (
WOLFSSL_SP_<arch>_ASM) exists only for x86_64, Aarch64, ARM32, ARM Thumb and Cortex-M. For every other CPU the assembly available on axis B is the inline tier (WOLFSSL_SP_<arch>) only../configure --enable-sp-asmerrors out on unsupported CPUs. - On x86_64,
WOLFSSL_SP_X86_64_ASMis not supported for Windows hosts built with MinGW/Cygwin. Use the C SP implementation there. MSVC builds use the.asmfiles from the Visual Studio project instead. WOLFSSL_SP_X86_64(or_ASM) also auto-definesHAVE_INTEL_AVX1, andHAVE_INTEL_AVX2unlessNO_AVX2_SUPPORTis defined, when 64-bit words are available.- Every assembly file has a matching
.asm(MASM/Intel syntax) alongside the.S(GNU as/AT&T syntax). Autotools and CMake build the.S; Visual Studio builds the.asm. - ARM covers a wide range of profiles and architecture versions, and the right defines differ noticeably between them. Section 6 has a per-architecture table; use it rather than the summary above if your target is anything other than a mainstream Cortex-A or Cortex-M.
3. Math back end
Exactly one back end provides mp_int and the mp_* API. Unless you have a
specific reason to do otherwise, choose WOLFSSL_SP_MATH_ALL.
| Define | Implementation | ./configure |
Use when |
|---|---|---|---|
WOLFSSL_SP_MATH_ALL |
sp_int.c — all key sizes and curves |
default | Recommended for everything. Replaces tfm.c and integer.c. |
WOLFSSL_SP_MATH |
sp_int.c — only the sizes SP was built for |
--enable-sp-math |
Smallest footprint. Any key size or curve not compiled in fails at run time. |
USE_FAST_MATH |
tfm.c — fixed-size stack-based |
--enable-fastmath |
Legacy. Kept for compatibility. |
USE_INTEGER_HEAP_MATH |
integer.c — heap-based |
--enable-heapmath |
Legacy, not timing resistant. Avoid. |
WOLFSSL_SP_MATH_ALL and WOLFSSL_SP_MATH both compile sp_int.c;
WOLFSSL_SP_MATH additionally restricts operations to what the specialised SP
code supports. WOLFSSL_SP_MATH requires the matching WOLFSSL_HAVE_SP_*
defines for whichever of RSA/DH/ECC are enabled — otherwise there is no
implementation to fall back to.
Related:
SP_WORD_SIZE— force32or64. Normally derived automatically from the CPU define (seesp_int.h); set it explicitly only when the default is wrong for the target.WOLFSSL_SP_DIV_32— do not use 64-bit divides (impliesWOLFSSL_SP_DIV_WORD_HALF). For CPUs without a hardware 64/32 divide.NO_64BIT— for a target with no 64-bit integer type. This dropsSP_WORD_SIZEto 16, and the specialised RSA/DH/ECC implementations are not provided at that width, so the build will not link once a public key algorithm is enabled. It also requires a target whoseunsigned longis 32-bit or smaller; on a 64-bit host the size-detection chain insp_int.hreports#error "Size of unsigned long not detected". Contact support if you need public key support on such a target.
Migrating from USE_FAST_MATH
Fastmath (tfm.c) was the default for many years and a great deal of existing
user_settings.h carries it. SP math is now the default and the actively
developed path, and moving over is usually a matter of translating a handful of
options. Nothing in your application code changes — the mp_* API is the same.
| Fastmath option | SP equivalent |
|---|---|
USE_FAST_MATH |
WOLFSSL_SP_MATH_ALL |
FP_MAX_BITS |
The size defines in section 5 — WOLFSSL_SP_NO_2048, WOLFSSL_SP_NO_3072, WOLFSSL_SP_4096 — or SP_INT_BITS to bound sp_int directly. Watch the units: FP_MAX_BITS is twice the key size, so FP_MAX_BITS 6144 means RSA-3072, whereas the SP defines name the key size itself |
TFM_TIMING_RESISTANT |
Nothing to carry over. It only affects tfm.c and wolfmath.c. Hardening inside SP is on unless you define WC_NO_HARDEN. ECC_TIMING_RESISTANT and WC_RSA_BLINDING are independent of the back end — and are not set for you in a hand-written user_settings.h, so carry them across explicitly; see doc/ALGORITHM_DEFINES.md § 6 |
TFM_ECC256, TFM_ECC384, TFM_ECC521 |
WOLFSSL_SP_NO_256 to drop P-256, WOLFSSL_SP_384 and WOLFSSL_SP_521 to add the others |
TFM_SMALL_SET |
WOLFSSL_SP_SMALL |
TFM_HUGE_SET |
WOLFSSL_SP_LARGE_CODE |
TFM_NO_ASM |
WOLFSSL_NO_ASM for all assembly, or SP_INT_NO_ASM for just the inline tier |
TFM_X86_64, TFM_ARM, TFM_AARCH_64, TFM_PPC32, TFM_PPC64, TFM_SSE2 |
The CPU defines in sections 2 and 4. Fastmath selected its assembly per architecture in the same way, but the names and the code are entirely separate |
ALT_ECC_SIZE carries over unchanged and is still worth setting — despite the
comment in ecc.h describing it in fastmath terms, it shrinks the SP
structures too.
Two things to check after the move:
- Key sizes. Fastmath sized one array for everything; SP compiles a
specialised implementation per size. Make sure every size your product
actually uses is enabled, or use
WOLFSSL_SP_MATH_ALLso anything not specialised still works through the generic code. - Memory profile. The two back ends allocate differently, so re-measure stack and heap rather than assuming your old figures hold. Section 12 covers how.
Fastmath remains supported for existing products, so there is no urgency, but new designs should start on SP math.
4. sp_int.c — generic multi-precision math
sp_int.c implements the whole mp_* API. The options below tune it for your
target. Most builds only need the CPU define from the first table; the rest are
there for when you are trading size against speed or working within a specific
memory budget.
CPU selection (inline assembly tier)
Define the one that matches your processor. Each enables inline assembly for
the word-level primitives when SP_WORD_SIZE matches.
| Define | CPU | Word size |
|---|---|---|
WOLFSSL_SP_X86_64 |
x86_64 | 64 |
WOLFSSL_SP_X86 |
x86 | 32 |
WOLFSSL_SP_ARM64 |
Aarch64 | 64 |
WOLFSSL_SP_ARM32 |
ARM32 | 32 |
WOLFSSL_SP_ARM_THUMB |
ARM Thumb (uses r7 explicitly) |
32 |
WOLFSSL_SP_ARM_CORTEX_M |
Cortex-M | 32 |
WOLFSSL_SP_PPC64 / WOLFSSL_SP_PPC |
PowerPC | 64 / 32 |
WOLFSSL_SP_MIPS64 / WOLFSSL_SP_MIPS |
MIPS | 64 / 32 |
WOLFSSL_SP_RISCV64 / WOLFSSL_SP_RISCV32 |
RISC-V | 64 / 32 |
WOLFSSL_SP_S390X |
s390x | 64 |
SP_INT_NO_ASM disables this tier even when a CPU define is set. Use it to
rule the inline assembly in or out when investigating a problem, without
changing the rest of your configuration.
Two options apply to ARM targets specifically:
WOLFSSL_SP_ARM32_UDIV— use theUDIVinstruction for word division. Thumb-2 cores haveUDIVfrom ARMv7-M onwards, but in ARM mode it belongs to the integer divide extension (ARMv7VE, or-march=armv7-a+idiv). Enabling it on a plain ARMv7-A build will not assemble, so leave it off unless you know your core has the instruction. The C fallback is used otherwise.WOLFSSL_SP_NO_UMAAL— the CPU has noUMAAL. Set automatically for Cortex-M3 (WOLFSSL_ARM_ARCH_7M) whenWOLFSSL_SP_ARM_CORTEX_M_ASMis defined; set it by hand for other cores that lack the instruction.
Size and speed
| Define | Effect |
|---|---|
WOLFSSL_SP_SMALL |
Smaller code, avoids large stack variables. Costs speed. |
WOLFSSL_SP_LOW_MEM |
Algorithms that use less memory. |
WOLFSSL_SP_INT_LARGE_COMBA |
Enable large Comba multiply/square. |
WOLFSSL_SP_FAST_MODEXP |
Faster mod_exp for a small amount of extra code. |
WOLFSSL_SP_FAST_NCT_EXPTMOD |
Faster non-constant-time modular exponentiation. Public-key operations only. |
WOLFSSL_SP_MILLER_RABIN_CNT |
Miller-Rabin rounds for primality testing (default 8). |
Note that sp_int.c undefines WOLFSSL_SP_SMALL for itself on clang 12 and
later, to avoid a known compiler issue. The undef is local to that translation
unit, so the sp_<arch>.c files still see the small variants — do not rely on
the setting being uniform across the math in that combination.
Memory placement
| Define | Effect |
|---|---|
SP_INT_BITS |
Largest number, in bits, an sp_int has to hold. Every sp_int is sized from it, so it sets the memory floor for the math. Derived in sp_int.h from the algorithms enabled — 3072 for general RSA/DH, 521 for ECC-only — and worth setting by hand only when something outside that derivation needs more. |
WOLFSSL_SMALL_STACK |
Allocate large structures from the heap instead of the stack. |
WOLFSSL_SP_NO_MALLOC |
Never call XMALLOC/XFREE in SP — always use the stack. |
WOLFSSL_SP_SMALL_STACK |
Heap-allocate SP temporaries. Auto-set by sp_<arch>.c when WOLFSSL_SMALL_STACK is set and WOLFSSL_SP_NO_MALLOC is not. |
WOLFSSL_SP_NO_DYN_STACK |
Do not use C99 variable-length stack arrays. Set this for compilers or coding standards that forbid VLAs. |
WOLFSSL_SMALL_STACK and WOLFSSL_SP_NO_MALLOC pull in opposite directions,
so choose according to what your target has:
- Heap available, stack tight →
WOLFSSL_SMALL_STACK. - No heap at all →
WOLFSSL_SP_NO_MALLOC(usually withWOLFSSL_SP_SMALLand restricted key sizes so the stack frames stay bounded), plusWOLFSSL_NO_MALLOC/WOLFSSL_STATIC_MEMORYfor the rest of the library.
Correctness and hardening
| Define | Effect |
|---|---|
WOLFSSL_SP_INT_NEGATIVE |
Allow negative values. Required by FIPS and by some certificate paths. |
WOLFSSL_SP_INT_DIGIT_ALIGN |
The platform cannot do unaligned sp_int_digit access. |
WOLFSSL_SP_INT_SQR_VOLATILE |
Declare squaring intermediates volatile. |
WC_PROTECT_ENCRYPTED_MEM |
Extra protection for operations on encrypted memory. |
WC_NO_CACHE_RESISTANT |
Disable cache-resistant (constant-address) table access. Faster, weaker. |
WC_NO_HARDEN |
Disable timing-attack resistance. Faster, weaker. |
WOLFSSL_NO_CT_OPS |
Disable constant-time operations. |
WOLFSSL_CHECK_MEM_ZERO |
Check that sensitive memory is zeroed on free (debug). |
wolfSSL recommends against defining WC_NO_HARDEN, WC_NO_CACHE_RESISTANT or
WOLFSSL_NO_CT_OPS in any product that handles long-term private keys, unless
your threat model genuinely excludes an attacker able to observe local timing or
cache behaviour. The performance gain is small relative to the protection lost.
Non-blocking
WOLFSSL_SP_NONBLOCK makes long operations return FP_WOULDBLOCK and expect
repeated calls until they complete, so a single-threaded application can stay
responsive during a slow key operation. It cannot be combined with the
specialised SP assembly — ./configure rejects --enable-sp=nonblock together
with --enable-sp-asm — so use it with the C implementation. Note that
--enable-sp=nonblock also implies small and no-malloc SP.
examples/configs/user_settings_eccnonblock.h is a worked example.
5. SP — specialised RSA/DH/ECC
These select the fixed-size implementations in sp_c32.c / sp_c64.c (C) and
sp_<arch>.c + sp_<arch>_asm.S (assembly). They are what make RSA, DH and
ECC fast, and sp_int.c handles anything they do not cover. If public key
performance matters to your product, this is the section that will affect it
most.
Algorithms
| Define | Enables | ./configure |
|---|---|---|
WOLFSSL_HAVE_SP_RSA |
SP RSA | --enable-sp with RSA enabled |
WOLFSSL_HAVE_SP_DH |
SP DH | --enable-sp with DH enabled |
WOLFSSL_HAVE_SP_ECC |
SP ECC | --enable-sp with ECC enabled |
Sizes
RSA/DH 2048 and 3072 and ECC P-256 are on by default once the corresponding
WOLFSSL_HAVE_SP_* is defined. Turn them off, or add the others, explicitly:
| Define | Effect |
|---|---|
WOLFSSL_SP_NO_2048 |
Drop RSA/DH 2048 |
WOLFSSL_SP_NO_3072 |
Drop RSA/DH 3072 |
WOLFSSL_SP_4096 |
Add RSA/DH 4096 |
WOLFSSL_SP_NO_256 |
Drop ECC P-256 |
WOLFSSL_SP_384 |
Add ECC P-384 (pair with HAVE_ECC384) |
WOLFSSL_SP_521 |
Add ECC P-521 (pair with HAVE_ECC521) |
WOLFSSL_SP_SM2 |
Add SM2 (sp_sm2_*.c) |
WOLFSSL_SP_1024 |
Add 1024-bit for SAKKE |
Each size costs code space, so on a constrained target enable only the sizes
your protocol actually negotiates. Note that with WOLFSSL_SP_MATH (rather
than WOLFSSL_SP_MATH_ALL), a size you have not compiled in is not merely
slower — it is unavailable, and the operation fails at run time.
WOLFSSL_SP_LARGE_CODE selects larger/faster variants; ./configure sets it
automatically on x86_64 and Aarch64 when WOLFSSL_SP_SMALL is not requested.
ALT_ECC_SIZE dimensions ecc_point from the curve rather than from the
largest key the math was built for. If your build has both RSA and ECC enabled,
your ECC points are otherwise sized for RSA, and defining this is usually the
single largest memory saving available in the math. Measured on the embedded template's default profile
(WOLFSSL_SP_MATH_ALL, ECC-only, 32-bit SP words) built for x86_64, it takes
ecc_point from 436 to 256 bytes and ecc_key from 624 to 384; the saving
scales with how much larger the math is than the curve. It needs a heap: ecc.h rejects it with an #error when
WOLFSSL_NO_MALLOC is set.
Remember to build the digest each curve is used with. P-384 is signed with
SHA-384 and P-521 with SHA-512, and the wolfCrypt test suite reports
BAD_LENGTH_E if that digest is missing from your configuration. See
doc/ALGORITHM_DEFINES.md for the hash options.
Assembly
| Define | CPU | Files |
|---|---|---|
WOLFSSL_SP_X86_64_ASM |
x86_64 | sp_x86_64.c, sp_x86_64_asm.S |
WOLFSSL_SP_ARM64_ASM |
Aarch64 | sp_arm64.c |
WOLFSSL_SP_ARM32_ASM |
ARM32 | sp_arm32.c |
WOLFSSL_SP_ARM_THUMB_ASM |
ARM Thumb | sp_armthumb.c |
WOLFSSL_SP_ARM_CORTEX_M_ASM |
Cortex-M | sp_cortexm.c |
Any of these implies WOLFSSL_SP_ASM. Without one of them, sp_c32.c or
sp_c64.c is compiled instead, chosen by SP_WORD_SIZE.
Only x86_64 needs a separate assembly file. The ARM sp_*.c files carry their
assembly inline, so an ARM project adds a single .c file and no .S — useful
if your toolchain or coding standard makes separate assembly files awkward.
RSA_LOW_MEM implies SP_RSA_PRIVATE_EXP_D and WOLFSSL_SP_SMALL. It performs
RSA private key operations with the plain private exponent instead of the
Chinese Remainder Theorem, which uses considerably less memory but is several
times slower.
None of this applies to the post-quantum algorithms. ML-KEM
(WOLFSSL_HAVE_MLKEM) and ML-DSA (WOLFSSL_HAVE_MLDSA) use polynomial
arithmetic rather than big-number math, so no SP define affects them. They are
accelerated through the per-algorithm assembly in section 6 instead:
wc_mlkem_asm.S and wc_mldsa_asm.S under USE_INTEL_SPEEDUP, and
armv8-mlkem-asm.S and armv8-32-mlkem-asm.S under WOLFSSL_ARMASM.
6. Per-algorithm assembly
These are independent of the math axes above, and are enabled per CPU family. They accelerate the symmetric algorithms, hashes and post-quantum algorithms rather than the public key math.
Intel (x86_64 and x86)
| Define | Effect | ./configure |
|---|---|---|
WOLFSSL_AESNI |
AES-NI for AES-CBC/ECB/CTR, key expansion, GCM, XTS | --enable-aesni |
USE_INTEL_SPEEDUP |
All Intel speedups: AES-NI plus AVX/AVX2 SHA-2, SHA-3, ChaCha20, Poly1305, X25519, ML-KEM, ML-DSA, FrodoKEM, SM3 | --enable-intelasm |
USE_INTEL_SPEEDUP_FOR_AES |
AVX acceleration for AES only | --enable-aesni-with-avx |
AES_GCM_AESNI_NO_UNROLL |
Smaller AES-GCM assembly | --enable-aesni=small |
HAVE_INTEL_AVX1 / HAVE_INTEL_AVX2 |
Select instruction set. Auto-defined by the x86_64 SP defines; NO_AVX2_SUPPORT suppresses AVX2. |
— |
WOLFSSL_X86_64_BUILD / WOLFSSL_X86_BUILD |
64-/32-bit x86 target. Must also reach the assembler. | — |
USE_INTEL_SPEEDUP implies WOLFSSL_AESNI. Instruction selection happens at
run time through cpuid.c, so a binary built with these defines still runs on
processors that lack the instructions. The exception is code compiled with
-maes, -msse4 or -mpclmul, which the compiler may then use unconditionally;
autotools adds those flags for the intrinsics in AES key setup. For
kernel-module builds, WC_C_DYNAMIC_FALLBACK keeps a C path available.
ARM
| Define | Effect |
|---|---|
WOLFSSL_ARMASM |
Master switch: AES, SHA-256, SHA-512, SHA-3, ChaCha20, Poly1305, Curve25519, ML-KEM, FrodoKEM assembly from port/arm/ |
WOLFSSL_ARMASM_INLINE |
Use the *_asm_c.c inline-assembly variants instead of the .S files. Needed when the toolchain will not assemble .S, and used for FIPS on ARMv7. |
WOLFSSL_ARMASM_NO_HW_CRYPTO |
No ARMv8 Crypto Extensions (no AES/SHA instructions) |
WOLFSSL_ARMASM_NO_NEON |
No NEON |
WOLFSSL_ARMASM_THUMB2 |
Thumb-2 encoding (Cortex-M, ARMv7-M) |
WOLFSSL_ARM_ARCH=<n> |
Architecture level: 4, 6, 7… Gates instruction availability. |
WOLFSSL_AARCH64_BUILD |
Aarch64 target |
WOLFSSL_ARMASM_CRYPTO_SHA512 and WOLFSSL_ARMASM_CRYPTO_SHA3 |
Use the Aarch64 SHA-512 / SHA-3 instructions (ARMv8.2+). ./configure sets the pair together from --enable-armasm=sha512-crypto or sha3-crypto. |
WOLFSSL_ARMASM_CRYPTO_SM3 / _SM4 |
Use the Aarch64 SM3 / SM4 instructions |
WOLFSSL_ARMASM_SHA256_SMALL |
Smaller 32-bit ARM SHA-256 |
WOLFSSL_ARMASM_AES_BLOCK_INLINE |
32-bit ARM AES block-function inlining |
WOLFSSL_ARMASM_BARRIER_SB / _BARRIER_DETECT |
Use the SB speculation barrier (ARMv8.5+) / detect it at run time |
WOLFSSL_AARCH64_NO_SQRDMLSH |
Target lacks SQRDMLSH |
Which defines for which ARM architecture
ARM spans three profiles and many architecture versions, and the correct selection differs between them. Find your core here.
32-bit (AArch32) — the SP tier column is the inline sp_int.c assembly,
and the SP asm column is the specialised implementation:
| Architecture | Typical cores | SP tier | SP asm | Per-algorithm assembly |
|---|---|---|---|---|
| ARMv4, ARMv5 | ARM7TDMI, ARM9 | WOLFSSL_SP_ARM32 |
WOLFSSL_SP_ARM32_ASM |
WOLFSSL_ARMASM with WOLFSSL_ARM_ARCH 4, WOLFSSL_ARMASM_NO_NEON, WOLFSSL_ARMASM_NO_HW_CRYPTO |
| ARMv6 | ARM11, Raspberry Pi 1/Zero | WOLFSSL_SP_ARM32 |
WOLFSSL_SP_ARM32_ASM |
as above with WOLFSSL_ARM_ARCH 6 |
| ARMv6-M | Cortex-M0, M0+, M1 | WOLFSSL_SP_ARM_THUMB |
WOLFSSL_SP_ARM_THUMB_ASM |
none available — see below |
| ARMv7-M, ARMv7E-M | Cortex-M3, M4, M7 | WOLFSSL_SP_ARM_CORTEX_M |
WOLFSSL_SP_ARM_CORTEX_M_ASM |
WOLFSSL_ARMASM with WOLFSSL_ARMASM_THUMB2, WOLFSSL_ARM_ARCH 7, WOLFSSL_ARMASM_NO_NEON, WOLFSSL_ARMASM_NO_HW_CRYPTO |
| ARMv8-M baseline | Cortex-M23 | WOLFSSL_SP_ARM_THUMB |
WOLFSSL_SP_ARM_THUMB_ASM |
none available — see below |
| ARMv8-M mainline | Cortex-M33, M35P, M55, M85 | WOLFSSL_SP_ARM_CORTEX_M |
WOLFSSL_SP_ARM_CORTEX_M_ASM |
as ARMv7-M |
| ARMv7-R, ARMv8-R | Cortex-R4 to R8, R52 | WOLFSSL_SP_ARM32 |
WOLFSSL_SP_ARM32_ASM |
WOLFSSL_ARMASM with WOLFSSL_ARM_ARCH 7; NEON if the core has it |
| ARMv7-A | Cortex-A5 to A17 | WOLFSSL_SP_ARM32 |
WOLFSSL_SP_ARM32_ASM |
WOLFSSL_ARMASM with WOLFSSL_ARM_ARCH 7; NEON usually present, no crypto extensions |
| ARMv8-A in 32-bit mode | Cortex-A32, or A53/A72 built for AArch32 | WOLFSSL_SP_ARM32 |
WOLFSSL_SP_ARM32_ASM |
WOLFSSL_ARMASM with WOLFSSL_ARM_ARCH 7; crypto extensions available, so omit WOLFSSL_ARMASM_NO_HW_CRYPTO |
Points that catch people out:
- Cortex-M0, M0+, M1 and Cortex-M23 are Thumb-1 (ARMv6-M / ARMv8-M
baseline), not Thumb-2. Use the
WOLFSSL_SP_ARM_THUMBpair, and do not defineWOLFSSL_ARMASM_THUMB2. wolfSSL ships no Thumb-1 per-algorithm assembly —wolfcrypt/src/port/arm/contains onlyarmv8-*andthumb2-*files — so on these cores you get the SP acceleration but the C implementations of AES, SHA and the rest. - Cortex-M3 has no
UMAAL.settings.hdetects this through__ARM_ARCH_7M__and definesWOLFSSL_SP_NO_UMAALfor you whenWOLFSSL_SP_ARM_CORTEX_M_ASMis set. Define it by hand for any other core that lacks the instruction. UDIVis not universal in ARM mode. SeeWOLFSSL_SP_ARM32_UDIVin section 4 before enabling it.- Cortex-R is a real-time profile but assembles as ARMv7. Use the ARM32
defines with
WOLFSSL_ARM_ARCH 7.
64-bit (AArch64). All of these use WOLFSSL_SP_ARM64,
WOLFSSL_SP_ARM64_ASM, WOLFSSL_AARCH64_BUILD and WOLFSSL_ARMASM. What
changes with the architecture version is the instruction groups you can add:
| Architecture | Typical cores | Add | Compiler flag |
|---|---|---|---|
| ARMv8-A | Cortex-A53, A57, A72, A73 | nothing beyond the base set | -mcpu=generic+crypto |
| ARMv8.2-A and later | Cortex-A55, A75, A76, A78, Neoverse N1 | WOLFSSL_ARMASM_CRYPTO_SHA512 and WOLFSSL_ARMASM_CRYPTO_SHA3, which ./configure sets as a pair |
-march=armv8.2-a+crypto+sha3 |
| ARMv8.2-A with the SM extensions | cores implementing FEAT_SM3 / FEAT_SM4 | WOLFSSL_ARMASM_CRYPTO_SM3, WOLFSSL_ARMASM_CRYPTO_SM4 |
-march=armv8.2-a+crypto+sm4 — one +sm4 covers both |
| ARMv8.5-A and later | Cortex-A710, Neoverse V2 | WOLFSSL_ARMASM_BARRIER_SB, or WOLFSSL_ARMASM_BARRIER_DETECT to test for it at run time |
-march=armv8.5-a, which you supply yourself |
| SVE or SME capable | Neoverse V1/V2 and later, Apple M4 | WOLFSSL_FRODOKEM_SVE, WOLFSSL_FRODOKEM_SME for FrodoKEM matrix work; both are selected at run time |
-march=armv9-a+sve, which you supply yourself |
| Apple silicon | M1 to M4 | SHA-512 and SHA-3 instructions are enabled by default on Darwin | — |
Further AArch64 options:
| Define | Effect |
|---|---|
WOLFSSL_AARCH64_NO_SQRDMLSH |
The target lacks SQRDMLSH. ./configure sets this whenever it selects the plain -mcpu=generic+crypto baseline |
WOLFSSL_AARCH64_PRIVILEGE_MODE |
Detect CPU features at run time by reading the ID registers (ID_AA64ISAR0_EL1, ID_AA64PFR0_EL1, ID_AA64PFR1_EL1) with mrs. Reading them needs a privileged exception level, so settings.h auto-defines it only for kernel-module builds — inside #ifdef WOLFSSL_LINUXKM — on Aarch64. See the note below |
WOLFSSL_ARMASM_NEON_NO_TABLE_LOOKUP |
Avoid NEON table lookups in AES, which removes a data-dependent memory access pattern |
WOLFSSL_ARMASM_AES_BLOCK_INLINE |
32-bit ARM only: inline the AES block function |
WOLFSSL_ARMASM_SHA256_SMALL |
32-bit ARM only: smaller SHA-256 |
Without WOLFSSL_AARCH64_PRIVILEGE_MODE there is no run-time detection on
Aarch64 at all: cpuid.c sets its feature flags from what the build was
compiled for, taking WOLFSSL_ARMASM_NO_NEON, WOLFSSL_ARMASM_NO_HW_CRYPTO,
WOLFSSL_ARMASM_CRYPTO_SHA512 and the rest at face value. That is the right
behaviour for a fixed target, but it does mean your -march and
WOLFSSL_ARMASM_* settings must actually match the hardware — nothing checks.
Set the define by hand only where your code runs privileged enough to read the
ID registers, such as a bare-metal build at EL1 or above.
You must also tell the compiler about the instructions, with flags such as
-march=armv8.2-a+crypto+sha3, -mcpu=generic+crypto, -mfpu=neon and
-mstrict-align as appropriate for your core. ./configure adds these for you;
in a hand-written build you need to supply them yourself.
RISC-V (64-bit)
WOLFSSL_RISCV_ASM enables AES, SHA-256, SHA-512, SHA-3, ChaCha20 and Poly1305
assembly from port/riscv64/. Then add the defines for whichever extensions
your hardware implements:
| Define | Extension |
|---|---|
WOLFSSL_RISCV_BASE_BIT_MANIPULATION |
Zbb (REV8) |
WOLFSSL_RISCV_BASE_ADDRESS |
Zba (SH2ADD) |
WOLFSSL_RISCV_CARRYLESS |
Zbc/Zbkc (CLMUL, CLMULH) — reported only, see below |
WOLFSSL_RISCV_BIT_MANIPULATION |
Zbkb (PACK, REV8). ./configure also sets the Zbb define alongside it; nothing in the library derives one from the other, so in a hand-written build set WOLFSSL_RISCV_BASE_BIT_MANIPULATION yourself as well |
WOLFSSL_RISCV_BIT_MANIPULATION_TERNARY |
Zbt (FSL, FSR, CMOV, CMIX) |
WOLFSSL_RISCV_SCALAR_CRYPTO_ASM |
Zkned — scalar AES and SHA-2 |
WOLFSSL_RISCV_VECTOR |
V — vector extension |
WOLFSSL_RISCV_VECTOR_BASE_BIT_MANIPULATION |
Zvbb/Zvkb (VBREV8) |
WOLFSSL_RISCV_VECTOR_CARRYLESS |
Zvbc (VCLMUL, VCLMULH) |
WOLFSSL_RISCV_VECTOR_GCM |
Zvkg (VGMUL, VGHSH) — reported only, see below |
WOLFSSL_RISCV_VECTOR_CRYPTO_ASM |
Zvkned — vector AES and SHA-2 |
WOLFSSL_RISCV_ASM_INLINE selects the *_asm_c.c inline variants in place of
the .S files, as on ARM. WOLFSSL_RISCV_ASM_NO_UNALIGNED builds the paths
that avoid unaligned loads and stores, for a core that does not permit them.
Three of the defines above are reported but not selective:
WOLFSSL_RISCV_CARRYLESS, WOLFSSL_RISCV_VECTOR_CARRYLESS and
WOLFSSL_RISCV_VECTOR_GCM appear only in the build capability string that
wolfmath.c assembles — no port file consults them. The CLMUL and
VGMUL/VGHSH instructions they name are emitted unconditionally by the
assembly that WOLFSSL_RISCV_VECTOR_CRYPTO_ASM brings in, so it is that
define, not these, which decides whether your hardware needs the extension.
The rest of the table does gate real code.
Take care to enable only the extensions your hardware actually has. Unlike the
Intel options, there is no run-time check: an extension that is not present
produces an illegal-instruction trap at run time rather than a build error.
RISC-V has no specialised SP assembly, so use WOLFSSL_SP_RISCV64 for the
inline tier.
PowerPC
32-bit (port/ppc32/, AES + SHA-256 + SHA-512 + SHA-3):
| Define | Effect |
|---|---|
WOLFSSL_PPC32_ASM |
Master switch |
WOLFSSL_PPC32_ASM_INLINE |
Use *_asm_c.c inline variants |
WOLFSSL_PPC32_ASM_INLINE_REG |
Selects the register-naming inline variant. In a hand-written build this define alone has no effect: compile ppc32-*-asm_cr.c in place of ppc32-*-asm_c.c and assemble with -Wa,-mregnames. |
WOLFSSL_PPC32_ASM_SMALL |
Smaller code |
WOLFSSL_PPC32_ASM_SPE |
Signal Processing Engine |
64-bit (port/ppc64/, same algorithms):
| Define | Effect |
|---|---|
WOLFSSL_PPC64_ASM |
Master switch |
WOLFSSL_PPC64_ASM_INLINE |
Use *_asm_c.c inline variants |
WOLFSSL_PPC64_ASM_SMALL |
Smaller code |
WOLFSSL_PPC64_ASM_CRYPTO |
POWER8 vshasigmaw SHA-256, selected at run time |
WOLFSSL_PPC64_ASM_POWER8 |
POWER8 VSX vrld SHA-3, selected at run time |
The POWER8 variants mark their own sections, so you do not need a global
-mcpu=power8 and the rest of the library stays portable across PowerPC
models.
7. Hardware acceleration and offload
Before working through the assembly options above, check whether your target has a hardware crypto engine. On many microcontrollers and SoCs an on-chip AES or SHA block, or a secure element, will outperform any software implementation and free the CPU entirely — and on a part with a secure element it may also be the only way to keep a key out of main memory.
There are three routes, and they compose with everything in this guide:
| Route | Define | What it covers |
|---|---|---|
| Crypto callbacks | WOLF_CRYPTO_CB |
A generic hook. You register a device with wc_CryptoCb_RegisterDevice() and handle the operations you want; anything you decline falls back to the software path built from the options above. Covers ciphers, hashes, HMAC, CMAC, KDF and public key operations |
| PKCS#11 | HAVE_PKCS11 |
Offload to a PKCS#11 token or HSM. HAVE_PKCS11_STATIC links the module statically instead of loading it at run time |
| Vendor ports | per-port defines | Direct support for a specific device, under wolfcrypt/src/port/ |
The vendor ports cover, among others, Espressif, STM32, Renesas, NXP, Microchip
(ATECC), Silicon Labs, Xilinx, Infineon, Nordic, TI, Cypress/Infineon PSoC,
Raspberry Pi Pico, ARM PSA, Linux kernel crypto (KCAPI), /dev/crypto, and
AF_ALG. Each has its own defines and, usually, its own README under that
directory; see wolfcrypt/src/port/ for the current list.
Two points worth knowing:
- Offload and software assembly are not exclusive. A device that accelerates AES but not ECC is common; enable the offload for AES and the SP assembly from this guide for the ECC.
- Hardware is not automatically faster. For small messages the driver call overhead can exceed the cost of a software implementation, particularly one using the CPU's own crypto instructions. Measure both on your hardware before committing — see section 12.
8. FIPS builds
If you build against a FIPS-validated wolfCrypt module, the options in this guide are constrained. The validated module was certified with a particular implementation of the math, and you cannot substitute another without invalidating the certificate.
What ./configure fixes for you in a FIPS build:
WOLFSSL_SP_INT_NEGATIVEis defined — the FIPS code paths require negative value support in the math.- On 32-bit ARM,
WOLFSSL_ARMASM_INLINEis forced for any FIPS build, so the inline assembly-in-C variants are used rather than the.Sfiles. This applies to the ARMv7-A and ARMv7-M host cases, and the reason given inconfigure.acis a known issue with the assembly code. - The math back end is selected for you; do not override it.
Start from --enable-fips=<version>, or from user_settings_fipsv2.h or
user_settings_fipsv5.h in examples/configs/, and change only what those
leave open. If you need assembly acceleration in a FIPS build, or are unsure
whether a given option is inside the boundary, contact fips@wolfssl.com
before you finalise the configuration.
9. Linux kernel modules
Building wolfSSL as a Linux kernel module (linuxkm/) adds one requirement to
everything above: SIMD and vector registers cannot be used freely in kernel
context, they must be saved and restored around the code that uses them.
linuxkm/linuxkm_wc_port.h detects this for you. When the configuration
enables x86 SIMD, or any of WOLFSSL_ARMASM, WOLFSSL_SP_ARM32_ASM,
WOLFSSL_SP_ARM64_ASM, WOLFSSL_SP_ARM_THUMB_ASM or
WOLFSSL_SP_ARM_CORTEX_M_ASM, it defines WOLFSSL_LINUXKM_SIMD and
WOLFSSL_USE_SAVE_VECTOR_REGISTERS, and raises an #error if the kernel
configuration does not actually support the architecture you asked for.
WC_C_DYNAMIC_FALLBACK is the companion option: it keeps a C implementation
available alongside the accelerated one, so an operation can still complete
when the vector registers are unavailable. ./configure sets it automatically
for kernel-mode builds that enable AES-NI.
10. Toolchains
The assembly in wolfCrypt comes in two forms — separate .S files, and inline
assembly inside C — and toolchains differ in what they accept. This matters
most on embedded ARM, where MDK-ARM and IAR are as common as GCC.
| Toolchain | What to do |
|---|---|
| GCC, Clang | Nothing special. Both forms work as shipped |
| Arm Compiler / Keil MDK | Define WOLFSSL_KEIL. The inline assembly in sp_int.c has a Keil-specific form, and __KEIL__ selects the right __asm/volatile spelling |
| IAR EWARM | No define needed for the spelling — __IAR_SYSTEMS_ICC__ is detected and the asm/volatile keywords adjusted. If the toolchain will not assemble the .S files, use WOLFSSL_ARMASM_INLINE and compile the *_asm_c.c variants instead |
| Visual Studio (MSVC) | Compiles the .asm files rather than the .S; the supplied project files already reference them. Some inline paths need MSVC 2019 or later (_MSC_VER >= 1920) for the 64-bit division intrinsic, and fall back to the half-word implementation otherwise |
A general rule for any toolchain that cannot assemble .S files: ARM, RISC-V
and PowerPC all ship inline assembly-in-C alternatives, selected with
WOLFSSL_ARMASM_INLINE, WOLFSSL_RISCV_ASM_INLINE,
WOLFSSL_PPC32_ASM_INLINE or WOLFSSL_PPC64_ASM_INLINE, and the project then
compiles the matching *_asm_c.c file in place of the .S. Only x86_64 SP has
no inline alternative.
Whichever toolchain you use, the defines must reach the assembler as well as
the compiler when building .S files. See the first row of section 13.
Sample projects for several of these live under IDE/ — IDE/MDK-ARM,
IDE/MDK5-ARM, IDE/IAR-EWARM, IDE/GCC-ARM and others.
11. Recommended configurations
Four starting points, covering the usual trade-offs. Copy the one closest to your situation and adjust from the tables above.
Fastest on a 64-bit server or desktop
#define WOLFSSL_SP_MATH_ALL
#define WOLFSSL_X86_64_BUILD
#define WOLFSSL_SP_X86_64
#define WOLFSSL_SP_X86_64_ASM
#define WOLFSSL_HAVE_SP_RSA
#define WOLFSSL_HAVE_SP_DH
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_384
#define HAVE_ECC384
#define WOLFSSL_AESNI
#define USE_INTEL_SPEEDUP
Aarch64 equivalent: WOLFSSL_AARCH64_BUILD, WOLFSSL_SP_ARM64,
WOLFSSL_SP_ARM64_ASM, WOLFSSL_ARMASM.
Smallest with a heap (Cortex-M4/M7, RAM available)
#define WOLFSSL_SP_MATH_ALL
#define WOLFSSL_SP_SMALL
#define WOLFSSL_SMALL_STACK
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_ARM_CORTEX_M_ASM
#define WOLFSSL_ARMASM
#define WOLFSSL_ARMASM_THUMB2
#define WOLFSSL_ARMASM_NO_HW_CRYPTO
#define WOLFSSL_ARMASM_NO_NEON
#define WOLFSSL_ARM_ARCH 7
Smallest with no heap at all
#define WOLFSSL_SP_MATH /* only the compiled sizes/curves */
#define WOLFSSL_SP_SMALL
#define WOLFSSL_SP_NO_MALLOC
#define WOLFSSL_SP_NO_DYN_STACK /* no C99 VLAs */
#define WOLFSSL_NO_MALLOC
#define WOLFSSL_STATIC_MEMORY
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_NO_2048 /* ECC only — drop the FF sizes */
#define WOLFSSL_SP_NO_3072
With WOLFSSL_SP_NO_MALLOC, every SP temporary lives on the stack. Keep the
enabled key sizes small and measure your worst-case stack usage before
shipping.
Portable C, no assembly anywhere
#define WOLFSSL_SP_MATH_ALL
#define WOLFSSL_NO_ASM
#define TFM_NO_ASM
Use this as your reference build when bringing up a new target, then enable the CPU defines one axis at a time.
Bringing up a new CPU
Enabling everything at once makes a failure hard to attribute, so wolfSSL recommends working up in stages:
- Build with
WOLFSSL_NO_ASMand confirm./wolfcrypt/test/testwolfcryptpasses. This establishes that the port itself is sound. - Add the inline SP define (
WOLFSSL_SP_<arch>) and re-test. If something fails,SP_INT_NO_ASMwill confirm whether the inline assembly is the cause. - Add the specialised SP assembly (
WOLFSSL_SP_<arch>_ASM) if your CPU has it, and re-test. - Add the per-algorithm assembly (
WOLFSSL_ARMASM,WOLFSSL_RISCV_ASMand so on) last, enabling one extension at a time on RISC-V.
Benchmark each step with ./wolfcrypt/benchmark/benchmark so you can see what
each one is worth on your hardware. If you get stuck at any stage, contact
support@wolfssl.com with the defines you used and the output you saw.
12. Verifying and measuring the result
Check what you actually built. Configuration is layered — your defines,
what settings.h derives from them, and what the platform contributes — so the
set that reaches the compiler is rarely exactly the set you wrote. Ask the
preprocessor:
gcc -DWOLFSSL_USER_SETTINGS -I. -Ipath/to/wolfssl -dM -E - \
< /dev/null -include wolfssl/wolfcrypt/settings.h | sort | grep -E \
'WOLFSSL_SP|SP_WORD_SIZE|WOLFSSL_ARMASM|WOLFSSL_AESNI|USE_INTEL'
That prints the defines as the compiler sees them, including everything
settings.h implied, and is the quickest way to confirm that an option you set
took effect — or to find one you did not expect. Use your cross compiler for a
cross build, since much of the derivation depends on the target.
For an autotools build, wolfssl/options.h records the same information.
Note that the HAVE_WC_INTROSPECTION API — wolfSSL_configure_args() and
wolfSSL_global_cflags() — reports the ./configure invocation, so it tells
you nothing useful about a hand-written user_settings.h build.
Then two numbers matter, and both are worth checking on your own hardware rather than assumed from the tables in this guide.
Speed. ./wolfcrypt/benchmark/benchmark reports throughput for every
algorithm compiled in. Run it before and after each change so you can see what
an option is actually worth on your part — the benefit of assembly varies
enormously between cores, and an option that doubles throughput on one target
can be worth almost nothing on another. On an embedded target, define
BENCH_EMBEDDED so the benchmark uses small buffers and short runs.
Size. Build the static library and use your toolchain's size on it, or
on the objects you care about:
size -t src/.libs/libwolfssl.a | tail -1
Comparing that figure across configurations tells you what each option costs. Note that the linker discards what your application does not reference, so the library figure is an upper bound — link your own application to see the number that will ship. wolfSSL also publishes a per-build memory report through the Membrowse tooling used in CI, which breaks a build down by section and symbol.
13. Troubleshooting
Common symptoms and what to do about them.
| Symptom | Cause and resolution |
|---|---|
Assembler errors on .S files |
The defines must reach the assembler, not just the compiler. Autotools uses AM_CCASFLAGS; hand-written builds must pass the same -D flags to the assembler, or use WOLFSSL_USER_SETTINGS_ASM with a user_settings_asm.h generated by user_settings_asm.sh. |
inlining failed in call to 'always_inline' '_mm_aesimc_si128' |
WOLFSSL_AESNI is set but the compiler was not given -maes (and -msse4 -mpclmul on Windows). Some accelerated code is intrinsics, not assembly, so the ISA flags are needed even though the assembly itself is in .S. The ARM equivalent is a missing -march=...+crypto. |
Undefined references to Transform_Sha256_*, AES_GCM_*_aesni, … |
The defines enable a code path whose assembly file is not in the build. With ./configure --enable-usersettings no CFLAGS are added and no --enable-* is inferred from user_settings.h, so the matching --enable-sp-asm/--enable-intelasm/--enable-armasm/… must be given as well. In a hand-built project, add the file. |
Undefined Transform_Sha256_Len_base on a Cortex-M/Thumb build |
The ARM-mode port file was compiled instead of the Thumb-2 one. ./configure selects between armv8-32-* and thumb2-* from the host triple, and a generic arm host gets ARM mode. Select the files in the project build instead. |
| Illegal instruction at run time | An extension define was enabled that the hardware lacks (common on RISC-V and on ARM +crypto). |
| Windows build misses the assembly | Visual Studio compiles the .asm files, not .S. Both exist for every accelerated primitive and are generated from the same source. |
--enable-sp=nonblock rejected |
WOLFSSL_SP_NONBLOCK cannot be combined with the specialised SP assembly. Use the C implementation for non-blocking builds. |
| SP assembly silently not used | SP_WORD_SIZE did not resolve to the value the assembly needs — e.g. WOLFSSL_SP_X86_64 without a 64-bit unsigned long/long long falls back to 32 and undefines WOLFSSL_SP_ASM. |
| Key size or curve fails at run time | WOLFSSL_SP_MATH was used without the size compiled in. Use WOLFSSL_SP_MATH_ALL, or add the size define. |
#error "Size of unsigned long not detected" from sp_int.h |
NO_64BIT on a target whose unsigned long is 64-bit. See the note in section 3; this combination is not supported. |
Undefined sp_ecc_*_256 and similar after setting NO_64BIT |
SP_WORD_SIZE has dropped to 16, and the specialised curves are not implemented at that width. Remove NO_64BIT, or contact support if your target genuinely has no 64-bit type. |
| Stack overflow after enabling SP | WOLFSSL_SP_NO_MALLOC moves everything to the stack. Either raise the stack, add WOLFSSL_SP_SMALL, or switch to WOLFSSL_SMALL_STACK if a heap exists. |
| Build fails on C99 VLAs | Define WOLFSSL_SP_NO_DYN_STACK. |
See also
doc/ALGORITHM_DEFINES.md— the options that select which algorithms are built and how each one is configured.examples/configs/user_settings_embedded.h— an editable template covering both guides.INSTALL— full build instructions for every supported toolchain.wolfcrypt/src/sp_int.c— the complete list of SP build options, in the comment block at the top of the file, including internal defines not described here.wolfssl/wolfcrypt/settings.h— platform detection and implied defines.
For help choosing a configuration for your hardware, or for a build that this guide does not cover, contact support@wolfssl.com.