@@ -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)"
0 commit comments