Randall Spangler 6f7f5df816 vboot2: un-nest data structures
Originally, we designed the vboot data structures so that some of them
had sub-structures.  Then the variable-length data for each of the
structures was at the end.  So:

    struct vb2_keyblock {
      struct vb2_packed_key
      struct vb2_signature
    }
    // Followed by variable-length data for keyblock
    // Followed by variable-length data for packed key
    // Followed by variable-length data for signature

This had the weird side effect that the header and data for the
sub-structs were not contiguous.  That wasn't too bad before, but it
gets more complicated with the new data structures.  Each structure
now can also have a description.  And keyblocks can have a list of
signatures.

Structures also couldn't really know their own size, since a
sub-struct might have a 20-byte header, but then 2K of other data in
between that and the data for the sub-struct itself.

So, un-nest all the data structures.  That is, the keyblock now
contains the offset of the signature struct, rather than the signature
struct itself.  And then all the variable-length data for each struct
immediately follows the struct itself.  So:

    struct vb2_keyblock2 {
      // Offset of packed key
      // Offset of first signature
    }
    // Followed by variable-length data for keyblock
    struct vb2_packed_key
    // Followed by variable-length data for packed key
    struct vb2_signature2
    // Followed by variable-length data for signature (desc, sig data)

Verifying and traversing these objects is much more straightforward.
And each struct can now know its own size.

This first change rearranges the structures.  Descriptions now
immediately follow the fixed size structure headers.

The next change adds better verification of the structures, using the
fixed_size and total_size fields in the common header.

BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests

Change-Id: Ieb9148d6f26c3e59ea542f3a95e59d8019ccee21
Reviewed-on: https://chromium-review.googlesource.com/226824
Tested-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Randall Spangler <rspangler@chromium.org>
2014-11-01 01:27:55 +00:00
2014-11-01 01:27:55 +00:00
2010-08-05 16:42:43 -07:00
2014-10-31 20:55:24 +00:00
2014-11-01 01:27:55 +00:00
2014-09-02 20:25:22 +00:00
2010-08-05 14:18:38 -07:00
2013-01-31 09:38:28 -08:00
2010-06-17 13:22:34 -07:00

This directory contains a reference implementation for Chrome OS
verified boot in firmware.

----------
Directory Structure
----------

The source is organized into distinct modules -

firmware/

  Contains ONLY the code required by the BIOS to validate the secure boot
  components. There shouldn't be any code in here that signs or generates
  images. BIOS should require ONLY this directory to implement secure boot.
  Refer to firmware/README for futher details.

cgpt/

  Utility to read/write/modify GPT partitions. Similar to GNU parted or any
  other GPT tool, but this has support for Chrome OS extensions.

host/

  Miscellaneous functions needed by userland utilities.

futility/

  The "firmware utility" tool, used to create, sign, and validate Chrome OS
  images.

utility/

  Random other utilities, not necesssarily related to verified boot as such.

tests/

  User-land tests and benchmarks that test the reference implementation.
  Please have a look at these if you'd like to understand how to use the
  reference implementation.

build/

  The output directory where the generated files will be placed, and where
  tests are run.

scripts/

  Tools and scripts used to generate and use new signing keypairs. These are
  typically used only on a secure machine.


--------------------
Building and testing
--------------------

The suite can be built on the host or in the chroot environment.

Building on the host could fail if certain packages are not installed. If
there are host environment build problems due to missing .h files, try
researching what packages the files belong to and install the missing packages
before reporting a problem.


The commands are the more-or-less expected ones:

  make
  make runtests
  make install [ DESTDIR=/usr/local ]



----------
Some useful utilities:
----------

futility vbutil_key         Convert a public key into .vbpubk format
futility vbutil_keyblock    Wrap a public key inside a signature and checksum
futility vbutil_firmware    Create a .vblock with signature info for a
                              firmware image
futility vbutil_kernel      Pack a kernel image, bootloader, and config into
                              a signed binary

dumpRSAPublicKey            Dump RSA Public key (from a DER-encoded X509
                            certificate) in a format suitable for use by
                            RSAVerify* functions in crypto/.

verify_data.c               Verify a given signature on a given file.



----------
Generating a signed firmware image:
----------

* Step 0: Build the tools, install them somewhere.

* Step 1: Generate RSA root and signing keys.

  The root key is always 8192 bits.

    $ openssl genrsa -F4 -out root_key.pem 8192

  The signing key can be between 1024-8192 bits.

    $ openssl genrsa -F4 -out signing_key.pem <1024|2048|4096|8192>

  Note: The -F4 option must be specified to generate RSA keys with a public
  exponent of 65535. RSA keys with 3 as a public exponent (the default)
  won't work.

* Step 2: Generate pre-processed public versions of the above keys using
          dumpRSAPublicKey. This utility expects an x509 certificate as
          input, and emits an intermediate representation for further
          processing.

    $ openssl req -batch -new -x509 -key root_key.pem -out root_key.crt
    $ openssl req -batch -new -x509 -key signing_key.pem -out signing_key.crt
    $ dumpRSAPublicKey root_key.crt > root_key.keyb
    $ dumpRSAPublicKey signing_key.crt > signing_key.keyb

************** TODO: STUFF PAST HERE IS OUT OF DATE ***************

At this point we have all the requisite keys needed to generate a signed
firmware image.

.pem   RSA Public/Private Key Pair
.crt   X509 Key Certificate
.keyb  Pre-processed RSA Public Key


* Step 3: Use utility/firmware_utility to generate a signed firmare blob.

$ utility/firmware_utility --generate \
  --root_key root_key.pem \
  --firmware_sign_key signing_key.pem \
  --firmware_sign_key_pub signing_key.keyb \
  --firmware_sign_algorithm <algoid> \
  --firmware_key_version 1 \
  --firmware_version 1 \
  --in <firmware blob file> \
  --out <output file>

Where <algoid> is based on the signature algorithm to use for firmware
signining. The list of <algoid> specifications can be output by running
'utility/firmware_utility' without any arguments.

Note: --firmware_key_version and --firmware_version are part of a signed
      image and are used to prevent rollbacks to older version. For testing,
      they can just be set to valid values.


* Step 4: Verify that this image verifies.

$ utility/firmware_utility --verify \
                         --in <signed firmware image>
                         --root_key_pub root_key.keyb
Verification SUCCESS.


Note: The verification functions expects a pointer to the
      pre-processed public root key as input. For testing purposes,
      root_key.keyb can be stored in RW part of the firmware. For the
      final firmware, this will be a fixed public key which cannot be
      changed and must be stored in RO firmware.

----------
Generating a signed kernel image:
----------

The steps for generating a signed kernel image are similar to that of
a firmware image. Since verification is chained - RO firmware verifies
RW firmware which verifies the kernel, only the keys change. An additional
kernel signing key must be generated. The firmware signing generated above
is the root key equivalent for signed kernel images.
Description
No description provided
Readme 1.4 GiB
Languages
C 64.7%
Lasso 20.7%
ASL 3.6%
JavaScript 3.2%
C# 2.9%
Other 4.6%