DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
crypto_opt.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file crypto_opt.h
6 * @brief Per-translation-unit optimization override for hot, pure-integer crypto.
7 *
8 * The library ships at the arduino framework's `-Os` (the framework appends it AFTER any PlatformIO env
9 * `build_flags`, so a plain `-O2` there is overridden). `-Os` roughly halves the throughput of the software
10 * ciphers/MACs. Put @ref DETWS_CRYPTO_HOT at the top of such a `.cpp` (after its includes) to force a higher
11 * level for that one translation unit, regardless of the consumer's size-optimized build:
12 *
13 * @code
14 * #include "ssh_chacha20.h"
15 * #include "shared_primitives/crypto_opt.h"
16 * DETWS_CRYPTO_HOT // this TU builds at -O2 (or the configured level)
17 * @endcode
18 *
19 * Configure with `DETWS_CRYPTO_OPT_LEVEL` (define in `build_flags` or ServerConfig): `2` (default) or `3`;
20 * define it to `0` to inherit the framework `-Os`. Only GCC honors `#pragma GCC optimize`; clang/other
21 * compilers get a no-op and inherit their normal level.
22 *
23 * ═══════════════════════════════════════════════════════════════════════════
24 * CAVEATS - read before applying this to a new file
25 * ═══════════════════════════════════════════════════════════════════════════
26 *
27 * 1. CONSTANT TIME. Apply this ONLY to code that is constant-time by STRUCTURE - no secret-dependent
28 * branches and no secret-dependent memory indexing: stream ciphers (ChaCha20), MACs (Poly1305), hashes.
29 * Do NOT put it on scalar-multiplication / bignum / point-arithmetic code that relies on branchless
30 * mask-selects to stay constant-time: an aggressive optimizer can (rarely, but it is documented) turn a
31 * mask-select into a data-dependent branch and reintroduce a timing side channel. Those paths are also
32 * HW-accelerator-dominated (RSA/MPI MODMULT, HW AES/SHA), so the `-O` level buys them almost nothing -
33 * all risk, no reward. When in doubt, leave it off.
34 *
35 * 2. SIZE. `-O2`/`-O3` inline and unroll aggressively -> larger flash and IRAM; `-O3` more so. On the
36 * classic ESP32 (tight internal DRAM/IRAM, where TLS example builds already run close to the limit)
37 * prefer level `2` or `0`.
38 *
39 * 3. `-O3` IS NOT RELIABLY FASTER than `-O2` here. The bigger unrolled code can thrash the instruction /
40 * flash cache and regress, and `-O3` widens the miscompile and latent-UB surface. `-O2` captures
41 * essentially all of the practical win; treat `3` as a measure-it-yourself option, not a default.
42 */
43
44#ifndef DETERMINISTICESPASYNCWEBSERVER_CRYPTO_OPT_H
45#define DETERMINISTICESPASYNCWEBSERVER_CRYPTO_OPT_H
46
47#if defined(__GNUC__) && !defined(__clang__)
48#ifndef DETWS_CRYPTO_OPT_LEVEL
49#define DETWS_CRYPTO_OPT_LEVEL 2 // default: -O2 (the -Os -> -O2 jump is the ~2x win; O2 -> O3 is marginal)
50#endif
51#if DETWS_CRYPTO_OPT_LEVEL == 3
52#define DETWS_CRYPTO_HOT _Pragma("GCC optimize(\"O3\")")
53#elif DETWS_CRYPTO_OPT_LEVEL == 2
54#define DETWS_CRYPTO_HOT _Pragma("GCC optimize(\"O2\")")
55#else
56#define DETWS_CRYPTO_HOT // 0 / other: inherit the framework -Os
57#endif
58#else
59#define DETWS_CRYPTO_HOT // non-GCC: no per-TU pragma; inherit the toolchain default
60#endif
61
62#endif // DETERMINISTICESPASYNCWEBSERVER_CRYPTO_OPT_H