diff --git a/.github/configs/os-check-linux.json b/.github/configs/os-check-linux.json index 23dfc3a4e24..6b187416899 100644 --- a/.github/configs/os-check-linux.json +++ b/.github/configs/os-check-linux.json @@ -241,7 +241,7 @@ {"name": "no-wolfssl-client", "minutes": 1.0, "configure": ["CPPFLAGS=-DNO_WOLFSSL_CLIENT"]}, {"name": "testwolfcrypt-ca", "minutes": 1.0, - "comment": "user_settings.h builds running only testwolfcrypt: pure crypto, no platform-specific features, so Linux-only coverage is sufficient. Not converted: user_settings_pq.h (requires --enable-experimental) and user_settings_baremetal.h (static memory, custom platform).", + "comment": "user_settings.h builds running only testwolfcrypt: pure crypto, no platform-specific features, so Linux-only coverage is sufficient. Not converted: user_settings_baremetal.h.", "user_settings": "examples/configs/user_settings_ca.h", "cflags": "", "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, @@ -261,6 +261,35 @@ "user_settings": "examples/configs/user_settings_curve25519nonblock.h", "cflags": "", "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-embedded", "minutes": 1.0, + "comment": "Default profile of the embedded template: portable C, SP math all, TLS 1.3 client, ECC P-256 + AES-GCM.", + "user_settings": "examples/configs/user_settings_embedded.h", + "cflags": "", + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-embedded-noheap", "minutes": 1.0, + "comment": "Same template with the no-heap profile (WOLFSSL_NO_MALLOC/WOLFSSL_SP_NO_MALLOC via WC_CFG_HEAP 0), which is the configuration its stack-only constraints apply to.", + "user_settings": "examples/configs/user_settings_embedded.h", + "cflags": "", + "prepare": [["../.github/scripts/set-user-setting.sh", "user_settings.h", "WC_CFG_HEAP=0", "WC_CFG_SMALL_STACK=0"]], + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-embedded-cryptonly", "minutes": 1.0, + "comment": "wolfCrypt-only profile (both TLS versions off), which exercises the WOLFCRYPT_ONLY/NO_TLS path and the derived WC_CFG_TLS.", + "user_settings": "examples/configs/user_settings_embedded.h", + "cflags": "", + "prepare": [["../.github/scripts/set-user-setting.sh", "user_settings.h", "WC_CFG_TLS13=0"]], + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-embedded-spmath", "minutes": 1.0, + "comment": "Restricted SP math (WOLFSSL_SP_MATH) with the assembly off, covering the other math back end and the WC_CFG_ASM_SP 0 path.", + "user_settings": "examples/configs/user_settings_embedded.h", + "cflags": "", + "prepare": [["../.github/scripts/set-user-setting.sh", "user_settings.h", "WC_CFG_MATH_ALL_SIZES=0", "WC_CFG_ASM_SP=0"]], + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-embedded-maxed", "minutes": 1.0, + "comment": "Wide profile: RSA, DH, the extra curves, X25519/Ed25519, ML-KEM and ML-DSA, every digest, ChaCha-Poly and the size knobs off.", + "user_settings": "examples/configs/user_settings_embedded.h", + "cflags": "", + "prepare": [["../.github/scripts/set-user-setting.sh", "user_settings.h", "WC_CFG_SMALL=0", "WC_CFG_RSA=1", "WC_CFG_DH=1", "WC_CFG_ECC_P384=1", "WC_CFG_CURVE25519=1", "WC_CFG_ED25519=1", "WC_CFG_MLKEM=1", "WC_CFG_MLDSA=1", "WC_CFG_SHA224=1", "WC_CFG_SHA3=1", "WC_CFG_CHACHA_POLY=1"]], + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, {"name": "testwolfcrypt-min-ecc", "minutes": 1.0, "user_settings": "examples/configs/user_settings_min_ecc.h", "cflags": "", @@ -273,6 +302,11 @@ "user_settings": "examples/configs/user_settings_pkcs7.h", "cflags": "", "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, +{"name": "testwolfcrypt-pq", "minutes": 1.0, + "comment": "ML-KEM + ML-DSA post-quantum profile. Builds without --enable-experimental; testwolfcrypt runs the ML-DSA KATs.", + "user_settings": "examples/configs/user_settings_pq.h", + "cflags": "", + "configure": ["--enable-usersettings", "--disable-examples"], "check": false, "run": [["wolfcrypt/test/testwolfcrypt"]]}, {"name": "testwolfcrypt-rsa-only", "minutes": 1.0, "user_settings": "examples/configs/user_settings_rsa_only.h", "cflags": "", diff --git a/.github/scripts/set-user-setting.sh b/.github/scripts/set-user-setting.sh new file mode 100755 index 00000000000..c34ee779eec --- /dev/null +++ b/.github/scripts/set-user-setting.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# +# set-user-setting.sh +# +# Set WC_CFG_* switches in a copy of a user_settings.h template, for CI configs +# that build the same template in more than one profile. +# +# Usage: +# set-user-setting.sh NAME=VALUE [NAME=VALUE ...] +# +# Why this exists rather than a sed in the JSON: a `sed -i` matching the whole +# line, interior alignment included, silently does nothing if the template is +# ever re-aligned, and the config then quietly tests the default profile +# instead of the one it names. This matches on the switch name alone and fails +# if a switch is missing, so a rename or a typo is a build failure rather than +# a test that stopped testing anything. + +set -eu + +if [ "$#" -lt 2 ]; then + echo "usage: $0 NAME=VALUE [NAME=VALUE ...]" >&2 + exit 2 +fi + +file=$1 +shift + +[ -f "$file" ] || { echo "$0: no such file: $file" >&2; exit 1; } + +for pair in "$@"; do + case $pair in + *=*) ;; + *) echo "$0: expected NAME=VALUE, got '$pair'" >&2; exit 2 ;; + esac + name=${pair%%=*} + value=${pair#*=} + + # The switch must exist, and exactly once, or the caller's intent is + # already wrong. + count=$(grep -c "^#define ${name}[[:space:]]" "$file" || true) + if [ "$count" != "1" ]; then + echo "$0: '${name}' appears ${count} time(s) in ${file}, expected 1" >&2 + exit 1 + fi + + # Rewrite just the value field, keeping the column the template aligns to + # and any trailing comment on the line. + awk -v n="$name" -v v="$value" ' + $0 ~ "^#define " n "[[:space:]]" { + # prefix = "#define NAME" plus the alignment whitespace + match($0, "^#define[ \t]+" n "[ \t]+") + prefix = substr($0, 1, RLENGTH) + rest = substr($0, RLENGTH + 1) + # drop the old value token, keep whatever follows it + sub("^[^ \t]+", "", rest) + print prefix v rest + next + } + { print } + ' "$file" > "$file.tmp" + mv "$file.tmp" "$file" + + # Confirm it took. + if ! grep -q "^#define ${name}[[:space:]]\+${value}\([[:space:]]\|$\)" \ + "$file"; then + echo "$0: failed to set ${name} to ${value} in ${file}" >&2 + exit 1 + fi +done diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 814001c990c..21e70955733 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -862,6 +862,7 @@ WOLFSSL_HARDEN_TLS_ALLOW_OLD_TLS WOLFSSL_HARDEN_TLS_ALLOW_TRUNCATED_HMAC WOLFSSL_HARDEN_TLS_NO_PKEY_CHECK WOLFSSL_HARDEN_TLS_NO_SCR_CHECK +WOLFSSL_HAVE_KYBER WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY WOLFSSL_I2D_ECDSA_SIG_ALLOC WOLFSSL_IAR_ARM_TIME diff --git a/doc/ALGORITHM_DEFINES.md b/doc/ALGORITHM_DEFINES.md new file mode 100644 index 00000000000..6763f2e0803 --- /dev/null +++ b/doc/ALGORITHM_DEFINES.md @@ -0,0 +1,677 @@ +# Algorithm Build Options + +This guide is for developers deciding which cryptographic algorithms to include +in a wolfSSL build, and how to configure each one. Selecting only what your +product uses is the most effective way to reduce code size and memory, and on a +constrained target it is usually where the largest savings are found. + +It is written for builds that configure wolfSSL through a hand-written +`user_settings.h` and `WOLFSSL_USER_SETTINGS`. Each table also lists the +`./configure` option that produces the same define, so you can reproduce an +autotools build by hand or check what your current one selected. + +`examples/configs/user_settings_embedded.h` is an editable template that wires +most of these options to a block of on/off switches, and is the quickest way to +get a working configuration. + +For the options that select the math back end and the assembly for your +processor, see the companion guide `doc/ASM_AND_MATH_DEFINES.md`. Where an +algorithm has a math or assembly dimension, this guide points there rather than +repeating it. + +## Contents + +1. [How selection works](#1-how-selection-works) +2. [Symmetric ciphers](#2-symmetric-ciphers) +3. [Hashes](#3-hashes) +4. [MAC and KDF](#4-mac-and-kdf) +5. [RSA](#5-rsa) +6. [ECC](#6-ecc) +7. [DH](#7-dh) +8. [Curve25519, Curve448, Ed25519, Ed448](#8-curve25519-curve448-ed25519-ed448) +9. [Post-quantum](#9-post-quantum) +10. [Random number generation](#10-random-number-generation) +11. [Other schemes](#11-other-schemes) +12. [FIPS builds](#12-fips-builds) +13. [Reducing an algorithm to what you use](#13-reducing-an-algorithm-to-what-you-use) +14. [Options that weaken security](#14-options-that-weaken-security) + +--- + +## 1. How selection works + +Two naming conventions run through wolfCrypt. Understanding the difference will +save you time, as mixing them up is the most common configuration mistake. + +* **`HAVE_` / `WOLFSSL_`** turns on something that is **off by + default**. You define it to opt in. +* **`NO_`** turns off something that is **on by default**. You define it + to opt out. + +The point to watch is that a feature's internal flag is often the `HAVE_` form, +while the setting you are meant to change is the `NO_` form. `settings.h` +derives one from the other: + +```c +/* settings.h */ +#ifndef NO_AES_CBC /* you set this */ + #define HAVE_AES_CBC /* the library tests this */ +#endif +``` + +So to remove AES-CBC you define `NO_AES_CBC`. Defining `HAVE_AES_CBC` to `0`, +or simply leaving it out, will not do it. The same pattern governs the ECC +operation flags (`NO_ECC_SIGN` gives `HAVE_ECC_SIGN`, and likewise for +`VERIFY`, `DHE`, `KEY_IMPORT`, `KEY_EXPORT` and `CHECK_KEY`). Whenever a table +below says *default: on*, look for a `NO_` define to switch it off. + +**Where to find the complete list.** This guide covers the options most builds +need. Most algorithm sources also carry a build options block in the comment +header listing every define and its default. Those blocks are the complete +list, are longer than what is summarised here, and are maintained alongside +the code: + +| Algorithm | Block | +| --- | --- | +| AES | top of `wolfcrypt/src/aes.c` | +| ECC | top of `wolfcrypt/src/ecc.c` | +| RSA | top of `wolfcrypt/src/rsa.c` | +| ML-DSA | top of `wolfcrypt/src/wc_mldsa.c` | +| ML-KEM | top of `wolfcrypt/src/wc_mlkem.c` | +| SHA-3 | top of `wolfcrypt/src/sha3.c` | +| SHA-256 | top of `wolfcrypt/src/sha256.c` | +| RNG | top of `wolfcrypt/src/random.c` | +| SP math | top of `wolfcrypt/src/sp_int.c` | + +Refer to those when you need an option this guide does not describe. + +One practical note if you test a `user_settings.h` through autotools: defining +an algorithm here selects the code inside the sources, but it does not add a +source file to the build. `./configure --enable-usersettings` reads no defines +from your header, so pass the matching `--enable-*` as well — otherwise the +algorithm's `.c` file is never compiled and you get undefined references at +link time. `doc/ASM_AND_MATH_DEFINES.md` § 13 covers this and the related +assembly cases. + +--- + +## 2. Symmetric ciphers + +### AES + +Core: + +The Default column describes the **feature**, not the define — "on" means the +feature is present unless you define the `NO_` form. + +| Define | Effect | Feature default | +| --- | --- | --- | +| `NO_AES` | Remove AES entirely | on | +| `NO_AES_128` / `NO_AES_192` / `NO_AES_256` | *remove* a key size | all three on | +| `AES_MAX_KEY_SIZE` | Largest key size in bits. Also gates the sizes above: at 128 the 192 and 256 keys are dropped whether or not you named them | 256 | +| `NO_AES_DECRYPT` | *removes* decryption — suits an encrypt-only device | on | + +`settings.h` turns each of those into the `WOLFSSL_AES_128`/`_192`/`_256` and +`HAVE_AES_DECRYPT` flags the library tests, so the `NO_` forms above are the +ones to set. + +Modes. CBC is the only one on by default; the rest are opt-in: + +| Define | Mode | `./configure` | +| --- | --- | --- | +| `NO_AES_CBC` | *removes* CBC | `--disable-aescbc` | +| `HAVE_AESGCM` | GCM | `--enable-aesgcm` | +| `HAVE_AESCCM` | CCM | `--enable-aesccm` | +| `WOLFSSL_AES_COUNTER` | CTR | `--enable-aesctr` | +| `HAVE_AES_ECB` | ECB — see the caution below | `--enable-aesecb` | +| `WOLFSSL_AES_CFB` / `WOLFSSL_AES_OFB` | CFB / OFB | `--enable-aescfb` / `--enable-aesofb` | +| `WOLFSSL_AES_XTS` | XTS (storage) | `--enable-aesxts` | +| `WOLFSSL_AES_SIV` | AES-SIV (RFC 5297) | `--enable-aessiv` | +| `WOLFSSL_AESGCM_SIV` | AES-GCM-SIV (RFC 8452), nonce-misuse resistant. Requires AES-GCM | `--enable-aesgcm-siv` | +| `WOLFSSL_AES_EAX` | EAX | `--enable-aeseax` | +| `WOLFSSL_AES_CTS` | Ciphertext stealing | `--enable-aescts` | +| `HAVE_AES_KEYWRAP` | Key wrap (RFC 3394) | `--enable-aeskeywrap` | +| `WOLFSSL_AES_DIRECT` | Single-block encrypt/decrypt API. No configure option of its own — define it in `user_settings.h`, or get it as a side effect of an option that needs it, such as `--enable-aesofb` | — | + +For TLS you will want GCM, or CCM on a target where that is preferred; CBC +alone only reaches the older cipher suites. + +As the API documentation notes, ECB is considered less secure in nearly all use +cases, and wolfSSL recommends avoiding it unless you are implementing a +construction that specifically requires the raw block operation. + +`settings.h` pulls in `WOLFSSL_AES_DIRECT` automatically for XTS and CFB, which +call the single-block functions, but not for CTR. The library itself builds +without it; the bundled benchmark application does not, because its CTR +benchmark calls `wc_AesSetKeyDirect`. If you build the benchmark, define +`WOLFSSL_AES_DIRECT` alongside `WOLFSSL_AES_COUNTER`. + +GHASH implementation — pick exactly one, largest and fastest first: + +| Define | Table | Notes | +| --- | --- | --- | +| `GCM_TABLE` | 256-entry | Fastest, largest | +| `GCM_TABLE_4BIT` | 16-entry | The usual compromise | +| `GCM_WORD32` | none, 32-bit words | For CPUs without a fast 64-bit multiply | +| `GCM_SMALL` | none | Smallest, slowest | + +If you define none of them the choice is made for you, but not by `settings.h`: +`aes.h` picks a table on ARM, and otherwise `aes.c` falls through to the +table-less implementation. On a constrained target choose explicitly — the +difference in both size and speed is substantial. + +Size and side channels: + +| Define | Effect | +| --- | --- | +| `WOLFSSL_AES_SMALL_TABLES` | 256-byte tables instead of 4 × 1 kB | +| `WOLFSSL_AES_NO_UNROLL` | Do not unroll the round loop | +| `WOLFSSL_AES_TOUCH_LINES` | Touch every cache line — cache-timing resistance | +| `WC_AES_BITSLICED` | Bitsliced implementation, constant time by construction | +| `AES_GCM_GMULT_NCT` | Non-constant-time GHASH. Faster, weaker | +| `WOLFSSL_AESGCM_STREAM` | Streaming GCM API for data that does not fit in memory | + +Assembly (`WOLFSSL_AESNI`, `USE_INTEL_SPEEDUP`, `WOLFSSL_ARMASM`, …) is in +`doc/ASM_AND_MATH_DEFINES.md` § 6. + +### ChaCha20-Poly1305 + +| Define | Effect | `./configure` | +| --- | --- | --- | +| `HAVE_CHACHA` | ChaCha20 stream cipher | `--enable-chacha` | +| `HAVE_POLY1305` | Poly1305 MAC | `--enable-poly1305` | +| `HAVE_XCHACHA` | XChaCha20, 24-byte nonce | `--enable-xchacha` | +| `HAVE_ONE_TIME_AUTH` | The one-time-auth wrapper TLS uses | — | + +The TLS AEAD cipher suite needs all three of `HAVE_CHACHA`, `HAVE_POLY1305` and +`HAVE_ONE_TIME_AUTH`. On a processor with no AES instructions, ChaCha20-Poly1305 +is usually both faster and smaller than AES-GCM, so it is worth considering as +your primary suite on such targets. + +### Others + +| Define | Algorithm | Notes | +| --- | --- | --- | +| `HAVE_CAMELLIA` | Camellia | | +| `WOLFSSL_SM4` | SM4. Each mode is selected individually with `WOLFSSL_SM4_ECB`, `_CBC`, `_CTR`, `_GCM` or `_CCM`, from `--enable-sm4-ecb` and so on | Chinese national standard | +| `HAVE_ARIA` | ARIA | Needs a third-party `MagicCrypto` source drop | +| `HAVE_ASCON` | ASCON | NIST lightweight standard | +| `NO_DES3` | *removes* 3DES | On by default; obsolete, remove it | +| `NO_DES3_TLS_SUITES` | Removes the 3DES TLS suites while keeping the primitive | | +| `NO_RC4` | *removes* ARC4 | Broken; remove it | + +--- + +## 3. Hashes + +| Define | Hash | Default | +| --- | --- | --- | +| `NO_MD5`, `NO_MD4` | *remove* MD5 / MD4 | on — remove both | +| `NO_SHA` | *removes* SHA-1 | on | +| `NO_SHA256` | *removes* SHA-256 | on | +| `WOLFSSL_SHA224` | SHA-224 | off | +| `WOLFSSL_SHA384` | SHA-384 | off | +| `WOLFSSL_SHA512` | SHA-512 | off | +| `WOLFSSL_NOSHA512_224` / `WOLFSSL_NOSHA512_256` | *remove* SHA-512/224 and SHA-512/256, which come with SHA-512 | on | +| `WOLFSSL_SHA3` | SHA-3 (all four sizes) | off | +| `WOLFSSL_SHAKE128` / `WOLFSSL_SHAKE256` | SHAKE XOFs | off | +| `WOLFSSL_SM3` | SM3 | off | +| `HAVE_BLAKE2B` / `HAVE_BLAKE2S` | BLAKE2 | off | +| `WOLFSSL_RIPEMD` | RIPEMD-160 | off | + +Dependencies to be aware of: + +* **SHA-384 lives in `sha512.c`.** Both are selected by `WOLFSSL_SHA384` and + `WOLFSSL_SHA512` and by nothing else — `sha512.h:32` gates on those two. There + is no `NO_SHA512` to reach for: `settings.h` defines that macro in places but + no library source ever reads it. +* **SHA-224 shares the SHA-256 core.** `settings.h` raises an `#error` if + `WOLFSSL_SHA224` is set with `NO_SHA256`. It costs almost nothing once + SHA-256 is in. +* **Curves imply digests.** P-384 is signed with SHA-384 and P-521 with + SHA-512. If the matching digest is not in your build, the wolfCrypt test + suite reports `BAD_LENGTH_E`. +* **Ed25519 requires `WOLFSSL_SHA512`.** The build stops with an explicit + `#error` if it is missing. +* **ML-KEM and ML-DSA require SHA-3 plus both SHAKEs**, since they are built on + SHAKE. See § 9. +* **TLS 1.3 requires SHA-256.** + +Size: + +| Define | Effect | +| --- | --- | +| `USE_SLOW_SHA`, `USE_SLOW_SHA256`, `USE_SLOW_SHA512` | Loop rather than unroll the compression rounds. `USE_SLOW_SHA256` saves about 2 kB for roughly 25 % of the speed | +| `WOLFSSL_SHA3_SMALL` | Compact SHA-3 | +| `WOLFSSL_SHA256_ALT_CH_MAJ` | Ch/Maj forms some compilers optimise better | +| `SHA256_MANY_REGISTERS` | Keep state in registers, partially unrolled | + +--- + +## 4. MAC and KDF + +| Define | Effect | `./configure` | +| --- | --- | --- | +| `NO_HMAC` | *removes* HMAC | `--disable-hmac` | +| `WOLFSSL_CMAC` | AES-CMAC (RFC 4493). Requires `WOLFSSL_AES_DIRECT` — the CMAC functions are compiled only when it is defined, otherwise `wc_AesCmacGenerate_ex` and `wc_AesCmacVerify_ex` are left undefined at link time | `--enable-cmac` | +| `WOLFSSL_SIPHASH` | SipHash | `--enable-siphash` | +| `HAVE_HKDF` | HKDF — **required by TLS 1.3** | `--enable-hkdf` | +| `NO_PWDBASED` | *removes* the PBKDF family | `--disable-pwdbased` | +| `HAVE_X963_KDF` | ANSI X9.63 KDF, used by ECIES | `--enable-x963kdf` | +| `WOLFSSL_HAVE_PRF` | The TLS PRF | — | + +`NO_PWDBASED` also removes what PKCS#8 and PKCS#12 need in order to decrypt +password-protected key files. That is usually safe to do unless your device +reads such files. + +Password-based KDFs. All of these live inside the `NO_PWDBASED` group, so +`NO_PWDBASED` removes the lot; within that group PBKDF1 and PBKDF2 are both +**on by default** and are removed individually with the `NO_` forms: + +| Define | Effect | Default | `./configure` | +| --- | --- | --- | --- | +| `NO_PBKDF1` | *removes* PBKDF1 (PKCS#5 v1), legacy | on | — | +| `NO_PBKDF2` | *removes* PBKDF2 (PKCS#5 v2). PBKDF2 also needs HMAC, so it is unavailable under `NO_HMAC` regardless | on | — | +| `HAVE_SCRYPT` | scrypt (RFC 7914), memory-hard. Requires PWDBASED | off | `--enable-scrypt` | +| `HAVE_CMAC_KDF` | CMAC-based KDF (SP 800-108). Requires `--enable-kdf` | off | `--enable-cmac-kdf` | + +The `NO_` forms are not absolute: `settings.h` turns `HAVE_PBKDF1` back on for +`WOLFSSL_ENCRYPTED_KEYS`, PKCS#8 or PKCS#12, and `HAVE_PBKDF2` back on for +PKCS#7 or scrypt, because those features need the KDF to work. If you want a +KDF genuinely gone, check that nothing above it is pulling it back in. + +scrypt is memory-hard by design — that is the point of it — so check the +parameters against the RAM you have before enabling it on a small target. + +--- + +## 5. RSA + +As above, the Default column describes the feature. + +| Define | Effect | Feature default | +| --- | --- | --- | +| `NO_RSA` | Remove RSA | on | +| `WOLFSSL_RSA_PUBLIC_ONLY` | Public key operations only | off | +| `WOLFSSL_RSA_VERIFY_ONLY` | Verify only — smallest useful RSA | off | +| `WOLFSSL_RSA_VERIFY_INLINE` | Verify without copying the output | off | +| `WC_RSA_PSS` | RSA-PSS signatures — **required by TLS 1.3** | off | +| `WC_NO_RSA_OAEP` | Remove OAEP padding | off | +| `WC_RSA_NO_PADDING` | Raw, unpadded RSA | off | +| `WC_RSA_DIRECT` | Direct encrypt/decrypt API | off | +| `WOLFSSL_KEY_GEN` | Key generation | off | +| `WOLFSSL_RSA_KEY_CHECK` | Key pair consistency check | off | + +Performance and hardening: + +| Define | Effect | +| --- | --- | +| `WC_RSA_BLINDING` | Blind private key operations. Costs roughly 20 % in speed. **`./configure` sets this for you; a hand-written `user_settings.h` does not — you must define it yourself.** Your key must be associated with an RNG through `wc_RsaSetRNG()`. wolfSSL recommends it on any device holding a long-term private key | +| `RSA_LOW_MEM` | Private operations without CRT: far less memory, several times slower. Implies `SP_RSA_PRIVATE_EXP_D` and `WOLFSSL_SP_SMALL` | +| `WC_RSA_NONBLOCK` | Return and resume rather than block | + +Key sizes come from the SP configuration (`WOLFSSL_SP_NO_2048`, +`WOLFSSL_SP_NO_3072`, `WOLFSSL_SP_4096`) — see +`doc/ASM_AND_MATH_DEFINES.md` § 5. `FP_MAX_BITS` bounds the size under +`USE_FAST_MATH` and is *twice* the key size: RSA-3072 needs `FP_MAX_BITS 6144`. + +--- + +## 6. ECC + +Enable with `HAVE_ECC`. + +Curves. By default every supported size is built, which is rarely what a +product wants. Define `ECC_USER_CURVES` to take control, then opt in to the +curves you need: + +| Define | Curve | +| --- | --- | +| `NO_ECC256` | *removes* P-256, which is otherwise on | +| `HAVE_ECC384`, `HAVE_ECC521` | P-384, P-521 | +| `HAVE_ECC192`, `HAVE_ECC224`, `HAVE_ECC239`, `HAVE_ECC320`, `HAVE_ECC512` | Other sizes | +| `HAVE_ECC112`, `HAVE_ECC128`, `HAVE_ECC160` | Legacy, below any current security floor | +| `HAVE_ECC_BRAINPOOL`, `HAVE_ECC_KOBLITZ`, `HAVE_ECC_SECPR2`, `HAVE_ECC_SECPR3` | Curve families | +| `WOLFSSL_CUSTOM_CURVES` | Allow non-standard curves (carries the curve `a` term) | +| `ECC_MIN_KEY_SZ` | Reject keys below this size | + +The specialised SP implementations are selected separately, with +`WOLFSSL_SP_NO_256`, `WOLFSSL_SP_384` and `WOLFSSL_SP_521`. A curve enabled +here without its SP counterpart still works, but falls back to the generic math +and is markedly slower. See `doc/ASM_AND_MATH_DEFINES.md` § 5. + +Operations are all on by default once `HAVE_ECC` is set. Remove the ones your +product does not perform, using the `NO_` form: + +| Define | Removes | +| --- | --- | +| `NO_ECC_SIGN` | Signing | +| `NO_ECC_VERIFY` | Verification | +| `NO_ECC_DHE` | ECDH shared secret | +| `NO_ECC_KEY_IMPORT` / `NO_ECC_KEY_EXPORT` | Key import / export | +| `NO_ECC_CHECK_PUBKEY_ORDER` | Public key order validation. This is a security check and wolfSSL recommends leaving it enabled | + +`WOLFSSL_ECC_BLIND_K` blinds the private scalar, adding protection against +side-channel recovery of the key at some cost in speed. It needs an RNG. + +Opt-in extras: `HAVE_ECC_ENCRYPT` (ECIES), `HAVE_ECC_CDH` (cofactor DH), +`HAVE_COMP_KEY` (point compression), `WOLFSSL_VALIDATE_ECC_IMPORT` and +`WOLFSSL_VALIDATE_ECC_KEYGEN`. + +Speed and memory: + +| Define | Effect | Default | +| --- | --- | --- | +| `ECC_TIMING_RESISTANT` | Constant-time scalar multiplication | **not automatic — see below** | +| `ECC_SHAMIR` | Shamir's trick for verify: about twice as fast, larger working set | **not automatic — see below** | +| `FP_ECC` | Fixed-point cache. Faster repeat operations, holds a large table for the process lifetime — rarely worth it on a microcontroller. Sized by `FP_ENTRIES` (15) and `FP_LUT` (8) | off | +| `ALT_ECC_SIZE` | Size `ecc_point` from the curve, not from the largest RSA/DH key the math was built for. The single largest avoidable allocation in a build with both. Requires a heap — rejected with `WOLFSSL_NO_MALLOC` | off | +| `WC_ECC_NONBLOCK` | Non-blocking sign/verify/keygen. Needs `WOLFSSL_SP_NONBLOCK` | off | + +**These are not on by default in a hand-written build.** `./configure` defines +`ECC_TIMING_RESISTANT`, `WC_RSA_BLINDING` and `ECC_SHAMIR` for you, and the +algorithm sources describe them as "default: on" on that basis. `settings.h` +only sets them inside platform blocks — Arduino and ESP-IDF — so a +`user_settings.h` build that does not name them gets **none of the three**, +including the two that are side-channel protections. Define them explicitly: + +```c +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING +#define ECC_SHAMIR /* speed, not security */ +``` + +`examples/configs/user_settings_embedded.h` sets all three unconditionally. + +### Other elliptic-curve algorithms + +| Define | Algorithm | `./configure` | +| --- | --- | --- | +| `WOLFSSL_SM2` | SM2 signatures and key exchange. Also pulls in `WOLFSSL_BASE16`. Pair with `WOLFSSL_SM3` and `WOLFSSL_SM4` for the full Chinese suite, and with `WOLFSSL_SP_SM2` for the specialised curve implementation | `--enable-sm2` | +| `WOLFCRYPT_HAVE_ECCSI` | ECCSI (RFC 6507), identity-based signatures | `--enable-eccsi` | +| `WOLFCRYPT_HAVE_SAKKE` | SAKKE (RFC 6508), identity-based key encapsulation. Uses the 1024-bit SP support, so pair it with `WOLFSSL_SP_1024` | `--enable-sakke` | +| `WOLFCRYPT_SAKKE_SMALL` | Smaller, slower SAKKE | `--enable-sakke=small` | + +ECCSI and SAKKE are used together in MIKEY-SAKKE deployments. Both are large +additions; enable them only if your application implements those protocols. + +--- + +## 7. DH + +| Define | Effect | +| --- | --- | +| `NO_DH` | Remove DH — it is on by default | +| `HAVE_FFDHE_2048` / `_3072` / `_4096` / `_6144` / `_8192` | Named finite-field groups (RFC 7919) | +| `HAVE_DH_DEFAULT_PARAMS` | Built-in parameter sets | +| `WOLFSSL_DH_EXTRA` | Key import/export and additional API | +| `HAVE_PUBLIC_FFDHE` | Expose the group parameters | + +**TLS 1.3 will not build with DH enabled and no group named.** The build stops +with `#error Please configure your TLS 1.3 DH key size using either: +HAVE_FFDHE_2048, …`. Choose at least one group, matching the RSA/DH sizes your +SP math was built for. ECDHE is smaller and faster than finite-field DH, so +unless you need to interoperate with a peer that requires DH, you can leave it +disabled. + +--- + +## 8. Curve25519, Curve448, Ed25519, Ed448 + +| Define | Effect | +| --- | --- | +| `HAVE_CURVE25519` | X25519 key agreement | +| `HAVE_ED25519` | Ed25519 signatures. **Requires `WOLFSSL_SHA512`** | +| `HAVE_CURVE448` / `HAVE_ED448` | The 448-bit pair; needs SHAKE256 | +| `CURVE25519_SMALL` / `ED25519_SMALL` | Small, slow implementations for tight targets | +| `WOLFSSL_CURVE25519_BLINDING` | Blind the X25519 scalar against side-channel recovery. **On by default** for the C, non-small build (`settings.h:4711`), needing an RNG; opt out with `NO_CURVE25519_BLINDING`. Unavailable with `CURVE25519_SMALL` — `curve25519.c` rejects the pair — so choosing the small implementation forfeits it | +| `HAVE_ED25519_SIGN` / `_VERIFY` / `_KEY_IMPORT` / `_KEY_EXPORT` | Trim to what is used | +| `WC_X25519_NONBLOCK` | Non-blocking X25519. There is no Ed25519 equivalent — the non-blocking defines are `WC_X25519_NONBLOCK`, `WC_ECC_NONBLOCK`, `WC_RSA_NONBLOCK` and `WC_DH_NONBLOCK` | + +X25519 is a good default on constrained targets. There is one curve and no +parameter choices to make, it is constant time by construction, and it does not +need the SP curve machinery that P-256 does. + +--- + +## 9. Post-quantum + +### ML-KEM (FIPS 203) and ML-DSA (FIPS 204) + +| Define | Effect | `./configure` | +| --- | --- | --- | +| `WOLFSSL_HAVE_MLKEM` | ML-KEM key encapsulation | `--enable-mlkem` | +| `WOLFSSL_HAVE_MLDSA` | ML-DSA signatures | `--enable-mldsa` | +| `WOLFSSL_MLKEM_KYBER` | The original round-3 Kyber instead of FIPS 203 | `--enable-mlkem=original` | + +These algorithms were previously named Kyber and Dilithium, and the older +`HAVE_DILITHIUM` and `--enable-dilithium` spellings remain valid. If you are +updating an existing configuration, `doc/dilithium-to-mldsa-migration.md` lists +every renamed build gate and API. + +**Parameter sets are opt-out.** Defining `WOLFSSL_HAVE_MLKEM` alone builds all +three sets, so each one not wanted must be named: + +| Define | Removes | +| --- | --- | +| `WOLFSSL_NO_ML_KEM_512` / `_768` / `_1024` | An ML-KEM parameter set | +| `WOLFSSL_NO_ML_DSA_44` / `_65` / `_87` | An ML-DSA parameter set | + +This differs from `./configure`, where the parameter sets appear to be opt-in, +so take care when converting an autotools configuration by hand. ML-KEM-768 and +ML-DSA-44 are the widely deployed tiers and are a sensible default. + +Operations and size: + +| Define | Effect | +| --- | --- | +| `WOLFSSL_MLKEM_NO_MAKE_KEY` / `_NO_ENCAPSULATE` / `_NO_DECAPSULATE` | Drop an operation | +| `WOLFSSL_MLDSA_NO_MAKE_KEY` / `_NO_SIGN` / `_NO_VERIFY` | Drop an operation | +| `WOLFSSL_MLDSA_VERIFY_ONLY` | Verify only — the firmware-check case | +| `WOLFSSL_MLDSA_VERIFY_SMALL_MEM` | Stream the verify instead of expanding the key at once | +| `WOLFSSL_MLKEM_SMALL`, `WOLFSSL_MLKEM_NO_LARGE_CODE` | Loop rather than unroll | +| `WOLFSSL_MLDSA_SMALL`, `WOLFSSL_MLDSA_NO_LARGE_CODE` | As above for ML-DSA | +| `WOLFSSL_MLKEM_DYNAMIC_KEYS` | Allocate key buffers to the size actually needed, rather than carrying the largest in the key structure. Reduces handshake memory on constrained systems. **Cannot be used with `WOLFSSL_NO_MALLOC`** | +| `WOLFSSL_MLDSA_NO_ASN1` | No ASN.1 — for builds with no X.509 | + +Both algorithms need `WOLFSSL_SHA3`, `WOLFSSL_SHAKE128` and `WOLFSSL_SHAKE256`, +as they are built on SHAKE. Budget for the SHA-3 code when sizing a +post-quantum build. + +Neither uses the big-number math, so none of the SP options affect them. They +are accelerated through the per-algorithm assembly instead — see +`doc/ASM_AND_MATH_DEFINES.md` § 6. + +### Falcon and FrodoKEM + +Both are native implementations with no liboqs dependency, and both currently +require `--enable-experimental`. + +| Define | Effect | `./configure` | +| --- | --- | --- | +| `HAVE_FALCON` | Falcon signatures | `--enable-falcon` | +| `WOLFSSL_FALCON_FPR_ASM`, `WOLFSSL_FALCON_FPR_DOUBLE` | Floating-point back end for the FFT: assembly, or the C double implementation | `--enable-falcon=asm,double` | +| `WOLFSSL_FALCON_FFT_AVX2`, `WOLFSSL_FALCON_FFT_NEON` | Vectorised FFT on x86_64 and Aarch64 | `--enable-falcon=avx2,neon` | +| `WOLFSSL_FALCON_SIGN_SMALL_MEM` | Low-memory signing | `--enable-falcon=small-mem` | +| `WOLFSSL_HAVE_FRODOKEM` | FrodoKEM key encapsulation | `--enable-frodokem` | +| `WOLFSSL_NO_FRODOKEM_640` / `_976` / `_1344` | Remove a parameter set — at least one must remain | | +| `WOLFSSL_FRODOKEM_SHAKE` / `WOLFSSL_FRODOKEM_AES` | Matrix generation method — at least one is required | `--enable-frodokem-shake` / `-aes` | +| `WOLFSSL_FRODOKEM_NO_MAKE_KEY` / `_NO_ENCAPSULATE` / `_NO_DECAPSULATE` | Drop an operation — at least one must remain | | +| `WOLFSSL_FRODOKEM_EPHEMERAL` | eFrodoKEM (ephemeral, salt-less) variants | `--enable-frodokem-ephemeral` | +| `WOLFSSL_FRODOKEM_SMALL` | Looped rather than unrolled matrix arithmetic | `--enable-frodokem=small` | +| `WOLFSSL_FRODOKEM_SVE` / `WOLFSSL_FRODOKEM_SME` | Aarch64 SVE and SME matrix acceleration | `--enable-frodokem-sve` / `-sme` | + +FrodoKEM is conservative by design and its keys and ciphertexts are far larger +than ML-KEM's, so it is usually chosen for a specific compliance requirement +rather than for general use. ML-KEM is the better default. + +### Stateful hash-based signatures + +| Define | Effect | +| --- | --- | +| `WOLFSSL_HAVE_LMS` | LMS/HSS (RFC 8554) | +| `WOLFSSL_HAVE_XMSS` | XMSS/XMSS^MT (RFC 8391) | +| `WOLFSSL_HAVE_SLHDSA` | SLH-DSA (FIPS 205), stateless | + +LMS and XMSS suit firmware verification well: verification is inexpensive and +the public key is small. They are **stateful**, meaning a signing key must never +reuse an index. That makes them an excellent fit for a device that only +verifies, and a demanding one for a device that signs, since you become +responsible for persisting the signing state reliably. + +--- + +## 10. Random number generation + +This is the most important section to get right on a bare-metal port. A weak or +repeating entropy source undermines every key the device generates, and it does +so silently. + +| Define | Effect | +| --- | --- | +| `HAVE_HASHDRBG` | Hash-based DRBG (SP 800-90A). On by default and what you want | +| `WC_NO_HASHDRBG` | Use the raw source directly, no DRBG | +| `WC_NO_RNG` | No RNG at all. Only for a build that performs no operation needing randomness | +| `CUSTOM_RAND_GENERATE_SEED` | Your seed function — the usual bare-metal hook | +| `CUSTOM_RAND_GENERATE_BLOCK` | Your full block generator, e.g. a hardware RNG | +| `WC_RNG_SEED_CB` | Register the seed source at run time instead | +| `HAVE_ENTROPY_MEMUSE` | Memory-use based entropy where no hardware source exists | +| `HAVE_INTEL_RDRAND` | Seed from the Intel `RDRAND` instruction | +| `HAVE_INTEL_RDSEED` | Seed from the Intel `RDSEED` instruction | +| `HAVE_AMD_RDSEED` | Seed from the AMD `RDSEED` instruction | +| `WOLFSSL_GENSEED_FORTEST` | **Deterministic stub. Bring-up only — never ship it** | + +On x86 and x86_64, `RDRAND` and `RDSEED` give you an on-chip entropy source +with no operating system involvement, which is often the simplest answer for a +bare-metal build on those parts. They depend on the CPUID feature detection, +which `cpuid.h` compiles only when one of `WOLFSSL_X86_64_BUILD`, +`USE_INTEL_SPEEDUP`, `WOLFSSL_AESNI` or `WOLFSSL_SP_X86_64_ASM` is defined and +`WOLFSSL_NO_ASM` is not. Enabling `HAVE_INTEL_RDRAND` in a build without one of +those leaves `IS_INTEL_RDRAND` and `cpuid_get_flags_ex` undeclared. + +On a target with no operating system and no `/dev/random`, define +`NO_DEV_RANDOM` and supply entropy through one of the hooks above, or implement +`wc_GenerateSeed()` in your port. If you do neither, the build stops with +`#error "you need to write an os specific wc_GenerateSeed() here"`. wolfSSL +raises that error deliberately rather than fall back to a predictable source, so +treat it as a prompt to connect a real entropy source on your hardware. + +--- + +## 11. Other schemes + +| Define | Scheme | `./configure` | +| --- | --- | --- | +| `HAVE_HPKE` | Hybrid Public Key Encryption (RFC 9180). Pulls in HKDF, and needs a KEM — ECC or Curve25519 | `--enable-hpke` | +| `WOLFCRYPT_HAVE_SRP` | SRP password-authenticated key exchange (RFC 5054) | `--enable-srp` | +| `HAVE_PKCS7` | PKCS#7 / CMS signing and enveloping, used for firmware signing and S/MIME | `--enable-pkcs7` | + +HPKE is what wolfSSL's Encrypted Client Hello support is built on, so enable it +if you need ECH. + +--- + +## 12. FIPS builds + +If you are building against a FIPS-validated wolfCrypt module, the choices in +this guide narrow considerably. The validated module has a fixed algorithm +boundary, and you cannot add an algorithm to it or replace one of its +implementations without invalidating the certificate. + +In practice: + +* The algorithm set is determined by the FIPS module you have, not by these + defines. Options that remove an algorithm inside the boundary should not be + used. +* Non-FIPS algorithms can still be built alongside the module, but they sit + outside the boundary and cannot be used for FIPS-approved operations. +* `./configure` selects the correct settings for your module from + `--enable-fips=`. Start from that, and from the matching template in + `examples/configs/` — `user_settings_fipsv2.h` or `user_settings_fipsv5.h` — + rather than assembling a FIPS configuration by hand. + +`doc/ASM_AND_MATH_DEFINES.md` § 8 covers what a FIPS build fixes on the math and +assembly side. If you are planning a FIPS build, contact **fips@wolfssl.com** +before finalising your configuration. + +--- + +## 13. Reducing an algorithm to what you use + +Beyond choosing algorithms, the largest remaining savings come from removing +operations your device never performs. A device that verifies firmware does not +sign; a sensor that only encrypts telemetry does not decrypt. + +| What the device does | Defines | +| --- | --- | +| Verify signatures only (ECC) | `NO_ECC_SIGN`, `NO_ECC_DHE`, `NO_ECC_KEY_EXPORT` | +| Verify signatures only (RSA) | `WOLFSSL_RSA_VERIFY_ONLY`, `WOLFSSL_RSA_PUBLIC_ONLY` | +| Verify signatures only (ML-DSA) | `WOLFSSL_MLDSA_VERIFY_ONLY`, `WOLFSSL_MLDSA_VERIFY_SMALL_MEM` | +| Encrypt only | `NO_AES_DECRYPT` | +| No key generation | leave `WOLFSSL_KEY_GEN` undefined; `WOLFSSL_MLKEM_NO_MAKE_KEY`, `WOLFSSL_MLDSA_NO_MAKE_KEY` | + +Two points to bear in mind when you do this. + +**The TLS layer needs the full set of operations.** Once `HAVE_ECC` is defined, +the TLS code references ECC signing unconditionally, so a verify-only ECC build +will not link against TLS — not even a PSK-only one. Reductions of this kind +belong in wolfCrypt-only builds, or in a TLS build where the reduced algorithm +is not the one TLS uses. + +**The bundled test application exercises the full API.** +`wolfcrypt/test/testwolfcrypt` signs as well as verifies, so a verify-only build +will report a failure there: `WOLFSSL_RSA_VERIFY_ONLY` produces `RSA test +failed!` with error `-231`, *Signature type not enabled/available*. This is the +test application exercising an operation you have deliberately removed, and does +not indicate a problem with your build. Similarly, a `NO_ASN` build does not +compile the test application at all, as it uses the ASN.1 API unconditionally. +Build `src/libwolfssl.la` on its own to check such configurations, and validate +them against your own application instead. + +--- + +## 14. Options that weaken security + +Several options in this guide and its companion buy speed or size by giving up +a protection. Each is reasonable in the right circumstances and wrong in most, +so they are collected here as a single list to check a configuration against +before it ships. + +| Option | What you give up | +| --- | --- | +| `WC_NO_HARDEN` | Constant-time modular exponentiation in `sp_int.c`. It also silences the build warning that would otherwise tell you a build lacks hardening, so a configuration carrying it will not warn you about the other omissions below | +| `WC_NO_CACHE_RESISTANT` | Cache-resistant, constant-address table access | +| `WOLFSSL_NO_CT_OPS` | Constant-time helper operations | +| `USE_INTEGER_HEAP_MATH` | The `integer.c` back end is not timing resistant | +| `USE_FAST_MATH` without `TFM_TIMING_RESISTANT` | Timing resistance in the fastmath back end | +| `HAVE_ECC` without `ECC_TIMING_RESISTANT` | Constant-time ECC scalar multiplication. Not automatic in a hand-written build — see § 6 | +| RSA without `WC_RSA_BLINDING` | Blinding of RSA private key operations. Not automatic in a hand-written build — see § 5 | +| `WOLFSSL_SP_FAST_NCT_EXPTMOD` | Constant-time modular exponentiation. Intended for public key operations only, where the exponent is not secret | +| `AES_GCM_GMULT_NCT` | Constant-time GHASH | +| `NO_ECC_CHECK_PUBKEY_ORDER` | Validation of the order of a received public key | +| `NO_RSA_BOUNDS_CHECK` | Bounds checking on RSA input | +| `WC_RSA_NO_PADDING` | RSA padding. Raw RSA is only safe inside a scheme that provides its own padding | +| `WOLFSSL_GENSEED_FORTEST` | A real entropy source. This is a deterministic stub for bring-up and must never ship | +| `WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS` | Blinding, when `WC_NO_RNG` has removed the RNG it depends on. `settings.h` raises an `#error` precisely so that this cannot happen silently | + +wolfSSL leaves the first several on by default, and `settings.h` emits a build +warning when a configuration is missing them — *"For timing resistance / +side-channel attack prevention consider using harden options"*. If you see that +warning, treat it as a finding rather than noise. + +If any of these appear in a product configuration, it is worth recording why. +For a review of a configuration before release, contact +**support@wolfssl.com**. + +## See also + +* `doc/ASM_AND_MATH_DEFINES.md` — math back end, SP configuration and per-CPU + assembly. +* `examples/configs/user_settings_embedded.h` — an editable template covering + both guides. +* `examples/configs/README.md` — the full set of configuration templates, + including profiles for TLS 1.3, DTLS, bare metal and post-quantum. +* `INSTALL` — full build instructions for every supported toolchain. + +If you are unsure which algorithms your product needs, or want a configuration +reviewed before you ship it, contact **support@wolfssl.com**. diff --git a/doc/ASM_AND_MATH_DEFINES.md b/doc/ASM_AND_MATH_DEFINES.md new file mode 100644 index 00000000000..70d2794a3f7 --- /dev/null +++ b/doc/ASM_AND_MATH_DEFINES.md @@ -0,0 +1,850 @@ +# 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 `#define`s 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 + +1. [The three independent axes](#1-the-three-independent-axes) +2. [Per-CPU quick reference](#2-per-cpu-quick-reference) +3. [Math back end](#3-math-back-end) +4. [`sp_int.c` — generic multi-precision math](#4-sp_intc--generic-multi-precision-math) +5. [SP — specialised RSA/DH/ECC](#5-sp--specialised-rsadhecc) +6. [Per-algorithm assembly](#6-per-algorithm-assembly) +7. [Hardware acceleration and offload](#7-hardware-acceleration-and-offload) +8. [FIPS builds](#8-fips-builds) +9. [Linux kernel modules](#9-linux-kernel-modules) +10. [Toolchains](#10-toolchains) +11. [Recommended configurations](#11-recommended-configurations) +12. [Verifying and measuring the result](#12-verifying-and-measuring-the-result) +13. [Troubleshooting](#13-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_` (inline) and `WOLFSSL_SP__ASM` (specialised) | `sp_int.c`, `sp_.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//*` | + +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_`** (no `_ASM` suffix) — *inline* assembly macros inside + `sp_int.c` for 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 + internal `SP_INT_ASM_AVAILABLE`. +* **`WOLFSSL_SP__ASM`** — the *specialised* fixed-size implementations in + `sp_.c`. Only x86_64 adds a separate `sp_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__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__ASM` does not turn off the inline +`WOLFSSL_SP_`, 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=` | +| 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__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_`) only. + `./configure --enable-sp-asm` errors out on unsupported CPUs. +* On x86_64, `WOLFSSL_SP_X86_64_ASM` is not supported for Windows hosts built + with MinGW/Cygwin. Use the C SP implementation there. MSVC builds use the + `.asm` files from the Visual Studio project instead. +* `WOLFSSL_SP_X86_64` (or `_ASM`) also auto-defines `HAVE_INTEL_AVX1`, and + `HAVE_INTEL_AVX2` unless `NO_AVX2_SUPPORT` is 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` — force `32` or `64`. Normally derived automatically from the + CPU define (see `sp_int.h`); set it explicitly only when the default is wrong + for the target. +* `WOLFSSL_SP_DIV_32` — do not use 64-bit divides (implies + `WOLFSSL_SP_DIV_WORD_HALF`). For CPUs without a hardware 64/32 divide. +* `NO_64BIT` — for a target with no 64-bit integer type. This drops + `SP_WORD_SIZE` to 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 whose `unsigned long` is 32-bit or + smaller; on a 64-bit host the size-detection chain in `sp_int.h` reports + `#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_ALL` so 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 the `UDIV` instruction for word division. + Thumb-2 cores have `UDIV` from 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 no `UMAAL`. Set automatically for + Cortex-M3 (`WOLFSSL_ARM_ARCH_7M`) when `WOLFSSL_SP_ARM_CORTEX_M_ASM` is + 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_.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_.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 with `WOLFSSL_SP_SMALL` and + restricted key sizes so the stack frames stay bounded), plus + `WOLFSSL_NO_MALLOC` / `WOLFSSL_STATIC_MEMORY` for 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_.c` + `sp__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=` | 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_THUMB` pair, and do **not** + define `WOLFSSL_ARMASM_THUMB2`. wolfSSL ships no Thumb-1 per-algorithm + assembly — `wolfcrypt/src/port/arm/` contains only `armv8-*` and `thumb2-*` + 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.h` detects this through + `__ARM_ARCH_7M__` and defines `WOLFSSL_SP_NO_UMAAL` for you when + `WOLFSSL_SP_ARM_CORTEX_M_ASM` is set. Define it by hand for any other core + that lacks the instruction. +* **`UDIV` is not universal in ARM mode.** See `WOLFSSL_SP_ARM32_UDIV` in + 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_NEGATIVE` is defined — the FIPS code paths require negative + value support in the math. +* On 32-bit ARM, `WOLFSSL_ARMASM_INLINE` is forced for **any** FIPS build, so + the inline assembly-in-C variants are used rather than the `.S` files. This + applies to the ARMv7-A and ARMv7-M host cases, and the reason given in + `configure.ac` is a known issue with the assembly code. +* The math back end is selected for you; do not override it. + +Start from `--enable-fips=`, 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 + +```c +#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) + +```c +#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 + +```c +#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 + +```c +#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: + +1. Build with `WOLFSSL_NO_ASM` and confirm `./wolfcrypt/test/testwolfcrypt` + passes. This establishes that the port itself is sound. +2. Add the inline SP define (`WOLFSSL_SP_`) and re-test. If something + fails, `SP_INT_NO_ASM` will confirm whether the inline assembly is the cause. +3. Add the specialised SP assembly (`WOLFSSL_SP__ASM`) if your CPU has it, + and re-test. +4. Add the per-algorithm assembly (`WOLFSSL_ARMASM`, `WOLFSSL_RISCV_ASM` and 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**. diff --git a/doc/include.am b/doc/include.am index 0d63432f2f1..182e9aff59c 100644 --- a/doc/include.am +++ b/doc/include.am @@ -6,7 +6,9 @@ dist_doc_DATA+= doc/README.txt \ doc/QUIC.md \ doc/dilithium-to-mldsa-migration.md \ doc/SBOM.md \ - doc/CRA.md + doc/CRA.md \ + doc/ASM_AND_MATH_DEFINES.md \ + doc/ALGORITHM_DEFINES.md dox-pdf: diff --git a/examples/configs/README.md b/examples/configs/README.md index 90358249af6..9fb0123dfc8 100644 --- a/examples/configs/README.md +++ b/examples/configs/README.md @@ -9,6 +9,7 @@ Example wolfSSL configuration file templates for use when autoconf is not availa * `user_settings_arduino.h`: An example Arduino file. See also [wolfSSL/Arduino-wolfSSL](https://github.com/wolfSSL/Arduino-wolfSSL). * `user_settings_EBSnet.h`: Example configuration file for use with EBSnet ports. * `user_settings_eccnonblock.h`: Example for non-blocking ECC crypto only. See comment at top for test results. +* `user_settings_embedded.h`: Embedded profile driven by `WC_CFG_*` on/off switches at the top - target CPU, assembly (big-number and per-algorithm), memory model, math back end, key sizes and TLS. Covers Cortex-M, ARM32/Thumb, Aarch64, RISC-V, PowerPC and x86_64. See [doc/ASM_AND_MATH_DEFINES.md](../../doc/ASM_AND_MATH_DEFINES.md) for what the generated defines do. * `user_settings_espressif.h`: Example configuration for Espressif ESP32. See also [wolfSSL/IDE/Espressif](https://github.com/wolfSSL/wolfssl/tree/master/IDE/Espressif). * `user_settings_fipsv2.h`: The FIPS v2 (3389) 140-2 certificate build options. * `user_settings_fipsv5.h`: The FIPS v5 (ready) 140-3 build options. Equivalent to `./configure --enable-fips=v5-dev`. diff --git a/examples/configs/include.am b/examples/configs/include.am index 4ea3e15fbb9..eb23e7fb041 100644 --- a/examples/configs/include.am +++ b/examples/configs/include.am @@ -10,6 +10,7 @@ EXTRA_DIST += examples/configs/user_settings_curve25519nonblock.h EXTRA_DIST += examples/configs/user_settings_dtls13.h EXTRA_DIST += examples/configs/user_settings_EBSnet.h EXTRA_DIST += examples/configs/user_settings_eccnonblock.h +EXTRA_DIST += examples/configs/user_settings_embedded.h EXTRA_DIST += examples/configs/user_settings_espressif.h EXTRA_DIST += examples/configs/user_settings_fipsv2.h EXTRA_DIST += examples/configs/user_settings_fipsv5.h diff --git a/examples/configs/user_settings_embedded.h b/examples/configs/user_settings_embedded.h new file mode 100644 index 00000000000..957b267cc29 --- /dev/null +++ b/examples/configs/user_settings_embedded.h @@ -0,0 +1,1329 @@ +/* user_settings_embedded.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 + */ + +/* Embedded configuration with CPU, assembly and math selection. + * + * Everything is driven by the WC_CFG_* switches in sections 1 to 8 below. + * Set those; the "derived settings" half of the file turns them into the + * wolfSSL defines and does not normally need editing. + * + * See doc/ASM_AND_MATH_DEFINES.md for what each generated define does and + * which CPUs support which kind of assembly. + * + * Build and test: + * cp ./examples/configs/user_settings_embedded.h user_settings.h + * ./configure --enable-usersettings --disable-examples + * make + * ./wolfcrypt/test/testwolfcrypt + * + * The defaults are portable C, so the recipe above works on a host as-is. + * Set one WC_CFG_CPU_* switch in section 1 for a real target. + * + * Testing an assembly configuration with autotools needs two extra things, + * because --enable-usersettings deliberately adds no CFLAGS of its own: + * - the matching --enable-* option, so the assembly files are added to the + * build at all (--enable-sp-asm, --enable-intelasm, --enable-armasm, + * --enable-riscv-asm, --enable-ppc32-asm, --enable-ppc64-asm); + * - the instruction set flags for the compiler, since some accelerated code + * is written as intrinsics rather than assembly. + * For example: + * x86_64 ./configure --enable-usersettings --disable-examples \ + * --enable-intelasm --enable-sp-asm + * make CFLAGS="-O2 -maes -msse4 -mpclmul" + * Aarch64 ./configure --host=aarch64-linux-gnu --enable-usersettings \ + * --disable-examples --enable-armasm --enable-sp-asm \ + * CFLAGS="-O2 -march=armv8-a+crypto -mstrict-align" + * Autotools picks the ARM-mode port files for a generic "arm" host, so a + * Cortex-M or Thumb profile is best built from the project's own makefile or + * IDE with the file list below rather than through ./configure. + * + * Source files to add to a hand-built project, by CPU (in addition to the + * usual wolfcrypt sources): + * all targets wolfcrypt/src/sp_int.c + * portable 32-bit wolfcrypt/src/sp_c32.c + * portable 64-bit wolfcrypt/src/sp_c64.c + * Cortex-M wolfcrypt/src/sp_cortexm.c + * ARM Thumb wolfcrypt/src/sp_armthumb.c + * ARM32 wolfcrypt/src/sp_arm32.c + * Aarch64 wolfcrypt/src/sp_arm64.c + * x86_64 wolfcrypt/src/sp_x86_64.c, sp_x86_64_asm.S + * The ARM SP files hold their assembly inline in C, so no .S file is needed + * for them. For the per-algorithm assembly add the matching files from + * wolfcrypt/src/port/arm/, port/riscv64/, port/ppc32/ or port/ppc64/ - the + * ".S" variants, or the "_asm_c.c" variants when WC_CFG_ASM_INLINE is set. + */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================= */ +/* 1. TARGET CPU - set exactly one to 1 */ +/* ========================================================================= */ +/* PORTABLE is plain C for any CPU. It ignores section 2 entirely. */ +#define WC_CFG_CPU_PORTABLE 1 +#define WC_CFG_CPU_CORTEX_M 0 /* Cortex-M3/M4/M7/M33 (Thumb-2) */ +#define WC_CFG_CPU_ARM_THUMB 0 /* Thumb: Cortex-M0/M0+/M1/M23 */ +#define WC_CFG_CPU_ARM32 0 /* ARMv4/v6/v7-A, ARM mode */ +#define WC_CFG_CPU_AARCH64 0 /* ARMv8-A 64-bit */ +#define WC_CFG_CPU_RISCV32 0 +#define WC_CFG_CPU_RISCV64 0 +#define WC_CFG_CPU_PPC32 0 +#define WC_CFG_CPU_PPC64 0 +#define WC_CFG_CPU_X86_64 0 /* host builds / simulators */ + +/* ARM architecture level: 4, 6 or 7. Ignored for Aarch64. Set 6 for a + * Thumb-1 core (ARMv6-M / ARMv8-M baseline), which has no Thumb-2 assembly; + * 7 for Thumb-2 (ARMv7-M and later, ARMv7-A, Cortex-R). See + * doc/ASM_AND_MATH_DEFINES.md section 6 for the full per-architecture table. */ +#define WC_CFG_ARM_ARCH 7 + +/* ========================================================================= */ +/* 2. ASSEMBLY */ +/* ========================================================================= */ +/* Master switch. 0 gives pure C everywhere (WOLFSSL_NO_ASM). */ +#define WC_CFG_ASM 1 + +/* Big-number assembly - speeds up RSA, DH and ECC. */ +#define WC_CFG_ASM_SP 1 + +/* Per-algorithm assembly - AES, SHA-2, SHA-3, ChaCha20, Poly1305. */ +#define WC_CFG_ASM_CRYPTO 1 + +/* Set when the toolchain cannot assemble .S files. Uses the inline + * assembly-in-C variants (*_asm_c.c) instead. ARM, RISC-V and PowerPC only. + * This define only tells the sources which form to compile - the project must + * also build the *_asm_c.c files in place of the .S ones. Under autotools + * that means the matching --enable-armasm=inline (or --enable-riscv-asm, + * --enable-ppc32-asm=inline, ...); setting this alone leaves the inline + * bodies compiled out and the .S symbols undefined at link time. */ +#define WC_CFG_ASM_INLINE 0 + +/* --- ARM ---------------------------------------------------------------- */ +/* ARMv8 Crypto Extensions (AES/SHA instructions). Aarch64 and some ARMv8 + * 32-bit cores only. Cortex-M and ARMv7-A and earlier must leave this 0. */ +#define WC_CFG_ARM_HW_CRYPTO 0 +/* NEON. Not present on Cortex-M. */ +#define WC_CFG_ARM_NEON 0 +/* Aarch64 only: use the ARMv8.2 SHA-512 and SHA-3 instructions. */ +#define WC_CFG_ARM_SHA512_CRYPTO 0 +/* Cortex-M (Thumb-2) only: the core has no UMAAL instruction, so use the + * code paths that avoid it. Cortex-M3 is detected automatically; set this by + * hand for any other Thumb-2 core that lacks the instruction. Thumb-1 cores + * (Cortex-M0/M0+/M1, Cortex-M23) are unaffected - their SP implementation + * never emits UMAAL, so this switch does nothing there. */ +#define WC_CFG_ARM_NO_UMAAL 0 +/* The core has a UDIV instruction in the mode being built for, so use the + * word-divide assembly that needs it. Applies to both the ARM32 and Cortex-M + * selections, which share one block in sp_int.c. + * Cortex-M ARMv7-M and later have UDIV, so this is safe on M3 and above. + * ARM mode needs the integer divide extension (ARMv7VE, or + * -march=armv7-a+idiv); a plain ARMv7-A build will not assemble. + * Leave 0 if unsure - the C fallback is used instead. */ +#define WC_CFG_ARM_UDIV 0 + +/* --- RISC-V (64-bit) ---------------------------------------------------- */ +#define WC_CFG_RISCV_BITMANIP 0 /* Zbb / Zbkb */ +#define WC_CFG_RISCV_SCALAR_CRYPTO 0 /* Zkned - AES, SHA-2 */ +#define WC_CFG_RISCV_VECTOR 0 /* V */ +#define WC_CFG_RISCV_VECTOR_CRYPTO 0 /* Zvkned - vector AES, SHA-2 */ +/* No switches for Zbc/Zbkc or Zvkg: WOLFSSL_RISCV_CARRYLESS and + * WOLFSSL_RISCV_VECTOR_GCM select no code - the CLMUL and VGMUL/VGHSH + * instructions come with the vector-crypto assembly itself, and those two + * defines only add text to the build capability string in wolfmath.c. */ + +/* --- PowerPC ------------------------------------------------------------ */ +#define WC_CFG_PPC_SMALL 0 /* smaller PowerPC assembly */ +#define WC_CFG_PPC64_POWER8 0 /* POWER8 SHA-256 / SHA-3 */ + +/* --- hardware offload --------------------------------------------------- */ +/* Route operations to a crypto engine or secure element through the crypto + * callback layer (wolfcrypt/src/cryptocb.c). This is the third option beside + * plain C and assembly, and is independent of both: register a device with + * wc_CryptoCb_RegisterDevice() and anything it declines falls back to the + * software path built by the switches above. */ +#define WC_CFG_CRYPTO_CB 0 + +/* ========================================================================= */ +/* 3. MEMORY */ +/* ========================================================================= */ +/* 0 = no malloc anywhere. Everything comes off the stack or a static pool, + * so keep the enabled key sizes small and check the worst-case frame. */ +#define WC_CFG_HEAP 1 + +/* Move large variables off the stack and onto the heap. Requires a heap. */ +#define WC_CFG_SMALL_STACK 1 + +/* Serve allocations from a caller-provided static buffer. Verified here only + * alongside WC_CFG_HEAP 0: with the C heap still present and no pool loaded, + * the wolfCrypt RNG self-test fails (DRBG_CONT_FIPS_E), because nothing has + * given the allocator a pool to work from. */ +#define WC_CFG_STATIC_MEMORY 0 + +/* Compiler or coding standard forbids C99 variable-length arrays. */ +#define WC_CFG_NO_VLA 0 + +/* ========================================================================= */ +/* 4. SIZE VERSUS SPEED */ +/* ========================================================================= */ +/* Smaller code, smaller stack frames, slower. Applies to the math and to the + * individual algorithms: small AES tables with no loop unrolling, the small + * GCM multiply instead of the 4-bit table, the compact SHA implementations, + * and RSA without CRT. */ +#define WC_CFG_SMALL 1 + +/* 1 = math for any key size or curve (WOLFSSL_SP_MATH_ALL). + * 0 = only the sizes selected in section 5 (WOLFSSL_SP_MATH). Smaller, but + * anything not compiled in fails at run time - including certificates + * signed with a key size that is not enabled. */ +#define WC_CFG_MATH_ALL_SIZES 1 + +/* Largest number, in bits, an sp_int has to hold. 0 lets sp_int.h derive it + * from the algorithms enabled below, which is right unless something outside + * this file (a large FFDHE group, a big certificate key) needs more. Every + * sp_int is sized from this, so it sets the memory floor for the math. */ +#define WC_CFG_SP_INT_BITS 0 + +/* ========================================================================= */ +/* 5. PUBLIC KEY */ +/* ========================================================================= */ +#define WC_CFG_ECC 1 +#define WC_CFG_ECC_P256 1 +#define WC_CFG_ECC_P384 0 +#define WC_CFG_ECC_P521 0 + +#define WC_CFG_RSA 0 +#define WC_CFG_RSA_2048 1 /* only used when WC_CFG_RSA is 1 */ +#define WC_CFG_RSA_3072 0 +#define WC_CFG_RSA_4096 0 + +#define WC_CFG_DH 0 +/* Finite-field groups to offer. TLS 1.3 will not build with DH enabled and + * none of these selected. Separate from the RSA sizes above: a build can want + * RSA-2048 certificates and FFDHE-3072 key exchange. */ +#define WC_CFG_DH_2048 1 +#define WC_CFG_DH_3072 0 +#define WC_CFG_DH_4096 0 +#define WC_CFG_CURVE25519 0 +#define WC_CFG_ED25519 0 + +/* Small, slow X25519/Ed25519 implementations. Off by default: the normal C + * implementation gets scalar blinding automatically (settings.h enables + * WOLFSSL_CURVE25519_BLINDING for the C non-small build), and the small one + * cannot have it - curve25519.c rejects the combination outright. Turn this + * on only if the code size matters more than that protection. */ +#define WC_CFG_25519_SMALL 0 + +/* Verify only - no signing, no ECDH, no key export. Suits a bootloader or a + * device that only checks signatures. Note that key generation is not gated + * by these: ecc.c has no keygen switch, so wc_ecc_make_key stays in the + * build. */ +#define WC_CFG_ECC_VERIFY_ONLY 0 + +/* Shamir's trick for ECC verify: roughly twice as fast, at the cost of a + * larger table on the stack or heap during the operation. */ +#define WC_CFG_ECC_SHAMIR 1 + +/* Fixed-point ECC cache. Faster repeated operations on the same key, but it + * holds a large table for the life of the process - rarely worth it on a + * microcontroller. Sizes are FP_ENTRIES and FP_LUT (see ecc.c). */ +#define WC_CFG_ECC_FP_CACHE 0 + +/* Size ecc_point from the curve rather than from the RSA/DH key size. Saves + * a large amount of memory whenever RSA or DH is also enabled, since the + * math is otherwise dimensioned for the biggest of them. Requires a heap - + * ecc.h rejects it outright when WOLFSSL_NO_MALLOC is set. */ +#define WC_CFG_ALT_ECC_SIZE 0 + +/* --- post-quantum ------------------------------------------------------- */ +/* ML-KEM (FIPS 203) key encapsulation, and ML-DSA (FIPS 204) signatures. + * Neither uses the big-number math, so the SP switches in sections 2 and 4 + * do not apply to them - they are polynomial arithmetic with their own + * assembly, reached through the same WC_CFG_ASM_CRYPTO switch. Both pull in + * SHA-3 and SHAKE regardless of WC_CFG_SHA3. Expect a few kB of extra code + * and noticeably larger keys and signatures than ECC. + * + * Enable one parameter set unless interoperating with something specific. + * 768 and ML-DSA-44 are the widely deployed tiers. */ +#define WC_CFG_MLKEM 0 +#define WC_CFG_MLKEM_512 0 +#define WC_CFG_MLKEM_768 1 +#define WC_CFG_MLKEM_1024 0 + +#define WC_CFG_MLDSA 0 +#define WC_CFG_MLDSA_44 1 +#define WC_CFG_MLDSA_65 0 +#define WC_CFG_MLDSA_87 0 + +/* Verify only - no key generation and no signing. The natural choice for a + * device that authenticates a peer or checks a firmware image but never + * issues a signature itself. */ +#define WC_CFG_MLDSA_VERIFY_ONLY 0 + +/* ========================================================================= */ +/* 6. SYMMETRIC AND HASH */ +/* ========================================================================= */ +/* AES itself. 0 removes aes.c entirely, for a ChaCha20-Poly1305-only + * profile; the mode switches below then have nothing to apply to. */ +#define WC_CFG_AES 1 +#define WC_CFG_AES_GCM 1 +#define WC_CFG_AES_CBC 0 +#define WC_CFG_AES_CCM 0 +#define WC_CFG_CHACHA_POLY 0 + +#define WC_CFG_SHA256 1 +#define WC_CFG_SHA224 0 /* shares the SHA-256 core */ +#define WC_CFG_SHA384 0 +#define WC_CFG_SHA512 0 +#define WC_CFG_SHA3 0 +#define WC_CFG_SHA1 0 /* legacy, off by default */ + +/* ========================================================================= */ +/* 7. TLS */ +/* ========================================================================= */ +/* Protocol versions. The TLS layer is built when at least one of these is + * selected; with both off there is no TLS at all and the build is wolfCrypt + * only (WOLFCRYPT_ONLY plus NO_TLS), which is what a device using the crypto + * API directly wants. Everything else in this section then has no effect. + * There is deliberately no separate on/off switch for the layer, so that + * "TLS enabled with no version" - which wolfSSL rejects with "No TLS version + * enabled!" - cannot be expressed. */ +#define WC_CFG_TLS13 1 +#define WC_CFG_TLS12 0 +#define WC_CFG_DTLS 0 +#define WC_CFG_CLIENT_ONLY 1 +#define WC_CFG_SERVER_ONLY 0 + +/* X.509 certificates. 0 drops ASN.1, certificate handling and base64/base16 + * entirely - the smallest TLS build there is, but then authentication has to + * come from a pre-shared key, so WC_CFG_PSK must be on. Note that + * wolfcrypt/test/test.c calls the ASN.1 API unconditionally, so the library + * builds but that test program does not; build src/libwolfssl.la alone. */ +#define WC_CFG_CERTS 1 + +/* Pre-shared keys. Required when WC_CFG_CERTS is 0; also how TLS 1.3 + * resumption works. */ +#define WC_CFG_PSK 0 + +/* Negotiate a smaller record size with the peer. This is the switch that + * most directly cuts RAM, since the I/O buffers are sized from it. */ +#define WC_CFG_MAX_FRAGMENT 0 + +/* Server Name Indication. Needed to reach a virtual host, so in practice + * most clients talking to the public internet want it. */ +#define WC_CFG_SNI 0 + +/* Application-Layer Protocol Negotiation, e.g. to select HTTP/2 or MQTT. */ +#define WC_CFG_ALPN 0 + +/* Session tickets - resume without holding session state on the device. + * Needs WC_CFG_RTC: a ticket carries a validity time, and settings.h drops + * ticket support outright when NO_ASN_TIME is set. */ +#define WC_CFG_SESSION_TICKET 0 + +/* Session cache size. Needs WC_CFG_RTC for the same reason as tickets - + * settings.h forces NO_SESSION_CACHE when NO_ASN_TIME is set, so without a + * clock this switch has no effect. The cache is pure RAM, so on a target that + * does have a clock it is one of the larger levers: + * 0 none (NO_SESSION_CACHE) + * 1 MICRO_SESSION_CACHE - 1 session, about 400 bytes + 576 bytes + * 2 SMALL_SESSION_CACHE - 6 sessions, about 2 kB + 3 kB + * The library default, used by neither of these, holds 33 sessions and costs + * roughly 13 kB + 17 kB. A client that only ever talks to one server needs + * no more than 1. */ +#define WC_CFG_SESSION_CACHE 0 + +/* TLS record buffer size in bytes, 128 to 16384. 0 leaves the library + * default, which is already small (128 for TLS, the MTU for DTLS) and grows + * the buffer from the heap when a peer sends a larger record. Set a value + * only to pin the buffer, and pair it with WC_CFG_MAX_FRAGMENT so the peer + * agrees not to exceed it. */ +#define WC_CFG_RECORD_SIZE 0 + +/* Never grow the output buffer beyond the record size, even for a large + * write. Needed if the build has no heap to grow into. */ +#define WC_CFG_STATIC_CHUNKS_ONLY 0 + +/* Longest peer certificate chain accepted. Each link costs parsing time and + * memory; the library default is 9. A device that talks to one known service + * usually needs 2 or 3. 0 leaves the default. */ +#define WC_CFG_MAX_CHAIN_DEPTH 0 + +/* Verify certificates with less memory, at some cost in speed. */ +#define WC_CFG_SMALL_CERT_VERIFY 0 + +/* Trust a specific peer certificate directly instead of building a chain to + * a CA. Suits a device pinned to one known server, and avoids carrying and + * parsing CA certificates at all. */ +#define WC_CFG_TRUST_PEER_CERT 0 + +/* TLS 1.3 0-RTT early data: one fewer round trip on resumption, which matters + * on a battery-powered or high-latency link. Replayable by design - only use + * it for idempotent requests. Requires resumption to be possible at all: + * either session tickets, which need WC_CFG_RTC, or WC_CFG_PSK. */ +#define WC_CFG_EARLY_DATA 0 + +/* OCSP stapling: the server supplies its own revocation proof, so the device + * never opens a second connection to a responder. It still needs the OCSP + * parsing code, which this pulls in, and certificate support. Currently also + * needs WC_CFG_TLS12 - see the validation note below. */ +#define WC_CFG_OCSP_STAPLING 0 + +/* --- DTLS ---------------------------------------------------------------- */ +/* Connection ID (RFC 9146). The session survives the peer's address changing, + * which on a NATed or roaming IoT link saves a full handshake. */ +#define WC_CFG_DTLS_CID 0 + +/* Fix the DTLS MTU rather than using the default of 1400 bytes. Set to the + * link MTU on a constrained network; 0 leaves the default. */ +#define WC_CFG_DTLS_MTU 0 + +/* ========================================================================= */ +/* 8. PLATFORM */ +/* ========================================================================= */ +#define WC_CFG_SINGLE_THREADED 1 +#define WC_CFG_FILESYSTEM 0 +#define WC_CFG_USER_IO 1 /* provide send/recv callbacks */ +#define WC_CFG_BIG_ENDIAN 0 +#define WC_CFG_NO_HW_DIVIDE 0 /* no hardware 64/32 divide */ + +/* There is deliberately no "no 64-bit type" switch. NO_64BIT drops sp_int.h + * to 16-bit words, and no sp_*.c provides the specialised RSA/ECC code at + * that width, so the build fails to link as soon as a public key algorithm + * is enabled. On a 64-bit host it does not even compile: the ULONG_MAX chain + * in sp_int.h has no branch for a 64-bit long with NO_64BIT set. */ + +/* Build the BSD socket I/O layer. Off for a target with no sockets, which is + * the usual case when WC_CFG_USER_IO supplies the transport instead. */ +#define WC_CFG_SOCKETS 0 + +/* /dev/random is present and readable. Left at 1 so the file builds and runs + * on a host out of the box. A bare metal target has no such device: set this + * to 0 and supply entropy another way, either WC_CFG_HW_RNG or a + * wc_GenerateSeed() in the port. Setting it to 0 with no replacement is a + * compile error from random.c, by design. */ +#define WC_CFG_DEV_RANDOM 1 + +/* Inline the small helpers in misc.c into each caller. On for speed; turn it + * off to compile misc.c once, which shrinks code and makes the helpers + * visible to a debugger. Turning it off means the project must also build + * wolfcrypt/src/misc.c as its own translation unit, otherwise min(), + * ForceZero(), xorbuf() and rotrFixed() are left undefined at link time. + * With autotools that is ./configure --disable-inline. */ +#define WC_CFG_INLINE 1 + +/* wolfSSL's memory abstraction, which is what makes XMALLOC/XFREE routable + * and lets wolfSSL_SetAllocators() and the static memory pool work. Turning + * it off calls the C library directly. Ignored when WC_CFG_STATIC_MEMORY is + * set, since the pool is built on the wrapper. */ +#define WC_CFG_MEMORY_WRAPPER 1 + +/* Runtime logging through wolfSSL_Debugging_ON(). Costs code and const data, + * but is the first thing to reach for when a handshake fails on a board. */ +#define WC_CFG_DEBUG 0 + +/* Building with the Arm Compiler / Keil MDK. The inline assembly in sp_int.c + * has a Keil-specific form that is not selected automatically, so this must be + * set by hand for that toolchain. IAR and MSVC are detected on their own and + * need nothing here. */ +#define WC_CFG_KEIL 0 + +/* Real time clock available for certificate validity checking. Without it, + * date checks are compiled out. */ +#define WC_CFG_RTC 1 + +/* Hardware RNG. When 1, implement my_rng_gen_block() below. + * When 0 the hash DRBG is used and you must still provide entropy: either + * implement wc_GenerateSeed() for the port, or set CUSTOM_RAND_GENERATE_SEED + * in the derived section. */ +#define WC_CFG_HW_RNG 0 + +/* Error strings cost several kB of const data. */ +#define WC_CFG_ERROR_STRINGS 0 + +/* ========================================================================= */ +/* ========================================================================= */ +/* DERIVED SETTINGS - not normally edited */ +/* ========================================================================= */ +/* ========================================================================= */ + +/* The TLS layer follows the protocol versions selected in section 7. */ +#define WC_CFG_TLS (WC_CFG_TLS13 || WC_CFG_TLS12) + +/* --- validation --------------------------------------------------------- */ +#if (WC_CFG_CPU_PORTABLE + WC_CFG_CPU_CORTEX_M + WC_CFG_CPU_ARM_THUMB + \ + WC_CFG_CPU_ARM32 + WC_CFG_CPU_AARCH64 + WC_CFG_CPU_RISCV32 + \ + WC_CFG_CPU_RISCV64 + WC_CFG_CPU_PPC32 + WC_CFG_CPU_PPC64 + \ + WC_CFG_CPU_X86_64) != 1 + #error "Set exactly one WC_CFG_CPU_* switch to 1 in section 1." +#endif + +#if !WC_CFG_HEAP && WC_CFG_SMALL_STACK + #error "WC_CFG_SMALL_STACK moves data to the heap - needs WC_CFG_HEAP." +#endif + +#if WC_CFG_TLS && WC_CFG_CERTS && !WC_CFG_ECC && !WC_CFG_RSA + #error "Certificate-based TLS needs one of WC_CFG_ECC or WC_CFG_RSA." +#endif + +#if WC_CFG_TLS && !WC_CFG_CERTS && !WC_CFG_PSK + #error "TLS without certificates needs WC_CFG_PSK for authentication." +#endif + +#if WC_CFG_CLIENT_ONLY && WC_CFG_SERVER_ONLY + #error "WC_CFG_CLIENT_ONLY and WC_CFG_SERVER_ONLY are exclusive." +#endif + +/* internal.c calls wc_ecc_sign_hash unconditionally once HAVE_ECC is in, so + * a verify-only ECC build does not link against the TLS layer at all - not + * even a PSK one. Turn WC_CFG_ECC off instead if TLS needs no ECC. */ +#if WC_CFG_ECC_VERIFY_ONLY && WC_CFG_TLS && WC_CFG_ECC + #error "WC_CFG_ECC_VERIFY_ONLY cannot be combined with TLS and ECC." +#endif + +#if WC_CFG_RECORD_SIZE && \ + (WC_CFG_RECORD_SIZE < 128 || WC_CFG_RECORD_SIZE > 16384) + #error "WC_CFG_RECORD_SIZE must be between 128 and 16384." +#endif + +#if WC_CFG_SESSION_CACHE && !WC_CFG_TLS + #error "WC_CFG_SESSION_CACHE only applies to a TLS build." +#endif + +#if (WC_CFG_DTLS_CID || WC_CFG_DTLS_MTU) && !WC_CFG_DTLS + #error "The DTLS switches need WC_CFG_DTLS." +#endif + +#if WC_CFG_TRUST_PEER_CERT && !WC_CFG_CERTS + #error "WC_CFG_TRUST_PEER_CERT needs certificate support." +#endif + +#if WC_CFG_OCSP_STAPLING && !WC_CFG_CERTS + #error "WC_CFG_OCSP_STAPLING needs certificate support." +#endif + +/* Stapling in a TLS 1.3-only build does not currently compile: internal.c + * guards ProcessCSR_ex() on !WOLFSSL_NO_TLS12 while the TLS 1.3 code path + * calls it, so the call is built and the definition is not. Enable TLS 1.2 + * alongside until that is resolved upstream. */ +#if WC_CFG_OCSP_STAPLING && WC_CFG_TLS13 && !WC_CFG_TLS12 + #error "WC_CFG_OCSP_STAPLING needs WC_CFG_TLS12 - see comment above." +#endif + +/* Session resumption of any kind carries a validity time, so settings.h + * disables the cache and tickets when NO_ASN_TIME is set. Catch that here + * rather than let the switches silently do nothing. */ +#if (WC_CFG_SESSION_CACHE || WC_CFG_SESSION_TICKET) && !WC_CFG_RTC + #error "Session cache and tickets need a clock - set WC_CFG_RTC." +#endif + +#if WC_CFG_EARLY_DATA && !WC_CFG_SESSION_TICKET && !WC_CFG_PSK + #error "WC_CFG_EARLY_DATA needs WC_CFG_SESSION_TICKET or WC_CFG_PSK." +#endif + +#if WC_CFG_EARLY_DATA && !WC_CFG_TLS13 + #error "WC_CFG_EARLY_DATA is a TLS 1.3 feature." +#endif + +#if WC_CFG_ALT_ECC_SIZE && !WC_CFG_HEAP + #error "WC_CFG_ALT_ECC_SIZE needs a heap - ecc.h rejects it with no malloc." +#endif + +#if WC_CFG_MLKEM && !WC_CFG_MLKEM_512 && !WC_CFG_MLKEM_768 && !WC_CFG_MLKEM_1024 + #error "WC_CFG_MLKEM is set but no parameter set is enabled." +#endif + +#if WC_CFG_MLDSA && !WC_CFG_MLDSA_44 && !WC_CFG_MLDSA_65 && !WC_CFG_MLDSA_87 + #error "WC_CFG_MLDSA is set but no parameter set is enabled." +#endif + +#if WC_CFG_ECC && !WC_CFG_ECC_P256 && !WC_CFG_ECC_P384 && !WC_CFG_ECC_P521 + #error "WC_CFG_ECC is set but no curve is enabled." +#endif + +#if WC_CFG_RSA && !WC_CFG_RSA_2048 && !WC_CFG_RSA_3072 && !WC_CFG_RSA_4096 + #error "WC_CFG_RSA is set but no key size is enabled." +#endif + +#if WC_CFG_TLS && WC_CFG_TLS13 && !WC_CFG_SHA256 + #error "TLS 1.3 requires SHA-256." +#endif + +/* Every TLS 1.3 cipher suite is AEAD, so a build with none has no suite to + * negotiate. internal.h derives HAVE_AEAD from these. */ +#if WC_CFG_TLS13 && !(WC_CFG_AES && (WC_CFG_AES_GCM || WC_CFG_AES_CCM)) && \ + !WC_CFG_CHACHA_POLY + #error "TLS 1.3 needs an AEAD cipher: AES-GCM, AES-CCM or ChaCha-Poly." +#endif + +#if WC_CFG_SHA224 && !WC_CFG_SHA256 + #error "SHA-224 shares the SHA-256 core - enable WC_CFG_SHA256." +#endif + +#if WC_CFG_ARM_HW_CRYPTO && WC_CFG_CPU_CORTEX_M + #error "Cortex-M has no ARMv8 Crypto Extensions." +#endif + +/* The Thumb-1 cores have no ARMv8 crypto extensions either, and asking for + * them pulls in AArch32 AES entry points that are never compiled. */ +#if WC_CFG_ARM_HW_CRYPTO && WC_CFG_CPU_ARM_THUMB + #error "Thumb-1 cores have no ARMv8 Crypto Extensions." +#endif + +/* Cortex-M uses the Thumb-2 assembly, which needs ARMv7-M or later. */ +#if WC_CFG_CPU_CORTEX_M && WC_CFG_ASM_CRYPTO && (WC_CFG_ARM_ARCH < 7) + #error "Cortex-M assembly is Thumb-2 - set WC_CFG_ARM_ARCH 7 or later." +#endif + +#if WC_CFG_STATIC_MEMORY && WC_CFG_HEAP + #error "WC_CFG_STATIC_MEMORY needs WC_CFG_HEAP 0 - see its comment." +#endif + +#if WC_CFG_DH && !WC_CFG_DH_2048 && !WC_CFG_DH_3072 && !WC_CFG_DH_4096 + #error "WC_CFG_DH needs at least one FFDHE group." +#endif + +/* --- platform ----------------------------------------------------------- */ +/* Alignment, in bytes, applied to generated data buffers - it is what + * XGEN_ALIGN expands to. Hardware crypto engines and some assembly need their + * input aligned, and the TLS record header otherwise leaves payloads on an odd + * boundary. 4 suits a 32-bit embedded target; raise it if your port's engine + * needs more, or set 0 to emit no alignment attribute at all. + * + * Not set for x86_64, because settings.h makes a better choice there on its + * own: 16 when AES-NI is in use, which the SSE loads in aes.c require, and 0 + * otherwise. Overriding it with 4 would quietly weaken the AES-NI build. */ +#if !WC_CFG_CPU_X86_64 + #define WOLFSSL_GENERAL_ALIGNMENT 4 +#endif + +/* Size of "long long" on this target, in bytes. Without autoconf there is no + * config.h to supply it, so state it here: types.h uses it to pick the 64-bit + * word type, and only guesses from limits.h or a list of known targets when it + * is absent. sp_int.h also sizes its own word types from it, so it is stated + * unconditionally. */ +#ifndef SIZEOF_LONG_LONG + #define SIZEOF_LONG_LONG 8 +#endif + +#if WC_CFG_SINGLE_THREADED + #define SINGLE_THREADED +#endif + +#if !WC_CFG_FILESYSTEM + #define NO_FILESYSTEM + #define NO_WOLFSSL_DIR + #define NO_WRITEV + #define WOLFSSL_IGNORE_FILE_WARN +#endif + +#if WC_CFG_USER_IO + /* set with wolfSSL_CTX_SetIORecv() / wolfSSL_CTX_SetIOSend() */ + #define WOLFSSL_USER_IO +#endif + +#if WC_CFG_BIG_ENDIAN + #define BIG_ENDIAN_ORDER +#endif + +#if !WC_CFG_ERROR_STRINGS + #define NO_ERROR_STRINGS +#endif + +#if !WC_CFG_SOCKETS + #define WOLFSSL_NO_SOCK +#endif + +#if !WC_CFG_DEV_RANDOM + #define NO_DEV_RANDOM +#endif + +#if !WC_CFG_INLINE + #define NO_INLINE +#endif + +#if WC_CFG_DEBUG + #define DEBUG_WOLFSSL +#endif + +#if WC_CFG_KEIL + #define WOLFSSL_KEIL +#endif + +#if WC_CFG_CRYPTO_CB + #define WOLF_CRYPTO_CB +#endif + +/* Make wolfcrypt/benchmark/benchmark.c use small buffers and short run times + * so it fits, and finishes, on a microcontroller. No effect on the library. */ +#define BENCH_EMBEDDED + +/* Do not declare the legacy "RNG" alias for WC_RNG. The short name collides + * with symbols in many embedded SDKs and RTOS headers. */ +#define NO_OLD_RNGNAME + +/* Use the table-driven ASN.1 parser rather than the original hand-written one. + * Smaller and the maintained path - see wolfcrypt/src/ASN_TEMPLATE.md. */ +#define WOLFSSL_ASN_TEMPLATE + +/* --- memory ------------------------------------------------------------- */ +#if WC_CFG_SMALL_STACK + #define WOLFSSL_SMALL_STACK +#endif + +#if !WC_CFG_HEAP + #define WOLFSSL_NO_MALLOC + #define WOLFSSL_SP_NO_MALLOC +#endif + +#if WC_CFG_STATIC_MEMORY + #define WOLFSSL_STATIC_MEMORY + #define WOLFSSL_MALLOC_CHECK +#endif + +#if !WC_CFG_MEMORY_WRAPPER && !WC_CFG_STATIC_MEMORY + /* The static memory pool is implemented on top of the wrapper, so the + * wrapper can only be dropped when that is off too. */ + #define NO_WOLFSSL_MEMORY +#endif + +#if WC_CFG_NO_VLA + #define WOLFSSL_SP_NO_DYN_STACK +#endif + +/* --- math back end ------------------------------------------------------ */ +#if WC_CFG_MATH_ALL_SIZES + #define WOLFSSL_SP_MATH_ALL +#else + #define WOLFSSL_SP_MATH +#endif + +#if WC_CFG_SMALL + #define WOLFSSL_SP_SMALL +#endif + +#if WC_CFG_NO_HW_DIVIDE + #define WOLFSSL_SP_DIV_32 +#endif + +#if WC_CFG_SP_INT_BITS + #define SP_INT_BITS WC_CFG_SP_INT_BITS +#endif + +/* Timing-attack hardening. All three are on by default in wolfSSL and are + * repeated here so they survive a hand-written build, where nothing else + * turns them on. They cost speed; leave them alone unless the threat model + * genuinely excludes an attacker who can observe timing. + * + * TFM_TIMING_RESISTANT applies to the fastmath back end (tfm.c) and to + * wolfmath.c, so it only bites if this configuration is later switched away + * from SP math. ECC_TIMING_RESISTANT makes ECC scalar multiplication + * constant time. WC_RSA_BLINDING blinds RSA private key operations, which + * needs an RNG to be available. */ +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/* --- CPU: assembly and word size ---------------------------------------- */ +#if !WC_CFG_ASM || WC_CFG_CPU_PORTABLE + /* Portable C. WOLFSSL_NO_ASM also keeps the legacy math back ends from + * pulling in their own assembly. */ + #define WOLFSSL_NO_ASM + #define TFM_NO_ASM + +#elif WC_CFG_CPU_CORTEX_M + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM_CORTEX_M + #endif + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM_CORTEX_M_ASM + #endif + #if WC_CFG_ARM_NO_UMAAL + #define WOLFSSL_SP_NO_UMAAL + #endif + #if WC_CFG_ARM_UDIV + #define WOLFSSL_SP_ARM32_UDIV + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_ARMASM + #define WOLFSSL_ARMASM_THUMB2 + #define WOLFSSL_ARMASM_NO_NEON + #define WOLFSSL_ARMASM_NO_HW_CRYPTO + #endif + +#elif WC_CFG_CPU_ARM_THUMB + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM_THUMB + #endif + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM_THUMB_ASM + #endif + /* The per-algorithm ARM assembly is Thumb-2, which needs ARMv7 or later. + * On a Thumb-1 core (ARMv6-M: Cortex-M0/M0+/M1, or ARMv8-M baseline: + * Cortex-M23) there is no assembly to use - wolfSSL ships none for + * Thumb-1 - so only the SP acceleration above applies and the algorithms + * use their C implementations. */ + #if WC_CFG_ASM_CRYPTO && (WC_CFG_ARM_ARCH >= 7) + #define WOLFSSL_ARMASM + #define WOLFSSL_ARMASM_THUMB2 + #if !WC_CFG_ARM_NEON + #define WOLFSSL_ARMASM_NO_NEON + #endif + #if !WC_CFG_ARM_HW_CRYPTO + #define WOLFSSL_ARMASM_NO_HW_CRYPTO + #endif + #endif + +#elif WC_CFG_CPU_ARM32 + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM32 + #endif + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM32_ASM + #endif + #if WC_CFG_ARM_UDIV + #define WOLFSSL_SP_ARM32_UDIV + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_ARMASM + #if !WC_CFG_ARM_NEON + #define WOLFSSL_ARMASM_NO_NEON + #endif + #if !WC_CFG_ARM_HW_CRYPTO + #define WOLFSSL_ARMASM_NO_HW_CRYPTO + #endif + #endif + +#elif WC_CFG_CPU_AARCH64 + #define WOLFSSL_AARCH64_BUILD + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM64 + #endif + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_ARM64_ASM + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_ARMASM + #if !WC_CFG_ARM_NEON + #define WOLFSSL_ARMASM_NO_NEON + #endif + #if !WC_CFG_ARM_HW_CRYPTO + #define WOLFSSL_ARMASM_NO_HW_CRYPTO + #endif + #if WC_CFG_ARM_SHA512_CRYPTO + /* needs -march=armv8.2-a+crypto+sha3 */ + #define WOLFSSL_ARMASM_CRYPTO_SHA512 + #define WOLFSSL_ARMASM_CRYPTO_SHA3 + #endif + #endif + +#elif WC_CFG_CPU_RISCV32 + /* No specialised SP assembly and no algorithm port for 32-bit RISC-V. + * The inline SP assembly in sp_int.c is all that is available. */ + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_RISCV32 + #endif + +#elif WC_CFG_CPU_RISCV64 + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_RISCV64 + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_RISCV_ASM + #if WC_CFG_RISCV_BITMANIP + #define WOLFSSL_RISCV_BASE_BIT_MANIPULATION + #define WOLFSSL_RISCV_BIT_MANIPULATION + #endif + #if WC_CFG_RISCV_SCALAR_CRYPTO + #define WOLFSSL_RISCV_SCALAR_CRYPTO_ASM + #endif + #if WC_CFG_RISCV_VECTOR + #define WOLFSSL_RISCV_VECTOR + #endif + #if WC_CFG_RISCV_VECTOR_CRYPTO + #define WOLFSSL_RISCV_VECTOR_CRYPTO_ASM + #endif + #endif + +#elif WC_CFG_CPU_PPC32 + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_PPC + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_PPC32_ASM + #if WC_CFG_PPC_SMALL + #define WOLFSSL_PPC32_ASM_SMALL + #endif + #endif + +#elif WC_CFG_CPU_PPC64 + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_PPC64 + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_PPC64_ASM + #if WC_CFG_PPC_SMALL + #define WOLFSSL_PPC64_ASM_SMALL + #endif + #if WC_CFG_PPC64_POWER8 + #define WOLFSSL_PPC64_ASM_CRYPTO + #define WOLFSSL_PPC64_ASM_POWER8 + #endif + #endif + +#elif WC_CFG_CPU_X86_64 + #define WOLFSSL_X86_64_BUILD + #if WC_CFG_ASM_SP + #define WOLFSSL_SP_X86_64 + #endif + #if WC_CFG_ASM_SP + /* not supported for MinGW/Cygwin hosts - use the C code there */ + #define WOLFSSL_SP_X86_64_ASM + #endif + #if WC_CFG_ASM_CRYPTO + #define WOLFSSL_AESNI + #define USE_INTEL_SPEEDUP + #endif +#endif + +/* Architecture level for the 32-bit ARM targets. Set outside the assembly + * blocks above because sp_int.c consults WOLFSSL_ARM_ARCH for its own inline + * assembly, so it must be right even when the per-algorithm assembly is off. */ +#if WC_CFG_CPU_CORTEX_M || WC_CFG_CPU_ARM_THUMB || WC_CFG_CPU_ARM32 + #define WOLFSSL_ARM_ARCH WC_CFG_ARM_ARCH +#endif + +/* Inline assembly-in-C variants, for toolchains that cannot assemble .S. */ +#if WC_CFG_ASM && WC_CFG_ASM_INLINE + #define WOLFSSL_ARMASM_INLINE + #define WOLFSSL_RISCV_ASM_INLINE + #define WOLFSSL_PPC32_ASM_INLINE + #define WOLFSSL_PPC64_ASM_INLINE +#endif + +/* --- SP: which algorithms and sizes ------------------------------------- */ +#if WC_CFG_RSA + #define WOLFSSL_HAVE_SP_RSA +#endif +#if WC_CFG_DH + #define WOLFSSL_HAVE_SP_DH +#endif +#if WC_CFG_ECC + #define WOLFSSL_HAVE_SP_ECC +#endif + +#if WC_CFG_RSA || WC_CFG_DH + #if !WC_CFG_RSA_2048 + #define WOLFSSL_SP_NO_2048 + #endif + #if !WC_CFG_RSA_3072 + #define WOLFSSL_SP_NO_3072 + #endif + #if WC_CFG_RSA_4096 + #define WOLFSSL_SP_4096 + #endif +#endif + +#if WC_CFG_ECC + #if !WC_CFG_ECC_P256 + #define WOLFSSL_SP_NO_256 + #endif + #if WC_CFG_ECC_P384 + #define WOLFSSL_SP_384 + #define HAVE_ECC384 + #endif + #if WC_CFG_ECC_P521 + #define WOLFSSL_SP_521 + #define HAVE_ECC521 + #endif +#endif + +/* --- public key --------------------------------------------------------- */ +#if WC_CFG_ECC + #define HAVE_ECC + #define ECC_USER_CURVES /* only the curves selected above */ + #if !WC_CFG_ECC_P256 + #define NO_ECC256 + #endif + #if WC_CFG_ECC_VERIFY_ONLY + /* settings.h turns each of these into the matching HAVE_ECC_* */ + #define NO_ECC_SIGN + #define NO_ECC_DHE + #define NO_ECC_KEY_EXPORT + #endif + #if WC_CFG_ECC_SHAMIR + #define ECC_SHAMIR + #endif + #if WC_CFG_ECC_FP_CACHE + #define FP_ECC + #endif + #if WC_CFG_ALT_ECC_SIZE + #define ALT_ECC_SIZE + #endif +#endif +/* There is no NO_ECC: ECC is absent whenever HAVE_ECC is not defined. */ + +#if !WC_CFG_RSA + #define NO_RSA +#else + #define WC_RSA_PSS + #if WC_CFG_SMALL + /* Private key operations without CRT: much less memory, several + * times slower. Also forces WOLFSSL_SP_SMALL in the sp_*.c files. */ + #define RSA_LOW_MEM + #endif +#endif + +#if WC_CFG_DH + #if WC_CFG_DH_2048 + #define HAVE_FFDHE_2048 + #endif + #if WC_CFG_DH_3072 + #define HAVE_FFDHE_3072 + #endif + #if WC_CFG_DH_4096 + #define HAVE_FFDHE_4096 + #endif +#else + #define NO_DH +#endif + +#if WC_CFG_CURVE25519 + #define HAVE_CURVE25519 + #if WC_CFG_25519_SMALL + #define CURVE25519_SMALL + #endif +#endif +#if WC_CFG_ED25519 + #define HAVE_ED25519 + #if WC_CFG_25519_SMALL + #define ED25519_SMALL + #endif +#endif + +/* DSA is not offered as a switch: it has no role in TLS 1.2 or 1.3 as + * deployed, and ECDSA covers the same ground. */ +/* --- post-quantum ------------------------------------------------------- */ +/* Parameter sets are opt-out here: defining WOLFSSL_HAVE_MLKEM alone builds + * all three, so each one not selected has to be turned off by name. */ +#if WC_CFG_MLKEM + #define WOLFSSL_HAVE_MLKEM + #if !WC_CFG_MLKEM_512 + #define WOLFSSL_NO_ML_KEM_512 + #endif + #if !WC_CFG_MLKEM_768 + #define WOLFSSL_NO_ML_KEM_768 + #endif + #if !WC_CFG_MLKEM_1024 + #define WOLFSSL_NO_ML_KEM_1024 + #endif + #if WC_CFG_SMALL + /* Loop the polynomial arithmetic instead of unrolling it. */ + #define WOLFSSL_MLKEM_SMALL + #define WOLFSSL_MLKEM_NO_LARGE_CODE + #endif + #if WC_CFG_HEAP && !WC_CFG_STATIC_MEMORY + /* Allocate the key buffers rather than carrying them in the key + * struct. Rejected by wc_mlkem.c when there is no malloc. */ + #define WOLFSSL_MLKEM_DYNAMIC_KEYS + #endif +#endif + +#if WC_CFG_MLDSA + #define WOLFSSL_HAVE_MLDSA + #if !WC_CFG_MLDSA_44 + #define WOLFSSL_NO_ML_DSA_44 + #endif + #if !WC_CFG_MLDSA_65 + #define WOLFSSL_NO_ML_DSA_65 + #endif + #if !WC_CFG_MLDSA_87 + #define WOLFSSL_NO_ML_DSA_87 + #endif + #if WC_CFG_MLDSA_VERIFY_ONLY + #define WOLFSSL_MLDSA_VERIFY_ONLY + /* Stream the verify rather than expanding the whole key at once. */ + #define WOLFSSL_MLDSA_VERIFY_SMALL_MEM + #endif + #if WC_CFG_SMALL + #define WOLFSSL_MLDSA_SMALL + #endif + #if !WC_CFG_CERTS + /* Nothing decodes an ML-DSA certificate in a no-X.509 build. */ + #define WOLFSSL_MLDSA_NO_ASN1 + #endif +#endif + +#if WC_CFG_MLKEM || WC_CFG_MLDSA + /* Both are built on SHAKE, so SHA-3 comes in whether or not it was asked + * for in section 6. sha3.h hides the wc_Shake* API behind these. */ + #ifndef WOLFSSL_SHA3 + #define WOLFSSL_SHA3 + #endif + #define WOLFSSL_SHAKE128 + #define WOLFSSL_SHAKE256 +#endif + +#define NO_DSA + +/* --- symmetric and hash ------------------------------------------------- */ +#if !WC_CFG_AES + #define NO_AES +#endif + +#if WC_CFG_AES && WC_CFG_AES_GCM + #define HAVE_AESGCM + #if WC_CFG_SMALL + /* GHASH without a precomputed table - smallest, slowest. */ + #define GCM_SMALL + #else + /* 4-bit table: the usual speed/size compromise for GHASH. */ + #define GCM_TABLE_4BIT + #endif +#endif + +#if WC_CFG_SMALL && WC_CFG_AES + /* Compact AES: 256-byte tables instead of 4 x 1kB, and no unrolling of + * the round loop. */ + #define WOLFSSL_AES_SMALL_TABLES + #define WOLFSSL_AES_NO_UNROLL +#endif +#if WC_CFG_AES && !WC_CFG_AES_CBC + #define NO_AES_CBC +#endif +#if WC_CFG_AES && WC_CFG_AES_CCM + #define HAVE_AESCCM +#endif + +#if WC_CFG_CHACHA_POLY + #define HAVE_CHACHA + #define HAVE_POLY1305 + #define HAVE_ONE_TIME_AUTH +#endif + +#if !WC_CFG_SHA256 + #define NO_SHA256 +#endif +#if WC_CFG_SHA224 + /* Truncated SHA-256 with a different IV - it is compiled into sha256.c, + * so it costs almost nothing once SHA-256 is already in. */ + #define WOLFSSL_SHA224 +#endif + +/* The larger SHA-2 sizes are also pulled in by what depends on them, not only + * by the switches in section 6: P-384 is signed with SHA-384 and P-521 with + * SHA-512 (the wolfCrypt test vectors do exactly this, and fail with + * BAD_LENGTH_E if the digest is missing), and Ed25519 is defined in terms of + * SHA-512 - settings.h refuses to build it otherwise. */ +#if WC_CFG_SHA384 || (WC_CFG_ECC && WC_CFG_ECC_P384) + #define WOLFSSL_SHA384 +#endif +#if WC_CFG_SHA512 || (WC_CFG_ECC && WC_CFG_ECC_P521) || WC_CFG_ED25519 + #define WOLFSSL_SHA512 +#endif +/* SHA-384 and SHA-512 are both absent simply by not defining WOLFSSL_SHA384 + * or WOLFSSL_SHA512 - sha512.h gates on those two. There is no NO_SHA512 to + * emit: the library never reads that macro. */ +#if WC_CFG_SHA3 + #define WOLFSSL_SHA3 +#endif + +/* Compact hash cores - loop rather than unroll the compression rounds. Placed + * after the digests are selected so each only lands when its digest is built. + */ +#if WC_CFG_SMALL + #if WC_CFG_SHA1 + #define USE_SLOW_SHA + #endif + #if WC_CFG_SHA256 + #define USE_SLOW_SHA256 + #endif + #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + #define USE_SLOW_SHA512 + #endif +#endif +#if !WC_CFG_SHA1 + #define NO_SHA +#endif + +/* Never wanted on a new embedded design, so these are compiled out rather + * than offered as switches. Drop the relevant line if an existing protocol + * or file format forces one of them on you. + * + * MD4, MD5 and RC4 are broken. 3DES is obsolete and slow, and + * NO_DES3_TLS_SUITES additionally removes the 3DES TLS cipher suites from + * the suite tables in internal.h even if 3DES itself were built. PWDBASED is + * the PBKDF family, PKCS#8 and PKCS#12 are encrypted key container formats - + * all three are only needed to read password-protected key files, which an + * embedded target normally does not do. NO_SIG_WRAPPER drops the generic + * wc_Signature* layer in signature.c; call the RSA or ECC API directly. */ +#define NO_MD4 +#define NO_MD5 +#define NO_RC4 +#define NO_DES3 +#define NO_DES3_TLS_SUITES +#define NO_PWDBASED +#define NO_PKCS8 +#define NO_PKCS12 +#define NO_SIG_WRAPPER + +/* --- RNG ---------------------------------------------------------------- */ +#if WC_CFG_HW_RNG + #define WC_NO_HASHDRBG + extern int my_rng_gen_block(unsigned char* output, unsigned int sz); + #define CUSTOM_RAND_GENERATE_BLOCK my_rng_gen_block +#else + #define HAVE_HASHDRBG + /* Entropy source. Implement wc_GenerateSeed() in a port file, or supply + * a seed function here: + * extern int my_rng_seed(unsigned char* output, unsigned int sz); + * #define CUSTOM_RAND_GENERATE_SEED my_rng_seed + * + * WOLFSSL_GENSEED_FORTEST provides a non-random stub. Bring-up only - + * it is not safe for anything that leaves the bench. */ +#endif + +/* --- time --------------------------------------------------------------- */ +#if !WC_CFG_RTC + /* No clock: certificate validity dates cannot be checked. */ + #define NO_ASN_TIME +#else + /* Provide the platform clock: + * #define USER_TIME + * extern unsigned long my_time(unsigned long* timer); + * #define XTIME my_time + */ +#endif + +/* --- TLS ---------------------------------------------------------------- */ +#if WC_CFG_TLS + #define HAVE_TLS_EXTENSIONS + /* Supported groups. This is a TLS extension, not an ECC feature: it + * carries whichever key exchange groups the build offers - ECC curves, + * X25519, ML-KEM hybrids - so it belongs to the TLS layer and is needed + * even by a build that does key exchange without ECC. TLS 1.3 cannot + * offer a key share without it. */ + #define HAVE_SUPPORTED_CURVES + #define HAVE_EXTENDED_MASTER + #if WC_CFG_SESSION_CACHE == 0 + #define NO_SESSION_CACHE + #elif WC_CFG_SESSION_CACHE == 1 + #define MICRO_SESSION_CACHE + #else + #define SMALL_SESSION_CACHE + #endif + + #if WC_CFG_TLS13 + #define WOLFSSL_TLS13 + #define HAVE_HKDF + /* HAVE_AEAD is deliberately not defined here: internal.h derives it + * from whether an AEAD cipher is actually built (AES-GCM, AES-CCM, + * ChaCha20-Poly1305, ...). Forcing it would claim AEAD support a + * cipher-less configuration does not have. */ + #endif + #if !WC_CFG_TLS12 + #define WOLFSSL_NO_TLS12 + #endif + #define NO_OLD_TLS + + #if WC_CFG_DTLS + #define WOLFSSL_DTLS + #if WC_CFG_TLS13 + #define WOLFSSL_DTLS13 + #endif + #endif + + #if WC_CFG_CLIENT_ONLY + #define NO_WOLFSSL_SERVER + #endif + #if WC_CFG_SERVER_ONLY + #define NO_WOLFSSL_CLIENT + #endif + + #if !WC_CFG_PSK + #define NO_PSK + #endif + #if WC_CFG_EARLY_DATA + #define WOLFSSL_EARLY_DATA + #endif + #if WC_CFG_OCSP_STAPLING + /* Stapling is an OCSP consumer, so the OCSP code has to be present; + * internal.h refuses to build the extension without it. The device + * still never fetches a response itself - the server supplies it. */ + #define HAVE_OCSP + #define HAVE_CERTIFICATE_STATUS_REQUEST + #endif + #if WC_CFG_TRUST_PEER_CERT + #define WOLFSSL_TRUST_PEER_CERT + #endif + #if WC_CFG_SMALL_CERT_VERIFY + #define WOLFSSL_SMALL_CERT_VERIFY + #endif + #if WC_CFG_RECORD_SIZE + #define RECORD_SIZE WC_CFG_RECORD_SIZE + #endif + #if WC_CFG_STATIC_CHUNKS_ONLY + #define STATIC_CHUNKS_ONLY + #endif + #if WC_CFG_MAX_CHAIN_DEPTH + #define MAX_CHAIN_DEPTH WC_CFG_MAX_CHAIN_DEPTH + #endif + #if WC_CFG_DTLS && WC_CFG_DTLS_CID + #define WOLFSSL_DTLS_CID + #endif + #if WC_CFG_DTLS && WC_CFG_DTLS_MTU + #define WOLFSSL_DTLS_MTU + #define WOLFSSL_MAX_MTU WC_CFG_DTLS_MTU + #endif + #if WC_CFG_MAX_FRAGMENT + #define HAVE_MAX_FRAGMENT + #endif + #if WC_CFG_SNI + #define HAVE_SNI + #endif + #if WC_CFG_ALPN + #define HAVE_ALPN + #endif + #if WC_CFG_SESSION_TICKET + #define HAVE_SESSION_TICKET + #endif +#else + #define WOLFCRYPT_ONLY + #define NO_TLS + #define NO_PSK +#endif + +#if !WC_CFG_CERTS + /* No X.509 at all: no DER/PEM parsing, no certificate store, and no + * base64/base16 since nothing is left that needs to decode them. */ + #define NO_ASN + #define NO_CERTS + #define NO_CODING +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/examples/configs/user_settings_pq.h b/examples/configs/user_settings_pq.h index d49a5406acc..8269d99d518 100644 --- a/examples/configs/user_settings_pq.h +++ b/examples/configs/user_settings_pq.h @@ -76,11 +76,12 @@ extern "C" { /* ML-KEM / Kyber (Key Encapsulation) */ /* ------------------------------------------------- */ #if 1 /* ML-KEM (FIPS 203) */ - #define WOLFSSL_HAVE_KYBER - #define WOLFSSL_WC_KYBER - #define WOLFSSL_KYBER512 /* Level 1: 128-bit security */ - #define WOLFSSL_KYBER768 /* Level 3: 192-bit security */ - #define WOLFSSL_KYBER1024 /* Level 5: 256-bit security */ + #define WOLFSSL_HAVE_MLKEM + /* All three parameter sets are built by default - Level 1 (ML-KEM-512), + * Level 3 (768) and Level 5 (1024). Remove one with the matching + * WOLFSSL_NO_ML_KEM_512 / _768 / _1024. */ + #define WOLFSSL_SHAKE128 + #define WOLFSSL_SHAKE256 #endif /* ------------------------------------------------- */ diff --git a/wolfcrypt/src/port/cypress/psoc6_crypto.c b/wolfcrypt/src/port/cypress/psoc6_crypto.c index 39e51de30c3..83eeddc9201 100644 --- a/wolfcrypt/src/port/cypress/psoc6_crypto.c +++ b/wolfcrypt/src/port/cypress/psoc6_crypto.c @@ -181,7 +181,7 @@ int wc_Psoc6_Sha1_Sha2_Init(void* sha, wc_psoc6_hash_sha1_sha2_t hash_mode, res = Cy_Crypto_Core_Sha_Start(crypto_base, &((wc_Sha512*)sha)->hash_state); break; -#endif /* WOLFSSL_SHA512_224 */ +#endif /* !WOLFSSL_NOSHA512_224 */ #if !defined(WOLFSSL_NOSHA512_256) case WC_PSOC6_SHA512_256: @@ -192,7 +192,7 @@ int wc_Psoc6_Sha1_Sha2_Init(void* sha, wc_psoc6_hash_sha1_sha2_t hash_mode, res = Cy_Crypto_Core_Sha_Start(crypto_base, &((wc_Sha512*)sha)->hash_state); break; -#endif /* WOLFSSL_SHA512_256 */ +#endif /* !WOLFSSL_NOSHA512_256 */ #endif /* WOLFSSL_SHA512 */