Skip to content

Commit 073f4eb

Browse files
committed
feat(sbom): validation, reproducibility, install targets
- Validate SPDX with pyspdxtools and emit tag-value wolfhsm-<ver>.spdx; SBOM_VALIDATE=no skips both - Honor SOURCE_DATE_EPOCH, defaulting to last git commit time, so repeated runs are byte-identical - Add opt-in install-sbom / uninstall-sbom under $(PREFIX)/share/doc/wolfhsm - List wolfssl as a dependency component with version read from WOLFSSL_DIR; SBOM_DEP_WOLFSSL=no for WOLFHSM_CFG_NO_CRYPTO builds
1 parent d03b224 commit 073f4eb

2 files changed

Lines changed: 74 additions & 5 deletions

File tree

Makefile

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,17 @@ clean:
6161
CC ?= cc
6262
WOLFSSL_DIR ?= ../wolfssl
6363
WOLFHSM_CFG_DIR ?= test/config
64+
PREFIX ?= /usr/local
65+
SBOM_INSTALL_DIR ?= $(PREFIX)/share/doc/wolfhsm
66+
SBOM_VALIDATE ?= yes
67+
SBOM_DEP_WOLFSSL ?= yes
6468
VERSION = $(shell sed -n 's/^. wolfHSM Release v//p' ChangeLog.md | head -1 | cut -d' ' -f1)
6569
SRCS := $(sort $(wildcard src/*.c))
6670
SBOM_CDX = wolfhsm-$(VERSION).cdx.json
6771
SBOM_SPDX = wolfhsm-$(VERSION).spdx.json
72+
SBOM_SPDX_TV = wolfhsm-$(VERSION).spdx
6873

69-
.PHONY: sbom
74+
.PHONY: sbom install-sbom uninstall-sbom
7075

7176
sbom:
7277
@if [ -z "$(VERSION)" ]; then \
@@ -91,6 +96,13 @@ sbom:
9196
echo " wolfhsm_cfg.h (and user_settings.h) your build uses." >&2; \
9297
exit 1; \
9398
fi
99+
@if [ "$(SBOM_VALIDATE)" != "no" ] && \
100+
! command -v pyspdxtools >/dev/null 2>&1; then \
101+
echo "ERROR: 'pyspdxtools' not found (pip install spdx-tools)." >&2; \
102+
echo " It validates the SPDX output and converts it to" >&2; \
103+
echo " tag-value. Set SBOM_VALIDATE=no to skip both." >&2; \
104+
exit 1; \
105+
fi
94106
@echo "wolfHSM version: $(VERSION)"
95107
@echo "Sources: $(words $(SRCS)) .c files in src/"
96108
@echo "Config: $(WOLFHSM_CFG_DIR)/wolfhsm_cfg.h"
@@ -124,13 +136,59 @@ sbom:
124136
if ! command -v python3 >/dev/null 2>&1; then \
125137
echo "ERROR: python3 not found." >&2; exit 1; \
126138
fi && \
139+
if [ -z "$${SOURCE_DATE_EPOCH:-}" ] && \
140+
command -v git >/dev/null 2>&1 && \
141+
git rev-parse --git-dir >/dev/null 2>&1; then \
142+
sde=$$(git log -1 --format=%ct 2>/dev/null); \
143+
if [ -n "$$sde" ]; then \
144+
SOURCE_DATE_EPOCH="$$sde"; export SOURCE_DATE_EPOCH; \
145+
fi; \
146+
fi && \
147+
dep_args=""; \
148+
if [ "$(SBOM_DEP_WOLFSSL)" != "no" ]; then \
149+
if python3 $(WOLFSSL_DIR)/scripts/gen-sbom --help 2>/dev/null \
150+
| grep -q -- '--dep-wolfssl'; then \
151+
dep_args="--dep-wolfssl yes"; \
152+
wv=$$(sed -n 's/.*LIBWOLFSSL_VERSION_STRING[[:space:]]*"\([^"]*\)".*/\1/p' \
153+
"$(WOLFSSL_DIR)/wolfssl/version.h" 2>/dev/null); \
154+
if [ -n "$$wv" ]; then \
155+
dep_args="$$dep_args --dep-version wolfssl=$$wv"; \
156+
fi; \
157+
else \
158+
echo "NOTE: this gen-sbom lacks --dep-wolfssl; wolfssl will not"; \
159+
echo " be listed as a dependency component in the SBOM."; \
160+
fi; \
161+
fi && \
127162
python3 $(WOLFSSL_DIR)/scripts/gen-sbom \
128163
--name wolfhsm \
129164
--version $(VERSION) \
130165
--supplier "wolfSSL Inc." \
131166
--license-file LICENSING \
132167
--options-h "$$_defines" \
133168
--srcs $(SRCS) \
169+
$$dep_args \
134170
--cdx-out $(SBOM_CDX) \
135-
--spdx-out $(SBOM_SPDX)
136-
@echo "Done: $(SBOM_CDX) $(SBOM_SPDX)"
171+
--spdx-out $(SBOM_SPDX) && \
172+
if [ "$(SBOM_VALIDATE)" != "no" ]; then \
173+
pyspdxtools --infile $(SBOM_SPDX) --outfile $(SBOM_SPDX_TV) && \
174+
echo "Done: $(SBOM_CDX) $(SBOM_SPDX) $(SBOM_SPDX_TV)"; \
175+
else \
176+
echo "Done: $(SBOM_CDX) $(SBOM_SPDX)"; \
177+
fi
178+
179+
# SBOM install is opt-in (`make install-sbom`), matching the family
180+
# convention in wolfssl's scripts/sbom.am: plain `make` never installs
181+
# SBOM files. wolfHSM's root Makefile has no install/uninstall targets
182+
# to hook, so uninstall-sbom is standalone rather than chained.
183+
install-sbom: sbom
184+
@mkdir -p $(DESTDIR)$(SBOM_INSTALL_DIR)
185+
install -m 0644 $(SBOM_CDX) $(DESTDIR)$(SBOM_INSTALL_DIR)/
186+
install -m 0644 $(SBOM_SPDX) $(DESTDIR)$(SBOM_INSTALL_DIR)/
187+
@if [ -f "$(SBOM_SPDX_TV)" ]; then \
188+
install -m 0644 $(SBOM_SPDX_TV) $(DESTDIR)$(SBOM_INSTALL_DIR)/; \
189+
fi
190+
191+
uninstall-sbom:
192+
-rm -f $(DESTDIR)$(SBOM_INSTALL_DIR)/$(SBOM_CDX) \
193+
$(DESTDIR)$(SBOM_INSTALL_DIR)/$(SBOM_SPDX) \
194+
$(DESTDIR)$(SBOM_INSTALL_DIR)/$(SBOM_SPDX_TV)

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,17 @@ make sbom WOLFSSL_DIR=../wolfssl
3838
```
3939

4040
This parses the version from `ChangeLog.md`, collects `src/*.c`, and writes
41-
`wolfhsm-<version>.cdx.json` and `wolfhsm-<version>.spdx.json`.
41+
`wolfhsm-<version>.cdx.json` and `wolfhsm-<version>.spdx.json`, then
42+
validates the SPDX output with `pyspdxtools` and converts it to tag-value
43+
`wolfhsm-<version>.spdx` (skip both with `SBOM_VALIDATE=no`). The SBOM
44+
lists wolfSSL as a dependency component with its version read from
45+
`WOLFSSL_DIR` (disable with `SBOM_DEP_WOLFSSL=no` for a
46+
`WOLFHSM_CFG_NO_CRYPTO` build). Output is reproducible: `SOURCE_DATE_EPOCH`
47+
is honoured and defaults to the last git commit time.
48+
49+
Install the generated files under `$(PREFIX)/share/doc/wolfhsm` (default
50+
`PREFIX=/usr/local`) with `make install-sbom`; remove them with
51+
`make uninstall-sbom`. Plain `make` never generates or installs SBOM files.
4252

4353
The SBOM records the build configuration by preprocessing
4454
`wolfhsm/wh_settings.h` against a config directory. `WOLFHSM_CFG_DIR`
@@ -59,7 +69,8 @@ the planned gen-sbom fix is.
5969
which ships in wolfSSL PR #10343 (pending a future wolfSSL release). If the
6070
script is absent the target fails with a message telling you what is missing.
6171

62-
Requires `python3` and `pyspdxtools` (`pip install spdx-tools`).
72+
Requires `python3`, plus `pyspdxtools` (`pip install spdx-tools`) unless
73+
`SBOM_VALIDATE=no`.
6374

6475
To invoke `gen-sbom` directly instead of through the target, run the same
6576
command it runs:

0 commit comments

Comments
 (0)