tree: c454ba7c6a74d633ac8d91f93f73ae42454af80f [path history] [tgz]
  1. doc/
  2. src/
  3. tests/
  4. BUILD.gn
  5. gen_expected_descriptor.py
  6. README.md
src/lib/assembly/vbmeta/README.md

VBMeta

This Rust crate can be used to generate the VBMeta block of the system image. VBMeta holds a key and descriptors needed during startup to verify the integrity of the image, which is part of the Verified Boot process.

It further defines the vbmeta tool, which is a thin wrapper around the main functionality of the library. It serves as a means of creating one-off VBMeta images from ZBIs - and its source further serves as example usage of the crate.

Usage

use vbmeta::{Key, HashDescriptor, Salt, VBMeta};

let key = Key::try_new(PRIVATE_KEY_PEM, PUBLIC_KEY_METADATA).unwrap();
let salt = Salt::random().unwrap();
let descriptor = HashDescriptor::new("zircon", ZBI_BYTES, salt);
let descriptors = vec![descriptor];

let mut vbmeta = VBMeta::sign(descriptors, key).unwrap();
let vbmeta_bytes = vbmeta.bytes;

VBMeta struct

The layout of the VBMeta struct consists of a header, authentication data, and auxiliary data. The header is required and is always 0x100 bytes in length. Both the authentication and auxiliary data are generally optional, but in this API must be explicitly specified in VBMeta::sign(descriptors, key), because a VBMeta block without a descriptor and key is not useful on Fuchsia.

drawing

Header

The VBMeta header contains information about how the block was generated, and section offsets for the authentication and auxiliary data.

drawing

Authentication Data

The authentication data is used to verify the integrity of the vbmeta header and auxiliary data by signing it with the private key. First, the hash is calculated by digesting the header concatenated with the auxiliary data. Second, the signature is found by signing the hash with the private key.

Auxiliary Data

Descriptors

Currently, Fuchsia only uses hash descriptors. VBMeta hash descriptors are used to verify the integrity of a particular image (such as the ZBI). The salt is added to the image before generating the digest. During startup, the image is hashed, and if it does not match the digest in VBMeta, the image is found to be untrustworthy.

drawing

Public key header

The public key is used to verify the signature in the authentication data matches the hash in the authentication data. On startup, the public key header is verified by comparing with a known trustworthy public key (usually fused onto the device).

As RSA signing large images is quite slow, intermediate values (n0inv and rr) are pre-calculated and stored in VBMeta's public key header to speed up the process.

drawing

Public key metadata

The public key metadata is copied directly from the input of Key::try_new(PRIVATE_KEY_PEM, PUBLIC_KEY_METADATA), and placed after the public key header.

Device startup and image verification

When a device starts up, before loading the ZBI, Zircon uses libavb to verify the authenticity of the VBMeta struct and each image. This is completed with the ZirconVBootSlotVerify function in Zircon's boot process, and performs the following steps:

  1. Verifying the validity of the VBMeta header
  2. Verifying the VBMeta hash by digesting the header and auxiliary data
  3. Verifying that the VBMeta signature came from the hash using the public key header
  4. Verifying the authenticity of the public key header by comparing with a stored trusted public key
  5. Verifying the authenticity of each image by comparing their digest with the VBMeta descriptors