1#!/bin/bash
2# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# Wrapper script for re-signing a firmware image.
7
8# Determine script directory.
9SCRIPT_DIR=$(dirname "$0")
10
11# Load common constants and variables.
12. "${SCRIPT_DIR}/common_minimal.sh"
13
14# Abort on error.
15set -e
16
17usage() {
18  cat<<EOF
19Usage: $0 <input_firmware> <key_dir> <output_firmware> [firmware_version] \
20[loem_output_dir]
21
22Signs <input_firmware> with keys in <key_dir>, setting firmware version
23to <firmware_version>. Outputs signed firmware to <output_firmware>.
24If no firmware version is specified, it is set as 1.
25EOF
26  exit 1
27}
28
29gbb_update() {
30  local in_firmware="$1"
31  local key_dir="$2"
32  local out_firmware="$3"
33  local rootkey="$4"
34
35  # Replace the root and recovery key in the Google Binary Block of the
36  # firmware.  Note: This needs to happen after calling resign_firmwarefd.sh
37  # since it needs to be able to verify the firmware using the root key to
38  # determine the preamble flags.
39  gbb_utility \
40    -s \
41    --recoverykey="${key_dir}/recovery_key.vbpubk" \
42    --rootkey="${rootkey}" \
43    "${in_firmware}" \
44    "${out_firmware}"
45}
46
47# Sign a single firmware image.
48# ARGS: [loem_key] [loemid]
49sign_one() {
50  local loem_key="$1"
51  local loemid="$2"
52
53  # Resign the firmware with new keys.
54  "${SCRIPT_DIR}/resign_firmwarefd.sh" \
55    "${in_firmware}" \
56    "${temp_fw}" \
57    "${key_dir}/firmware_data_key${loem_key}.vbprivk" \
58    "${key_dir}/firmware${loem_key}.keyblock" \
59    "${key_dir}/dev_firmware_data_key${loem_key}.vbprivk" \
60    "${key_dir}/dev_firmware${loem_key}.keyblock" \
61    "${key_dir}/kernel_subkey.vbpubk" \
62    "${firmware_version}" \
63    "" \
64    "${loem_output_dir}" \
65    "${loemid}"
66}
67
68# Process all the keysets in the loem.ini file.
69sign_loems() {
70  local line loem_section=false loem_index loemid
71  local rootkey
72
73  rm -f "${out_firmware}"
74  while read line; do
75    # Find the [loem] section.
76    if ! ${loem_section}; then
77      if grep -q "^ *\[loem\] *$" <<<"${line}"; then
78        loem_section=true
79      fi
80      continue
81    # Abort when we hit the next section.
82    elif [[ ${line} == *"["* ]]; then
83      break
84    fi
85
86    # Strip comments/whitespace.
87    line=$(sed -e 's:#.*::' -e 's:^ *::' -e 's: *$::' <<<"${line}")
88    loem_index=$(cut -d= -f1 <<<"${line}" | sed 's: *$::')
89    loemid=$(cut -d= -f2 <<<"${line}" | sed 's:^ *::')
90
91    echo "### Processing LOEM ${loem_index} ${loemid}"
92    sign_one ".loem${loem_index}" "${loemid}"
93
94    rootkey="${key_dir}/root_key.loem${loem_index}.vbpubk"
95    cp "${rootkey}" "${loem_output_dir}/rootkey.${loemid}"
96
97    if [[ ! -e ${out_firmware} ]]; then
98      gbb_update "${temp_fw}" "${key_dir}" "${out_firmware}" "${rootkey}"
99    fi
100    echo
101  done <"${key_dir}/loem.ini"
102}
103
104main() {
105  if [[ $# -lt 3 || $# -gt 5 ]]; then
106    usage
107  fi
108
109  local in_firmware=$1
110  local key_dir=$2
111  local out_firmware=$3
112  local firmware_version=${4:-1}
113  local loem_output_dir=${5:-}
114
115  local temp_fw=$(make_temp_file)
116
117  if [[ -e ${key_dir}/loem.ini ]]; then
118    if [[ -z ${loem_output_dir} ]]; then
119      err_die "need loem_output_dir w/loem keysets"
120    fi
121    sign_loems
122  else
123    sign_one
124    gbb_update "${temp_fw}" "${key_dir}" "${out_firmware}" \
125      "${key_dir}/root_key.vbpubk"
126  fi
127}
128main "$@"
129