From 688ef575a4f62673f7a459e8549de49dfa041964 Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Wed, 16 Sep 2026 15:48:54 +0900 Subject: [PATCH] headers: resolve wolfSSL's config through settings.h - check_config.h includes in place of , defining WOLFSSL_USE_OPTIONS_H first unless WOLFSSL_USER_SETTINGS, WOLFSSL_NO_OPTIONS_H, WOLFSSL_CUSTOM_CONFIG, ARDUINO, PLATFORMIO, USE_HAL_DRIVER, NUCLEUS_PLUS_2_3 or WOLFSSL_MX2_CONF_INCLUDE is defined. It resolves this above tier 1 and stops a build whose wolfSSL header arrived first, with the tier-2 checks silent in that case. - memory.h reaches that resolution through ; wolfcert.h includes types.h before memory.h; CMakeLists.txt and configure.ac probe wolfSSL through the same preamble. - The 32 files that included after a wolfCert header drop that include, internal.h drops its settings.h include, and compile-freestanding.sh stages no options.h. - scripts/ci/check-config-resolution.sh compares what and resolve from scripts/ci/config-probe.c against a disagreeing options.h, over five cases; pr.yml runs it in no-posix-arm and lint.yml covers scripts/ci/*.c and *.h. - docs/EMBEDDED.md and docs/CI.md describe the new behaviour; examples/user_settings.h.example and memory.h's comments name the macros integrators actually define. --- .github/workflows/lint.yml | 3 +- .github/workflows/pr.yml | 6 +- CMakeLists.txt | 27 +- cli/wolfcert_client.c | 1 - configure.ac | 27 +- docs/CI.md | 16 +- docs/EMBEDDED.md | 36 ++- examples/enroll_cryptocb.c | 1 - examples/enroll_scep.c | 1 - examples/user_settings.h.example | 15 +- scripts/ci/check-config-resolution.sh | 233 ++++++++++++++++++ scripts/ci/compile-freestanding.sh | 9 +- scripts/ci/config-probe.c | 161 ++++++++++++ scripts/ci/wolfcert-only-user_settings.h | 45 ++++ src/ca_issue.c | 1 - src/est/est_server.c | 1 - src/internal.h | 2 - src/key_algs.h | 1 - src/pkcs7_util.c | 1 - src/scep/scep_client.c | 1 - src/scep/scep_msg.c | 1 - src/scep/scep_server.c | 1 - tests/integration/test_est_async_roundtrip.c | 1 - .../test_est_csr_attrs_apply_roundtrip.c | 1 - tests/integration/test_est_mldsa_roundtrip.c | 1 - tests/integration/test_est_mtls_roundtrip.c | 1 - .../integration/test_est_pending_roundtrip.c | 1 - tests/integration/test_est_pha_roundtrip.c | 1 - tests/integration/test_est_roundtrip.c | 1 - tests/integration/test_est_tls_roundtrip.c | 1 - tests/integration/test_scep_async_roundtrip.c | 1 - tests/integration/test_scep_get_cert.c | 1 - tests/integration/test_scep_poll_roundtrip.c | 1 - tests/integration/test_scep_roundtrip.c | 1 - tests/integration/test_server_stop_idle.c | 1 - tests/integration/test_tls_http.c | 1 - tests/integration/tls_test_util.h | 1 - tests/test_static_mem.h | 2 - tests/unit/test_csr.c | 1 - tests/unit/test_est.c | 1 - tests/unit/test_keygen.c | 2 - tests/unit/test_scep_msg.c | 1 - tests/unit/test_server_ca_store.c | 1 - wolfcert/check_config.h | 30 ++- wolfcert/memory.h | 16 +- wolfcert/wolfcert.h | 2 +- 46 files changed, 563 insertions(+), 98 deletions(-) create mode 100755 scripts/ci/check-config-resolution.sh create mode 100644 scripts/ci/config-probe.c create mode 100644 scripts/ci/wolfcert-only-user_settings.h diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ad986e2..6cf14dd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,7 +39,8 @@ jobs: fi done < <(git ls-files 'src/*.c' 'src/**/*.c' 'wolfcert/*.h' \ 'cli/*.c' 'tests/*.c' 'tests/*.h' \ - 'tests/**/*.c' 'tests/**/*.h') + 'tests/**/*.c' 'tests/**/*.h' \ + 'scripts/ci/*.c' 'scripts/ci/*.h') if [ "$missing" -ne 0 ]; then echo "One or more sources lack the GPL copyright block (copy it" echo "verbatim from any existing .c/.h)." diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 98a3ab1..29bcc3a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -239,7 +239,7 @@ jobs: ctest --test-dir build -j "$(nproc)" --output-on-failure no-posix-arm: - name: freestanding ARM compile (no POSIX) + name: header hygiene (freestanding ARM + config resolution) runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -258,6 +258,10 @@ jobs: run: | scripts/ci/compile-freestanding.sh \ --wolfssl-src "$RUNNER_TEMP/wolfssl" + - name: Assert both entry headers resolve wolfSSL's config identically + run: | + scripts/ci/check-config-resolution.sh \ + --wolfssl-src "$RUNNER_TEMP/wolfssl" negative-config: name: negative-config (fail-fast gates) diff --git a/CMakeLists.txt b/CMakeLists.txt index f54e4ef..8cce058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,13 +109,21 @@ if(TARGET PkgConfig::WOLFSSL) elseif(TARGET wolfssl::wolfssl) get_target_property(_wolfssl_cflags wolfssl::wolfssl INTERFACE_INCLUDE_DIRECTORIES) endif() +# Probe wolfSSL's feature set the way wolfcert/check_config.h resolves it, so +# configure and the headers agree. +set(_wc_wolfssl_prologue " +#if !defined(WOLFSSL_USER_SETTINGS) && !defined(WOLFSSL_USE_OPTIONS_H) && !defined(WOLFSSL_NO_OPTIONS_H) && !defined(WOLFSSL_CUSTOM_CONFIG) && !defined(ARDUINO) && !defined(PLATFORMIO) && !defined(USE_HAL_DRIVER) && !defined(NUCLEUS_PLUS_2_3) && !defined(WOLFSSL_MX2_CONF_INCLUDE) +#define WOLFSSL_USE_OPTIONS_H +#endif +#include +") + set(CMAKE_REQUIRED_INCLUDES ${_wolfssl_cflags}) foreach(sym IN ITEMS HAVE_PKCS7 WOLFSSL_CERT_GEN WOLFSSL_CERT_REQ WOLFSSL_CERT_EXT WOLFSSL_KEY_GEN WOLF_CRYPTO_CB WOLFSSL_BASE64_ENCODE OPENSSL_EXTRA WOLFSSL_ALT_NAMES WOLFSSL_CERT_NAME_ALL) unset(_have_${sym} CACHE) - check_c_source_compiles(" - #include + check_c_source_compiles("${_wc_wolfssl_prologue} #ifndef ${sym} #error missing #endif @@ -140,8 +148,7 @@ foreach(entry IN ITEMS "NO_AES;AES;--enable-aes" list(GET entry 1 _name) list(GET entry 2 _flag) unset(_off_${_neg} CACHE) - check_c_source_compiles(" - #include + check_c_source_compiles("${_wc_wolfssl_prologue} #ifdef ${_neg} #error disabled #endif @@ -159,8 +166,7 @@ endforeach() # optional for an EST-only build (ECC / Ed25519 / Ed448 / ML-DSA). The # WOLFCERT_HAVE_RSA definition gates the RSA key algorithm. unset(_off_NO_RSA CACHE) -check_c_source_compiles(" - #include +check_c_source_compiles("${_wc_wolfssl_prologue} #ifdef NO_RSA #error disabled #endif @@ -183,16 +189,14 @@ endif() # TLS: the HTTPS transport needs at least TLS 1.2 or TLS 1.3; the endpoints pin # their floor to whichever lower version is available. unset(_have_tls12 CACHE) -check_c_source_compiles(" - #include +check_c_source_compiles("${_wc_wolfssl_prologue} #ifdef WOLFSSL_NO_TLS12 #error notls12 #endif int main(void) { return 0; } " _have_tls12) unset(_have_tls13 CACHE) -check_c_source_compiles(" - #include +check_c_source_compiles("${_wc_wolfssl_prologue} #ifndef WOLFSSL_TLS13 #error notls13 #endif @@ -214,8 +218,7 @@ foreach(entry IN ITEMS "HAVE_ECC;ECC;--enable-ecc" list(GET entry 1 _short) list(GET entry 2 _flag) unset(_have_${_sym} CACHE) - check_c_source_compiles(" - #include + check_c_source_compiles("${_wc_wolfssl_prologue} #ifndef ${_sym} #error missing #endif diff --git a/cli/wolfcert_client.c b/cli/wolfcert_client.c index 22d2763..4837d54 100644 --- a/cli/wolfcert_client.c +++ b/cli/wolfcert_client.c @@ -32,7 +32,6 @@ # include #endif -#include #include #include diff --git a/configure.ac b/configure.ac index ad1c82a..90785e9 100644 --- a/configure.ac +++ b/configure.ac @@ -173,10 +173,19 @@ PKG_CHECK_MODULES([WOLFSSL], [wolfssl >= 5.9.2], WOLFSSL_ALT_NAMES, WOLFSSL_CERT_NAME_ALL.])]) AM_CONDITIONAL([HAVE_WOLFSSL], [test "x$have_wolfssl" = "xyes"]) +# Probe wolfSSL's feature set the way wolfcert/check_config.h resolves it, so +# configure and the headers agree. +m4_define([WOLFCERT_WOLFSSL_PROLOGUE], [[ +#if !defined(WOLFSSL_USER_SETTINGS) && !defined(WOLFSSL_USE_OPTIONS_H) && !defined(WOLFSSL_NO_OPTIONS_H) && !defined(WOLFSSL_CUSTOM_CONFIG) && !defined(ARDUINO) && !defined(PLATFORMIO) && !defined(USE_HAL_DRIVER) && !defined(NUCLEUS_PLUS_2_3) && !defined(WOLFSSL_MX2_CONF_INCLUDE) +#define WOLFSSL_USE_OPTIONS_H +#endif +#include +]]) + AC_DEFUN([WOLFCERT_REJECT_NEG], [AC_MSG_CHECKING([that wolfSSL does not define $1]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], + [AC_LANG_PROGRAM(WOLFCERT_WOLFSSL_PROLOGUE, [[#ifdef $1 #error disabled #endif]])], @@ -212,7 +221,7 @@ AC_CHECK_DECLS([HAVE_PKCS7, WOLFSSL_CERT_GEN, WOLFSSL_CERT_REQ, WOLFSSL_CERT_EXT --enable-certgen --enable-certreq --enable-certext --enable-keygen --enable-base64encode --enable-opensslextra CPPFLAGS="-DWOLFSSL_ALT_NAMES -DWOLFSSL_CERT_NAME_ALL".])], - [[#include ]]) + WOLFCERT_WOLFSSL_PROLOGUE) # wolfSSL default-on features that wolfCert requires unconditionally: AES, # SHA-256. Each must NOT be marked disabled by a NO_* macro. @@ -224,7 +233,7 @@ WOLFCERT_REJECT_NEG([NO_SHA256], [SHA-256]) # WOLFCERT_HAVE_RSA gates the RSA key algorithm. AC_MSG_CHECKING([whether wolfSSL provides RSA]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], + [AC_LANG_PROGRAM(WOLFCERT_WOLFSSL_PROLOGUE, [[#ifdef NO_RSA #error disabled #endif]])], @@ -242,14 +251,14 @@ AM_CONDITIONAL([WOLFCERT_HAVE_RSA], [test "x$have_rsa" = "xyes"]) # their floor to whichever lower version is available. AC_MSG_CHECKING([whether wolfSSL provides TLS 1.2]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], + [AC_LANG_PROGRAM(WOLFCERT_WOLFSSL_PROLOGUE, [[#ifdef WOLFSSL_NO_TLS12 #error notls12 #endif]])], [AC_MSG_RESULT([yes]); have_tls12=yes], [AC_MSG_RESULT([no]); have_tls12=no]) AC_MSG_CHECKING([whether wolfSSL provides TLS 1.3]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], + [AC_LANG_PROGRAM(WOLFCERT_WOLFSSL_PROLOGUE, [[#ifndef WOLFSSL_TLS13 #error notls13 #endif]])], @@ -263,22 +272,22 @@ AS_IF([test "x$have_tls12" = "xno" && test "x$have_tls13" = "xno"], AC_CHECK_DECL([HAVE_ECC], [have_ecc=yes], [have_ecc=no; AC_MSG_WARN([wolfSSL was built without HAVE_ECC; ECC key types will return WOLFCERT_ERR_UNSUPPORTED. Rebuild with --enable-ecc.])], - [[#include ]]) + WOLFCERT_WOLFSSL_PROLOGUE) AC_CHECK_DECL([HAVE_ED25519], [have_ed25519=yes], [have_ed25519=no; AC_MSG_WARN([wolfSSL was built without HAVE_ED25519; Ed25519 key types will return WOLFCERT_ERR_UNSUPPORTED. Rebuild with --enable-ed25519.])], - [[#include ]]) + WOLFCERT_WOLFSSL_PROLOGUE) AC_CHECK_DECL([HAVE_ED448], [have_ed448=yes], [have_ed448=no; AC_MSG_WARN([wolfSSL was built without HAVE_ED448; Ed448 key types will return WOLFCERT_ERR_UNSUPPORTED. Rebuild with --enable-ed448.])], - [[#include ]]) + WOLFCERT_WOLFSSL_PROLOGUE) AC_CHECK_DECL([WOLFSSL_HAVE_MLDSA], [have_mldsa=yes], [have_mldsa=no; AC_MSG_WARN([wolfSSL was built without WOLFSSL_HAVE_MLDSA; mldsa:44/65/87 will return WOLFCERT_ERR_UNSUPPORTED. Rebuild with --enable-mldsa.])], - [[#include ]]) + WOLFCERT_WOLFSSL_PROLOGUE) CPPFLAGS="$save_CPPFLAGS" # Require at least one key algorithm. diff --git a/docs/CI.md b/docs/CI.md index 4f078ad..c920910 100644 --- a/docs/CI.md +++ b/docs/CI.md @@ -10,7 +10,7 @@ build entirely. | Workflow | Trigger | What it does | |----------|---------|--------------| -| `pr.yml` | PR + push | Merge gate: CMake (`-Werror`) + autoconf + ASan/UBSan on the canonical config, plus per-PR feature/config gating — EST-only, SCEP-only, server-off, the key-alg variants (NO_RSA, ECC-only, RSA-only, no-3DES), TLS 1.3-only, the three ML-DSA per-level builds, the static-memory and no-malloc constrained builds, the platform-pieces-off build (`cmake-no-builtin-transport`), the freestanding ARM compile (`no-posix-arm`), the header-only (`WOLFCERT_USER_SETTINGS`) build, a macOS build, and the two cheapest configure-must-fail assertions. | +| `pr.yml` | PR + push | Merge gate: CMake (`-Werror`) + autoconf + ASan/UBSan on the canonical config, plus per-PR feature/config gating — EST-only, SCEP-only, server-off, the key-alg variants (NO_RSA, ECC-only, RSA-only, no-3DES), TLS 1.3-only, the three ML-DSA per-level builds, the static-memory and no-malloc constrained builds, the platform-pieces-off build (`cmake-no-builtin-transport`), the freestanding ARM compile and config-resolution check (`no-posix-arm`), the header-only (`WOLFCERT_USER_SETTINGS`) build, a macOS build, and the two cheapest configure-must-fail assertions. | | `lint.yml` | PR + push | GPL license-header check and CMake↔autoconf parity of both the library and test source lists (`scripts/ci/check-buildsystem-parity.sh`). No wolfSSL build — fails in seconds. | | `nightly.yml` | schedule + dispatch | Re-runs the wolfSSL-variant build matrix against fresh wolfSSL `master`, the macOS extras, and the full negative-config set. Also **reseeds the wolfSSL prefix caches** so the next day's PRs restore instead of build. The feature/config gating itself now runs per-PR (see `pr.yml`). | | `sanitizers.yml` | schedule + dispatch | ASan+UBSan over the full test suite, ThreadSanitizer over the threaded integration roundtrips (against a TSAN-instrumented wolfSSL), and valgrind over a representative subset. | @@ -76,3 +76,17 @@ scripts/ci/compile-freestanding.sh --wolfssl-src /tmp/wolfssl-src Its companion is the `cmake-no-builtin-transport` row: the ARM job proves the code is header-clean, that row proves the gated build links and passes tests. + +The same job then runs `scripts/ci/check-config-resolution.sh`, which preprocesses +one `` translation unit and one `` one and +requires the two to resolve the same wolfSSL feature set, since `memory.h` and +`check_config.h` reach that config separately. Each case stages an +`` that disagrees with `user_settings.h`; an absent or +forwarding one would let the two agree for the wrong reason. The cases cover +both provenances - `user_settings.h` winning under `WOLFSSL_USER_SETTINGS`, and +`options.h` winning without it. It uses the host `cc` and takes seconds. + +```sh +scripts/ci/check-config-resolution.sh --wolfssl-src /tmp/wolfssl-src +scripts/ci/check-config-resolution.sh --wolfssl-src /tmp/wolfssl-src optionsh-decoy +``` diff --git a/docs/EMBEDDED.md b/docs/EMBEDDED.md index f361d02..ca43ded 100644 --- a/docs/EMBEDDED.md +++ b/docs/EMBEDDED.md @@ -21,8 +21,7 @@ as a header, exactly like wolfSSL's `WOLFSSL_USER_SETTINGS` / `user_settings.h`: to `user_settings.h` somewhere on your include path and edit which `WOLFCERT_HAVE_*` macros are defined. 2. Compile wolfCert (and your application) with `-DWOLFCERT_USER_SETTINGS`. - `wolfcert/types.h` then pulls your `user_settings.h` in place of the - generated `options.h`. + `wolfcert/types.h` then reads it instead. The macro set is small and closed - three protocol switches (`WOLFCERT_HAVE_EST` / `_SCEP` / `_SERVER`) and five key algorithms @@ -37,10 +36,35 @@ rules the configure step does: at least one key algorithm, SCEP requires RSA (RFC 8894), and the wolfSSL feature set wolfCert depends on (PKCS#7, cert gen/req/ext, key gen, CryptoCb, base64 encode, OpenSSL-extra, alt names, `WOLFSSL_CERT_NAME_ALL`, AES, SHA-256, and TLS 1.2 or 1.3). The header you copy -documents the matching wolfSSL configure flags. If wolfSSL itself is configured -through *its own* `user_settings.h` (so `` does not reflect -its real feature set), define `WOLFCERT_NO_WOLFSSL_FEATURE_CHECK` to skip just -the wolfSSL half of the validation. +documents the matching wolfSSL configure flags. + +wolfCert reads that feature set through ``, so a +wolfSSL configured by its own `user_settings.h` is validated correctly and needs +nothing extra. Define `WOLFCERT_NO_WOLFSSL_FEATURE_CHECK` to skip the wolfSSL +half of the validation. wolfCert reaches for `` only when +none of `WOLFSSL_USER_SETTINGS`, `WOLFSSL_NO_OPTIONS_H`, +`WOLFSSL_CUSTOM_CONFIG`, `ARDUINO`, `PLATFORMIO`, `USE_HAL_DRIVER`, +`NUCLEUS_PLUS_2_3` or `WOLFSSL_MX2_CONF_INCLUDE` is defined - the platform names +among those because `settings.h` picks a config for them itself, past the point +it would read `options.h`. + +STM32CubeMX2 needs one extra step on wolfSSL 5.9.2, where `settings.h` locates +`mx_wolfSSL_conf.h` by probing with `__has_include` and so sets +`WOLFSSL_MX2_CONF_INCLUDE` too late for the test above to see. Those builds need +`WOLFSSL_CUSTOM_CONFIG` *and* an explicit `#include "mx_wolfSSL_conf.h"`, since +the probe is itself switched off by `WOLFSSL_CUSTOM_CONFIG`, as it is by +`WOLFSSL_NO_OPTIONS_H`. Later wolfSSL drops the probe and takes +`WOLFSSL_MX2_CONF_INCLUDE` from the pack's generated `Pre_Include_Global.h`, +which the test above does see, so nothing extra is needed there. + +This makes include order matter for a build that takes its feature set from +`` - the ordinary autoconf or CMake wolfSSL. `settings.h` is +header-guarded, so a wolfSSL header reaching it before any wolfCert header +leaves `options.h` unread, and wolfCert fails the build rather than compile +against wolfSSL's defaults. Include `` first, or define +`WOLFSSL_USE_OPTIONS_H` before the wolfSSL header. A `WOLFSSL_USER_SETTINGS` +build is unaffected, since `settings.h` reads `user_settings.h` whichever +header reaches it first. When you build wolfCert's own tree this way, the `WOLFCERT_ENABLE_EST` / `_SCEP` / `_SERVER` options (CMake `-DWOLFCERT_USER_SETTINGS=ON diff --git a/examples/enroll_cryptocb.c b/examples/enroll_cryptocb.c index 9766f27..14b2f83 100644 --- a/examples/enroll_cryptocb.c +++ b/examples/enroll_cryptocb.c @@ -39,7 +39,6 @@ # error "examples/enroll_cryptocb.c needs wolfCert built with EST enabled" #endif -#include #include #include diff --git a/examples/enroll_scep.c b/examples/enroll_scep.c index 81c77d3..1f116eb 100644 --- a/examples/enroll_scep.c +++ b/examples/enroll_scep.c @@ -33,7 +33,6 @@ #endif #include -#include #include #include diff --git a/examples/user_settings.h.example b/examples/user_settings.h.example index 485cce9..5ddec93 100644 --- a/examples/user_settings.h.example +++ b/examples/user_settings.h.example @@ -28,13 +28,14 @@ * their own build. wolfcert/check_config.h validates the result at compile * time, so a contradictory or incomplete config fails with a clear #error. * - * The "user_settings.h" name is shared with wolfSSL's own WOLFSSL_USER_SETTINGS - * header on purpose. The macro namespaces are disjoint (wolfCert reads only - * WOLFCERT_HAVE_*; wolfSSL reads HAVE_* / NO_* / WOLFSSL_*), so a single - * user_settings.h can carry both libraries' config - the recommended setup. - * Keep only one file by this name on your include path: both wolfSSL and - * wolfCert include it unqualified, so the first one found serves both. See - * docs/EMBEDDED.md. + * This template carries wolfCert's half of the config only. The + * "user_settings.h" name is shared with wolfSSL's own WOLFSSL_USER_SETTINGS + * header on purpose, and the macro namespaces are disjoint (wolfCert reads only + * WOLFCERT_HAVE_*; wolfSSL reads HAVE_* / NO_* / WOLFSSL_*), so one file can + * carry both. Building wolfSSL that way means adding its macros here too - the + * flag list at the end of this comment names them. Keep only one file by this + * name on your include path: both wolfSSL and wolfCert include it unqualified, + * so the first one found serves both. See docs/EMBEDDED.md. * * RULES * - To ENABLE a feature, leave its #define uncommented. diff --git a/scripts/ci/check-config-resolution.sh b/scripts/ci/check-config-resolution.sh new file mode 100755 index 0000000..f24bfd3 --- /dev/null +++ b/scripts/ci/check-config-resolution.sh @@ -0,0 +1,233 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Config-resolution gate: wolfCert's two public entry points must resolve the +# same wolfSSL feature set from the same flags. +# +# -> memory.h -> types.h -> check_config.h +# -> types.h -> check_config.h +# +# Each case stages an that disagrees with user_settings.h; +# docs/CI.md says why. +# +# Preprocess-only, so it wants a wolfSSL checkout for headers rather than a +# build, and finishes in seconds. +# +# Usage: +# check-config-resolution.sh --wolfssl-src DIR [--cc CC] [CASE ...] +# +# Defaults: --cc cc (CC_BIN also overrides), every case. + +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "$HERE/../.." && pwd)" + +CC_BIN="${CC_BIN:-cc}" +WOLFSSL_SRC="" +WANTED="" + +while [ "$#" -gt 0 ]; do + case "$1" in + --wolfssl-src) WOLFSSL_SRC="$2"; shift 2 ;; + --cc) CC_BIN="$2"; shift 2 ;; + -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; + --*) echo "ERROR: unknown flag '$1'." >&2; exit 2 ;; + *) WANTED="$WANTED $1"; shift ;; + esac +done + +if [ -z "$WOLFSSL_SRC" ]; then + echo "ERROR: --wolfssl-src is required." >&2 + exit 2 +fi +if [ ! -d "$WOLFSSL_SRC/wolfssl" ]; then + echo "ERROR: '$WOLFSSL_SRC' does not look like a wolfSSL checkout." >&2 + exit 2 +fi + +STAGE="$(mktemp -d)" +trap 'rm -rf "$STAGE"' EXIT +mkdir -p "$STAGE/inc" + +# Never a configured tree's own options.h: it describes that build, not the +# feature set each case pins here. +cp -R "$WOLFSSL_SRC/wolfssl" "$STAGE/inc/wolfssl" +rm -f "$STAGE/inc/wolfssl/options.h" + +# poison satisfies nothing wolfCert requires, rich satisfies everything. +write_decoy() { + { + echo '#ifndef WOLFSSL_OPTIONS_H' + echo '#define WOLFSSL_OPTIONS_H' + echo '#define WOLFCERT_CI_DECOY_OPTIONS_H' + if [ "$1" = "rich" ]; then + for m in HAVE_PKCS7 WOLFSSL_CERT_GEN WOLFSSL_CERT_REQ \ + WOLFSSL_CERT_EXT WOLFSSL_KEY_GEN WOLF_CRYPTO_CB \ + WOLFSSL_BASE64_ENCODE OPENSSL_EXTRA WOLFSSL_ALT_NAMES \ + WOLFSSL_CERT_NAME_ALL HAVE_SNI WOLFSSL_TLS13; do + echo "#define $m" + done + fi + echo '#endif' + } > "$STAGE/inc/wolfssl/options.h" +} + +# Preprocess one entry header into a sorted probe report. +probe() { + local hdr="$1" out="$2" rc=0 + "$CC_BIN" -E -P "${CPP_ARGS[@]}" -D"WOLFCERT_PROBE_HEADER=<$hdr>" \ + "$HERE/config-probe.c" > "$out.raw" 2> "$out.err" || rc=$? + grep -o 'wcprobe_[A-Za-z0-9_]*_is_[01]' "$out.raw" | sort -u > "$out.fp" || true + echo "$rc" > "$out.rc" +} + +# Compiler-independent diagnostic set: message text only. +norm_err() { + sed -nE 's/^.*(error|fatal error): //p' "$1" | sed 's/[[:space:]]*$//' | sort -u +} + +indent() { sed 's/^/ /'; } + +# name : decoy : user_settings.h source : WOLFSSL_USER_SETTINGS : header forced +# ahead of wolfCert's ("-" for none) : macro appended to the staged +# user_settings.h, so it arrives from inside the file rather than the command +# line ("-" for none) : expectation +CASES=" +usersettings-wins:poison:scripts/ci/freestanding-user_settings.h:on:-:-:agree-ok +optionsh-decoy:rich:scripts/ci/wolfcert-only-user_settings.h:on:-:-:agree-fail +optionsh-wins:rich:scripts/ci/wolfcert-only-user_settings.h:off:-:-:agree-ok-optionsh +wolfssl-header-first:rich:scripts/ci/wolfcert-only-user_settings.h:off:wolfssl/ssl.h:-:agree-fail-order +selector-in-user-settings:poison:scripts/ci/freestanding-user_settings.h:off:-:WOLFSSL_NO_OPTIONS_H:agree-ok +" + +status=0 +ran=0 + +for spec in $CASES; do + name="${spec%%:*}"; rest="${spec#*:}" + flavour="${rest%%:*}"; rest="${rest#*:}" + us_src="${rest%%:*}"; rest="${rest#*:}" + us_def="${rest%%:*}"; rest="${rest#*:}" + preinc="${rest%%:*}"; rest="${rest#*:}" + us_extra="${rest%%:*}"; expect="${rest#*:}" + + if [ -n "$WANTED" ]; then + case " $WANTED " in *" $name "*) ;; *) continue ;; esac + fi + ran=$((ran + 1)) + + write_decoy "$flavour" + cp "$ROOT/$us_src" "$STAGE/inc/user_settings.h" + if [ "$us_extra" != "-" ]; then + echo "#define $us_extra" >> "$STAGE/inc/user_settings.h" + fi + + CPP_ARGS=(-DWOLFCERT_USER_SETTINGS -I"$ROOT" -I"$STAGE/inc") + if [ "$us_def" = "on" ]; then + CPP_ARGS=(-DWOLFSSL_USER_SETTINGS "${CPP_ARGS[@]}") + fi + if [ "$preinc" != "-" ]; then + CPP_ARGS+=(-include "$preinc") + fi + + probe wolfcert/est.h "$STAGE/est" + probe wolfcert/wolfcert.h "$STAGE/umbrella" + + est_rc="$(cat "$STAGE/est.rc")" + umb_rc="$(cat "$STAGE/umbrella.rc")" + bad=0 + + if [ "$est_rc" != "$umb_rc" ]; then + echo " FAIL $name: the entry headers disagree on compilability" + echo " exit $est_rc" + echo " exit $umb_rc" + bad=1 + fi + + if ! diff -u "$STAGE/est.fp" "$STAGE/umbrella.fp" > "$STAGE/fp.diff"; then + echo " FAIL $name: the entry headers resolved a different wolfSSL" + echo " feature set from identical flags (-est.h, +wolfcert.h):" + grep '^[-+]wcprobe_' "$STAGE/fp.diff" | indent || true + bad=1 + fi + + if ! diff -u <(norm_err "$STAGE/est.err") <(norm_err "$STAGE/umbrella.err") \ + > "$STAGE/err.diff"; then + echo " FAIL $name: the entry headers produced different diagnostics" + echo " (-est.h, +wolfcert.h):" + grep '^[-+][^-+]' "$STAGE/err.diff" | indent || true + bad=1 + fi + + # Agreement alone is satisfiable by "both broken the same way", so pin the + # expected polarity too. + case "$expect" in + agree-ok) + if [ "$est_rc" != 0 ]; then + echo " FAIL $name: both agree but both failed; expected both to build." + sed 's/^/ /' "$STAGE/est.err" + bad=1 + fi + if grep -q 'wcprobe_WOLFCERT_CI_DECOY_OPTIONS_H_is_1' "$STAGE/est.fp"; then + echo " FAIL $name: a translation unit read while" + echo " WOLFSSL_USER_SETTINGS was defined; expected settings.h" + echo " to reach user_settings.h in both." + bad=1 + fi + ;; + agree-ok-optionsh) + if [ "$est_rc" != 0 ]; then + echo " FAIL $name: both agree but both failed; expected both to build." + sed 's/^/ /' "$STAGE/est.err" + bad=1 + elif ! grep -q 'wcprobe_WOLFCERT_CI_DECOY_OPTIONS_H_is_1' "$STAGE/est.fp"; then + echo " FAIL $name: no translation unit read while" + echo " WOLFSSL_USER_SETTINGS was undefined; expected" + echo " WOLFSSL_USE_OPTIONS_H to carry options.h into both." + bad=1 + fi + ;; + agree-fail-order) + if [ "$est_rc" = 0 ]; then + echo " FAIL $name: both agree but both built; a wolfSSL header" + echo " came first, so the ordering check was expected to stop them." + bad=1 + elif ! grep -q 'included before wolfCert' "$STAGE/est.err"; then + echo " FAIL $name: expected the include-order #error; got:" + sed 's/^/ /' "$STAGE/est.err" + bad=1 + elif grep -q 'wolfSSL is missing' "$STAGE/est.err"; then + echo " FAIL $name: tier-2 errors reported alongside the ordering" + echo " error; they name a feature set that was never resolved." + bad=1 + fi + ;; + agree-fail) + if [ "$est_rc" = 0 ]; then + echo " FAIL $name: both agree but both built; the decoy options.h was" + echo " expected to be ignored, leaving the tier-2 set unmet." + bad=1 + elif ! grep -q 'missing HAVE_PKCS7' "$STAGE/est.err"; then + echo " FAIL $name: expected the tier-2 HAVE_PKCS7 #error; got:" + sed 's/^/ /' "$STAGE/est.err" + bad=1 + fi + ;; + esac + + if [ "$bad" -eq 0 ]; then + printf ' ok %s (both exit %s)\n' "$name" "$est_rc" + else + status=1 + fi +done + +if [ "$ran" -eq 0 ]; then + echo "ERROR: no case matched '$WANTED'." >&2 + exit 2 +fi +if [ "$status" -eq 0 ]; then + echo "config resolution OK: $ran case(s), both entry headers agree." +fi +exit "$status" diff --git a/scripts/ci/compile-freestanding.sh b/scripts/ci/compile-freestanding.sh index 513d03f..0d7197d 100755 --- a/scripts/ci/compile-freestanding.sh +++ b/scripts/ci/compile-freestanding.sh @@ -47,16 +47,9 @@ trap 'rm -rf "$STAGE"' EXIT mkdir -p "$STAGE/inc" "$STAGE/obj" # Never a configured tree's own options.h: it describes that build, not the set -# pinned here. The stub replacing it is what --enable-usersettings generates, -# which check_config.h and memory.h need to resolve . +# pinned here. cp -R "$WOLFSSL_SRC/wolfssl" "$STAGE/inc/wolfssl" rm -f "$STAGE/inc/wolfssl/options.h" -cat > "$STAGE/inc/wolfssl/options.h" <<'EOF' -#ifndef WOLFSSL_OPTIONS_H -#define WOLFSSL_OPTIONS_H -#include -#endif -EOF cp "$HERE/freestanding-user_settings.h" "$STAGE/inc/user_settings.h" diff --git a/scripts/ci/config-probe.c b/scripts/ci/config-probe.c new file mode 100644 index 0000000..c1f6b09 --- /dev/null +++ b/scripts/ci/config-probe.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfCert. + * + * wolfCert 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. + * + * wolfCert 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 wolfCert. If not, see . + */ + +/* + * scripts/ci/config-probe.c - one translation unit, one wolfCert entry header. + * + * Driven by check-config-resolution.sh. WOLFCERT_PROBE_HEADER selects the + * header under test. Each macro below becomes a declaration naming itself, so + * `cc -E` alone reports the resolved wolfSSL feature set, and the report + * survives a tier-2 #error earlier in the file. + * + * WC_PROBE takes each macro name as a literal token: ## suppresses expansion, + * which matters because wolfSSL's feature macros are defined empty. + */ + +#include WOLFCERT_PROBE_HEADER + +#define WC_PROBE(name, v) extern int wcprobe_##name##_is_##v; + + +/* Provenance: which file supplied the feature set. */ +#ifdef WOLFCERT_CI_DECOY_OPTIONS_H +WC_PROBE(WOLFCERT_CI_DECOY_OPTIONS_H, 1) +#else +WC_PROBE(WOLFCERT_CI_DECOY_OPTIONS_H, 0) +#endif +#ifdef WOLFSSL_OPTIONS_H +WC_PROBE(WOLFSSL_OPTIONS_H, 1) +#else +WC_PROBE(WOLFSSL_OPTIONS_H, 0) +#endif +#ifdef WOLFSSL_USER_SETTINGS_H +WC_PROBE(WOLFSSL_USER_SETTINGS_H, 1) +#else +WC_PROBE(WOLFSSL_USER_SETTINGS_H, 0) +#endif +#ifdef WOLF_CRYPT_SETTINGS_H +WC_PROBE(WOLF_CRYPT_SETTINGS_H, 1) +#else +WC_PROBE(WOLF_CRYPT_SETTINGS_H, 0) +#endif + +/* The tier-2 set wolfcert/check_config.h validates. */ +#ifdef HAVE_PKCS7 +WC_PROBE(HAVE_PKCS7, 1) +#else +WC_PROBE(HAVE_PKCS7, 0) +#endif +#ifdef WOLFSSL_CERT_GEN +WC_PROBE(WOLFSSL_CERT_GEN, 1) +#else +WC_PROBE(WOLFSSL_CERT_GEN, 0) +#endif +#ifdef WOLFSSL_CERT_REQ +WC_PROBE(WOLFSSL_CERT_REQ, 1) +#else +WC_PROBE(WOLFSSL_CERT_REQ, 0) +#endif +#ifdef WOLFSSL_CERT_EXT +WC_PROBE(WOLFSSL_CERT_EXT, 1) +#else +WC_PROBE(WOLFSSL_CERT_EXT, 0) +#endif +#ifdef WOLFSSL_KEY_GEN +WC_PROBE(WOLFSSL_KEY_GEN, 1) +#else +WC_PROBE(WOLFSSL_KEY_GEN, 0) +#endif +#ifdef WOLF_CRYPTO_CB +WC_PROBE(WOLF_CRYPTO_CB, 1) +#else +WC_PROBE(WOLF_CRYPTO_CB, 0) +#endif +#ifdef WOLFSSL_BASE64_ENCODE +WC_PROBE(WOLFSSL_BASE64_ENCODE, 1) +#else +WC_PROBE(WOLFSSL_BASE64_ENCODE, 0) +#endif +#ifdef OPENSSL_EXTRA +WC_PROBE(OPENSSL_EXTRA, 1) +#else +WC_PROBE(OPENSSL_EXTRA, 0) +#endif +#ifdef WOLFSSL_ALT_NAMES +WC_PROBE(WOLFSSL_ALT_NAMES, 1) +#else +WC_PROBE(WOLFSSL_ALT_NAMES, 0) +#endif +#ifdef WOLFSSL_CERT_NAME_ALL +WC_PROBE(WOLFSSL_CERT_NAME_ALL, 1) +#else +WC_PROBE(WOLFSSL_CERT_NAME_ALL, 0) +#endif +#ifdef NO_AES +WC_PROBE(NO_AES, 1) +#else +WC_PROBE(NO_AES, 0) +#endif +#ifdef NO_SHA256 +WC_PROBE(NO_SHA256, 1) +#else +WC_PROBE(NO_SHA256, 0) +#endif +#ifdef WOLFSSL_NO_CONST_CMP +WC_PROBE(WOLFSSL_NO_CONST_CMP, 1) +#else +WC_PROBE(WOLFSSL_NO_CONST_CMP, 0) +#endif +#ifdef WOLFSSL_NO_FORCE_ZERO +WC_PROBE(WOLFSSL_NO_FORCE_ZERO, 1) +#else +WC_PROBE(WOLFSSL_NO_FORCE_ZERO, 0) +#endif +#ifdef HAVE_SNI +WC_PROBE(HAVE_SNI, 1) +#else +WC_PROBE(HAVE_SNI, 0) +#endif +#ifdef WOLFSSL_NO_TLS12 +WC_PROBE(WOLFSSL_NO_TLS12, 1) +#else +WC_PROBE(WOLFSSL_NO_TLS12, 0) +#endif +#ifdef WOLFSSL_TLS13 +WC_PROBE(WOLFSSL_TLS13, 1) +#else +WC_PROBE(WOLFSSL_TLS13, 0) +#endif + +/* Allocator shape, the reason wolfcert/memory.h resolves the config at all. */ +#ifdef WOLFSSL_STATIC_MEMORY +WC_PROBE(WOLFSSL_STATIC_MEMORY, 1) +#else +WC_PROBE(WOLFSSL_STATIC_MEMORY, 0) +#endif +#ifdef WOLFSSL_NO_MALLOC +WC_PROBE(WOLFSSL_NO_MALLOC, 1) +#else +WC_PROBE(WOLFSSL_NO_MALLOC, 0) +#endif +#ifdef WOLFCERT_CUSTOM_ALLOC +WC_PROBE(WOLFCERT_CUSTOM_ALLOC, 1) +#else +WC_PROBE(WOLFCERT_CUSTOM_ALLOC, 0) +#endif diff --git a/scripts/ci/wolfcert-only-user_settings.h b/scripts/ci/wolfcert-only-user_settings.h new file mode 100644 index 0000000..787e4e1 --- /dev/null +++ b/scripts/ci/wolfcert-only-user_settings.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfCert. + * + * wolfCert 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. + * + * wolfCert 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 wolfCert. If not, see . + */ + +/* + * scripts/ci/wolfcert-only-user_settings.h - fixture for the optionsh-decoy + * case of check-config-resolution.sh. + * + * Carries wolfCert's half of the config and no wolfSSL macros, so the case can + * tell whether the staged was consulted: the tier-2 checks + * are met only if it was. Do not add wolfSSL feature macros here. + */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#define WOLFCERT_HAVE_EST 1 +#define WOLFCERT_HAVE_SCEP 1 +#define WOLFCERT_HAVE_SERVER 1 + +#define WOLFCERT_HAVE_POSIX_STORE 1 +#define WOLFCERT_HAVE_BUILTIN_TRANSPORT 1 + +#define WOLFCERT_HAVE_RSA 1 +#define WOLFCERT_HAVE_ECC 1 +#define WOLFCERT_HAVE_ED25519 1 +#define WOLFCERT_HAVE_ED448 1 +#define WOLFCERT_HAVE_MLDSA 1 + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/src/ca_issue.c b/src/ca_issue.c index 584c1de..8894d29 100644 --- a/src/ca_issue.c +++ b/src/ca_issue.c @@ -30,7 +30,6 @@ #include "key_algs.h" #include -#include #include #include #include diff --git a/src/est/est_server.c b/src/est/est_server.c index 90dd88b..8a06233 100644 --- a/src/est/est_server.c +++ b/src/est/est_server.c @@ -32,7 +32,6 @@ #include #include "../internal.h" -#include #include #include #include diff --git a/src/internal.h b/src/internal.h index 9d012d9..8bc96bf 100644 --- a/src/internal.h +++ b/src/internal.h @@ -32,8 +32,6 @@ #include #include -#include -#include /* wolfssl/wolfcrypt/random.h declares a `pid_t` member under HAVE_GETPID * (e.g. static-memory builds). Pull in its POSIX declaration first so that * header compiles; harmless on configs that don't reference it. */ diff --git a/src/key_algs.h b/src/key_algs.h index ae1480a..4918938 100644 --- a/src/key_algs.h +++ b/src/key_algs.h @@ -33,7 +33,6 @@ #include -#include #include struct WolfCertKey; diff --git a/src/pkcs7_util.c b/src/pkcs7_util.c index 4835ec7..acc83ca 100644 --- a/src/pkcs7_util.c +++ b/src/pkcs7_util.c @@ -35,7 +35,6 @@ #include "internal.h" #include -#include #include #include #include diff --git a/src/scep/scep_client.c b/src/scep/scep_client.c index 9f7ae7d..9265c33 100644 --- a/src/scep/scep_client.c +++ b/src/scep/scep_client.c @@ -26,7 +26,6 @@ #include #include "../internal.h" -#include #include #include #include diff --git a/src/scep/scep_msg.c b/src/scep/scep_msg.c index f11c9ba..2ccce53 100644 --- a/src/scep/scep_msg.c +++ b/src/scep/scep_msg.c @@ -27,7 +27,6 @@ #include "../internal.h" #include -#include #include #include #include diff --git a/src/scep/scep_server.c b/src/scep/scep_server.c index 5e793a3..3b4903e 100644 --- a/src/scep/scep_server.c +++ b/src/scep/scep_server.c @@ -29,7 +29,6 @@ #include #include "../internal.h" -#include #include #include #include diff --git a/tests/integration/test_est_async_roundtrip.c b/tests/integration/test_est_async_roundtrip.c index 5d4d194..a474acf 100644 --- a/tests/integration/test_est_async_roundtrip.c +++ b/tests/integration/test_est_async_roundtrip.c @@ -40,7 +40,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_est_csr_attrs_apply_roundtrip.c b/tests/integration/test_est_csr_attrs_apply_roundtrip.c index 2f501df..131b2a3 100644 --- a/tests/integration/test_est_csr_attrs_apply_roundtrip.c +++ b/tests/integration/test_est_csr_attrs_apply_roundtrip.c @@ -39,7 +39,6 @@ #include #include -#include #include #include #include diff --git a/tests/integration/test_est_mldsa_roundtrip.c b/tests/integration/test_est_mldsa_roundtrip.c index 7b67dca..06d44b7 100644 --- a/tests/integration/test_est_mldsa_roundtrip.c +++ b/tests/integration/test_est_mldsa_roundtrip.c @@ -33,7 +33,6 @@ #include #include -#include #include #include #include diff --git a/tests/integration/test_est_mtls_roundtrip.c b/tests/integration/test_est_mtls_roundtrip.c index 142bb5e..031e507 100644 --- a/tests/integration/test_est_mtls_roundtrip.c +++ b/tests/integration/test_est_mtls_roundtrip.c @@ -45,7 +45,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_est_pending_roundtrip.c b/tests/integration/test_est_pending_roundtrip.c index 0be8f5c..7b8836e 100644 --- a/tests/integration/test_est_pending_roundtrip.c +++ b/tests/integration/test_est_pending_roundtrip.c @@ -42,7 +42,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_est_pha_roundtrip.c b/tests/integration/test_est_pha_roundtrip.c index 321dd09..c3899a8 100644 --- a/tests/integration/test_est_pha_roundtrip.c +++ b/tests/integration/test_est_pha_roundtrip.c @@ -43,7 +43,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_est_roundtrip.c b/tests/integration/test_est_roundtrip.c index a22c7c6..33b8164 100644 --- a/tests/integration/test_est_roundtrip.c +++ b/tests/integration/test_est_roundtrip.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/tests/integration/test_est_tls_roundtrip.c b/tests/integration/test_est_tls_roundtrip.c index 939a229..4f8999b 100644 --- a/tests/integration/test_est_tls_roundtrip.c +++ b/tests/integration/test_est_tls_roundtrip.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include diff --git a/tests/integration/test_scep_async_roundtrip.c b/tests/integration/test_scep_async_roundtrip.c index fa3b532..054fecc 100644 --- a/tests/integration/test_scep_async_roundtrip.c +++ b/tests/integration/test_scep_async_roundtrip.c @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_scep_get_cert.c b/tests/integration/test_scep_get_cert.c index bcfa3d0..00577ed 100644 --- a/tests/integration/test_scep_get_cert.c +++ b/tests/integration/test_scep_get_cert.c @@ -36,7 +36,6 @@ #include #include "internal.h" -#include #include #include #include diff --git a/tests/integration/test_scep_poll_roundtrip.c b/tests/integration/test_scep_poll_roundtrip.c index 4a35303..1aace50 100644 --- a/tests/integration/test_scep_poll_roundtrip.c +++ b/tests/integration/test_scep_poll_roundtrip.c @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/tests/integration/test_scep_roundtrip.c b/tests/integration/test_scep_roundtrip.c index 03325bf..813d735 100644 --- a/tests/integration/test_scep_roundtrip.c +++ b/tests/integration/test_scep_roundtrip.c @@ -26,7 +26,6 @@ #include #include -#include #include #include /* SHA256h */ #include diff --git a/tests/integration/test_server_stop_idle.c b/tests/integration/test_server_stop_idle.c index 4cf54f3..b114e2f 100644 --- a/tests/integration/test_server_stop_idle.c +++ b/tests/integration/test_server_stop_idle.c @@ -54,7 +54,6 @@ #include "tls_test_util.h" -#include #include #include diff --git a/tests/integration/test_tls_http.c b/tests/integration/test_tls_http.c index 0491987..b6d4f4e 100644 --- a/tests/integration/test_tls_http.c +++ b/tests/integration/test_tls_http.c @@ -30,7 +30,6 @@ #include -#include #include #include #include diff --git a/tests/integration/tls_test_util.h b/tests/integration/tls_test_util.h index 835be7b..da32ada 100644 --- a/tests/integration/tls_test_util.h +++ b/tests/integration/tls_test_util.h @@ -34,7 +34,6 @@ #include /* pid_t, referenced by wolfssl/wolfcrypt/random.h */ -#include #include #include #include diff --git a/tests/test_static_mem.h b/tests/test_static_mem.h index 58b5724..04ecc69 100644 --- a/tests/test_static_mem.h +++ b/tests/test_static_mem.h @@ -31,8 +31,6 @@ #include -#include - #if defined(WOLFSSL_STATIC_MEMORY) && defined(WOLFSSL_NO_MALLOC) #include diff --git a/tests/unit/test_csr.c b/tests/unit/test_csr.c index 86be26d..78b83e9 100644 --- a/tests/unit/test_csr.c +++ b/tests/unit/test_csr.c @@ -24,7 +24,6 @@ #include "internal.h" #include "../test_static_mem.h" -#include #include #include diff --git a/tests/unit/test_est.c b/tests/unit/test_est.c index cb4b32b..29f6e02 100644 --- a/tests/unit/test_est.c +++ b/tests/unit/test_est.c @@ -31,7 +31,6 @@ #include "../test_static_mem.h" #include "internal.h" -#include #include #include #include diff --git a/tests/unit/test_keygen.c b/tests/unit/test_keygen.c index beb3d80..ab115f0 100644 --- a/tests/unit/test_keygen.c +++ b/tests/unit/test_keygen.c @@ -20,8 +20,6 @@ #include #include "../test_static_mem.h" -#include /* WOLFSSL_NO_ML_DSA_{44,65,87} for per-level gating */ - #include #include diff --git a/tests/unit/test_scep_msg.c b/tests/unit/test_scep_msg.c index 03a57fe..7c6f0fc 100644 --- a/tests/unit/test_scep_msg.c +++ b/tests/unit/test_scep_msg.c @@ -37,7 +37,6 @@ #include "../test_static_mem.h" #include "internal.h" -#include #include #include #include diff --git a/tests/unit/test_server_ca_store.c b/tests/unit/test_server_ca_store.c index 6627f1e..47069fa 100644 --- a/tests/unit/test_server_ca_store.c +++ b/tests/unit/test_server_ca_store.c @@ -23,7 +23,6 @@ #include "../test_static_mem.h" #include "../integration/tls_test_util.h" -#include #include #include diff --git a/wolfcert/check_config.h b/wolfcert/check_config.h index ac9f79d..eebf311 100644 --- a/wolfcert/check_config.h +++ b/wolfcert/check_config.h @@ -32,15 +32,30 @@ * * Two tiers: * 1. wolfCert's own constraints, from the WOLFCERT_HAVE_* macros. - * 2. The wolfSSL feature set wolfCert depends on, from . - * Define WOLFCERT_NO_WOLFSSL_FEATURE_CHECK to skip tier 2 - needed only - * when wolfSSL itself is configured through its own user_settings.h, where - * does not reflect the real feature set. + * 2. The wolfSSL feature set wolfCert depends on, read through + * so it also sees a wolfSSL configured by + * its own user_settings.h. Define WOLFCERT_NO_WOLFSSL_FEATURE_CHECK to + * skip the tier-2 checks. */ #ifndef WOLFCERT_CHECK_CONFIG_H #define WOLFCERT_CHECK_CONFIG_H +#if !defined(WOLFSSL_USER_SETTINGS) && !defined(WOLFSSL_USE_OPTIONS_H) && \ + !defined(WOLFSSL_NO_OPTIONS_H) && !defined(WOLFSSL_CUSTOM_CONFIG) && \ + !defined(ARDUINO) && !defined(PLATFORMIO) && \ + !defined(USE_HAL_DRIVER) && !defined(NUCLEUS_PLUS_2_3) && \ + !defined(WOLFSSL_MX2_CONF_INCLUDE) + #define WOLFSSL_USE_OPTIONS_H +#endif +#include + +#if defined(WOLFSSL_USE_OPTIONS_H) && !defined(WOLFSSL_OPTIONS_H) && \ + !defined(WOLFSSL_NO_OPTIONS_H) +#define WOLFCERT_WOLFSSL_CONFIG_UNRESOLVED +#error "A wolfSSL header was included before wolfCert's, so was never read and wolfSSL's feature set is at its defaults. Include first; or, if wolfSSL takes its configuration another way, define WOLFSSL_USE_OPTIONS_H, WOLFSSL_CUSTOM_CONFIG or WOLFSSL_NO_OPTIONS_H before the wolfSSL header." +#endif + /* ---- Tier 1: wolfCert feature constraints ---- */ /* At least one key algorithm must be present. */ @@ -67,9 +82,8 @@ /* ---- Tier 2: required wolfSSL feature set ---- */ -#ifndef WOLFCERT_NO_WOLFSSL_FEATURE_CHECK - -#include +#if !defined(WOLFCERT_NO_WOLFSSL_FEATURE_CHECK) && \ + !defined(WOLFCERT_WOLFSSL_CONFIG_UNRESOLVED) /* Mandatory wolfSSL features. Rebuild wolfSSL with: * ./configure --enable-pkcs7 --enable-certgen --enable-certreq \ @@ -141,6 +155,6 @@ #error "wolfSSL provides neither TLS 1.2 nor TLS 1.3; wolfCert needs at least one for its HTTPS transport." #endif -#endif /* WOLFCERT_NO_WOLFSSL_FEATURE_CHECK */ +#endif /* tier 2 */ #endif /* WOLFCERT_CHECK_CONFIG_H */ diff --git a/wolfcert/memory.h b/wolfcert/memory.h index 58935d0..bd44d22 100644 --- a/wolfcert/memory.h +++ b/wolfcert/memory.h @@ -28,12 +28,10 @@ * interpret any way it likes (wolfSSL static memory uses it to select a * bucket; host builds ignore it). * - * By default (`WOLFCERT_USE_WOLFSSL_HEAP` set at build time, which is the - * case for every supported wolfSSL build) the macros expand to wolfSSL's - * own XMALLOC/XFREE so wolfCert shares exactly the pool that the rest of - * the application's wolfSSL code uses. When wolfSSL's static-memory option - * is enabled the pool is hard-capped; wolfCert will honour that limit - * instead of silently reaching past it with raw libc malloc. + * By default the macros expand to wolfSSL's own XMALLOC/XFREE so wolfCert + * shares exactly the pool that the rest of the application's wolfSSL code + * uses. When wolfSSL's static-memory option is enabled the pool is + * hard-capped; wolfCert will honour that limit. * * Callers that want to pin wolfCert's allocations to a specific heap * register the hint through wolfcert_set_default_heap(); individual APIs @@ -47,6 +45,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -54,12 +53,11 @@ extern "C" { /* Pluggable allocator. If the application doesn't override it, we use * wolfSSL's XMALLOC family which in turn respects WOLFSSL_STATIC_MEMORY. - * Embedded integrators that build wolfCert with WOLFCERT_NO_MALLOC can - * replace the macros at compile time. */ + * Embedded integrators that define WOLFCERT_CUSTOM_ALLOC supply the three + * macros themselves. */ #if defined(WOLFCERT_CUSTOM_ALLOC) /* Project defines these macros externally. */ #else -# include # include # define WOLFCERT_XMALLOC(sz, heap) XMALLOC((sz), (heap), DYNAMIC_TYPE_TMP_BUFFER) # define WOLFCERT_XREALLOC(p, sz, heap) XREALLOC((p), (sz), (heap), DYNAMIC_TYPE_TMP_BUFFER) diff --git a/wolfcert/wolfcert.h b/wolfcert/wolfcert.h index 8f322b6..5ae8a0d 100644 --- a/wolfcert/wolfcert.h +++ b/wolfcert/wolfcert.h @@ -30,8 +30,8 @@ #include #include #include -#include #include +#include #include #include #include