Skip to content

Commit 0f8185e

Browse files
ci: add a freestanding ARM compile gate and require wolfSSL SNI
1 parent 3ee6529 commit 0f8185e

11 files changed

Lines changed: 255 additions & 5 deletions

File tree

.github/workflows/nightly.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ jobs:
4646
- { name: cmake-mldsa-44off, os: ubuntu-latest, build: cmake, wolfssl: mldsa-44off }
4747
- { name: cmake-mldsa-65off, os: ubuntu-latest, build: cmake, wolfssl: mldsa-65off }
4848
- { name: cmake-mldsa-87off, os: ubuntu-latest, build: cmake, wolfssl: mldsa-87off }
49+
# ---- Platform pieces compiled out (transport/store gates) ----
50+
- { name: cmake-no-builtin-transport, os: ubuntu-latest, build: cmake, wolfssl: full, cmake_extra: "-DWOLFCERT_ENABLE_BUILTIN_TRANSPORT=OFF -DWOLFCERT_ENABLE_POSIX_STORE=OFF -DWOLFCERT_ENABLE_CLI=OFF -DWOLFCERT_ENABLE_SERVER=OFF" }
4951
# ---- Constrained builds (unit tests only: single-thread / no-malloc) ----
5052
- { name: cmake-static-mem, os: ubuntu-latest, build: cmake, wolfssl: static-mem, cmake_extra: -DWOLFCERT_ENABLE_SERVER=OFF, ctest_exclude: "http|tls|roundtrip" }
5153
- { name: cmake-no-malloc, os: ubuntu-latest, build: cmake, wolfssl: no-malloc, ctest_exclude: "http|tls|roundtrip|est" }

.github/workflows/pr.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ jobs:
103103
os: ubuntu-latest
104104
build: cmake
105105
wolfssl: mldsa-87off
106+
# ---- Platform pieces compiled out (the transport/store gates) ----
107+
- name: cmake-no-builtin-transport
108+
os: ubuntu-latest
109+
build: cmake
110+
wolfssl: full
111+
# Neither the CLI nor the test server can supply a transport, so
112+
# both build systems reject them here. The socket-driven tests
113+
# exit 77 (skipped) on their own; nothing needs excluding.
114+
cmake_extra: >-
115+
-DWOLFCERT_ENABLE_BUILTIN_TRANSPORT=OFF
116+
-DWOLFCERT_ENABLE_POSIX_STORE=OFF
117+
-DWOLFCERT_ENABLE_CLI=OFF
118+
-DWOLFCERT_ENABLE_SERVER=OFF
106119
# ---- Constrained builds (unit tests only: single-thread / no-malloc) --
107120
- name: cmake-static-mem
108121
os: ubuntu-latest
@@ -224,6 +237,27 @@ jobs:
224237
cmake --build build -j "$(nproc)"
225238
ctest --test-dir build -j "$(nproc)" --output-on-failure
226239
240+
no-posix-arm:
241+
name: freestanding ARM compile (no POSIX)
242+
runs-on: ubuntu-latest
243+
timeout-minutes: 10
244+
steps:
245+
- uses: actions/checkout@v4
246+
- name: Install the bare-metal ARM toolchain
247+
run: |
248+
sudo apt-get update
249+
sudo apt-get install -y gcc-arm-none-eabi
250+
# Headers only: nothing is compiled from wolfSSL and nothing is linked,
251+
# so this needs no wolfSSL build and no prefix cache.
252+
- name: Check out wolfSSL headers
253+
run: |
254+
git clone --depth 1 --branch "$WOLFSSL_REF" \
255+
https://github.com/wolfSSL/wolfssl "$RUNNER_TEMP/wolfssl"
256+
- name: Compile every portable source for Cortex-M4
257+
run: |
258+
scripts/ci/compile-freestanding.sh \
259+
--wolfssl-src "$RUNNER_TEMP/wolfssl"
260+
227261
negative-config:
228262
name: negative-config (fail-fast gates)
229263
runs-on: ubuntu-latest

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ wolfSSL configure:
6767
--enable-certext --enable-keygen --enable-ecc --enable-cryptocb \
6868
--enable-base64encode --enable-ed25519 --enable-ed448 \
6969
--enable-mldsa --enable-postauth --enable-opensslextra \
70-
--enable-ip-alt-name --enable-des3 \
70+
--enable-ip-alt-name --enable-des3 --enable-sni \
7171
CPPFLAGS="-DWOLFSSL_ALT_NAMES -DWOLFSSL_CERT_NAME_ALL"
7272
```
7373

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ optional key types wolfCert picks up when available:
6868
--enable-keygen --enable-ecc --enable-cryptocb --enable-base64encode \
6969
--enable-ed25519 --enable-ed448 --enable-mldsa \
7070
--enable-postauth --enable-opensslextra --enable-ip-alt-name \
71-
--enable-des3 \
71+
--enable-des3 --enable-sni \
7272
CPPFLAGS="-DWOLFSSL_ALT_NAMES -DWOLFSSL_CERT_NAME_ALL"
7373
```
7474

docs/CI.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ build entirely.
1010

1111
| Workflow | Trigger | What it does |
1212
|----------|---------|--------------|
13-
| `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 header-only (`WOLFCERT_USER_SETTINGS`) build, a macOS build, and the two cheapest configure-must-fail assertions. |
13+
| `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. |
1414
| `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. |
1515
| `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`). |
1616
| `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. |
@@ -62,3 +62,17 @@ TLS / all key algorithms, so wolfCert's compile-time `#error` guards for those
6262
scripts/ci/assert-configure-fails.sh # all cases, both build systems
6363
scripts/ci/assert-configure-fails.sh no-rsa-scep # a single case
6464
```
65+
66+
The `no-posix-arm` gate compiles every portable `src/*.c` for a Cortex-M4
67+
against wolfSSL's headers only, keeping wolfCert runnable on a non-BSD-sockets
68+
stack. Nothing is built or linked, so it needs a wolfSSL checkout rather than a
69+
prefix. Its feature set is `scripts/ci/freestanding-user_settings.h`; the
70+
script's own header documents the rest.
71+
72+
```sh
73+
git clone --depth 1 https://github.com/wolfSSL/wolfssl /tmp/wolfssl-src
74+
scripts/ci/compile-freestanding.sh --wolfssl-src /tmp/wolfssl-src
75+
```
76+
77+
Its companion is the `cmake-no-builtin-transport` row: the ARM job proves the
78+
code is header-clean, that row proves the gated build links and passes tests.

docs/EMBEDDED.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,15 @@ build systems reject enabling them alongside `--disable-builtin-transport`.
245245
A wolfSSL built with `WOLFSSL_USER_IO` works: wolfCert installs its own CBIO
246246
callbacks on every session, so wolfSSL's own socket I/O is never needed.
247247

248+
**wolfCert requires `HAVE_SNI`**, which a cross-compiled wolfSSL often lacks;
249+
`check_config.h` fails the build with a message pointing at `--enable-sni`.
250+
251+
If your device only reaches endpoints that serve a single certificate, or
252+
addresses them by IP, define `WOLFCERT_NO_SNI` to build without it. Do not
253+
take that opt-out for a hosted EST service: the server would return its
254+
default certificate and `verify_server` would reject the handshake with
255+
`WOLFCERT_ERR_TLS`.
256+
248257
## A worked "small footprint" wolfSSL config
249258

250259
```c

scripts/ci/build-wolfssl.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ _base_flags() {
4545
--enable-keygen --enable-ecc --enable-cryptocb --enable-base64encode \
4646
--enable-ed25519 --enable-ed448 --enable-mldsa \
4747
--enable-postauth --enable-opensslextra --enable-ip-alt-name \
48-
--enable-des3 \
48+
--enable-des3 --enable-sni \
4949
'CPPFLAGS=-DWOLFSSL_ALT_NAMES -DWOLFSSL_CERT_NAME_ALL'
5050
}
5151

scripts/ci/compile-freestanding.sh

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: GPL-3.0-or-later
3+
#
4+
# Compile every portable wolfCert source for a bare-metal ARM target: no POSIX
5+
# headers, no built-in transport, no POSIX store, no test server. This keeps
6+
# src/http.c, src/csr.c and src/store.c free of syscalls, so wolfCert can run on
7+
# a non-BSD-sockets stack through a caller-supplied WolfCertTransport.
8+
#
9+
# Compile-only, so it wants a wolfSSL checkout for headers rather than a build,
10+
# and finishes in seconds. Feature set: freestanding-user_settings.h alongside.
11+
#
12+
# Usage:
13+
# compile-freestanding.sh --wolfssl-src DIR [--cc CC] [--cpu MCPU]
14+
#
15+
# Defaults: --cc arm-none-eabi-gcc, --cpu cortex-m4 (CC_BIN / CPU also override).
16+
17+
set -euo pipefail
18+
19+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20+
ROOT="$(cd "$HERE/../.." && pwd)"
21+
22+
CC_BIN="${CC_BIN:-arm-none-eabi-gcc}"
23+
CPU="${CPU:-cortex-m4}"
24+
WOLFSSL_SRC=""
25+
26+
while [ "$#" -gt 0 ]; do
27+
case "$1" in
28+
--wolfssl-src) WOLFSSL_SRC="$2"; shift 2 ;;
29+
--cc) CC_BIN="$2"; shift 2 ;;
30+
--cpu) CPU="$2"; shift 2 ;;
31+
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
32+
*) echo "ERROR: unknown flag '$1'." >&2; exit 2 ;;
33+
esac
34+
done
35+
36+
if [ -z "$WOLFSSL_SRC" ]; then
37+
echo "ERROR: --wolfssl-src is required." >&2
38+
exit 2
39+
fi
40+
if [ ! -d "$WOLFSSL_SRC/wolfssl" ]; then
41+
echo "ERROR: '$WOLFSSL_SRC' does not look like a wolfSSL checkout." >&2
42+
exit 2
43+
fi
44+
45+
STAGE="$(mktemp -d)"
46+
trap 'rm -rf "$STAGE"' EXIT
47+
mkdir -p "$STAGE/inc" "$STAGE/obj"
48+
49+
# Never a configured tree's own options.h: it describes that build, not the set
50+
# pinned here. The stub replacing it is what --enable-usersettings generates,
51+
# which check_config.h and memory.h need to resolve <wolfssl/options.h>.
52+
cp -R "$WOLFSSL_SRC/wolfssl" "$STAGE/inc/wolfssl"
53+
rm -f "$STAGE/inc/wolfssl/options.h"
54+
cat > "$STAGE/inc/wolfssl/options.h" <<'EOF'
55+
#ifndef WOLFSSL_OPTIONS_H
56+
#define WOLFSSL_OPTIONS_H
57+
#include <user_settings.h>
58+
#endif
59+
EOF
60+
61+
cp "$HERE/freestanding-user_settings.h" "$STAGE/inc/user_settings.h"
62+
63+
# From CMakeLists.txt, so a new src/*.c joins the gate automatically. Skipped:
64+
# the POSIX transport and the test server, both POSIX by design.
65+
SKIP_RE='^src/(net_posix|server|ca_issue|est/est_server|scep/scep_server)\.c$'
66+
SRCS="$(grep -oE 'src/[A-Za-z0-9_/]+\.c' "$ROOT/CMakeLists.txt" \
67+
| sort -u | grep -Ev "$SKIP_RE" || true)"
68+
69+
if [ -z "$SRCS" ]; then
70+
echo "ERROR: no sources extracted from CMakeLists.txt" >&2
71+
exit 1
72+
fi
73+
n_srcs="$(printf '%s\n' "$SRCS" | wc -l | tr -d ' ')"
74+
75+
# -Wno-error=cpp keeps wolfSSL's own #warning non-fatal; ours stay fatal.
76+
CFLAGS=(-c -mcpu="$CPU" -mthumb -ffreestanding
77+
-Wall -Wextra -Werror -Wno-error=cpp
78+
-DWOLFSSL_USER_SETTINGS -DWOLFCERT_USER_SETTINGS
79+
-I"$ROOT" -I"$STAGE/inc")
80+
81+
echo "Compiling $n_srcs sources with $CC_BIN (-mcpu=$CPU), no POSIX:"
82+
status=0
83+
# Fed by here-doc rather than an array: macOS ships bash 3.2, which has no
84+
# mapfile.
85+
while IFS= read -r s; do
86+
obj="$STAGE/obj/$(echo "$s" | tr '/' '_').o"
87+
if "$CC_BIN" "${CFLAGS[@]}" -o "$obj" "$ROOT/$s" 2> "$STAGE/err.log"; then
88+
printf ' ok %s\n' "$s"
89+
else
90+
printf ' FAIL %s\n' "$s"
91+
sed 's/^/ /' "$STAGE/err.log"
92+
status=1
93+
fi
94+
done <<EOF
95+
$SRCS
96+
EOF
97+
98+
if [ "$status" -eq 0 ]; then
99+
echo "freestanding compile OK: $n_srcs sources, no POSIX headers."
100+
fi
101+
exit "$status"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (C) 2026 wolfSSL Inc.
3+
*
4+
* This file is part of wolfCert.
5+
*
6+
* wolfCert is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* wolfCert is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with wolfCert. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
/* Combined wolfSSL + wolfCert config for the freestanding ARM gate
21+
* (scripts/ci/compile-freestanding.sh), read via -DWOLFSSL_USER_SETTINGS
22+
* -DWOLFCERT_USER_SETTINGS. One file for both, as docs/EMBEDDED.md advises.
23+
* Deliberately absent: the built-in transport, POSIX store, server and
24+
* HAVE_SNI, so this no-sockets target keeps those paths compiled out. */
25+
26+
#ifndef WOLFSSL_USER_SETTINGS_H
27+
#define WOLFSSL_USER_SETTINGS_H
28+
29+
/* --- target shape: no OS, no filesystem, app-supplied I/O --- */
30+
#define SINGLE_THREADED
31+
#define NO_FILESYSTEM
32+
#define NO_WRITEV
33+
#define WOLFSSL_USER_IO
34+
#define NO_MAIN_DRIVER
35+
#define WOLFSSL_IGNORE_FILE_WARN
36+
#define NO_WOLFSSL_DIR
37+
#define WOLFSSL_NO_SOCK
38+
39+
/* --- the ten wolfCert requires --- */
40+
#define HAVE_PKCS7
41+
#define WOLFSSL_CERT_GEN
42+
#define WOLFSSL_CERT_REQ
43+
#define WOLFSSL_CERT_EXT
44+
#define WOLFSSL_KEY_GEN
45+
#define WOLF_CRYPTO_CB
46+
#define WOLFSSL_BASE64_ENCODE
47+
#define OPENSSL_EXTRA
48+
#define WOLFSSL_ALT_NAMES
49+
#define WOLFSSL_CERT_NAME_ALL
50+
51+
/* --- algorithms PKCS#7 + TLS need --- */
52+
#define HAVE_AES_CBC
53+
#define HAVE_AESGCM
54+
#define WOLFSSL_AES_DIRECT
55+
#define HAVE_ECC
56+
#define HAVE_HKDF
57+
#define WOLFSSL_SHA384
58+
#define WOLFSSL_SHA512
59+
#define HAVE_TLS_EXTENSIONS
60+
#define HAVE_ED25519
61+
#define HAVE_ED448
62+
#define WOLFSSL_SHAKE256
63+
#define WOLFSSL_SHA3
64+
#define HAVE_DILITHIUM
65+
#define WOLFSSL_WC_DILITHIUM
66+
#define HAVE_SUPPORTED_CURVES
67+
#define WOLFSSL_TLS13
68+
#define HAVE_ENCRYPT_THEN_MAC
69+
70+
71+
/* ---- wolfCert: no sockets, no filesystem ---- */
72+
#define WOLFCERT_NO_SNI
73+
#define WOLFCERT_HAVE_EST 1 /* EST (RFC 7030) */
74+
#define WOLFCERT_HAVE_SCEP 1 /* SCEP (RFC 8894) - requires WOLFCERT_HAVE_RSA */
75+
#define WOLFCERT_HAVE_RSA 1
76+
#define WOLFCERT_HAVE_ECC 1
77+
#define WOLFCERT_HAVE_ED25519 1
78+
#define WOLFCERT_HAVE_ED448 1
79+
#define WOLFCERT_HAVE_MLDSA 1
80+
81+
#endif

src/http.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,9 @@ static int setup_tls_ex(WolfCertConn* c, const TlsDials* dials,
923923
}
924924

925925
if (sni_host != NULL) {
926+
#ifdef HAVE_SNI
926927
wolfSSL_UseSNI(ssl, 0, sni_host, (word16)strlen(sni_host));
928+
#endif
927929

928930
if (dials->verify_server) {
929931
/* RFC 6125: a literal address matches iPAddress SAN entries

0 commit comments

Comments
 (0)