@@ -332,6 +332,30 @@ jobs:
332332 f'host-leak macros filtered)')
333333 PY
334334
335+ # Upload the SBOMs produced by every standalone path (pcpp, pcpp+deps,
336+ # --options-h escape hatch, and the second pcpp run used for
337+ # reproducibility diffing) so a reviewer can inspect them - or hand
338+ # them to a downstream consumer / CRA reviewer - without re-running
339+ # the job. `if: always()` ensures triage artefacts ship even when an
340+ # assertion above fails (which is precisely when the bytes matter).
341+ - name : Upload standalone SBOMs
342+ if : always()
343+ uses : actions/upload-artifact@v4
344+ with :
345+ name : sbom-standalone-${{ github.sha }}
346+ path : |
347+ /tmp/standalone/wolfssl.cdx.json
348+ /tmp/standalone/wolfssl.spdx.json
349+ /tmp/standalone-r2/wolfssl.cdx.json
350+ /tmp/standalone-r2/wolfssl.spdx.json
351+ /tmp/standalone-deps/wolfssl.cdx.json
352+ /tmp/standalone-deps/wolfssl.spdx.json
353+ /tmp/standalone-dme/wolfssl.cdx.json
354+ /tmp/standalone-dme/wolfssl.spdx.json
355+ /tmp/standalone-dme/options.h
356+ if-no-files-found : warn
357+ retention-days : 90
358+
335359 # Tier 2 - integration: build wolfSSL, generate the SBOMs, and assert
336360 # everything an external auditor or vulnerability scanner relies on.
337361 integration :
@@ -581,12 +605,22 @@ jobs:
581605 cmake ninja-build libssl-dev
582606 git clone --depth=1 --branch 0.12.0 \
583607 https://github.com/open-quantum-safe/liboqs /tmp/liboqs
608+ # -DOQS_USE_OPENSSL=OFF is load-bearing: without it, liboqs's
609+ # installed common.h pulls <openssl/crypto.h> (system) into every
610+ # TU that includes <oqs/oqs.h>. wolfssl/wolfcrypt/falcon.h
611+ # includes <oqs/oqs.h>, so once --enable-falcon is on, every
612+ # wolfSSL TU that pulls falcon.h also pulls system OpenSSL,
613+ # which collides with wolfssl/openssl/ssl.h under -Werror
614+ # (CRYPTO_UNLOCK, sk_num, OPENSSL_malloc_init, ... all redefined).
615+ # OFF makes liboqs use its bundled SHA/randombytes (the #else
616+ # branches in oqs/common.h), keeping the build hermetic.
584617 cmake -S /tmp/liboqs -B /tmp/liboqs/build -GNinja \
585618 -DCMAKE_BUILD_TYPE=Release \
586619 -DCMAKE_INSTALL_PREFIX=/usr/local \
587620 -DBUILD_SHARED_LIBS=ON \
588621 -DOQS_BUILD_ONLY_LIB=ON \
589- -DOQS_DIST_BUILD=OFF
622+ -DOQS_DIST_BUILD=OFF \
623+ -DOQS_USE_OPENSSL=OFF
590624 cmake --build /tmp/liboqs/build --parallel "$(nproc)"
591625 sudo cmake --install /tmp/liboqs/build
592626 sudo ldconfig
@@ -706,6 +740,28 @@ jobs:
706740 exit 1
707741 fi
708742
743+ # Persist the SBOMs the integration matrix produces so a CRA reviewer,
744+ # a downstream packager, or the next maintainer triaging a regression
745+ # can download them straight from the run summary instead of replaying
746+ # the full job locally. `if: always()` so a failed assertion above
747+ # (license matrix, NTIA, CDX schema, liboqs dep entry, ...) still ships
748+ # the bytes it failed on. The last `make sbom` invocation in this job
749+ # is the simple SPDX override step, but the path matches every wolfssl
750+ # SPDX/CDX in $PWD - if any are present at job end they will be picked
751+ # up. if-no-files-found:warn keeps the upload soft so reordering the
752+ # steps later cannot regress this into a hard failure.
753+ - name : Upload SBOM artefacts (linux)
754+ if : always()
755+ uses : actions/upload-artifact@v4
756+ with :
757+ name : sbom-integration-linux-${{ github.sha }}
758+ path : |
759+ wolfssl-*.spdx.json
760+ wolfssl-*.cdx.json
761+ wolfssl-*.spdx
762+ if-no-files-found : warn
763+ retention-days : 90
764+
709765 # Tier 2 (macOS) - smoke test that gen-sbom finds .dylib artefacts and
710766 # that the autotools target works on Mach-O. Linux already exercises
711767 # the heavy validation matrix; this job is intentionally minimal so the
@@ -750,6 +806,21 @@ jobs:
750806 print('macOS SBOM checksum well-formed:', checksum)
751807 PY
752808
809+ # Persist the Mach-O variant SBOMs so the .dylib-flavoured outputs are
810+ # downloadable for cross-platform diffing against the linux artefacts.
811+ # Same `if: always()` rationale as the linux upload above.
812+ - name : Upload SBOM artefacts (macos)
813+ if : always()
814+ uses : actions/upload-artifact@v4
815+ with :
816+ name : sbom-integration-macos-${{ github.sha }}
817+ path : |
818+ wolfssl-*.spdx.json
819+ wolfssl-*.cdx.json
820+ wolfssl-*.spdx
821+ if-no-files-found : warn
822+ retention-days : 90
823+
753824 # Tier 2 (bomsh) - exercises the `make bomsh` target which traces a
754825 # full clean rebuild under bomtrace3 (patched strace, Linux-only) and
755826 # produces an OmniBOR artifact dependency graph. Without this job
@@ -825,9 +896,17 @@ jobs:
825896 /usr/local/bin/
826897 sudo install -m 755 /tmp/bomsh/scripts/bomsh_sbom.py \
827898 /usr/local/bin/
828- # bomtrace3 is patched strace; a `--version` invocation under
829- # ptrace requires no target so it must succeed cleanly.
830- bomtrace3 --version
899+ # bomtrace3 replaces strace's argv parsing in bomsh_init() (see
900+ # bomsh_config.c); its accepted long options are exactly
901+ # --help/--config/--output/--verbose/--watch. `--version` is
902+ # NOT a real flag and would exit non-zero. `-h` is the only
903+ # no-target invocation that returns 0 cleanly (bomsh_usage()
904+ # calls exit(0)). The grep doubles as a check that the binary
905+ # on PATH is genuinely bomsh-patched and not a vanilla strace
906+ # shadowing it ("Usage: bomtrace3 " only appears in
907+ # bomsh_usage()), guarding against a future BOMSH_SHA bump that
908+ # silently regresses the patch.
909+ bomtrace3 -h | grep -q '^Usage: bomtrace3 '
831910 which bomsh_create_bom.py bomsh_sbom.py
832911
833912 - name : Configure wolfSSL
@@ -871,6 +950,43 @@ jobs:
871950 print(f'bomsh enrichment ok: {len(gitoid_refs)} gitoid refs')
872951 PY
873952
953+ # The full provenance bundle - the high-value artefact of the whole
954+ # PR, the one a CRA reviewer or downstream packager wants to download.
955+ # MUST be uploaded BEFORE the `make clean` step below, which deletes
956+ # everything by design. `if: always()` so even when the assertion
957+ # above fails (which is when triage matters most), the bundle ships.
958+ #
959+ # Contents:
960+ # omnibor/ - OmniBOR Artifact Dependency Graph
961+ # (objects/ + metadata/bomsh/*),
962+ # content-addressed by gitoid; the
963+ # verifiable build-provenance proof.
964+ # omnibor.wolfssl-*.spdx.json - SPDX with PERSISTENT-ID gitoid
965+ # externalRef bridging SBOM <-> ADG.
966+ # wolfssl-*.spdx.json - the un-enriched SPDX (for diffing
967+ # against omnibor.* to confirm only
968+ # the externalRef was added).
969+ # wolfssl-*.cdx.json - CycloneDX equivalent.
970+ # bomsh_raw_logfile.sha1 - raw bomtrace3 syscall trace, for
971+ # debugging trace gaps (e.g. a build
972+ # step that escaped ptrace).
973+ # _bomsh.conf - 1-line config passed to bomtrace3
974+ # -c at trace time.
975+ - name : Upload OmniBOR graph + bomsh-enriched SBOMs
976+ if : always()
977+ uses : actions/upload-artifact@v4
978+ with :
979+ name : bomsh-omnibor-${{ github.sha }}
980+ path : |
981+ omnibor/
982+ omnibor.wolfssl-*.spdx.json
983+ wolfssl-*.spdx.json
984+ wolfssl-*.cdx.json
985+ bomsh_raw_logfile.sha1
986+ _bomsh.conf
987+ if-no-files-found : warn
988+ retention-days : 90
989+
874990 - name : make clean removes all bomsh + sbom artefacts
875991 # Regression guard: if a future change adds an output to either
876992 # recipe but forgets CLEANFILES, this will catch it.
0 commit comments