ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
crypto_opt.h File Reference

Per-translation-unit optimization override for hot, pure-integer crypto. More...

Go to the source code of this file.

Macros

#define PC_CRYPTO_HOT
 
#define PC_CRYPTO_HOT_PEEL
 
#define PC_CRYPTO_HOT_UNSWITCH
 

Detailed Description

Per-translation-unit optimization override for hot, pure-integer crypto.

The library ships at the arduino framework's -Os (the framework appends it AFTER any PlatformIO env build_flags, so a plain -O2 there is overridden). -Os roughly halves the throughput of the software ciphers/MACs. Put PC_CRYPTO_HOT at the top of such a .cpp (after its includes) to force a higher level for that one translation unit, regardless of the consumer's size-optimized build:

PC_CRYPTO_HOT // this TU builds at -O2 (or the configured level)
ChaCha20 stream cipher (D. J. Bernstein; RFC 8439).
Per-translation-unit optimization override for hot, pure-integer crypto.

The level is PC_CRYPTO_OPT_LEVEL: 2 or 3, or 0 to inherit the framework -Os. It is NOT a ServerConfig / user knob - it is internal crypto tuning with a measured per-die default (see below), which a hot TU can override for its own build with #define PC_CRYPTO_OPT_LEVEL 3 before this include. Only GCC honors #pragma GCC optimize; clang/other compilers get a no-op and inherit their normal level.

When a TU's -O3 win bisects (on-device) to a SINGLE named transform, prefer the deliberate PC_CRYPTO_HOT_PEEL / PC_CRYPTO_HOT_UNSWITCH pin (the -O2 floor + just that transform) over full -O3, scoped inside the TU's own die guard - same speed, none of -O3's extra code-size / miscompile risk:

#if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_IDF_TARGET_ESP32S3
PC_CRYPTO_HOT_UNSWITCH // S3: the -O3 win here is entirely -funswitch-loops (bisected)
#else
PC_CRYPTO_HOT // every other die: the per-die default
#endif
#define PC_CRYPTO_HOT_UNSWITCH
Definition crypto_opt.h:95

═══════════════════════════════════════════════════════════════════════════ CAVEATS - read before applying this to a new file ═══════════════════════════════════════════════════════════════════════════

  1. CONSTANT TIME. Apply this ONLY to code that is constant-time by STRUCTURE - no secret-dependent branches and no secret-dependent memory indexing: stream ciphers (ChaCha20), MACs (Poly1305), hashes. Do NOT put it on scalar-multiplication / bignum / point-arithmetic code that relies on branchless mask-selects to stay constant-time: an aggressive optimizer can (rarely, but it is documented) turn a mask-select into a data-dependent branch and reintroduce a timing side channel. Those paths are also HW-accelerator-dominated (RSA/MPI MODMULT, HW AES/SHA), so the -O level buys them almost nothing - all risk, no reward. When in doubt, leave it off.
  2. SIZE. -O2/-O3 inline and unroll aggressively -> larger flash and IRAM; -O3 more so. On the classic ESP32 (tight internal DRAM/IRAM, where TLS example builds already run close to the limit) prefer level 2 or 0.
  3. -O3 IS NOT UNIVERSALLY FASTER than -O2 here - it is per-die and per-algo. The bigger unrolled code can thrash the instruction / flash cache and regress (e.g. the S3's Ed25519 sign is ~1.2% SLOWER at -O3), and -O3 widens the miscompile / latent-UB surface. So full -O3 is taken only where it was MEASURED to help wholesale (the P4, whose win is -O3's parameter budget - see below); on the S3 the win of a given TU is one transform, taken via a PC_CRYPTO_HOT_* pin, and -O2 is the floor elsewhere.

Definition in file crypto_opt.h.

Macro Definition Documentation

◆ PC_CRYPTO_HOT

#define PC_CRYPTO_HOT

Definition at line 93 of file crypto_opt.h.

◆ PC_CRYPTO_HOT_PEEL

#define PC_CRYPTO_HOT_PEEL

Definition at line 94 of file crypto_opt.h.

◆ PC_CRYPTO_HOT_UNSWITCH

#define PC_CRYPTO_HOT_UNSWITCH

Definition at line 95 of file crypto_opt.h.