From 5d9a7cc1383fdf8b4e4b53e1928dcd06ce6885cd Mon Sep 17 00:00:00 2001 From: Maximilian Brune Date: Sun, 30 Oct 2022 01:00:41 +0200 Subject: [PATCH] Documentation/sbom: Add SBOM Documentation Change-Id: I39fbcba60a0fbdbed9f662119ed7692c0a0fd30e Signed-off-by: Maximilian Brune Reviewed-on: https://review.coreboot.org/c/coreboot/+/68995 Tested-by: build bot (Jenkins) Reviewed-by: Lean Sheng Tan --- Documentation/index.md | 1 + Documentation/sbom/sbom.md | 156 ++++++++++++++++++++ Documentation/sbom/sbom_generation.plantuml | 61 ++++++++ Documentation/sbom/sbom_generation.svg | 79 ++++++++++ 4 files changed, 297 insertions(+) create mode 100644 Documentation/sbom/sbom.md create mode 100644 Documentation/sbom/sbom_generation.plantuml create mode 100644 Documentation/sbom/sbom_generation.svg diff --git a/Documentation/index.md b/Documentation/index.md index 45ad8371df..44e52a2a54 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -193,6 +193,7 @@ Contents: * [SuperIO](superio/index.md) * [Vendorcode](vendorcode/index.md) * [Utilities](util.md) +* [Software Bill of Materials](sbom/sbom.md) * [Project infrastructure & services](infrastructure/index.md) * [Boards supported in each release directory](releases/boards_supported_on_branches.md) * [Release notes](releases/index.md) diff --git a/Documentation/sbom/sbom.md b/Documentation/sbom/sbom.md new file mode 100644 index 0000000000..c4984f971b --- /dev/null +++ b/Documentation/sbom/sbom.md @@ -0,0 +1,156 @@ +# Software Bill of Materials (SBOM) + +SBOM is a collection of information of each software component +you are supplying/building. Similar to a package manager on Linux +based systems, it holds information of as many software parts as +possible. This information can be a version, name of the software, URL, +license information and more. A SBOM can be saved in various formats. +In coreboot it's saved as "uSWID" file. uSWID is not a standard or +specification but it doesn't need to be, since it's basically just an +array/list of CoSWID (Concise Software Identification) files which in +turn are specified by a RFC specification. CoSWID files are saved in a +CBOR format. CBOR is like JSON if JSON were a binary format. Similar +to a package manager the CoSWID format can link multiple softwares +together. For example on most modern Intel systems FSP is included as +a dependency of coreboot. That kind of relationship between software +components (among others) can be expressed in an uSWID file. That makes +firmware/software much more transparent. One could for example create a +software that takes a coreboot firmware image as input and +automatically creates a graph with all software components the coreboot +image contains and their relationship to each other. + + +## SWID/CoSWID + +SWID is a standard hidden behind an ISO paywall. +It generally identifies/describes Software components. Since SWID files +are written in XML, they can get too large for devices with network and +storage constraints. CoSWID is basically SWID but in CBOR binary +format, which makes it far smaller compared to its big brother. Also, +CoSWID is a RFC specification (so publicly accessible). Therefore +CoSWID is the standard used in coreboot SBOM. But one CoSWID file/tag +can only describe one single software, but since software is usually +composed of multiple parts (especially in firmware with many binary +blobs) uSWID was born as a container format to hold multiple CoSWID +files. It also has a magic value, that makes software capable of +extracting uSWID/CoSWID data without the need to understand the +underlying format of the binary (in coreboot it's the CBFS and in EDK2 +it's the COFF). To get a simple overview of how a SWID/CoSWID file +looks like, just take a look at the various "templates" in src/sbom/. +There are of course other SBOM specifications out there, but most of +them are rather blown up and don't support a binary format at all. + + +## coreboot implementation + +Quick overview of how things are generated: + +![Generation of an SBOM File in coreboot][sbom_generation] + +[sbom_generation]: sbom_generation.svg + +After all SBOM data has been fetched from all the software components, +the 'goswid' tool links them all together into one sbom.uswid file. +Therefore the goswid tool is basically a linker that takes multiple +CoSWID/SWID files and converts them into one uSWID file. Although the +image shows only Files in JSON format it is also possible to supply +them in XML or CBOR format. + +The final SBOM file is located inside the CBFS. +For each software component in coreboot SBOM, there is an option in +Kconfig (usually called `CONFIG_INCLUDE_[software-name]_SBOM`) to either +include or not include SBOM metadata for the specified software. +Furthermore there is a `CONFIG_SBOM_[software-name]_PATH` option which +contains a path to a SWID/CoSWID file in a format of choice +(being either JSON, XML or CBOR). `CONFIG_SBOM_[software-name]_PATH` +option usually defaults to a very generic CoSWID file in JSON format +(which are stored in src/sbom/). That at least gives minimal +information like the name of the software and maybe a version. +But it is always preferred, that the `CONFIG_SBOM_[software-name]_PATH` +is set to a custom CoSWID/SWID file that contains much more information +(like version/commit-hash, license, URL, dependencies, ...). +Therefore using the defaults is by any means to be avoided, since they +hold very little information or even worse wrong information. +Furthermore some of these Kconfig options have a suboption +(usually called `CONFIG_SBOM_[software-name]_GENERATE`) to generate +some basic SBOM data for the specified software component, in order to +get at least some bit of information about it by analyzing the binary +(for binary blobs) or querying information via git (for open source +projects). This is for example currently done for all payloads. For +each payload the commit hash used in the build is taken and put into +the SBOM file. For open-source projects (like all payloads) crucial +information like the current commit-hash of the payload can easily be +put into the SBOM file. Extracting information out of binary blobs is a +bit trickier for obvious reasons. For closed source binary blobs it is +therefore recommended that vendors and software-engineers create a SBOM +file as part of their build process and add a path to that SBOM file +via Kconfig options in coreboot (`CONFIG_SBOM_[software-name]_PATH`). +That way the final SBOM has much more useful and correct data. + + +## Build coreboot with SBOM + +Directly under the 'General setup' Kconfig menu is a +'Software Bill of Materials (SBOM)' submenu where all options are to +enable/disable SBOM integration in to the corebeoot build. +Therefore one can just enable/disable them via `make menuconfig`. + + +## What to do as Developer of a binary blob (which is used in coreboot) + +1. Generate a SWID/CoSWID/uSWID File in either JSON, XML or CBOR Format +as part of your software build process + +2. Supply that generated File along with your binary blob (preferably +not inside the blob) + +3. To build coreboot: Add `CONFIG_SBOM_[software-name]_PATH` to your +defconfig pointing to your [software-name] generated File. + + +## What to do as Developer of an open source project (which is used in coreboot) + +1. Generate a SWID/CoSWID/uSWID file in either JSON, XML or CBOR format +as part of your software's build process. For example in form of a +Makefile target. + +2. Change src/sbom/Makefile.inc (in order to know where to find the +CoSWID/SWID/uSWID file) as well as the Makefile in coreboot which +builds said software. For example for GRUB2 that could mean to add a +Makefile target in payloads/external/GRUB2/Makefile. + + +## Problems + +What to do if the binary blob that is included in coreboot's build +already has a SBOM file embedded in the binary? One could supply the +path of the software binary itself (e.g. me.bin) as SBOM file path for +the software in question. Which would basically mean to set +`CONFIG_SBOM_[software-name]_PATH=/path/to/me.bin`. This is possible +since the 'goswid' tooling is able to extract uSWID information out of +an unknown binary format because of uSWIDs magic value. But even if +coreboot can extract the uSWID data there is still the question of what +to do next. One can do one of the following: + + - Do not include the Software's SBOM data in the final SBOM of + coreboot. Data would not be duplicated, but therefore not included + in coreboot SBOM file. + + - Extract the uSWID/CoSWID information from the binary and also + include it in the coreboot SBOM. That would mean, that SBOM data + is duplicated. + +The first solution should in general be preferred, since its no +problem if SBOM data is located at multiple locations/binaries if they +don't have a direct dependency on each other. It would be good if +software that cannot run on its own only supplies the SBOM data along +with it as kind of extra file instead of embedded in an unknown binary +blob. coreboot can then just take it and include it in its own SBOM +file. If on the other hand the binary can function on its own (e.g. EC +or BMC binary), it is generally preferred that the software supplies +its own SBOM data and coreboot just simply doesn't include it in its +own SBOM file. That would make a more or less clear distinction and +avoids duplication in case the BMC or EC is updated (without updating +coreboot). The distinction is not always easy and this problem is +currently not considered in the implementation, since none of the +software components currently create a SBOM file on their own. diff --git a/Documentation/sbom/sbom_generation.plantuml b/Documentation/sbom/sbom_generation.plantuml new file mode 100644 index 0000000000..e8d9f1ebbf --- /dev/null +++ b/Documentation/sbom/sbom_generation.plantuml @@ -0,0 +1,61 @@ +@startuml + +map "src/sbom/compiler-gcc.json" as gcc { + software-name => GCC + version => x.y.z + ... => ... +} +map "src/sbom/intel-me.json" as me { + software-name => Intel Mangement Engine + ... => ... +} +map "src/sbom/intel-microcode.json" as ucode { + software-name => Intel Microcode + ... => ... +} +map "src/sbom/generic-ec.json" as ec { + software-name => ecxyz + ... => ... +} +map "src/sbom/generic-fsp.json" as fsp { + software-name => Firmware Support Package + version => x.y.z + ... => ... +} +map "src/sbom/payload-[...].json" as payload { + software-name => ... + version => x.y.z + ... => ... +} +map "src/sbom/coreboot.json" as coreboot { + software-name => coreboot + version => x.y.z + url => coreboot.rocks + ... => ... +} +object "sbom.uswid" as uswid { + merged SBOM data in binary format +} +object goswid { + # ./goswid + --compiler gcc.json + --parent coreboot.json + --requires fsp.json,payload.json + intel-me.json + intel-ec.json + intel-ucode.json + --output sbom.uswid +} + +left to right direction +gcc --> goswid +me --> goswid +ucode --> goswid +goswid <-- ec +goswid <-- fsp +goswid <-- payload + +coreboot -up> goswid +goswid -up> uswid + +@enduml diff --git a/Documentation/sbom/sbom_generation.svg b/Documentation/sbom/sbom_generation.svg new file mode 100644 index 0000000000..2a5e4f57f2 --- /dev/null +++ b/Documentation/sbom/sbom_generation.svg @@ -0,0 +1,79 @@ +src/sbom/compiler-gcc.jsonsoftware-nameGCCversionx.y.z......src/sbom/intel-me.jsonsoftware-nameIntel Mangement Engine......src/sbom/intel-microcode.jsonsoftware-nameIntel Microcode......src/sbom/generic-ec.jsonsoftware-nameecxyz......src/sbom/generic-fsp.jsonsoftware-nameFirmware Support Packageversionx.y.z......src/sbom/payload-[...].jsonsoftware-name...versionx.y.z......src/sbom/coreboot.jsonsoftware-namecorebootversionx.y.zurlcoreboot.rocks......sbom.uswidmerged SBOM data in binary formatgoswid./goswid--compiler gcc.json--parent coreboot.json--requires fsp.json,payload.jsonintel-me.jsonintel-ec.jsonintel-ucode.json--output sbom.uswid