Skip to content

sbom: generate SBOMs from every wolfBoot build system#830

Open
sameehj wants to merge 3 commits into
wolfSSL:masterfrom
sameehj:sbom-wolfboot-full
Open

sbom: generate SBOMs from every wolfBoot build system#830
sameehj wants to merge 3 commits into
wolfSSL:masterfrom
sameehj:sbom-wolfboot-full

Conversation

@sameehj

@sameehj sameehj commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Description

wolfBoot ships as source. Users build it in many ways. Each user needs an
SBOM for the build that the user makes. This PR makes wolfBoot produce a
CycloneDX 1.6 and SPDX 2.3 SBOM from every build system, and it makes the
SBOM reproducible.

One engine does the work. Each build system gives the engine two inputs:
the compiled source list and the build configuration. The engine captures
the configuration with the host compiler, so the SBOM is the same for GCC,
Clang, LLVM, IAR, armcl, CCRX, and XC32.

What is new

  • A shared driver: tools/scripts/wolfboot-sbom.sh.
  • Front ends for each build system:
    • Make and arch.mk and vendor SDKs: make sbom.
    • CMake and the Pico SDK: cmake --build --target sbom.
    • IAR Embedded Workbench: ide-sbom/iar_sbom.py.
    • Any IDE with a compilation database: ide-sbom/compdb_sbom.py.
    • TI CCS, MPLAB X, Renesas, Xilinx: ide-sbom/route_through_sbom.sh.
    • Per-HAL component: make sbom-hal.
    • Zephyr module: ide-sbom/zephyr_sbom.py.
  • A validator: ide-sbom/validate_sbom.py.
  • A CI canary: .github/workflows/test-sbom.yml.
  • Documentation: docs/SBOM.md and docs/SBOM-WOLFGLASS.md.

Reproducibility fix

The driver captures build macros with the host compiler. Some macros hold
an absolute host path. For example, arch.mk passes
-DPICO_SDK_PATH=$(PICO_SDK_PATH). Before this change, the path entered
the SBOM. The SBOM was then different on each machine, and it leaked the
local file system.

The driver now redacts each absolute path in the captured macros. It keeps
the macro name, so the configuration record stays complete. The CI canary
asserts that no path leaks and that the macro name stays. Use --no-scrub
for debug only.

Toolchain support

The SBOM content does not depend on the cross-compiler. The config uses
the host compiler. The composition is a source list. So Clang, LLVM,
Renesas CCRX, TI armcl, and IAR all give the same SBOM. A new toolchain
needs no work. A new IDE that emits a compilation database needs no work.

Relation to wolfGlass

The tools are product-neutral. They are self-contained in wolfBoot on
purpose. They are the reference implementation of the shared SBOM layer
for every wolfSSL product (wolfSSL, wolfHSM, and others). docs/ SBOM-WOLFGLASS.md gives the file-by-file migration map and the list of
changes that wolfGlass must cover. No wolfBoot logic changes when the
tools move.

Prerequisite

The tools need gen-sbom from wolfSSL (lib/wolfssl/scripts/gen-sbom).
If the pinned submodule does not carry it, pass a path with GEN_SBOM=...
or the --gen-sbom option. The CI canary fetches it from wolfSSL master
as a fallback.

Testing

  • make sbom TARGET=sim produces a valid SBOM. The validator passes.
  • make sbom-hal TARGET=sim produces a valid per-HAL SBOM.
  • cmake --build <dir> --target sbom produces a valid SBOM.
  • The IAR, compdb, and Zephyr extractors produce valid SBOMs.
  • The scrub check confirms that no absolute path enters the SBOM and that
    the macro name stays.

Notes

  • wolfBoot embeds wolfCrypt sources. The SBOM lists these as wolfBoot
    sources, not as a separate component.
  • A vendor SDK build lists only the source files on disk.
  • The driver is a POSIX shell script. On Windows, run it in WSL, MSYS, or
    Git Bash. As an alternative, use compdb_sbom.py.

wolfBoot ships as source. Users build it in many ways. Before this
change, only the plain Make build could make an SBOM. So a user could not
make an SBOM for the build that the user runs.

This change adds one shared engine (tools/scripts/wolfboot-sbom.sh, which
calls wolfSSL gen-sbom) and a front end for each build system. Every
build makes a CycloneDX 1.6 and SPDX 2.3 document. The engine captures
the configuration with the host compiler, so the SBOM is the same for
GCC, Clang, LLVM, IAR, armcl, CCRX, and XC32.

Routes:
  - Make, arch.mk, and vendor SDKs: make sbom TARGET=<t> SIGN=<a>
  - CMake and the Pico SDK: cmake --build <dir> --target sbom
  - IAR Embedded Workbench: ide-sbom/iar_sbom.py
  - Any IDE with a compilation database: ide-sbom/compdb_sbom.py
  - TI CCS, MPLAB X, Renesas, Xilinx: ide-sbom/route_through_sbom.sh
  - Per-HAL component: make sbom-hal TARGET=<t>
  - Zephyr module: ide-sbom/zephyr_sbom.py

Make the SBOM reproducible. The captured macros can hold an absolute host
path. For example, arch.mk passes -DPICO_SDK_PATH=$(PICO_SDK_PATH). The
driver now redacts each absolute path but keeps the macro name, so the
configuration record stays complete. Add --no-scrub for debug.

Add a validator (ide-sbom/validate_sbom.py) and a CI canary
(.github/workflows/test-sbom.yml) that runs and validates every route.
The canary also checks that no host path leaks into the SBOM.

Add docs/SBOM.md. The tools are product-neutral by design, so they can be
shared across wolfSSL products later without logic changes.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@sameehj
sameehj force-pushed the sbom-wolfboot-full branch from 04988d9 to 9380897 Compare July 23, 2026 08:03
The SBOM canary now guards the properties customers rely on, not only
that each route runs.

sbom_canary job adds three checks:
  * Toolchain neutrality - build the same sim config with gcc and with
    clang and require a byte-identical CycloneDX and SPDX result. The
    driver captures configuration with the host compiler and a source
    list, so the cross-toolchain that builds the firmware does not change
    the SBOM. clang, LLVM and vendor compilers need no separate front end.
  * Reproducibility - build the same config from a second absolute path
    and require an identical SBOM, so no build path leaks into the output.
  * Path scrub in a real build - build rp2350 with an absolute
    PICO_SDK_PATH and assert the path is redacted while the macro key is
    kept. This exercises the scrub through arch.mk, not a synthetic line.

New cross_targets job runs make sbom for a spread of architectures with
no IDE and no cross-toolchain installed: stm32h7, nrf52840, imx-rt1060
and sama5d3 (Arm), nxp-t1040 (PowerPC), renesas-rx65n (Renesas RX) and
hifive1 (RISC-V). The driver never calls the cross compiler, so each
target produces a valid SBOM on a plain runner. This proves the "any
target, any toolchain, no hardware" guarantee.

Every produced document is checked with validate_sbom.py and uploaded as
a build artifact.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
@sameehj
sameehj force-pushed the sbom-wolfboot-full branch from e16d1a6 to df63948 Compare July 23, 2026 09:06
Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
@sameehj sameehj self-assigned this Jul 23, 2026

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #830

No scan targets match the changed files in this PR. Review skipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants