162 lines
6.9 KiB
ReStructuredText
162 lines
6.9 KiB
ReStructuredText
.. _stb-overview:
|
|
|
|
Secure and Trusted Boot Library (LibSTB) Documentation
|
|
======================================================
|
|
|
|
*LibSTB* provides APIs to support Secure Boot and Trusted Boot in skiboot.
|
|
|
|
``Secure Boot: verify and enforce.``
|
|
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.
|
|
|
|
``Trusted Boot: measure and record.``
|
|
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
|
|
-----------
|
|
|
|
``Requirements:``
|
|
#. CVC-verify service to verify signed firmware code.
|
|
|
|
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 :ref:`container-verification-code`,
|
|
precisely the *CVC-verify* service, which requires both the fetched code and the
|
|
hardware key hash trusted by the platform owner.
|
|
|
|
The secure mode status, hardware key hash and hardware key hash size
|
|
information is found in the device tree, see
|
|
:ref:`doc/device-tree/ibm,secureboot.rst <device-tree/ibm,secureboot>`.
|
|
|
|
.. _signing-firmware-code:
|
|
|
|
Signing Firmware Code
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
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.
|
|
|
|
.. _sb-signing-utils: https://github.com/open-power/sb-signing-utils
|
|
|
|
.. _container-verification-code:
|
|
|
|
Container Verification Code
|
|
---------------------------
|
|
|
|
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``.
|
|
|
|
CVC-verify Service
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
.. code-block:: c
|
|
|
|
int call_cvc_verify(void *buf, size_t size, const void *hw_key_hash,
|
|
size_t hw_key_hash_size, uint64_t *log)
|
|
|
|
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.
|
|
|
|
Enforcement is caller's responsibility.
|
|
|
|
CVC-sha512 Service
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
.. code-block:: c
|
|
|
|
int call_cvc_sha512(const uint8_t *data, size_t data_len, uint8_t *digest,
|
|
size_t digest_size)
|
|
|
|
This function wrapper calls into the *CVC-sha512*, which calculates the
|
|
sha512 hash of what is provided in @data. Its parameters are documented in
|
|
``libstb/cvc.h``.
|
|
|
|
Trusted Boot
|
|
------------
|
|
|
|
``Requirements:``
|
|
#. TPM device and TPM driver. See devices supported in
|
|
:ref:`doc/device-tree/tpm.rst <device-tree/tpm>`.
|
|
#. TCG Software Stack (TSS) to send commands to the TPM device.
|
|
#. Firmware Event Log driver to add new events to the log. Event log
|
|
address and size information is found in the device tree, see
|
|
:ref:`doc/device-tree/tpm.rst <device-tree/tpm>`.
|
|
#. 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 :ref:`doc/device-tree/ibm,secureboot.rst <device-tree/ibm,secureboot>`).
|
|
|
|
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.
|