summaryrefslogtreecommitdiff
path: root/docs/detachable_base_verified_boot.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/detachable_base_verified_boot.md')
-rw-r--r--docs/detachable_base_verified_boot.md432
1 files changed, 0 insertions, 432 deletions
diff --git a/docs/detachable_base_verified_boot.md b/docs/detachable_base_verified_boot.md
deleted file mode 100644
index c1eec3fc0b..0000000000
--- a/docs/detachable_base_verified_boot.md
+++ /dev/null
@@ -1,432 +0,0 @@
-# Detachable Base Verified Boot
-
-Authors: rspangler@google.com, drinkcat@google.com
-
-Last Updated: 2016-11-16
-
-Original: http://go/detachable-base-vboot
-
-[TOC]
-
-## Introduction
-
-### What's a Base?
-
-Detachable Chromebooks such as `Poppy` have a tablet-like `Lid` and a detachable
-keyboard `Base`. Effectively, the `Base` is a USB keyboard+trackpad which plugs
-into the `Lid`.
-
-The `Lid` contains most of the components, including:
-
-* AP
-* ECDisplay
-* Storage
-* Battery
-
-The `Base` connects to the `Lid` via USB pogo pins, and contains:
-
-* EC ([STM32F072]). To minimize confusion with the main EC in the `Lid`, this
- will always be called the `BaseEC`.
-* Matrixed keyboard
-* Touchpad
-
-The `Base` always gets its power from the `Lid` USB port. This means that
-attaching the base always triggers a power-on reset.
-
-### Verified Boot Requirements
-
-The `BaseEC` will be responsible for handling user input from the keyboard and
-touchpad. This means that a compromised `BaseEC` could implement a keylogger. To
-prevent this, we will use verified boot to protect the `BaseEC` firmware.
-
-We need a way to securely update the `BaseEC` firmware from the AP. We cannot
-use EC Software Sync as implemented on existing Chromebooks (and as still used
-in the `Lid`) because the `Base` cannot trust that it is talking to an official
-`Lid` firmware/OS. All the Base knows is that _something_ on the other end of
-USB is trying to send it an update. So the BaseEC will need to do its own public
-key verification of the firmware update. This includes rollback protection.
-
-Updating the `BaseEC` firmware should not require rebooting the lid. This means
-the update will take place after the OS has already booted on the lid. Ideally,
-it should also not require the user to detach/reattach the base during the
-update process. If the update takes longer than a few seconds, we should tell
-the user, because the keyboard and trackpad will be unavailable during the
-update.
-
-The solution should also have low (or no) BOM cost, and minimal flash size
-requirement.
-
-## Proposal
-
-`BaseEC` RO region includes a public key, whose private counterpart is kept
-safely on our signers. On boot, RO checks RW signature (RW image is signed by
-our signers), and will only jump to RW if the signature is valid.
-
-We also include a rollback region (RB) to implement rollback protection (and
-prevent rollback to a correctly signed, but compromised, RW). This region can
-only be updated by RO.
-
-We also devise a scheme to update RW firmware (the details are documented in
-[EC Update over USB]).
-
-Note: This proposal is very specific to the STM32 flash architecture. Other ECs
-(particularly ones with external SPI flash) may need additional external logic
-and/or a I2C EEPROM to hold the rollback info block.
-
-### Flash
-
-STM32F072 has 128KB flash, with 2KB erase sectors and 4KB protection blocks.
-
-We will divide flash into three sections:
-
-* `BaseEC`-RO firmware.
- * Not updatable in production.
- * Only capable of USB update, not keyboard/trackpad.
- * Contains public key to verify RW image (RSA-3072).
-* `BaseEC`-RW firmware.
- * Fully functional.
- * Updatable from AP.
- * Signature (SHA-256 + RSA-3072).
-* `BaseEC`-RB: Rollback info block (4KB).
- * Contains minimum RW version that RO will accept to jump to.
- * Updatable from RO.
-
-Each of those sections can be locked independently: In production, RO is always
-locked, and only RO can write to RB (RO will always make sure to lock RB before
-jumping to RW).
-
-Flash protection is a little entertaining on STM32:
-
-* The flash protection bits for the \*next\* boot are stored in a non-volatile
- `WRPx` register (in EC code, this is abstracted as
- `EC_FLASH_PROTECT_[REGION]_AT_BOOT` flags)..
-* On chip reset, `WRPx` is copied into a read-only `FLASH_WRPR` register; that
- controls which blocks are protected for this boot. This is abstracted as
- `EC_FLASH_PROTECT_[REGION]_NOW` in the EC code.
-
-### Rollback Info Block
-
-The Rollback Info Block (aka "RB") is a 4KB block of flash.
-
-It has two 2KB erase sectors. We will ping-pong writes to those sectors, so that
-interrupting power during an erase-write cannot cause data loss. If both sectors
-are valid, the stricter (i.e. the highest value) of the 2 sectors is used.
-
-We will use the RB to hold the following:
-
-* Minimum **RW rollback firmware** version: a 32-bit integer. Used for
- rollback protection. This number is independent of the actual EC version,
- and is stored a 32-bit integer as part of the `BaseEC`-RW region (see
- [CL:452815] for a possible implementation)
-* A magic signature that indicates that the RB section is valid.
-
-### RO Verified Boot Flow
-
-#### Write-Protect RO think test before this handles corrupt RW.
-
-Write protect of RO firmware works the same way it does now:
-
-* Early RO code looks at a write protect (WP) GPIO and a global PSTATE
- variable (part of the RO image itself). When we switch to RO that contains
- the MP key, we set the PSTATE to locked.
-* If both of those are set:
- * RO code sets `EC_FLASH_PROTECT_RO_AT_BOOT` to protect itself. This
- ensures RO code is never writable past this point.
- * If `_AT_BOOT` flags protects more than the current write protect range
- (`_NOW` flags), RO reboots so that changes take effect.
-* Otherwise, someone has physically disconnected WP. Set `WRPx=0` to unprotect
- all flash and reboot.
-
-#### Check if AP Wants To Update RW
-
-Next, RO needs to find out if the AP wants to update RW. RO initializes USB and
-starts a 1 second timer to give the AP an opportunity to send a command before
-RO jumps to RW. This delay gives us a way to regain control of the base, if the
-previous RW firmware is properly signed but bad/nonfunctional.
-
-That command can be:
-
-* `STOP_IN_RO`: Yes, I might want to update you. Stick around.
- * `UNLOCK_RW`: Tells EC to unlock RW region, if it is currently locked, so
- that it can be reprogrammed. This also locks RB region. EC reboots if
- needed.
-* `JUMP_TO_RW`: No, I don't want to update you. Go ahead and jump to your RW
- code if it verifies.
-
-RO will start verifying RW while it waits for the AP to send it a command or for
-the timeout. If a command is received, RO will stop the 1-second timer, and wait
-for more commands from the AP. This allows the AP to update RW.
-
-Verifying RW will take ~200 ms, and the AP should be able to send a command to
-the base within ~100 ms of it appearing on USB, so this check should not cause
-any delay to the base's boot process.
-
-#### Verify RW
-
-RO calculates the hash of RW.
-
-* Use the public key stored in RO to check if the hash matches the RSA-signed
- RW signature. On failure, go back to waiting for an update from the AP.
-* Check the RW rollback version against the stored minimum version in RB. If
- the RW version is too low, fail. Go back to waiting for an update from the
- AP.
-* If RO is protected, then also set `EC_FLASH_PROTECT_RW_AT_BOOT` so that RW
- will be protected on the next boot, the reboot.
-
-#### Roll Forward
-
-If `EC_FLASH_PROTECT_ROLLBACK_NOW` is set (RB is protected), do not attempt to
-roll forward. We know RW firmware is properly signed, but not if it's
-functional.
-
-If `EC_FLASH_PROTECT_ROLLBACK_NOW` is not set (RB is unprotected), \_and\_ the
-RW signature is correct, then update RB:
-
-* Erase/write the older sector of RB.
-* Set the stored minimum version to the RW rollback version.
-* If RO is protected, then also set `EC_FLASH_PROTECT_ROLLBACK_NOW` so that RB
- will be protected on the next boot.
-
-#### Jump to RW
-
-If the 1-second timer for the AP to send a command to RO has not expired, RO
-waits for it to expire or the AP to send a command, whichever happens first.
-
-If RB or RW is unprotected (`EC_FLASH_PROTECT_RW/ROLLBACK_NOW` are not set),
-protect it and reboot (we never want RW to be able to update RB on its own).
-
-Otherwise, jump to RW firmware.
-
-### RW Verified Boot Flow
-
-RW firmware provides the keyboard and trackpad functionality.
-
-#### AP Wants To Update RW
-
-At some point the AP may want to update RW. To do so, it sends `UNLOCK_RW`
-command, to ask RW to unlock itself and reboot, then follow the update steps
-above.
-
-#### AP Wants to Roll Forward RW
-
-After the update, the base boots to the new RW firmware. At that point, the AP
-knows the new RW firmware is good enough to talk to, so it tells RW to prepare
-for roll forward.
-
-* `UNLOCK_ROLLBACK` command: RW unprotects RB.
-* On next boot (not necessarily urgent, but can be forced), RO will update RB
- according to the steps above.
-
-### Write Protect GPIO
-
-The `BaseEC` needs a write protect (WP) GPIO signal to decide whether to keep RO
-firmware protected or not. This is the same requirement as on existing ECs.
-
-In an assembled base, the WP signal will be physically asserted. De-asserting
-the signal requires disassembling the base and disconnecting something.
-
-Typically, the `BaseEC` will apply a weak pull-up to the WP GPIO; the presence
-of the WP screw/flex will short the pin to ground.
-
-#### RO Updates During Development
-
-If RO is unprotected (i.e. during development), RW can also update it.
-
-If the key is \_not\_ the same (dev->premp, premp->mp updates) we can't update
-RW first (it won't verify). These steps should work though, if current RW is
-recent enough and stable enough to update RO:
-
-* Make sure RW is active
-* Update RO, reboot
-* Update RW from RO
-
-If the key is the same, we can update RW first.
-
-### Signer, image format, and verification process
-
-Memory map:
-
-RO | RB | RW
-------------------------------------------------- | --- | ---
-`...` \| `Public key` \| `...` \| `FMAP` \| `...` | | `EC code and data` \| `Blank (0xff)` \| `Signature`
-
-* RO contains an embedded RSA public key (`vb21_packed_key` format), at a
- variable location.
-* RW contains a signature (`vb21_signature`), packed at the end of the RW
- region.
- * The signature also contains the actual length of the EC code and image
- (ignoring 0xff padding)
- * RO validates signature against the provided length, then checks that the
- rest of the RW region (up to the signature itself) is filled with ones
- (padding).
- * This speeds up verification significantly, as SHA-256 is an
- expensive process.
-* RO contains an FMAP that allows futility to find the RO key, RW region, and
- RW signature location.
-
-For re-signing, `futility` (rwsig type) does this:
-
-* Look for FMAP to find RO public key RW region, and RW signature locations.
-* Resign RW region, using the length provided in existing RW signature.
-* Replace RO public key with the one used for signing.
-
-`vb21_packed_key` (public key) has a field for key version, that we can use to
-increment from dev keys, to premp, and final mp keys. BaseEC will need to report
-the key version, to avoid incorrect updates.
-
-## Example Boot / Update Flows
-
-The base starts in the following state:
-
-* Powered off
-* WP GPIO is asserted
-* PSTATE is set to protect RO firmware
-* RW firmware is valid, and currently version M
-* `EC_FLASH_PROTECT_[REGION]_AT_BOOT/_NOW` protects RO+RW+RB (that is,
- everything)
-
-All AP operations are done from the `Lid` OS.
-
-Base updates will interrupt keyboard/trackpad functionality, so the user should
-be informed when an update is taking place.
-
-Reboots of the `Base` do not cause or require reboots of the `Lid`, do not
-require action on the part of the user, and will not be visible to the user
-(other than the previously noted lack of functionality).
-
-### Power On, No Update
-
-Step | RW | RB contents | `_AT_BOOT` | `_NOW`
---------------------------------------------------------------------------------------------- | --- | ----------- | ---------- | ------
-(initial state) | M | 1/blank | RO/RW/RB | RO/RW/RB
-1. RO waits 1 second for an update request from AP | | | |
-2. RO verifies RW signature => RW is good | | | |
-3. RO notes that `_AT_BOOT` and `_NOW` already protect everything, so no reboot is necessary. | | | |
-4. RO jumps to RW | | | |
-
-### Updating RW
-
-Assume AP now has a new `BaseEC`-RW, version N>M. The base is already running RW
-version M. In this card, the rollback version in both version is identical
-("1"), so RB does not require an update.
-
-Step | RW | RB contents | `_AT_BOOT` | `_NOW`
-------------------------------------------------------- | --- | ----------- | -------------- | ------
-RW is running | M | 1/blank | RO/RW/RB | RO/RW/RB
-AP tells RW to prepare for an update (UNLOCK_RW) | | | |
-RW unsets `EC_FLASH_PROTECT_RW_AT_BOOT` to unprotect RW | | | **RO/\_\_/RB** |
-RW reboots to update `EC_FLASH_PROTECT_RW_NOW` | | | | **RO/\_\_/RB**
-
-The next base boot is where the update takes place:
-
-Step | RW | RB contents | `_AT_BOOT` | `_NOW`
----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----------- | ------------ | ------
-RO waits 2 seconds for an update request from the AP | M | 1/blank | RO/\_\_/RB | RO/\_\_/RB
-AP tells RO an update is coming (`STOP_IN_RO`) | | | |
-AP tells the user that a base update is taking place. UI should say: "Please don't be surprised that your keyboard and trackpad won't work for a few seconds..." | | | |
-AP writes RW version N | **N** | | |
-AP tells RO to reboot (`IMMEDIATE_RESET`) | | | |
-RO reboots, verifies RW signature => RW is good | | | |
-RO checks RW rollback version N (1) and sees it's greater or equal than RB rollback version 1. So, RW is good. | | | |
-RO sets `RW_AT_BOOT` to protect RW on the next boot. | | | **RO/RW/RB** |
-RO reboots | | | | **RO/RW/RB**
-
-The next base boot is where we first run the new RW firmware.
-
-### Roll forward
-
-Now let's assume we followed the steps above, and we now have a RW version O
-that has rollback version 2.
-
-Step | RW | RB contents | `_AT_BOOT` | `_NOW`
--------------------------------------------------------------------------------------------------------------- | ----- | ----------- | -------------- | ------
-RO verifies RW signature => RW is good | **O** | 1/blank | RO/RW/RB | RO/RW/RB
-RO checks RW rollback version O (2) and sees it's greater or equal than RB rollback version 1. So, RW is good. | | | |
-RO jumps to RW | | | |
-AP is satisfied that the base works, so it tells RW to prepare for a | | | |
-roll-forward (`UNLOCK_ROLLBACK`) | | | |
-RW unsets `ROLLBACK_AT_BOOT` | | | **RO/RW/\_\_** |
-RW may reboot (or just wait for next reattach) | | | | **RO/RW/\_\_**
-
-On next boot, RB will be updated:
-
-Step | RW | RB contents | `_AT_BOOT` | `_NOW`
------------------------------------------------------------------------------------------------------------------------------------------ | --- | ----------- | ------------ | ------
-RO verifies RW signature => RW is good | O | 1/blank | RO/RW/\_\_ | RO/RW/\_\_
-RO sees that RB is unprotected, and sees RW rollback version O (2) and sees is greater than RB rollback version 1. So RB needs an update. | | | |
-RO updates RB's second block | O | **1/2** | |
-RO sets `ROLLBACK_AT_BOOT` to protect RB on the next boot. | | | **RO/RW/RB** |
-RO reboots. | | | | **RO/RW/RB**
-
-## Details
-
-### STM32 Flash Protection
-
-At a high level, flash protection works on the STM32F072 chip works in the
-following manner:
-
-* 128KB flash total flash, organized as 32 independently protectable 4KB
- blocks. Each block has 2 independently erasable 2KB sectors.
-* `FLASH_WRPR` is the register controlling flash write protect of these
- blocks. It is not directly writable. In EC common code, these bits are
- abstracted as `EC_FLASH_PROTECT_[REGION]_NOW`.
-* Instead, there is a non-volatile register called `WRPx`, which is stored in
- a separate information block of flash. This is always writable. In EC common
- code, these bits are abstracted as `EC_FLASH_PROTECT_[REGION]_AT_BOOT`. On
- chip reset, `WRPx` is copied to the `FLASH_WRPR` register.
-
-Here's the interesting part. The only way to change read-only firmware is to
-change `WRPx` and then reset the chip, so that `WRPx` is copied into
-`FLASH_WRPR`. At that point, read-only firmware could be writable. But that same
-reset also transfers control back to the read-only firmware. If the read-only
-firmware doesn't want to be writable, all it has to do is change `WRPx` back to
-protect itself, and then reboot again. We do that already on all devices which
-use the STM32 chips.
-
-Flash protection works similarly on other STM32F chips, if we need to move to a
-larger or more capable EC for the base to support a more complex base.
-
-### Flash Contents
-
-The 128KB `BaseEC` flash will be divided into three parts.
-
-* Read-only firmware (`Base`-EC-RO, or just "RO" in this document)
- * ~40KB
- * Minimal functionality, so it can be small.
- * Verifies the rewritable firmware.
- * Updates the rewritable firmware over USB.
- * Does NOT have keyboard or trackpad support.
- * Includes the `Base-EC` root key.
-* Rewritable firmware (`Base-EC`-RW, or just "RW" in this document)
- * ~84KB
- * Supports keyboard and trackpad.
- * Trackpad drivers may be non-trivial in size.
- * Future bases may include type-C ports, sensors, or batteries, all of
- which will increase RW size.
- * As with the main EC, it is unlikely we will have space for multiple
- copies of RW (so, no RW-A and RW-B).
- * Updates the read-only firmware over USB (pre-production devices only).
-* Rollback block (`Base-EC`-RB, or just "RB" in this document)
- * 4KB (one protection block)
- * Contains rollback version information for RW
- * Only writable by RO.
- * Updates alternate between the 2 2KB erase sectors. We only erase one of
- them at a time, so an interrupted erase/write will not cause data loss.
-
-Adding the RB will decrease the total amount of flash available for RO and RW,
-but doesn't require any additional external components. This is acceptable
-because RO will be smaller (since it only has update/verify functionality).
-
-### Verification Speed
-
-On a STM32F072 chip running at 48 MHz,
-
-* SHA-256 of a 64KB RW image takes 200 ms (~3 ms/KB)
- * Reducing RW image size reduces verification time almost proportionally
- (even if we need to check that the rest of the image is erased).
-* RSA-2048 (exponent 3) signature verification takes ~50 ms
-* RSA-3072 (exponent 3) signature verification takes ~100 ms
-
-[STM32F072]: http://www.st.com/content/ccc/resource/technical/document/reference_manual/c2/f8/8a/f2/18/e6/43/96/DM00031936.pdf/files/DM00031936.pdf
-[EC Update over USB]: ./usb_updater.md
-[CL:452815]: https://chromium-review.googlesource.com/c/452815/2