Navigation

LibSTB provides APIs to support Secure Boot and Trusted Boot in skiboot.

SecureBoot:verifyandenforce.

When the system is booting in secure mode, Secure Boot MUST ensure that
only trusted code is executed during system boot by verifying if the
code is signed with trusted keys and halting the system boot if the
verification fails.

TrustedBoot:measureandrecord.

When the system is booting in trusted mode, Trusted Boot MUST create
artifacts during system boot to prove that a particular chain of events
have happened during boot. Interested parties can subsequently assess
the artifacts to check whether or not only trusted events happened and
then make security decisions. These artifacts comprise a log of
measurements and the digests extended into the TPM PCRs. Platform
Configuration Registers (PCRs) are registers in the Trusted Platform
Module (TPM) that are shielded from direct access by the CPU.

In order to support Secure and Trusted Boot, the flash driver calls libSTB to
verify and measure the code it fetches from PNOR.

LibSTB is initialized by calling secureboot_init(), see libstb/secureboot.h.

Secure boot is initialized by calling secureboot_init() and its API is quite
simple, see libstb/secureboot.h.

The flash driver calls secureboot_verify() to verify if the fetched firmware
blob is properly signed with keys trusted by the platform owner. This
verification is performed only when the system is booting in secure mode. If
the verification fails, it enforces a halt of the system boot.

The verification itself is performed by the Container Verification Code,
precisely the CVC-verify service, which requires both the fetched code and the
hardware key hash trusted by the platform owner.

Fimware code is signed using the sb-signing-utils utilities by running it
standalone or just calling op-build. The latter will automatically sign the
various firmware components that comprise the PNOR image if SECUREBOOT is
enabled for the platform.

The signing utilities also allow signing firmware code using published hardware
keys (a.k.a. imprint keys, only for development) or production hardware keys,
see sb-signing-utils.

The hardware keys are the root keys. The signing tool uses three hardware keys
to sign up to three firmware keys, which are then used to sign the firmware
code. The resulting signed firmware code is then assembled following the secure
boot container format. All the information required to verify the signatures is
placed in the first 4K reserved for the container header (e.g. public keys,
hashes and signatures). The firmware code itself is placed in the container
payload.

The Container Verification Code (a.k.a. ROM code) is stored in a secure
memory region and it provides basic Secure and Trusted Boot services for the
entire firmware stack. See doc/device-tree/ibm,secureboot.rst
<device-tree/ibm,secureboot> and doc/device-tree/ibm,cvc.rst
<device-tree/ibm,cvc>.

LibSTB uses function wrappers to call into each CVC service, see
libstb/cvc.h.

This function wrapper calls into the CVC-verify, which verifies if the
firmware code provided in @buf is properly signed with the keys trusted by
the platform owner. Its parameters are documented in libstb/cvc.h.

@hw_key_hash is used to check if the firware keys used to sign
the firmware blob can be trusted.

@log is optional. If the verification fails, the caller can interpret
it to find out what checks has failed.

Firmware Event Log driver to add new events to the log. Event log
address and size information is found in the device tree, see
doc/device-tree/tpm.rst.

CVC-sha512 service to calculate the sha512 hash of the data that
will be measured.

The Trusted Boot API is quite simple, see libstb/trustedboot.h.

The flash driver calls trustedboot_measure() to measure the firmware code
fetched from PNOR and also record its measurement in two places. This is
performed only when the system is booting in trusted mode (information found in
the device tree, see doc/device-tree/ibm,secureboot.rst).

Once the firmware code is measured by calling the CVC-sha512 service, its
measurement is first recorded in a TPM PCR statically defined for each event.
In order to record it, the skiboot TCG Software Stack (TSS) API is called to
extend the measurement into the PCR number of both the sha1 and sha256 banks.
The skiboot TSS is a light TSS implementation and its source code is shared
between hostboot and skiboot, see libstb/tss/trustedbootCmds.H.

PCR extend is an TPM operation that uses a hash function to combine a new
measurement with the existing digest saved in the PCR. Basically, it
concatenates the existing PCR value with the received measurement, and then
records the hash of this new string in the PCR.

The measurement is also recorded in the event log. The TpmLogMgr_addEvent()
function is called to add the measurement to the log, see
libstb/tss/tpmLogMgr.H.

When the system boot is complete, each non-zero PCR value represents one or more
events measured during the boot in chronological order. Interested parties
can make inferences about the system’s state by using an attestation tool to
remotely compare the PCR values of a TPM against known good values, and also
identify unexpected events by replaying the Event Log against known good Event
Log entries.