Skip to content

Commit d03b224

Browse files
committed
feat: add sbom Makefile target
1 parent 2a90a73 commit d03b224

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

Makefile

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,81 @@ clean:
5656
make -C benchmark clean
5757
make -C tools clean
5858
make -C examples clean
59+
60+
# ---- SBOM generation ----
61+
CC ?= cc
62+
WOLFSSL_DIR ?= ../wolfssl
63+
WOLFHSM_CFG_DIR ?= test/config
64+
VERSION = $(shell sed -n 's/^. wolfHSM Release v//p' ChangeLog.md | head -1 | cut -d' ' -f1)
65+
SRCS := $(sort $(wildcard src/*.c))
66+
SBOM_CDX = wolfhsm-$(VERSION).cdx.json
67+
SBOM_SPDX = wolfhsm-$(VERSION).spdx.json
68+
69+
.PHONY: sbom
70+
71+
sbom:
72+
@if [ -z "$(VERSION)" ]; then \
73+
echo "ERROR: could not parse version from ChangeLog.md." >&2; \
74+
exit 1; \
75+
fi
76+
@if [ -z "$(WOLFSSL_DIR)" ] || [ ! -d "$(WOLFSSL_DIR)" ]; then \
77+
echo "ERROR: WOLFSSL_DIR=$(WOLFSSL_DIR) is not a directory." >&2; \
78+
echo " Set WOLFSSL_DIR to your wolfssl source tree." >&2; \
79+
exit 1; \
80+
fi
81+
@if [ ! -f "$(WOLFSSL_DIR)/scripts/gen-sbom" ]; then \
82+
echo "ERROR: $(WOLFSSL_DIR)/scripts/gen-sbom not found." >&2; \
83+
echo " The sbom target needs a wolfSSL source tree that includes" >&2; \
84+
echo " scripts/gen-sbom (wolfSSL PR #10343, pending a future release)." >&2; \
85+
echo " Set WOLFSSL_DIR to such a tree." >&2; \
86+
exit 1; \
87+
fi
88+
@if [ ! -f "$(WOLFHSM_CFG_DIR)/wolfhsm_cfg.h" ]; then \
89+
echo "ERROR: $(WOLFHSM_CFG_DIR)/wolfhsm_cfg.h not found." >&2; \
90+
echo " Set WOLFHSM_CFG_DIR to the directory holding the" >&2; \
91+
echo " wolfhsm_cfg.h (and user_settings.h) your build uses." >&2; \
92+
exit 1; \
93+
fi
94+
@echo "wolfHSM version: $(VERSION)"
95+
@echo "Sources: $(words $(SRCS)) .c files in src/"
96+
@echo "Config: $(WOLFHSM_CFG_DIR)/wolfhsm_cfg.h"
97+
# Effective build config for the SBOM: preprocess wolfhsm/wh_settings.h with
98+
# the same defines and include path the test build compiles under, so the -dM
99+
# dump holds every WOLFHSM_CFG_* option (explicit and defaulted) plus the
100+
# wolfSSL options from user_settings.h — the configuration the library is
101+
# actually built with. Point WOLFHSM_CFG_DIR at the directory holding your
102+
# build's wolfhsm_cfg.h/user_settings.h for an integrator-accurate SBOM.
103+
#
104+
# ponytail: wh_settings.h pulls libc headers (stdint/stdio/strings/stdatomic),
105+
# so ~330 toolchain constants (INT16_MAX, ACCESSPERMS, ...) ride along into
106+
# the SBOM next to the ~175 real config macros. The dump is deliberately NOT
107+
# filtered here: a prefix allowlist would silently drop real options that
108+
# carry no standard prefix (GCM_TABLE_4BIT, FP_MAX_BITS, SINGLE_THREADED).
109+
# The durable fix belongs in gen-sbom's noise filter (wolfSSL PR #10343,
110+
# scripts/gen-sbom _NOISE_MACRO_RE), either of:
111+
# a) provenance filtering: accept a -dD dump and use its #line markers to
112+
# drop macros defined in system headers, or
113+
# b) an --options-baseline flag: subtract a second -dM dump made with the
114+
# same flags minus the -include, plus the libc headers it pulls.
115+
# Once gen-sbom grows that, this recipe needs no change — it already hands
116+
# over the full dump.
117+
@_defines=$$(mktemp "$${TMPDIR:-/tmp}/wolfhsm-defines.XXXXXX") && \
118+
trap 'rm -f "$$_defines"' 0 && \
119+
if ! $(CC) -dM -E -DWOLFHSM_CFG -DWOLFSSL_USER_SETTINGS \
120+
-I. -I$(WOLFHSM_CFG_DIR) -I$(WOLFSSL_DIR) \
121+
-include wolfhsm/wh_settings.h -x c /dev/null >"$$_defines"; then \
122+
echo "ERROR: $(CC) -dM -E on wolfhsm/wh_settings.h failed." >&2; exit 1; \
123+
fi && \
124+
if ! command -v python3 >/dev/null 2>&1; then \
125+
echo "ERROR: python3 not found." >&2; exit 1; \
126+
fi && \
127+
python3 $(WOLFSSL_DIR)/scripts/gen-sbom \
128+
--name wolfhsm \
129+
--version $(VERSION) \
130+
--supplier "wolfSSL Inc." \
131+
--license-file LICENSING \
132+
--options-h "$$_defines" \
133+
--srcs $(SRCS) \
134+
--cdx-out $(SBOM_CDX) \
135+
--spdx-out $(SBOM_SPDX)
136+
@echo "Done: $(SBOM_CDX) $(SBOM_SPDX)"

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,58 @@ please refer to the following resources.
2525
- [wolfHSM Manual](https://www.wolfssl.com/documentation/manuals/wolfhsm/index.html)
2626
- [wolfHSM API Reference](https://www.wolfssl.com/documentation/manuals/wolfhsm/appendix01.html)
2727
- [wolfHSM Examples](https://github.com/wolfSSL/wolfHSM/tree/main/examples)
28+
29+
## SBOM / EU CRA Compliance
30+
31+
wolfHSM generates a Software Bill of Materials (SBOM) in CycloneDX 1.6 and
32+
SPDX 2.3 formats to support compliance with the EU Cyber Resilience Act (CRA).
33+
34+
Generate both SBOMs with the `sbom` Makefile target:
35+
36+
```sh
37+
make sbom WOLFSSL_DIR=../wolfssl
38+
```
39+
40+
This parses the version from `ChangeLog.md`, collects `src/*.c`, and writes
41+
`wolfhsm-<version>.cdx.json` and `wolfhsm-<version>.spdx.json`.
42+
43+
The SBOM records the build configuration by preprocessing
44+
`wolfhsm/wh_settings.h` against a config directory. `WOLFHSM_CFG_DIR`
45+
(default: `test/config`) selects the directory holding the `wolfhsm_cfg.h`
46+
and `user_settings.h` your build uses — point it at your port's config so the
47+
recorded `WOLFHSM_CFG_*` and wolfSSL options match the library you ship:
48+
49+
```sh
50+
make sbom WOLFSSL_DIR=../wolfssl WOLFHSM_CFG_DIR=path/to/your/config
51+
```
52+
53+
Note: alongside the real config macros, the dump currently includes libc
54+
constants pulled in by `wh_settings.h`'s system includes; see the comment on
55+
the `sbom` target in `Makefile` for why they are not filtered here and what
56+
the planned gen-sbom fix is.
57+
58+
`WOLFSSL_DIR` must point to a wolfssl source tree containing `scripts/gen-sbom`,
59+
which ships in wolfSSL PR #10343 (pending a future wolfSSL release). If the
60+
script is absent the target fails with a message telling you what is missing.
61+
62+
Requires `python3` and `pyspdxtools` (`pip install spdx-tools`).
63+
64+
To invoke `gen-sbom` directly instead of through the target, run the same
65+
command it runs:
66+
67+
```sh
68+
cc -dM -E -DWOLFHSM_CFG -DWOLFSSL_USER_SETTINGS \
69+
-I. -Itest/config -I$WOLFSSL_DIR \
70+
-include wolfhsm/wh_settings.h -x c /dev/null > wolfhsm-defines.h
71+
python3 $WOLFSSL_DIR/scripts/gen-sbom \
72+
--name wolfhsm \
73+
--version $(sed -n 's/^# wolfHSM Release v\([0-9][0-9.]*\).*/\1/p' ChangeLog.md | head -1) \
74+
--supplier "wolfSSL Inc." \
75+
--license-file LICENSING \
76+
--options-h wolfhsm-defines.h \
77+
--srcs src/*.c \
78+
--cdx-out wolfhsm.cdx.json \
79+
--spdx-out wolfhsm.spdx.json
80+
```
81+
82+
For further CRA guidance see [wolfssl/doc/CRA.md](https://github.com/wolfSSL/wolfssl/blob/master/doc/CRA.md).

0 commit comments

Comments
 (0)