Files
wolfssl/doc/CRA.md
T
Sameeh Jubran 4ec80d309a feat: SBOM generation and OmniBOR build provenance (CRA compliance)
Add tooling to produce Software Bills of Materials and build provenance
for wolfSSL, supporting EU Cyber Resilience Act (CRA) obligations.

SBOM generation:
- New `make sbom` target producing SPDX 2.3 output with NTIA minimum
  elements, urn:uuid document namespaces, and SPDX LicenseRef compliance.
- Reproducible library discovery across autotools and CMake builds, with
  liboqs recorded as a linked artefact.
- Standalone `scripts/gen-sbom` for embedded / RTOS / custom-builder
  flows that do not use the main build system, plus --srcs-file,
  --no-artifact-hash, and hash-source options.

Build provenance (OmniBOR / bomsh):
- End-to-end bomsh tracing of the built binaries with ArtifactID
  insertion, snapshotting the traced library before libtool relink and
  hashing the bomsh-traced binary.
- `scripts/bomsh_verify.py` to validate provenance against the traced
  gitoid.

Security advisories:
- `scripts/gen-advisory` generating CSAF 2.0 and CycloneDX VEX, with a
  `make` target, VEX overlay schema/example, and CWE name data.

Docs, tests, and CI:
- doc/SBOM.md and doc/CRA.md, plus README/INSTALL updates.
- Unit and regression tests for gen-sbom and gen-advisory.
- New sbom.yml and advisory.yml workflows: SPDX validation via
  pyspdxtools, CSAF validation, bomsh provenance verification, SBOM
  artifact archiving, macOS coverage, and actions pinned to SHAs.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
2026-07-23 21:51:26 -07:00

13 KiB

wolfSSL and the EU Cyber Resilience Act

This guide is for product teams that ship a product containing wolfSSL and need to satisfy EU Cyber Resilience Act (CRA) obligations related to software component transparency and build traceability.

Background

The CRA requires manufacturers of products with digital elements placed on the EU market to identify and document the software components in those products. The practical requirement is a machine-readable Software Bill of Materials (SBOM) covering all open-source and third-party components, following the NTIA minimum element guidelines.

wolfSSL provides two complementary artefacts to help you meet this requirement:

Artefact Produced by What it answers
SBOM (SPDX 2.3 + CycloneDX 1.6) make sbom What is in wolfSSL (identity, license, CPE, PURL, checksum)
OmniBOR artifact graph make bomsh How wolfSSL was built (cryptographic source-to-binary traceability)

For most CRA use cases the SBOM alone is sufficient. The OmniBOR graph provides a deeper audit trail if your compliance posture requires it.

Quick Start

wolfSSL exposes two SBOM entry points, depending on how you build the library.

Embedded / RTOS / IDE-based builds (no ./configure)

If your product builds wolfSSL with a hand-edited user_settings.h and a custom Makefile, Keil / IAR / STM32CubeIDE project, ESP-IDF / Zephyr component, or plain CMake, invoke scripts/gen-sbom directly. No autotools required:

python3 wolfssl/scripts/gen-sbom \
    --name wolfssl --version 5.9.1 \
    --license-file wolfssl/LICENSING \
    --user-settings wolfssl/wolfssl/wolfcrypt/settings.h \
    --user-settings-include wolfssl \
    --user-settings-include path/to/your/user_settings_dir \
    --user-settings-define WOLFSSL_USER_SETTINGS \
    --srcs wolfssl/wolfcrypt/src/aes.c [and the rest of your wolfssl source list] \
    --cdx-out wolfssl-5.9.1.cdx.json \
    --spdx-out wolfssl-5.9.1.spdx.json

Requires Python 3 + pip install pcpp (used to walk user_settings.h the same way the C compiler does).

See doc/SBOM.md § 1 for per-toolchain recipes (Keil, IAR, STM32CubeIDE, ESP-IDF, Zephyr, plain CMake) and the full flag reference.

Linux / autotools builds

For Debian / RPM / Yocto / FIPS-Ready / cloud builds that already use ./configure && make:

./configure
make
make sbom         # produces wolfssl-<version>.spdx.json, .cdx.json, .spdx
make bomsh        # optional: produces omnibor/ + OmniBOR-enriched SPDX

make sbom is a convenience wrapper around the same scripts/gen-sbom script the embedded path uses.

See doc/SBOM.md for prerequisites and full details on both entry points.

What wolfSSL Provides

After make sbom:

wolfssl-<version>.spdx.json    SPDX 2.3 JSON (machine processing)
wolfssl-<version>.cdx.json     CycloneDX 1.6 JSON (supply-chain tooling, VEX)
wolfssl-<version>.spdx         SPDX 2.3 tag-value (human review, archival)

After make bomsh (with make sbom already run):

omnibor/                            OmniBOR artifact dependency graph
omnibor.wolfssl-<version>.spdx.json SPDX enriched with PERSISTENT-ID gitoid

Integrating wolfSSL into Your Product SBOM

Your product SBOM needs to list wolfSSL as a component. The two standard approaches are to reference wolfSSL's SBOM document from yours, or to copy the wolfSSL package entry directly into your document.

Reference wolfSSL's SPDX document from your product's SPDX document using externalDocumentRefs. This keeps the documents separate and lets wolfSSL's SBOM stand as an independently verifiable artefact.

wolfSSL ships the generated SBOM with the source distribution and does not currently publish it at a fixed, resolvable URL. In the spdxDocument field below, substitute the URI under which your distribution mirrors wolfssl-<version>.spdx.json (e.g. an artifact server, OCI registry, or distribution mirror you control). SPDX 2.3 §6.5 only requires the value be a unique URI; if you do not re-host, the urn:uuid:<uuid5-derived> form that make sbom emits by default is acceptable.

{
  "externalDocumentRefs": [
    {
      "externalDocumentId": "DocumentRef-wolfssl",
      "spdxDocument": "<URI where your distribution serves wolfssl-<version>.spdx.json>",
      "checksum": {
        "algorithm": "SHA256",
        "checksumValue": "<sha256-of-wolfssl-spdx.json>"
      }
    }
  ]
}

Then express the dependency in your relationships section:

{
  "spdxElementId": "SPDXRef-Package-YourProduct",
  "relatedSpdxElement": "DocumentRef-wolfssl:SPDXRef-Package-wolfssl",
  "relationshipType": "DYNAMIC_LINK"
}

Use STATIC_LINK if you link wolfSSL statically, DYNAMIC_LINK if you use the shared library, or CONTAINS if you redistribute the source.

Alternatively, copy the wolfSSL package entry from its SPDX document directly into your own SPDX document and add the DYNAMIC_LINK / STATIC_LINK relationship to your product package.

CycloneDX: component reference

Include wolfSSL as a component in your CycloneDX BOM, referencing the wolfSSL CycloneDX document via an external reference of type bom.

As with the SPDX spdxDocument URI above, wolfSSL does not currently publish CycloneDX SBOMs at a fixed, resolvable URL; substitute the URI under which your distribution mirrors wolfssl-<version>.cdx.json.

{
  "type": "library",
  "name": "wolfssl",
  "version": "<version>",
  "purl": "pkg:github/wolfSSL/wolfssl@v<version>",
  "cpe": "cpe:2.3:a:wolfssl:wolfssl:<version>:*:*:*:*:*:*:*",
  "licenses": [{ "license": { "id": "GPL-3.0-only" } }],
  "externalReferences": [
    {
      "type": "bom",
      "url": "<URI where your distribution serves wolfssl-<version>.cdx.json>",
      "hashes": [
        {
          "alg": "SHA-256",
          "content": "<sha256-of-wolfssl-cdx.json>"
        }
      ]
    }
  ]
}

Commercial License Users

wolfSSL's published SBOM records licenseConcluded: GPL-3.0-only, which reflects the open-source license. If you are distributing a product under a wolfSSL commercial license, you have two options:

Option 1: regenerate the SBOM with your license expression

Pass SBOM_LICENSE_OVERRIDE to make sbom to bake your SPDX expression directly into the artefact (preferred — survives re-runs, no manual editing):

make sbom \
    SBOM_LICENSE_OVERRIDE=LicenseRef-wolfSSL-Commercial \
    SBOM_LICENSE_TEXT=/path/to/wolfssl-commercial-license.txt

SBOM_LICENSE_TEXT is required whenever SBOM_LICENSE_OVERRIDE uses a custom LicenseRef-* identifier. SPDX 2.3 §10.1 requires the actual licence text to be embedded in hasExtractedLicensingInfos for any LicenseRef used in the document; SPDX-conformant validators (e.g. pyspdxtools) will reject the SBOM otherwise. ntia-conformance-checker validates a separate set of NTIA minimum elements (supplier, component name, version, unique identifier, dependency relationships, author, timestamp) and will not catch a missing extracted-text block — do not rely on it to gate this case. The file should contain the plain-text licence agreement you received from wolfSSL.

If SBOM_LICENSE_OVERRIDE is set to a LicenseRef-* and SBOM_LICENSE_TEXT is missing, make sbom exits with an error rather than emit an invalid SBOM that might end up in front of a regulator.

For a stock SPDX-listed identifier (Apache-2.0, MIT, etc.) the SBOM_LICENSE_TEXT argument is unnecessary because validators already know the canonical text.

Or invoke the generator directly with --license-override / --license-text if you are producing the SBOM outside the standard make target.

Option 2: update your product SBOM's reference to wolfSSL

Leave the upstream SBOM file alone and override licenseConcluded on the wolfSSL package entry in your product SBOM:

"licenseConcluded": "LicenseRef-wolfSSL-Commercial"

Do not modify the wolfSSL-published SBOM file in place; either regenerate it with the override (Option 1) or override at the consumer level (Option 2).

Reproducible SBOMs

The generator honors SOURCE_DATE_EPOCH for the SBOM creation timestamp and uses deterministic UUIDs derived from the package name and version, so two runs of make sbom against the same source tree, library binary, and build options produce byte-identical .spdx.json and .cdx.json files. This matters for downstream attestation pipelines that hash SBOMs as part of a provenance chain.

make sbom will derive SOURCE_DATE_EPOCH from git log -1 --format=%ct if you do not set it explicitly and the wolfSSL source tree is a git checkout.

Build Provenance (OmniBOR)

The CRA also encourages transparency about how software is built, not just what it contains. Running make bomsh after make sbom produces an OmniBOR artifact dependency graph and an enriched SPDX document:

omnibor.wolfssl-<version>.spdx.json

This file is identical to wolfssl-<version>.spdx.json except it adds a PERSISTENT-ID gitoid entry to the wolfSSL package's externalRefs:

{
  "referenceCategory": "PERSISTENT-ID",
  "referenceType": "gitoid",
  "referenceLocator": "gitoid:blob:sha1:<hash>"
}

The gitoid is the entry point into the OmniBOR Merkle DAG stored in omnibor/. A CRA auditor or supply-chain tool can follow that identifier through the graph to verify that a specific libwolfssl.so binary was produced from a specific, unmodified set of source files.

Use omnibor.wolfssl-<version>.spdx.json in place of the plain SPDX file when you want to include this traceability claim in your product SBOM.

What to Give Your Auditor

For a CRA conformity assessment, provide:

File Purpose
wolfssl-<version>.spdx.json Machine-readable component identity (SPDX 2.3)
wolfssl-<version>.cdx.json Machine-readable component identity (CycloneDX 1.6)
wolfssl-<version>.spdx Human-readable tag-value form
omnibor/ + omnibor.wolfssl-<version>.spdx.json Build traceability (optional, if bomsh was run)

If you have a product-level SBOM that references wolfSSL via ExternalDocumentRef (SPDX) or a bom external reference (CycloneDX), include that product SBOM alongside the wolfSSL artefacts.

CRA Article 10 also obliges manufacturers to handle and disclose vulnerabilities. wolfSSL's vulnerability disclosure process is documented in SECURITY-POLICY.md at the repository root, with a mandatory reporting template at SECURITY-REPORT-TEMPLATE.md. Reports go to support@wolfssl.com; published advisories live at https://www.wolfssl.com/docs/security-vulnerabilities/. The policy explicitly accommodates ecosystem-coordination embargoes for downstream integrators and certification bodies — point your auditor at this so they can verify the disclosure path before signing off.

Further Reading

wolfSSL documentation

  • doc/SBOM.md — unified reference covering SBOM generation, OmniBOR/Bomsh build provenance, combined workflow, output formats, and implementation notes
  • SECURITY-POLICY.md — vulnerability disclosure policy, severity rubric, coordinated-disclosure practice, embargo extensions for downstream integrators and certification bodies
  • SECURITY-REPORT-TEMPLATE.md — mandatory template for vulnerability reports submitted to wolfSSL

OpenSSF guidance

  • CRA Brief Guide for OSS Developers — Clarifies when the CRA applies to open source projects and maintainers, and what obligations fall on manufacturers integrating OSS components into commercial products (i.e., you, if you ship a product containing wolfSSL).

  • SBOM in Compliance — OpenSSF SBOM Everywhere SIG survey of the global regulatory landscape: CRA, NTIA minimum elements, US EO 14028, Germany TR-03183, and others. Useful for understanding how wolfSSL's SBOM artefacts map to each framework.

  • Getting Started with SBOMs — OpenSSF SBOM Everywhere SIG guidance on SBOM generation approaches (build-integrated vs. separate tooling), phase selection, and publication. wolfSSL's make sbom follows the build-integrated approach recommended here.

  • OpenSSF CRA Policy Hub — Ongoing OpenSSF coverage of CRA developments, implementation guidance, and community responses.

  • SBOM Everywhere Wiki — OpenSSF SIG home: tooling catalog, working group resources, naming conventions, and cross-format guidance for SPDX and CycloneDX.

Standards