sign_official_build.sh revision aa888463b860c2852f3fcb17baf8de395fcca294
137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah#!/bin/bash
237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
39137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Use of this source code is governed by a BSD-style license that can be
537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# found in the LICENSE file.
637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Sign the final build image using the "official" keys.
80c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#
90c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Prerequisite tools needed in the system path:
100c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#
110c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#  gbb_utility (from src/platform/vboot_reference)
120c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#  vbutil_kernel (from src/platform/vboot_reference)
130c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#  cgpt (from src/platform/vboot_reference)
140c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#  dump_kernel_config (from src/platform/vboot_reference)
150c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah#  verity (from src/platform/verity)
161cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah#  load_kernel_test (from src/platform/vboot_reference)
171a2e6fc765a13b636d3dd75dc7cae709e9e8d218Gaurav Shah#  dumpe2fs
18d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah#  sha1sum
1937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
2037522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Load common constants and variables.
2137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah. "$(dirname "$0")/common.sh"
2237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
231cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Print usage string
241cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahusage() {
2537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah  cat <<EOF
268ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahUsage: $PROG <type> input_image /path/to/keys/dir [output_image] [version_file]
2737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahwhere <type> is one of:
2837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah             ssd  (sign an SSD image)
291cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah             recovery (sign a USB recovery image)
3022bd8b0c29b485ccdaa4f63e6fdac9f097b60aabMike Frysinger             factory (sign a factory install image)
3122bd8b0c29b485ccdaa4f63e6fdac9f097b60aabMike Frysinger             install (old alias to "factory")
32283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger             update_payload (sign a delta update hash)
339c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah             firmware (sign a firmware image)
3464bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson             usb  (sign an image to boot directly from USB)
351cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah             verify (verify an image including rootfs hashes)
361cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
378ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahoutput_image: File name of the signed output image
388ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahversion_file: File name of where to read the kernel and firmware versions.
398ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah
408ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahIf you are signing an image, you must specify an [output_image] and
418ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahoptionally, a [version_file].
428ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah
4337522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahEOF
44b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  if [[ $# -gt 0 ]]; then
45b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    error "$*"
46b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    exit 1
47b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  fi
48b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  exit 0
491cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah}
501cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
51b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# Verify we have as many arguments as we expect, else show usage & quit.
52b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# Usage:
53b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger#  check_argc <number args> <exact number>
54b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger#  check_argc <number args> <lower bound> <upper bound>
55b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingercheck_argc() {
56b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  case $# in
57b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  2)
58b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    if [[ $1 -ne $2 ]]; then
59b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger      usage "command takes exactly $2 args"
60b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    fi
61b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    ;;
62b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  3)
63b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    if [[ $1 -lt $2 || $1 -gt $3 ]]; then
64b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger      usage "command takes $2 to $3 args"
65b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    fi
66b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    ;;
67b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  *)
68b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    die "check_argc: incorrect number of arguments"
69b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  esac
70b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger}
7137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
7237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Abort on errors.
7337522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahset -e
7437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
759dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah# Add to the path since some tools reside here and may not be in the non-root
769dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah# system path.
779dc90d36f8f2e2029adbfece0831c1a840e899caGaurav ShahPATH=$PATH:/usr/sbin:/sbin
789dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah
790500524edda44c770690bb942e916522f1eca5cdGaurav Shah# Make sure the tools we need are available.
801cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahfor prereqs in gbb_utility vbutil_kernel cgpt dump_kernel_config verity \
81ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  load_kernel_test dumpe2fs sha1sum e2fsck; do
820500524edda44c770690bb942e916522f1eca5cdGaurav Shah  type -P "${prereqs}" &>/dev/null || \
830500524edda44c770690bb942e916522f1eca5cdGaurav Shah    { echo "${prereqs} tool not found."; exit 1; }
840500524edda44c770690bb942e916522f1eca5cdGaurav Shahdone
850500524edda44c770690bb942e916522f1eca5cdGaurav Shah
8637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahTYPE=$1
8737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahINPUT_IMAGE=$2
8837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahKEY_DIR=$3
8937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahOUTPUT_IMAGE=$4
908ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahVERSION_FILE=$5
918ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah
928ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahFIRMWARE_VERSION=1
938ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahKERNEL_VERSION=1
9437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
951cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Get current rootfs hash and kernel command line
96d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah# ARGS: IMAGE KERNELPART
971cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahgrab_kernel_config() {
981cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local image=$1
99d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  local kernelpart=$2  # Kernel partition number to grab.
1001cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # Grab the existing kernel partition and get the kernel config.
1010c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  temp_kimage=$(make_temp_file)
102d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  extract_image_partition ${image} ${kernelpart} ${temp_kimage}
1031cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  dump_kernel_config ${temp_kimage}
1041cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah}
1051cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
10669b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# TODO(gauravsh): These are duplicated from chromeos-setimage. We need
10769b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# to move all signing and rootfs code to one single place where it can be
10869b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# reused. crosbug.com/19543
10969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah
11069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# get_verity_arg <commandline> <key> -> <value>
11169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shahget_verity_arg() {
112132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah  echo "$1" | sed -n "s/.*\b$2=\([^ \"]*\).*/\1/p"
11369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah}
11469b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah
11569b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shahis_old_verity_argv() {
11669b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local depth=$(echo "$1" | cut -f7 -d' ')
11769b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  if [ "$depth" = "0" ]; then
11869b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah    return 0
11969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  fi
12069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  return 1
12169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah}
12269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah
123ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah# Get the dmparams parameters from a kernel config.
124ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shahget_dmparams_from_config() {
125ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local kernel_config=$1
12696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  echo ${kernel_config} | sed -nre 's/.*dm="([^"]*)".*/\1/p'
127ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah}
128c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah# Get the verity root digest hash from a kernel config command line.
129c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shahget_hash_from_config() {
130c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah  local kernel_config=$1
131ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local dm_config=$(get_dmparams_from_config "${kernel_config}")
132c8c8dfd90992808a91ce85110218cf1f78fd7f92Paul Taysom  local vroot_dev=$(get_dm_slave "${dm_config}" vroot)
13396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  if is_old_verity_argv "${vroot_dev}"; then
13496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    echo ${vroot_dev} | cut -f9 -d ' '
135c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah  else
13696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    echo $(get_verity_arg "${vroot_dev}" root_hexdigest)
137c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah  fi
138c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah}
139c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah
14096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Get the slave device and its args
14196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# get_dm_ags $dm_config [vboot|vroot]
14296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Assumes we have only one slave device per device
14396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysomget_dm_slave() {
14496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local dm=$1
14596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local device=$2
14696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  echo $(echo "${dm}" | sed -nre "s/.*${device}[^,]*,([^,]*).*/\1/p")
14796d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom}
14896d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom
14996d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Set the slave device and its args for a device
15096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# get_dm_ags $dm_config [vboot|vroot] args
15196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Assumes we have only one slave device per device
15296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysomset_dm_slave() {
15396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local dm=$1
15496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local device=$2
15596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local slave=$3
15696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  echo $(echo "${dm}" |
157f5c62bd7dc1ef3d76d6e5f9119ad73ec95a926d7Paul Taysom    sed -nre "s#(.*${device}[^,]*,)([^,]*)(.*)#\1${slave}\3#p")
15896d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom}
15996d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom
160ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav ShahCALCULATED_KERNEL_CONFIG=
1611cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Calculate rootfs hash of an image
1621cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Args: ROOTFS_IMAGE KERNEL_CONFIG HASH_IMAGE
1631cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah#
1641cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# rootfs calculation parameters are grabbed from KERNEL_CONFIG
1651cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah#
166ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah# Updated kernel config command line with the new hash is stored in
167ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah# $CALCULATED_KERNEL_CONFIG and the new hash image is written to the file
168ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah# HASH_IMAGE.
1691cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahcalculate_rootfs_hash() {
1701cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local rootfs_image=$1
1711cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local kernel_config=$2
1721cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local hash_image=$3
173ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local dm_config=$(get_dmparams_from_config "${kernel_config}")
1740c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
17533c44fc14f6981601d0f0743d0705587d5f11c56Gaurav Shah  if [ -z "${dm_config}" ]; then
176ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "WARNING: Couldn't grab dm_config. Aborting rootfs hash calculation."
177ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    return 1
1780c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  fi
17996d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local vroot_dev=$(get_dm_slave "${dm_config}" vroot)
18069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah
18169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local rootfs_sectors
18269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local verity_depth
18369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local verity_algorithm
18469b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local root_dev
18569b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  local hash_dev
186132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah  local verity_bin="verity"
18796d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  if is_old_verity_argv "${vroot_dev}"; then
18869b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah    # dm="0 2097152 verity ROOT_DEV HASH_DEV 2097152 1 \
18969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah    # sha1 63b7ad16cb9db4b70b28593f825aa6b7825fdcf2"
19096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    rootfs_sectors=$(echo ${vroot_dev} | cut -f2 -d' ')
19196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    verity_depth=$(echo ${vroot_dev} | cut -f7 -d' ')
19296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    verity_algorithm=$(echo ${vroot_dev} | cut -f8 -d' ')
19396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    root_dev=$(echo ${vroot_dev} | cut -f4 -d ' ')
19496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    hash_dev=$(echo ${vroot_dev} | cut -f5 -d ' ')
195132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    # Hack around the fact that the signer needs to use the old version of
196132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    # verity to generate legacy verity kernel parameters. If we find it,
197132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    # we use it.
198132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    type -P "verity-old" &>/dev/null && verity_bin="verity-old"
19969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  else
20069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah    # Key-value parameters.
20196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    rootfs_sectors=$(get_verity_arg "${vroot_dev}" hashstart)
20269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah    verity_depth=0
20396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    verity_algorithm=$(get_verity_arg "${vroot_dev}" alg)
20496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    root_dev=$(get_verity_arg "${vroot_dev}" payload)
20596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    hash_dev=$(get_verity_arg "${vroot_dev}" hashtree)
20696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    salt=$(get_verity_arg "${vroot_dev}" salt)
207132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah  fi
208132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah
209132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah  local salt_arg
210132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah  if [ -n "$salt" ]; then
211132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    salt_arg="salt=$salt"
21269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah  fi
2130c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
2141cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # Run the verity tool on the rootfs partition.
21596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local slave=$(sudo ${verity_bin} mode=create \
216cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah    alg=${verity_algorithm} \
217cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah    payload="${rootfs_image}" \
218cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah    payload_blocks=$((rootfs_sectors / 8)) \
219132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah    hashtree="${hash_image}" ${salt_arg})
2200c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  # Reconstruct new kernel config command line and replace placeholders.
22196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  slave="$(echo "${slave}" |
2220c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    sed -s "s|ROOT_DEV|${root_dev}|g;s|HASH_DEV|${hash_dev}|")"
22396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom  local dm_args=$(set_dm_slave "${dm_config}" vroot "${slave}")
224ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  CALCULATED_KERNEL_CONFIG=$(echo ${kernel_config} |
22596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom    sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${dm_args}\3#g")
2261cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah}
2271cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
2281cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Re-calculate rootfs hash, update rootfs and kernel command line.
229d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah# Args: IMAGE KEYBLOCK PRIVATEKEY KERNELPART
2301cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahupdate_rootfs_hash() {
2311cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local image=$1  # Input image.
2321cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local keyblock=$2  # Keyblock for re-generating signed kernel partition
2331cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local signprivate=$3  # Private key to use for signing.
234d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  local kernelpart=$4  # Kernel partition number to update (usually 2 or 4)
235d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah
2368ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah  echo "Updating rootfs hash and updating config for Kernel partition" \
237d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    "$kernelpart"
2381cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
239ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # If we can't find dm parameters in the kernel config, bail out now.
240ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local kernel_config=$(grab_kernel_config "${image}" ${kernelpart})
241ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local dm_config=$(get_dmparams_from_config "${kernel_config}")
242ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  if [ -z "${dm_config}" ]; then
243ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "WARNING: Couldn't grab dm_config from kernel partition ${kernelpart}"
244ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "WARNING: Not performing rootfs hash update!"
245ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    return
246ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  fi
247ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah
24804c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin  # check and clear need_to_resign tag
24904c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin  local rootfs_dir=$(make_temp_dir)
25004c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin  mount_image_partition_ro "${image}" 3 "${rootfs_dir}"
25104c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin  if has_needs_to_be_resigned_tag "${rootfs_dir}"; then
25204c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin    # remount as RW
253d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah    sudo umount "${rootfs_dir}"
25404c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin    mount_image_partition "${image}" 3 "${rootfs_dir}"
25504c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin    sudo rm -f "${rootfs_dir}/${TAG_NEEDS_TO_BE_SIGNED}"
25604c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin  fi
257d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah  sudo umount "${rootfs_dir}"
25804c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin
2591cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local rootfs_image=$(make_temp_file)
2601cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  extract_image_partition ${image} 3 ${rootfs_image}
2611cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local hash_image=$(make_temp_file)
2621cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
263aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry  # Disable rw mount support prior to hashing.
264aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry  disable_rw_mount "${rootfs_image}"
265aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry
266ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  if ! calculate_rootfs_hash "${rootfs_image}"  "${kernel_config}" \
267ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    "${hash_image}"; then
268ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "calculate_rootfs_hash failed!"
269ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "Aborting rootfs hash update!"
270ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    return
271ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  fi
272ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah
273ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local new_kernel_config=$CALCULATED_KERNEL_CONFIG
274d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  echo "New config for kernel partition $kernelpart is:"
275d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  echo $new_kernel_config
2766bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  echo
2771cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
2781a2e6fc765a13b636d3dd75dc7cae709e9e8d218Gaurav Shah  local rootfs_blocks=$(sudo dumpe2fs "${rootfs_image}" 2> /dev/null |
2791cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    grep "Block count" |
2801cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    tr -d ' ' |
2811cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    cut -f2 -d:)
2821cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local rootfs_sectors=$((rootfs_blocks * 8))
2830c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
2840c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  # Overwrite the appended hashes in the rootfs
2850c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  local temp_config=$(make_temp_file)
2861cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo ${new_kernel_config} >${temp_config}
2871cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  dd if=${hash_image} of=${rootfs_image} bs=512 \
2886bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    seek=${rootfs_sectors} conv=notrunc 2>/dev/null
2890c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
2901cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local temp_kimage=$(make_temp_file)
291d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  extract_image_partition ${image} ${kernelpart} ${temp_kimage}
2920c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  # Re-calculate kernel partition signature and command line.
2930c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  local updated_kimage=$(make_temp_file)
2940c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  vbutil_kernel --repack ${updated_kimage} \
2950c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    --keyblock ${keyblock} \
2960c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    --signprivate ${signprivate} \
2978ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    --version "${KERNEL_VERSION}" \
2980c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    --oldblob ${temp_kimage} \
2990c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    --config ${temp_config}
30033c44fc14f6981601d0f0743d0705587d5f11c56Gaurav Shah
301d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  replace_image_partition ${image} ${kernelpart} ${updated_kimage}
3021cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  replace_image_partition ${image} 3 ${rootfs_image}
3030c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah}
3040c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
3055f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah# Do a sanity check on the image's rootfs
3065f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah# ARGS: Image
3075f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shahverify_image_rootfs() {
3085f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  local image=$1
3095f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  local rootfs_image=$(make_temp_file)
3105f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  extract_image_partition ${image} 3 ${rootfs_image}
3115f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  # This flips the read-only compatibility flag, so that e2fsck does not
3125f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  # complain about unknown file system capabilities.
3135f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  enable_rw_mount ${rootfs_image}
3145f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  echo "Running e2fsck to check root file system for errors"
3155f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  sudo e2fsck -fn "${rootfs_image}" ||
3165f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah    { echo "Root file system has errors!" && exit 1;}
3175f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah}
3188ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah
3199137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Extracts a firmware updater bundle (for firmware image binaries) file
3209137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# (generated by src/platform/firmware/pack_firmware.sh).
3219137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Args: INPUT_FILE OUTPUT_DIR
3229137e8df481906c7de15d92f639a6129adedd892Hung-Te Linextract_firmware_bundle() {
3239137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local input="$(readlink -f "$1")"
3249137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local output_dir="$2"
3259137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  if [ ! -s "${input}" ]; then
3269137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    return 1
3279137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  elif grep -q '^##CUTHERE##' "${input}"; then
3289137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Bundle supports self-extraction.
3299137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    "$input" --sb_extract "${output_dir}" ||
3309137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin      die "Extracting firmware autoupdate (--sb_extract) failed."
33171bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah  else
3329137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Legacy bundle - try uudecode.
3339137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null ||
3349137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin      die "Extracting firmware autoupdate failed."
3359137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  fi
3369137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin}
3379137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin
3389137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Repacks firmware updater bundle content from given folder.
3399137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Args: INPUT_DIR TARGET_SCRIPT
3409137e8df481906c7de15d92f639a6129adedd892Hung-Te Linrepack_firmware_bundle() {
3419137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local input_dir="$1"
3429137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local target="$(readlink -f "$2")"
3439137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin
3449137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  if [ ! -s "${target}" ]; then
34571bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah    return 1
3469137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  elif grep -q '^##CUTHERE##' "${target}"; then
3479137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Bundle supports repacking.
3489137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    "$target" --sb_repack "${input_dir}" ||
3499137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin      die "Updating firmware autoupdate (--sb_repack) failed."
3509137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  else
3519137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Legacy bundle using uuencode + tar.gz.
3529137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Replace MD5 checksum in the firmware update payload.
3539137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    local newfd_checksum="$(md5sum ${input_dir}/bios.bin | cut -f 1 -d ' ')"
3549137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    local temp_version="$(make_temp_file)"
3559137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    cat ${input_dir}/VERSION |
3569137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    sed -e "s#\(.*\)\ \(.*bios.bin.*\)#${newfd_checksum}\ \2#" > ${temp_version}
3579137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    mv ${temp_version} ${input_dir}/VERSION
3589137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin
3599137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # Re-generate firmware_update.tgz and copy over encoded archive in
3609137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    # the original shell ball.
3619137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    sed -ine '/^begin .*firmware_package/,/end/D' "$target"
3629137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin    tar zcf - -C "${input_dir}" . |
3639137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin      uuencode firmware_package.tgz >>"${target}"
36471bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah  fi
3650c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah}
3660c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
3679c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah# Sign a firmware in-place with the given keys.
368aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger# Args: FIRMWARE_IMAGE KEY_DIR FIRMWARE_VERSION [LOEM_OUTPUT_DIR]
3699c783ce3c132491e28efe84751b20d82fc571560Gaurav Shahsign_firmware() {
3709c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  local image=$1
3719c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  local key_dir=$2
3729c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  local firmware_version=$3
373aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger  local loem_output_dir=${4:-}
3749c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah
3759c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  local temp_firmware=$(make_temp_file)
3769c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  # Resign the firmware with new keys, also replacing the root and recovery
3779c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  # public keys in the GBB.
378aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger  "${SCRIPT_DIR}/sign_firmware.sh" "${image}" "${key_dir}" "${temp_firmware}" \
379aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    "${firmware_version}" "${loem_output_dir}"
3809c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  # Note: Although sign_firmware.sh may correctly handle specifying the same
3819c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  # output file as the input file, we do not want to rely on it correctly
3829c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  # handing that. Hence, the use of a temporary file.
3839c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  mv ${temp_firmware} ${image}
3849c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  echo "Signed firmware image output to ${image}"
3859c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah}
3869c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah
387283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger# Sign a delta update payload (usually created by paygen).
388283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger# Args: INPUT_IMAGE KEY_DIR OUTPUT_IMAGE
389283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysingersign_update_payload() {
390283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  local image=$1
391283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  local key_dir=$2
392283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  local output=$3
393283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  local key_size key_file="${key_dir}/update_key.pem"
394283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  local algo algos=(
395283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    # Maps key size to verified boot's algorithm id (for pad_digest_utility).
396283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    # Hashing algorithm is always SHA-256.
397283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    [1024]=1
398283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    [2048]=4
399283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    [4096]=7
400283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    [8192]=10
401283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  )
402283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger
403283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  key_size=$(openssl rsa -text -noout -in "${key_file}" | \
404283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    sed -n -r '1{s/Private-Key: \(([0-9]*) bit\)/\1/p}')
405283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  algo=${algos[${key_size}]}
406283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  if [[ -z ${algo} ]]; then
407283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    die "Unknown algorithm specified by key_size=${key_size}"
408283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  fi
409283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger
410283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  pad_digest_utility ${algo} "${image}" | \
411283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger    openssl rsautl -sign -pkcs -inkey "${key_file}" -out "${output}"
412283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger}
413283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger
4140c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Re-sign the firmware AU payload inside the image rootfs with a new keys.
4150c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Args: IMAGE
4160c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shahresign_firmware_payload() {
4170c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  local image=$1
4180c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
419815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah  if [ -n "${NO_FWUPDATE}" ]; then
420815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah    echo "Skipping firmware update."
421815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah    return
422815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah  fi
423815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah
4249137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  # Grab firmware image from the autoupdate bundle (shellball).
4250c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  local rootfs_dir=$(make_temp_dir)
4260c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  mount_image_partition ${image} 3 ${rootfs_dir}
42714805f555173cf430902ab415cef9d0d83182578Gaurav Shah  # Force unmount of the rootfs on function exit as it is needed later.
428d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah  trap "sudo umount ${rootfs_dir}" RETURN
4299137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local firmware_bundle="${rootfs_dir}/usr/sbin/chromeos-firmwareupdate"
4300c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  local shellball_dir=$(make_temp_dir)
4319137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin
4329137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  # extract_firmware_bundle can fail if the image has no firmware update.
4339137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  extract_firmware_bundle "${firmware_bundle}" "${shellball_dir}" ||
43471bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah    { echo "Didn't find a firmware update. Not signing firmware."
43571bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah    return; }
43671bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah  echo "Found a valid firmware update shellball."
4370c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
438aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger  local image_file sign_args=() loem_sfx loem_output_dir
439ca8c372e60d249cc49ecaf1d33ace2d53caadfaeHung-Te Lin  for image_file in "${shellball_dir}"/bios*.bin; do
440aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    if [[ -e "${KEY_DIR}/loem.ini" ]]; then
441aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      # Extract the extended details from "bios.bin" and use that in the
442aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      # subdir for the keyset.
443aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      loem_sfx=$(sed -r 's:.*/bios([^/]*)[.]bin$:\1:' <<<"${image_file}")
444aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      loem_output_dir="${shellball_dir}/keyset${loem_sfx}"
445aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      sign_args=( "${loem_output_dir}" )
446aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      mkdir -p "${loem_output_dir}"
447aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    fi
448aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    sign_firmware "${image_file}" "${KEY_DIR}" "${FIRMWARE_VERSION}" \
449aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger      "${sign_args[@]}"
450ca8c372e60d249cc49ecaf1d33ace2d53caadfaeHung-Te Lin  done
45142d23c664dbd1334c82b48b504b7d8499955963dGaurav Shah
4529137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  local signer_notes="${shellball_dir}/VERSION.signer"
4539137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  echo "" >"$signer_notes"
4549137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  echo "Signed with keyset in $(readlink -f "${KEY_DIR}") ." >>"$signer_notes"
4550c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah
4560c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  new_shellball=$(make_temp_file)
4579137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  cp -f "${firmware_bundle}" "${new_shellball}"
458bd3dad01b0c2d934462d70eeabb31abcd0310b3fHung-Te Lin  chmod a+rx "${new_shellball}"
4599137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  repack_firmware_bundle "${shellball_dir}" "${new_shellball}"
4609137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  sudo cp -f "${new_shellball}" "${firmware_bundle}"
4619137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin  sudo chmod a+rx "${firmware_bundle}"
4620c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah  echo "Re-signed firmware AU payload in $image"
4630c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah}
46437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
4651cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Verify an image including rootfs hash using the specified keys.
4661cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahverify_image() {
4671cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local rootfs_image=$(make_temp_file)
4681cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  extract_image_partition ${INPUT_IMAGE} 3 ${rootfs_image}
4691cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
4701cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo "Verifying RootFS hash..."
471ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # What we get from image.
472ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local kernel_config
473ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # What we calculate from the rootfs.
474ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local new_kernel_config
475ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # Depending on the type of image, the verity parameters may
476ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # exist in either kernel partition 2 or kernel partition 4
477ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  local partnum
478ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  for partnum in 2 4; do
479ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "Considering Kernel partition $partnum"
480ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    kernel_config=$(grab_kernel_config ${INPUT_IMAGE} $partnum)
481ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    local hash_image=$(make_temp_file)
482ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    if ! calculate_rootfs_hash "${rootfs_image}" "${kernel_config}" \
483ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah      "${hash_image}"; then
484ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah      echo "Trying next kernel partition."
485ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah      continue
486ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    fi
487ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    new_kernel_config="$CALCULATED_KERNEL_CONFIG"
488ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    break
489ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  done
490ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah
491ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # Note: If calculate_rootfs_hash succeeded above, these should
492ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  # be non-empty.
493ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  expected_hash=$(get_hash_from_config "${new_kernel_config}")
494ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  got_hash=$(get_hash_from_config "${kernel_config}")
495ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah
496ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah  if [ -z "${expected_hash}" ] || [ -z "${got_hash}" ]; then
497ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah    echo "FAILURE: Couldn't verify RootFS hash on the image."
498c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah    exit 1
499c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah  fi
500ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah
5011cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  if [ ! "${got_hash}" = "${expected_hash}" ]; then
5021cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    cat <<EOF
5031cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahFAILED: RootFS hash is incorrect.
5041cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahExpected: ${expected_hash}
5051cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahGot: ${got_hash}
5061cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahEOF
507c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah    exit 1
5081cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  else
5091cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    echo "PASS: RootFS hash is correct (${expected_hash})"
5101cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  fi
5111cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
5121cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # Now try and verify kernel partition signature.
5131cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  set +e
5141cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  local try_key=${KEY_DIR}/recovery_key.vbpubk
5151cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo "Testing key verification..."
5161cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # The recovery key is only used in the recovery mode.
5171cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo -n "With Recovery Key (Recovery Mode ON, Dev Mode OFF): " && \
5181cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 2 >/dev/null 2>&1 && \
5191cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    echo "YES"; } || echo "NO"
5201cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo -n "With Recovery Key (Recovery Mode ON, Dev Mode ON): " && \
5211cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 3 >/dev/null 2>&1 && \
5221cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    echo "YES"; } || echo "NO"
5231cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
5241cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  try_key=${KEY_DIR}/kernel_subkey.vbpubk
5251cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # The SSD key is only used in non-recovery mode.
5261cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo -n "With SSD Key (Recovery Mode OFF, Dev Mode OFF): " && \
5271cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 0 >/dev/null 2>&1  && \
5281cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    echo "YES"; } || echo "NO"
5291cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  echo -n "With SSD Key (Recovery Mode OFF, Dev Mode ON): " && \
5301cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 1 >/dev/null 2>&1 && \
5311cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah    echo "YES"; } || echo "NO"
5321cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  set -e
5331cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
5345f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah  verify_image_rootfs "${INPUT_IMAGE}"
5355f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah
5361cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  # TODO(gauravsh): Check embedded firmware AU signatures.
5371cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah}
5381cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
539276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Sign the kernel partition on an image using the given keys. Modifications are
540276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# made in-place.
541276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Args: src_bin kernel_datakey kernel_keyblock kernel_version
542276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shahsign_image_inplace() {
543276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  src_bin=$1
544276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  kernel_datakey=$2
545276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  kernel_keyblock=$3
546276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  kernel_version=$4
547276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah
548276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  temp_kimage=$(make_temp_file)
549276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  extract_image_partition ${src_bin} 2 ${temp_kimage}
550276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  updated_kimage=$(make_temp_file)
551276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah
552276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  vbutil_kernel --repack "${updated_kimage}" \
553276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  --keyblock "${kernel_keyblock}" \
554276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  --signprivate "${kernel_datakey}" \
555276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  --version "${kernel_version}" \
556276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  --oldblob "${temp_kimage}"
557276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  replace_image_partition ${src_bin} 2 ${updated_kimage}
558276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah}
559276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah
56037522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Generate the SSD image
561276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Args: image_bin
56237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahsign_for_ssd() {
563276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  image_bin=$1
564276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_image_inplace ${image_bin} ${KEY_DIR}/kernel_data_key.vbprivk \
5658ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    ${KEY_DIR}/kernel.keyblock \
5668ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    "${KERNEL_VERSION}"
567276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  echo "Signed SSD image output to ${image_bin}"
56837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah}
56937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
57064bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson# Generate the USB image (direct boot)
57164bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardsonsign_for_usb() {
572276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  image_bin=$1
573276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_image_inplace ${image_bin} ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
5748ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    ${KEY_DIR}/recovery_kernel.keyblock \
5758ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    "${KERNEL_VERSION}"
5764b86514d8581315fafc196d47d4412677f193750Bill Richardson
5774b86514d8581315fafc196d47d4412677f193750Bill Richardson  # Now generate the installer vblock with the SSD keys.
5784b86514d8581315fafc196d47d4412677f193750Bill Richardson  # The installer vblock is for KERN-A on direct boot images.
5794b86514d8581315fafc196d47d4412677f193750Bill Richardson  temp_kimagea=$(make_temp_file)
5804b86514d8581315fafc196d47d4412677f193750Bill Richardson  temp_out_vb=$(make_temp_file)
581276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  extract_image_partition ${image_bin} 2 ${temp_kimagea}
5824b86514d8581315fafc196d47d4412677f193750Bill Richardson  ${SCRIPT_DIR}/resign_kernel_partition.sh ${temp_kimagea} ${temp_out_vb} \
5834b86514d8581315fafc196d47d4412677f193750Bill Richardson    ${KEY_DIR}/kernel_data_key.vbprivk \
5848ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    ${KEY_DIR}/kernel.keyblock \
5858ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    "${KERNEL_VERSION}"
5864b86514d8581315fafc196d47d4412677f193750Bill Richardson
5874b86514d8581315fafc196d47d4412677f193750Bill Richardson  # Copy the installer vblock to the stateful partition.
5884b86514d8581315fafc196d47d4412677f193750Bill Richardson  local stateful_dir=$(make_temp_dir)
589276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  mount_image_partition ${image_bin} 1 ${stateful_dir}
5904b86514d8581315fafc196d47d4412677f193750Bill Richardson  sudo cp ${temp_out_vb} ${stateful_dir}/vmlinuz_hd.vblock
5914b86514d8581315fafc196d47d4412677f193750Bill Richardson
592276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  echo "Signed USB image output to ${image_bin}"
59364bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson}
59464bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson
59537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Generate the USB (recovery + install) image
596276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Args: image_bin
59737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahsign_for_recovery() {
598276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  image_bin=$1
5996bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah
6006bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # Sign the install kernel with SSD keys.
6016bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local temp_kimageb=$(make_temp_file)
602276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  extract_image_partition ${image_bin} 4 ${temp_kimageb}
6036bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local updated_kimageb=$(make_temp_file)
6046bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  vbutil_kernel --repack ${updated_kimageb} \
6056bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    --keyblock ${KEY_DIR}/kernel.keyblock \
6066bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    --signprivate ${KEY_DIR}/kernel_data_key.vbprivk \
6076bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    --version "${KERNEL_VERSION}" \
6086bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    --oldblob ${temp_kimageb}
6096bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah
6106bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  replace_image_partition ${image_bin} 4 ${updated_kimageb}
6116bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah
6126bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # Copy the SSD kernel vblock to the stateful partition.
6136bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # TODO(gauravsh): Get rid of this once --skip_vblock is nuked from
6146bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # orbit everywhere. crosbug.com/8378
6156bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local temp_out_vb=$(make_temp_file)
6166bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  ${SCRIPT_DIR}/resign_kernel_partition.sh ${temp_kimageb} ${temp_out_vb} \
6176bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    ${KEY_DIR}/kernel_data_key.vbprivk \
6186bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    ${KEY_DIR}/kernel.keyblock \
6196bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    "${KERNEL_VERSION}"
6206bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local stateful_dir=$(make_temp_dir)
6216bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  mount_image_partition ${image_bin} 1 ${stateful_dir}
6226bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  sudo cp ${temp_out_vb} ${stateful_dir}/vmlinuz_hd.vblock
623d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah  sudo umount "${stateful_dir}"
624d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah
6256bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # Update the Kernel B hash in Kernel A command line
6266bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local old_kerna_config=$(grab_kernel_config "${image_bin}" 2)
6276bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local new_kernb=$(make_temp_file)
6286bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # Can't use updated_kimageb since the hash is calculated on the
6296bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  # whole partition including the null padding at the end.
6306bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  extract_image_partition ${image_bin} 4 ${new_kernb}
6316bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  local new_kernb_hash=$(sha1sum ${new_kernb} | cut -f1 -d' ')
6326bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah
6336bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  new_kerna_config=$(make_temp_file)
6346bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  echo "$old_kerna_config" |
6356bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    sed -e "s#\(kern_b_hash=\)[a-z0-9]*#\1${new_kernb_hash}#" \
6366bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah      > ${new_kerna_config}
637d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  echo "New config for kernel partition 2 is"
6386bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah  cat ${new_kerna_config}
639d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah
640d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  local temp_kimagea=$(make_temp_file)
641276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  extract_image_partition ${image_bin} 2 ${temp_kimagea}
6426bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah
643d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  # Re-calculate kernel partition signature and command line.
644d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  local updated_kimagea=$(make_temp_file)
645d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  vbutil_kernel --repack ${updated_kimagea} \
646d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    --keyblock ${KEY_DIR}/recovery_kernel.keyblock \
647d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    --signprivate ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
6488ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    --version "${KERNEL_VERSION}" \
649d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    --oldblob ${temp_kimagea} \
6506bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah    --config ${new_kerna_config}
6518ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah
652276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  replace_image_partition ${image_bin} 2 ${updated_kimagea}
653276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  echo "Signed recovery image output to ${image_bin}"
65437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah}
65537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
65637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Generate the factory install image.
657276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Args: image_bin
65837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahsign_for_factory_install() {
659276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  image_bin=$1
660276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_image_inplace ${image_bin} ${KEY_DIR}/installer_kernel_data_key.vbprivk \
6618ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    ${KEY_DIR}/installer_kernel.keyblock \
6628ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah    "${KERNEL_VERSION}"
663276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  echo "Signed factory install image output to ${image_bin}"
66437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah}
66537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah
6661cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Verification
667b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingercase ${TYPE} in
668b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingerdump_config)
669b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  check_argc $# 2
670b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  for partnum in 2 4; do
671b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    echo "kernel config in partition number ${partnum}:"
672b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    grab_kernel_config "${INPUT_IMAGE}" ${partnum}
673b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    echo
674b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  done
675b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  exit 0
676b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  ;;
677b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingerverify)
678b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  check_argc $# 2
6791cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah  verify_image
680527612e3565be00030a082c262204a0562bc0d4aGaurav Shah  exit 0
681b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  ;;
682b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger*)
683b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  # All other signing commands take 4 to 5 args.
684b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  if [ -z "${OUTPUT_IMAGE}" ]; then
685b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    # Friendlier message.
686b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger    usage "Missing output image name"
687b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  fi
688b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  check_argc $# 4 5
689b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger  ;;
690b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingeresac
6911cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah
6928ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah# If a version file was specified, read the firmware and kernel
6938ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah# versions from there.
6948ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahif [ -n "${VERSION_FILE}" ]; then
6958ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah  FIRMWARE_VERSION=$(sed -n 's#^firmware_version=\(.*\)#\1#pg' ${VERSION_FILE})
6968ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah  KERNEL_VERSION=$(sed -n 's#^kernel_version=\(.*\)#\1#pg' ${VERSION_FILE})
6978ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahfi
6988ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahecho "Using firmware version: ${FIRMWARE_VERSION}"
6998ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahecho "Using kernel version: ${KERNEL_VERSION}"
70071bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah
701276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Make all modifications on output copy.
70237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahif [ "${TYPE}" == "ssd" ]; then
703276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
704276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  resign_firmware_payload ${OUTPUT_IMAGE}
7057a3a4676672525231c38612e6c8a820305d99de5Don Garrett  "${SCRIPT_DIR}/strip_boot_from_image.sh" --image "${OUTPUT_IMAGE}"
706276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  update_rootfs_hash ${OUTPUT_IMAGE} \
7070c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    ${KEY_DIR}/kernel.keyblock \
708d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    ${KEY_DIR}/kernel_data_key.vbprivk \
709d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    2
710276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_for_ssd ${OUTPUT_IMAGE}
71164bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardsonelif [ "${TYPE}" == "usb" ]; then
712276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
713276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  resign_firmware_payload ${OUTPUT_IMAGE}
7147a3a4676672525231c38612e6c8a820305d99de5Don Garrett  "${SCRIPT_DIR}/strip_boot_from_image.sh" --image "${OUTPUT_IMAGE}"
715276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  update_rootfs_hash ${OUTPUT_IMAGE} \
71664bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson    ${KEY_DIR}/recovery_kernel.keyblock \
71764bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson    ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
71864bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson    2
719276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_for_usb ${OUTPUT_IMAGE}
72037522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahelif [ "${TYPE}" == "recovery" ]; then
721276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
722276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  resign_firmware_payload ${OUTPUT_IMAGE}
7237a3a4676672525231c38612e6c8a820305d99de5Don Garrett  "${SCRIPT_DIR}/strip_boot_from_image.sh" --image "${OUTPUT_IMAGE}"
724d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah  # Both kernel command lines must have the correct rootfs hash
725276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  update_rootfs_hash ${OUTPUT_IMAGE} \
726d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    ${KEY_DIR}/recovery_kernel.keyblock \
727d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
728d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    4
729276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  update_rootfs_hash ${OUTPUT_IMAGE} \
7300c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    ${KEY_DIR}/recovery_kernel.keyblock \
731d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
732d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    2
733276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_for_recovery ${OUTPUT_IMAGE}
73422bd8b0c29b485ccdaa4f63e6fdac9f097b60aabMike Frysingerelif [ "${TYPE}" == "factory" ] || [ "${TYPE}" == "install" ]; then
735276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
736276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  resign_firmware_payload ${OUTPUT_IMAGE}
7377a3a4676672525231c38612e6c8a820305d99de5Don Garrett  # We do NOT strip /boot for factory, since some factory images need it
7387a3a4676672525231c38612e6c8a820305d99de5Don Garrett  # to boot EFI. crosbug.com/260512 would obsolete this requirement.
739276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  update_rootfs_hash ${OUTPUT_IMAGE} \
7400c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah    ${KEY_DIR}/installer_kernel.keyblock \
741baa09de3a426936de697895b95641254ebf2c01fGaurav Shah    ${KEY_DIR}/installer_kernel_data_key.vbprivk \
742d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah    2
743276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah  sign_for_factory_install ${OUTPUT_IMAGE}
7449c783ce3c132491e28efe84751b20d82fc571560Gaurav Shahelif [ "${TYPE}" == "firmware" ]; then
745aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger  if [[ -e "${KEY_DIR}/loem.ini" ]]; then
746aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    echo "LOEM signing not implemented yet for firmware images"
747aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger    exit 1
748aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger  fi
7499c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
7509c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah  sign_firmware ${OUTPUT_IMAGE} ${KEY_DIR} ${FIRMWARE_VERSION}
751283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysingerelif [ "${TYPE}" == "update_payload" ]; then
752283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger  sign_update_payload ${INPUT_IMAGE} ${KEY_DIR} ${OUTPUT_IMAGE}
75337522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahelse
75437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah  echo "Invalid type ${TYPE}"
75537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah  exit 1
75637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahfi
757