Skip to content

feat: SBOM generation and OmniBOR build provenance (CRA compliance)#10343

Open
MarkAtwood wants to merge 1 commit intowolfSSL:masterfrom
MarkAtwood:feat/sbom-bomsh
Open

feat: SBOM generation and OmniBOR build provenance (CRA compliance)#10343
MarkAtwood wants to merge 1 commit intowolfSSL:masterfrom
MarkAtwood:feat/sbom-bomsh

Conversation

@MarkAtwood
Copy link
Copy Markdown

Summary

Adds two complementary supply chain transparency targets to the wolfSSL autotools build:

  • make sbom — generates a Software Bill of Materials (SPDX 2.3 + CycloneDX 1.6) for EU Cyber Resilience Act (CRA) compliance
  • make bomsh — generates an OmniBOR artifact dependency graph (cryptographic source-to-binary traceability) using the Bomsh project
  • When both are run, make bomsh enriches the SPDX document with a PERSISTENT-ID gitoid ExternalRef, bridging component identity and build provenance in a single file

make sbom

Produces three files:

File Format
wolfssl-<version>.cdx.json CycloneDX 1.6 JSON
wolfssl-<version>.spdx.json SPDX 2.3 JSON
wolfssl-<version>.spdx SPDX 2.3 tag-value (validated by pyspdxtools)

SBOM contents: name, version, supplier, license (parsed from LICENSING at generation time), copyright, SHA-256 of installed library, CPE, PURL, download location, build configuration defines, and optional third-party dependency versions (liboqs, libz, libxmss, liblms).

Implementation: scripts/gen-sbom (Python 3, stdlib only) stages a make install into a temp directory, hashes the installed library, generates both formats, removes staging. configure.ac detects python3, pyspdxtools, and git via AC_PATH_PROG. make sbom fails with a clear error if either required tool is missing.

make bomsh

Runs a full clean rebuild under bomtrace3 (patched strace — userspace only, no kernel modifications) to produce an OmniBOR artifact graph in omnibor/. If bomsh_sbom.py is available and wolfssl-<version>.spdx.json exists, annotates the SPDX with a PERSISTENT-ID gitoid ExternalRef.

configure.ac detects bomtrace3, bomsh_create_bom.py, and bomsh_sbom.py via AC_PATH_PROG. The raw logfile and conf file are written to the build directory (not /tmp/) to avoid concurrent-build collisions. All generated files removed by make clean.

Install targets

make install-sbom     # installs SBOM files to $(datadir)/doc/wolfssl/
make install-bomsh    # installs omnibor/ and enriched SPDX to $(datadir)/doc/wolfssl/

Documentation

  • doc/SBOM.md — unified reference covering both targets, combined workflow, all output files, implementation notes
  • doc/CRA.md — product-integrator guide: how to incorporate wolfSSL's SBOM artefacts into a downstream product SBOM (SPDX ExternalDocumentRef, CycloneDX component reference), commercial license guidance, OmniBOR gitoid meaning, auditor handoff checklist, links to OpenSSF CRA and SBOM Everywhere SIG guidance
  • INSTALL: sections 21 and 22
  • README.md: brief SBOM/CRA and OmniBOR/Bomsh sections
  • doc/include.am: SBOM.md and CRA.md added to dist_doc_DATA

Test plan

  • ./autogen.sh && ./configure && make && make sbom — verify three SBOM files produced and SPDX validates
  • make install-sbom / make uninstall-sbom — verify files install and remove cleanly
  • make clean — verify all generated files removed
  • With bomtrace3 and bomsh_create_bom.py in PATH: make sbom && make bomsh — verify omnibor/ produced and omnibor.wolfssl-<ver>.spdx.json contains PERSISTENT-ID gitoid ExternalRef
  • Without bomtrace3 in PATH: make bomsh — verify clear error message, non-zero exit
  • Without prior make sbom: make bomsh — verify OmniBOR graph produced, NOTE printed about missing SPDX, no failure

Adds two complementary supply chain transparency targets to the
wolfSSL autotools build, and documentation covering both as a unified
whole.

## make sbom

Generates a Software Bill of Materials for EU Cyber Resilience Act
(CRA) compliance.  Produces three files in the build directory:

  wolfssl-<version>.cdx.json   CycloneDX 1.6 JSON
  wolfssl-<version>.spdx.json  SPDX 2.3 JSON
  wolfssl-<version>.spdx       SPDX 2.3 tag-value (validated)

The SPDX JSON is validated by pyspdxtools before the tag-value file
is written; make sbom fails if validation fails.

SBOM contents: package name/version, supplier, license (parsed from
LICENSING at generation time, not hardcoded), copyright, SHA-256 of
the installed library, CPE, PURL, download location, and build
configuration defines as a comment.  Third-party dependencies
(liboqs, libz, libxmss, liblms) are included when enabled.

Implementation: scripts/gen-sbom (Python 3, stdlib only) stages a
make install into a temporary directory, hashes the installed
library, generates both SBOM formats, then removes the staging
directory.  configure.ac detects python3, pyspdxtools, and git via
AC_PATH_PROG.

install-sbom / uninstall-sbom targets install the three files to
$(datadir)/doc/wolfssl/.  make clean removes all generated files.

## make bomsh

Generates an OmniBOR artifact dependency graph using the Bomsh
project (https://github.com/omnibor/bomsh), providing cryptographic
traceability from every built binary back to the exact set of source
files that produced it.

Runs a full clean rebuild under bomtrace3 (a patched strace, userspace
only — no kernel modifications required).  bomtrace3 intercepts every
compiler execve() syscall and records inputs and outputs; it cannot
post-process an already-built tree, hence the clean rebuild.
bomsh_create_bom.py processes the raw logfile to produce the OmniBOR
artifact objects and metadata in omnibor/.

If bomsh_sbom.py is available and wolfssl-<version>.spdx.json exists
(from make sbom), annotates that SPDX document with a PERSISTENT-ID
gitoid ExternalRef, producing omnibor.wolfssl-<version>.spdx.json.
This enriched SPDX bridges component identity and build provenance in
a single document.

configure.ac detects bomtrace3, bomsh_create_bom.py, and bomsh_sbom.py
via AC_PATH_PROG.  The raw logfile and conf file are written to the
build directory (not /tmp/) to avoid concurrent-build collisions, and
removed by make clean.

install-bomsh / uninstall-bomsh targets install omnibor/ and the
enriched SPDX to $(datadir)/doc/wolfssl/.

## Documentation

doc/SBOM.md: unified reference covering both make sbom and make bomsh
as parts of a single supply chain transparency story — component
identity (what) and build provenance (how) — with a combined workflow
section and full output file reference.

doc/CRA.md: product-integrator guide covering how to incorporate
wolfSSL's SBOM artefacts into a downstream product SBOM (SPDX
ExternalDocumentRef and CycloneDX component reference patterns),
commercial license concluded-field guidance, OmniBOR gitoid meaning,
auditor handoff checklist, and links to OpenSSF CRA and SBOM Everywhere
SIG guidance pages.

INSTALL: sections 21 (make sbom) and 22 (make bomsh).
README.md: brief SBOM/CRA and OmniBOR/Bomsh sections.
doc/include.am: SBOM.md and CRA.md added to dist_doc_DATA.
Copilot AI review requested due to automatic review settings April 28, 2026 21:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds build-integrated supply-chain transparency outputs to the Autotools build: SBOM generation (make sbom) and OmniBOR/Bomsh build provenance tracing (make bomsh) to support CRA-style compliance workflows.

Changes:

  • Add scripts/gen-sbom Python generator for CycloneDX 1.6 + SPDX 2.3 JSON SBOM outputs (plus tag-value conversion via pyspdxtools).
  • Wire new sbom, bomsh, and install/uninstall targets into Autotools (configure.ac, Makefile.am), with tool discovery via AC_PATH_PROG.
  • Add end-user documentation (doc/SBOM.md, doc/CRA.md) and reference it from README.md/INSTALL.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
scripts/gen-sbom New Python SBOM generator producing CycloneDX/SPDX JSON with optional dependency metadata.
Makefile.am Adds sbom/bomsh targets, install/uninstall rules, and clean integration.
configure.ac Detects required tools (python3, pyspdxtools, git, bomtrace3, bomsh scripts) and exports needed vars.
doc/include.am Ships new docs in the dist tarball; cleans generated OmniBOR directory.
doc/SBOM.md Primary documentation for SBOM + OmniBOR workflows and outputs.
doc/CRA.md Downstream integrator guidance for CRA-oriented SBOM/provenance usage.
README.md Adds brief pointers to the new SBOM/CRA and OmniBOR features.
INSTALL Adds new sections documenting make sbom / make bomsh usage and prerequisites.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/SBOM.md
tree root (passed via `configure` as `XMSS_ROOT` / `LIBLMS_ROOT`). If the
source tree has no tags, `git describe` returns the short commit hash, which
is recorded as-is. If the source tree is unavailable or `git` is not found,
version is recorded as `NOASSERTION`.
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This section says that when git is not found or the source tree is unavailable, the dependency version “is recorded as NOASSERTION”. In the current generator, SPDX uses NOASSERTION, but CycloneDX omits the version and purl fields entirely (and prints a warning). Please update the wording to reflect the CycloneDX behavior, or change the generator to emit a consistent placeholder.

Suggested change
version is recorded as `NOASSERTION`.
SPDX records the version as `NOASSERTION`; CycloneDX omits the `version` and
`purl` fields and emits a warning.

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +452 to +453
$(MKDIR_P) $(DESTDIR)$(bomshdir)
cp -r '$(BOMSH_OMNIBORDIR)' '$(DESTDIR)$(bomshdir)/omnibor'
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

install-bomsh uses cp -r to install the omnibor/ tree. This bypasses standard install tooling (permissions, verbosity, portability, $(INSTALL) overrides) and can behave differently across platforms. Consider using an Automake-friendly install approach (e.g., create the dir then copy files with $(INSTALL_DATA) via find, or use tar piping) so packaging/install behaves consistently.

Suggested change
$(MKDIR_P) $(DESTDIR)$(bomshdir)
cp -r '$(BOMSH_OMNIBORDIR)' '$(DESTDIR)$(bomshdir)/omnibor'
$(MKDIR_P) '$(DESTDIR)$(bomshdir)'
$(MKDIR_P) '$(DESTDIR)$(bomshdir)/omnibor'
@if test -d '$(BOMSH_OMNIBORDIR)'; then \
cd '$(BOMSH_OMNIBORDIR)' && tar cf - . | \
(cd '$(DESTDIR)$(bomshdir)/omnibor' && tar xpf -); \
fi

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +435 to +440
$(MAKE) clean
@printf 'raw_logfile=%s\n' '$(BOMSH_RAWLOG_BASE)' > '$(BOMSH_CONF)'
$(BOMTRACE3) -c '$(BOMSH_CONF)' $(MAKE)
$(BOMSH_CREATE_BOM) -r '$(BOMSH_RAWLOG)' -b '$(BOMSH_OMNIBORDIR)'
@if test -n "$(BOMSH_SBOM)" && test -f '$(abs_builddir)/wolfssl-$(PACKAGE_VERSION).spdx.json'; then \
echo "Enriching SPDX with OmniBOR ExternalRefs..."; \
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

make bomsh starts with $(MAKE) clean), but make clean removes the SBOM outputs (they’re in CLEANFILES). That means even if the user runs make sbom first, the subsequent test -f wolfssl-$(PACKAGE_VERSION).spdx.json will be false and the SPDX enrichment step won’t run. Consider preserving/regenerating the SPDX after the traced rebuild (e.g., run the SBOM generator after the bomtrace3 rebuild, or copy the SPDX aside before clean and restore it).

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +378 to +383
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
--name $(PACKAGE) \
--version $(PACKAGE_VERSION) \
--license-file $(srcdir)/LICENSING \
--options-h $(abs_builddir)/wolfssl/options.h \
--lib $(abs_builddir)/_sbom_staging$(libdir)/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD) \
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The SBOM hash input path is hard-coded to libwolfssl.so.<first>.<second>.<third>. This will fail on configurations that disable shared libraries (e.g., --disable-shared, and also when --with-libxmss / --with-liblms forces enable_shared=no in configure.ac). Please detect the installed library artifact dynamically (shared vs static, platform suffixes) or fall back to hashing the static archive when the .so is not present.

Suggested change
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
--name $(PACKAGE) \
--version $(PACKAGE_VERSION) \
--license-file $(srcdir)/LICENSING \
--options-h $(abs_builddir)/wolfssl/options.h \
--lib $(abs_builddir)/_sbom_staging$(libdir)/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD) \
@sbom_lib=""; \
for lib in \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.so.* \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.so \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.dylib \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.*.dylib \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.dll \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.dll.a \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.lib \
"$(abs_builddir)/_sbom_staging$(libdir)"/wolfssl.lib \
"$(abs_builddir)/_sbom_staging$(libdir)"/libwolfssl.a; do \
if test -f "$$lib"; then \
sbom_lib="$$lib"; \
break; \
fi; \
done; \
if test -z "$$sbom_lib"; then \
echo ""; \
echo "ERROR: Unable to locate installed wolfSSL library artifact for SBOM generation."; \
echo " Searched in $(abs_builddir)/_sbom_staging$(libdir) for shared and static library outputs."; \
echo ""; \
rm -rf $(abs_builddir)/_sbom_staging; \
exit 1; \
fi; \
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
--name $(PACKAGE) \
--version $(PACKAGE_VERSION) \
--license-file $(srcdir)/LICENSING \
--options-h $(abs_builddir)/wolfssl/options.h \
--lib "$$sbom_lib" \

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +440 to +446
echo "Enriching SPDX with OmniBOR ExternalRefs..."; \
$(BOMSH_SBOM) \
-b '$(BOMSH_OMNIBORDIR)' \
-i '$(abs_builddir)/wolfssl-$(PACKAGE_VERSION).spdx.json' \
-f '$(abs_builddir)/src/.libs/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD)' \
-s spdx-json \
-O '$(abs_builddir)'; \
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The Bomsh SPDX enrichment uses a hard-coded shared-library path (src/.libs/libwolfssl.so.<...>). This will fail on static-only builds and on non-ELF platforms (e.g., macOS .dylib). Consider resolving the built artifact path in a platform/config-aware way (or passing the installed artifact from the staging area, similar to make sbom).

Suggested change
echo "Enriching SPDX with OmniBOR ExternalRefs..."; \
$(BOMSH_SBOM) \
-b '$(BOMSH_OMNIBORDIR)' \
-i '$(abs_builddir)/wolfssl-$(PACKAGE_VERSION).spdx.json' \
-f '$(abs_builddir)/src/.libs/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD)' \
-s spdx-json \
-O '$(abs_builddir)'; \
bomsh_artifact=""; \
for candidate in \
$(abs_builddir)/src/.libs/libwolfssl.so \
$(abs_builddir)/src/.libs/libwolfssl.so.* \
$(abs_builddir)/src/.libs/libwolfssl.dylib \
$(abs_builddir)/src/.libs/libwolfssl.*.dylib \
$(abs_builddir)/src/.libs/libwolfssl.a \
$(abs_builddir)/src/libwolfssl.a; do \
if test -f "$$candidate"; then \
bomsh_artifact="$$candidate"; \
break; \
fi; \
done; \
if test -n "$$bomsh_artifact"; then \
echo "Enriching SPDX with OmniBOR ExternalRefs..."; \
$(BOMSH_SBOM) \
-b '$(BOMSH_OMNIBORDIR)' \
-i '$(abs_builddir)/wolfssl-$(PACKAGE_VERSION).spdx.json' \
-f "$$bomsh_artifact" \
-s spdx-json \
-O '$(abs_builddir)'; \
else \
echo "NOTE: unable to locate a built libwolfssl artifact for SPDX enrichment."; \
fi; \

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +378 to +392
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
--name $(PACKAGE) \
--version $(PACKAGE_VERSION) \
--license-file $(srcdir)/LICENSING \
--options-h $(abs_builddir)/wolfssl/options.h \
--lib $(abs_builddir)/_sbom_staging$(libdir)/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD) \
--dep-liboqs $(ENABLED_LIBOQS) \
--dep-libxmss $(ENABLED_LIBXMSS) \
--dep-libxmss-root '$(XMSS_ROOT)' \
--dep-liblms $(ENABLED_LIBLMS) \
--dep-liblms-root '$(LIBLMS_ROOT)' \
--dep-libz $(ENABLED_LIBZ) \
--git '$(GIT)' \
--cdx-out $(abs_builddir)/$(SBOM_CDX) \
--spdx-out $(abs_builddir)/$(SBOM_SPDX)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

scripts/gen-sbom is invoked from make sbom, but it is not currently listed in scripts/include.am’s EXTRA_DIST/dist_noinst_SCRIPTS. As a result, make dist tarballs are likely to omit the generator and make sbom will fail for users building from release archives. Please add scripts/gen-sbom to the distribution list.

Copilot uses AI. Check for mistakes.
Comment thread Makefile.am
Comment on lines +376 to +394
rm -rf $(abs_builddir)/_sbom_staging
$(MAKE) install DESTDIR=$(abs_builddir)/_sbom_staging
$(PYTHON3) $(srcdir)/scripts/gen-sbom \
--name $(PACKAGE) \
--version $(PACKAGE_VERSION) \
--license-file $(srcdir)/LICENSING \
--options-h $(abs_builddir)/wolfssl/options.h \
--lib $(abs_builddir)/_sbom_staging$(libdir)/libwolfssl.so.$(WOLFSSL_LIBRARY_VERSION_FIRST).$(WOLFSSL_LIBRARY_VERSION_SECOND).$(WOLFSSL_LIBRARY_VERSION_THIRD) \
--dep-liboqs $(ENABLED_LIBOQS) \
--dep-libxmss $(ENABLED_LIBXMSS) \
--dep-libxmss-root '$(XMSS_ROOT)' \
--dep-liblms $(ENABLED_LIBLMS) \
--dep-liblms-root '$(LIBLMS_ROOT)' \
--dep-libz $(ENABLED_LIBZ) \
--git '$(GIT)' \
--cdx-out $(abs_builddir)/$(SBOM_CDX) \
--spdx-out $(abs_builddir)/$(SBOM_SPDX)
rm -rf $(abs_builddir)/_sbom_staging
$(PYSPDXTOOLS) --infile $(abs_builddir)/$(SBOM_SPDX) \
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

If scripts/gen-sbom fails, the _sbom_staging directory is not cleaned up because rm -rf only runs after the generator completes successfully. Consider ensuring staging cleanup happens even on failure (e.g., trap/cleanup handler or chaining cleanup with ||), to avoid leaving large staged installs behind.

Copilot uses AI. Check for mistakes.
Comment thread scripts/gen-sbom
Comment on lines +314 to +321
'creationInfo': {
'licenseListVersion': '3.28',
'creators': [
f'Organization: {supplier}',
'Tool: wolfssl-sbom-gen-1.0'
],
'created': timestamp,
},
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

licenseListVersion is hard-coded to 3.28. If a user’s pyspdxtools/license-list data is older, this may cause SPDX validation to fail even when the document is otherwise correct. Consider omitting licenseListVersion (it’s optional in SPDX 2.3) or deriving it from the tool/runtime to keep make sbom robust across environments.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@Frauschi
Copy link
Copy Markdown
Contributor

Note that we are in the process of removing liblms and libxmss (see #10292), which will simplify the dependency analysis in the python script.

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.

4 participants