Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/guides/capsule-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ mentioned, it means that it doesn't support this update method.
| NovaCustom | NUC BOX | v0.9.0 | — |
| Protectli | Vault VP66xx | v0.9.3 | — |

!!! note

Enforcing capsule authentication in V2 made newer capsules incompatible
with the older ones. The first release with V2 publishes capsules of the
older kind which can be used to upgrade from prior releases, but starting
with this release **older capsules are no longer accepted** to not
compromise capsule authentication enhancements.

## Prerequisites

* _UEFI Shell_<br>
Expand Down
56 changes: 46 additions & 10 deletions docs/kb/capsule-updates-configs.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
# Capsule Update releases

Dasharo releases that support Capsule Updates need to include a number of
additional options in their coreboot configuration file. The options correspond
to the required payload data described in
[Capsule Updates Details - Required Payload Data](./edk2-capsule-updates.md#capsule-information)
additional options in their coreboot configuration file. The most important
options directly correspond to the required payload data described in
[Capsule Updates Details - Required Payload Data](./edk2-capsule-updates.md#capsule-information).

## Configuration

The coreboot configuration file can be found in the coreboot repository
in the `configs/` directory under the name of
`config.<coreboot_mainboard_vendor>_<coreboot_mainboard_model>`.

The options that need to be set are:
The options that must be set are:

- `CONFIG_DRIVERS_EFI_MAIN_FW_GUID`
- `CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`
- `CONFIG_DRIVERS_EFI_MAIN_FW_LSV`
- [`CONFIG_DRIVERS_EFI_MAIN_FW_GUID`](#config_drivers_efi_main_fw_guid)
- [`CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`](#config_drivers_efi_main_fw_version)
- [`CONFIG_DRIVERS_EFI_MAIN_FW_LSV`](#config_drivers_efi_main_fw_lsv)

The following settings may not be set (read their description to know under
which conditions):

- [`CONFIG_EDK2_CAPSULES_V2`](#config_edk2_capsules_v2)
- [`CONFIG_EDK2_CAPSULES_V2_TRANSITION`](#config_edk2_capsules_v2_transition)

### CONFIG_DRIVERS_EFI_MAIN_FW_GUID

Expand All @@ -40,8 +46,8 @@ Capsule Update.
The `CONFIG_LOCALVERSION` option is a string representation of the version
which does not allow reliable comparisons.
The value consists of 8 hexadecimal digits which are grouped
into four groups of two numbers. Each group represents a single component of
a Dasharo version according to the [Versioning](https://docs.dasharo.com/dev-proc/versioning/)
into four groups of two digits. Each group represents a single component of
a Dasharo version according to the [Versioning](../dev-proc/versioning.md).
`CONFIG_DRIVERS_EFI_MAIN_FW_VERSION` has to be updated on new releases to always
match the `CONFIG_LOCALVERSION`.

Expand All @@ -67,8 +73,38 @@ The value represents the lowest firmware version, that will be accepted as
a valid one. A Capsule Update to a version lower than
`CONFIG_DRIVERS_EFI_MAIN_FW_LSV` will not be allowed. May be used to forbid
downgrading to versions with severe security vulnerabilities. The value
takes the same format as `CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`
takes the same format as `CONFIG_DRIVERS_EFI_MAIN_FW_VERSION`.

Examples:

- Forbid changing the version to anything below release v0.1.0 - `CONFIG_DRIVERS_EFI_MAIN_FW_LSV="0x00010080"`

### CONFIG_EDK2_CAPSULES_V2

This boolean option enables more advanced features:

- Enforcing authentication of capsule images before processing them.
- Vendor's logo shown on the screen during an update, scaled proportionally.
- Smoother progress bar increments that better reflect amount of work done/left.
- Pop-up reporting success/failure of the firmware update with some diagnostic
information.
- Best-effort recovery if the update has failed halfway.

Some devices don't have this option set, but newer releases may transition to
this version of capsules (see
[`CONFIG_EDK2_CAPSULES_V2_TRANSITION`](#config_edk2_capsules_v2_transition)).
Devices that have capsules enabled for the first time should preferably use
this option from the start to avoid transitioning later.

### CONFIG_EDK2_CAPSULES_V2_TRANSITION

This boolean option marks a release as transitional from initial capsule
implementation (v1) to a more advanced version (v2). Due to authentication
changes capsules can only be processed by an appropriate firmware (i.e.,
v1-firmware and v1-capsule, v2-firmware and v2-capsule), which on its own makes
upgrading to a v2-firmware via capsules impossible. Enabling this option
requests [`capsule.sh` script](./edk2-capsule-updates.md#capsulesh-script) to
build v1-capsule for a v2-firmware thus permitting updates from v1-firmware.

This option needs to be set only for a single public release, the first one that
gets `CONFIG_EDK2_CAPSULES_V2` set after using v1-capsules in previous releases.
6 changes: 3 additions & 3 deletions docs/kb/capsule-updates-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ on the user, resulting in higher probability of making a mistake.
### Embedded Flashing Code

Firmware reads and writes system flash chip as part of its normal operation.
Capsule update mechanism reuses very same code to switch to a different firmware
image.
Capsule update mechanism reuses the very same code to switch to a different
firmware image.

This way the means for firmware update are always there and require only minimal
extra input to submit the capsule for an update.
Expand All @@ -53,7 +53,7 @@ require use of several firmware update tools in the right order.
The metadata can even take into account compatibility requirements between
firmware of different components. For example, if you're trying to update a
system firmware which requires EC version 1.2 but currently running EC firmware
is of version 1.1, the update will no happen, likely avoiding bricking the
is of version 1.1, the update will not happen, likely avoiding bricking the
device.

### Convenience
Expand Down
35 changes: 32 additions & 3 deletions docs/kb/edk2-capsule-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,15 +294,31 @@ of the output JSON file.

The verification of capsules is performed via
[public-key cryptography][wiki-pkc] (the concepts most relevant here: key pairs
and subkeys). This security mechanism uses a root key pair like this:
and subkeys). This security mechanism is meant to use a root key pair like
this:

1. Public key is embedded into the firmware at build time (one key is enough,
but using multiple keys is also supported).
2. Private key is used to (indirectly, via a subkey) sign capsules.
3. Signature embedded in the capsule is validated against the public key when
an update is attempted to decide whether to perform the update.

Things to note:
The above describes a situation when `FmpDxe` is part of the firmware rather
than a capsule. The latter is more desirable in practice because it distributes
update code in the capsule, thus permitting changes to the update process which
were not anticipated at the time of the previous release. Because `FmpDxe` is
the entity responsible for capsule verification, moving it into the capsule
removes the security guarantee unless it's enforced by other means.
`SignedCapsulePkg` is one way of addressing this situation which it does by
having a two-part driver: a smaller part lives in the firmware and another one
goes into capsules. However, `SignedCapsulePkg` comes with a lot of baggage
and is hard to use when EDK is a payload for a multitude of different devices,
which is why [sealed capsules] were implemented as a much simpler alternative.
In short: an update capsule with `FmpDxe` is embedded as a payload of a capsule
with no drivers, firmware checks signature on the outer capsule's payload and
then processes the inner capsule in its place.

More things to note:

- public root key is well-known
- private root key is stored in a safe place and nobody but the owner should
Expand All @@ -328,6 +344,7 @@ versions will be compatible with one another (unless `LowestSupportedVersion`
interferes).

[wiki-pkc]: https://en.wikipedia.org/wiki/Public-key_cryptography
[sealed capsules]: https://github.com/tianocore/edk2/pull/12254

## Generating signing keys with OpenSSL

Expand Down Expand Up @@ -440,7 +457,7 @@ for these types of files in general, so don't read too much meaning into them.

#### Prepare _root_ for EDK build system

EDK gets _root_ certificate(s) in a PCD. The PCD name differ and support one
EDK gets _root_ certificate(s) in a PCD. The PCD names differ and support one
or many certificates, in this case it's
`gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr` which expects one
or more certificates in DER (binary) form combined via XDR (simple format where
Expand Down Expand Up @@ -687,6 +704,18 @@ Output file name is generated based on coreboot options like
- `emulation-qemu-q35-v0.2.0.cap`
- `msi-ms7d25-ddr4-v1.1.9.cap`

### Sealed capsules

When `CONFIG_EDK2_CAPSULES_V2` is set but `CONFIG_EDK2_CAPSULES_V2_TRANSITION`
isn't, `capsule.sh` produces a two-level capsule where the outer one is signed
by the keys specified by the parameters and the inner one is signed with EDK's
test keys.

The inner capsule is signed because `FmpDxe` fails if there is no signature.
The test keys are used because it doesn't matter what the keys are as long as
the signature is valid and matches root key embedded into `FmpDxe` (not to be
confused with the key embedded into the firmware itself).

### Generating test signing keys

In order to test capsules signed with unsupported keys, one needs to generate a
Expand Down
Loading