mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-17 10:31:31 +00:00
A recent codebase change included the test RMA reset server public key
in the Cr50 image by default.
Prod images must not include the test key, and luckily recent
modifications of the cr50-codesigner utility allow to swap the keys
before signing. This patch adds the command line option for swapping
the keys and a check to ensure that the signed image includes the
prod key and does not include the test key.
Note that cr50-codesigner would fail to sign if the swap was requested
but the test RMA key was not found in the input .efl file. Thus both
conditions are verified: that the original image includes the test key
and that the signed image includes the prod key.
BRANCH=none
BUG=b:73296144
TEST=prod signed an image, verified that it can be RMA reset using the
prod RMA reset server.
Change-Id: Ic084d0c5e1de9f027db05c63f82542c2b7cbd916
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1000756
Reviewed-by: Randall Spangler <rspangler@chromium.org>
281 lines
8.2 KiB
Bash
Executable File
281 lines
8.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#
|
|
# Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
#
|
|
# This script is a utility which allows to create differently signed CR50
|
|
# images from different sources.
|
|
#
|
|
set -e
|
|
set -u
|
|
|
|
progname=$(basename $0)
|
|
|
|
OD="/usr/bin/od"
|
|
|
|
tmpf="/tmp/bs_manifest.$$"
|
|
trap "{ rm -rf [01].flat ${tmpf} ; }" EXIT
|
|
|
|
usage() {
|
|
local rv="${1}"
|
|
cat <<EOF
|
|
|
|
This script allows to sign CR50 RW images. By default it uses ec.RW.elf and
|
|
ec.RW_B.elf in build/cr50/RW as inputs and util/signer/ec_RW-manifest-dev.json
|
|
as the manifest, and places the newly signed images into build/cr50/ec.bin.
|
|
|
|
The only outside dependency of this script is the signing utility itself,
|
|
which is expected to be available as /usr/bin/cr50-codesigner.
|
|
|
|
The utility can be installed by running 'sudo emerge cr50-utils',
|
|
|
|
The following command line options are accepted:
|
|
|
|
b1 - generate signature for the b1 version of the H1 chip
|
|
elves <elf1> <elf2> - sign the supplied elf files instead of the default
|
|
ones. Handy if the builder generated files need to be signed
|
|
help - print this message
|
|
hex - generate hex output instead of binary (place in 0.signed.hex and
|
|
1.signed.hex in the local directory)
|
|
prod - sign with prod key (no debug image will be signed)
|
|
|
|
This script also allows to sign dev images for running on prod RO. To do that
|
|
invoke this script as follows:
|
|
|
|
H1_DEVIDS='<dev id0> <dev id1>' ${progname} [other options, if any]
|
|
|
|
where <dev id0> <dev id1> are values reported by sysinfo command in the
|
|
DEV_ID: line when run on the CR50 for which the image is built.
|
|
|
|
The same values can be obtained in the lsusb command output:
|
|
|
|
lsusb -vd 18d1:5014 | grep -i serial
|
|
|
|
note that the lsusb reported values are in hex and need to be prefixed with
|
|
0x.
|
|
|
|
Finally, this script also allows to specify the board ID fields of the RW
|
|
headers. The fields come from the evironment variable CR50_BOARD_ID, which is
|
|
required to include three colon separated fields. The first field is a four
|
|
letter board RLZ code, the second field is board id mask in hex, no 0x prefix,
|
|
and the third field - board ID flags, again, hex, no 0x prefix.
|
|
|
|
CR50_BOARD_ID='XXYY:ffffff00:ff00' ${progname} [other options, if any]
|
|
|
|
both H1_DEVIDS and CR50_BOARD_ID can be defined independently.
|
|
|
|
EOF
|
|
exit "${rv}"
|
|
}
|
|
|
|
# This function modifies the manifest to include device ID and board ID nodes,
|
|
# if H1_DEVIDS and CR50_BOARD_ID are defined in the environment, respectively,
|
|
tweak_manifest () {
|
|
local sub
|
|
|
|
# If defined, plug in dev ID nodes before the 'fuses' node.
|
|
if [[ -z "${do_prod}" && -n "${H1_DEVIDS}" ]]; then
|
|
echo "creating a customized DEV image for DEV IDS ${H1_DEVIDS}"
|
|
sub=$(printf "\\\n \"DEV_ID0\": %s,\\\n \"DEV_ID1\": %s," ${H1_DEVIDS})
|
|
sed -i "s/\"fuses\": {/\"fuses\": {${sub}/" "${tmpf}"
|
|
fi
|
|
|
|
if [[ -z "${CR50_BOARD_ID}" ]]; then
|
|
return
|
|
fi
|
|
|
|
# CR50_BOARD_ID is set, let's parse it and plug in the board ID related
|
|
# nodes into manifest before the 'fuses' node.
|
|
local bid_params
|
|
local rlz
|
|
|
|
bid_params=( $(echo $CR50_BOARD_ID | sed 's/:/ /g') )
|
|
# A very basic sanity check: it needs to consist of three colon separated
|
|
# fields.
|
|
if [[ ${#bid_params[@]} != 3 ]]; then
|
|
echo "Wrong board ID string \"$CR50_BOARD_ID\"}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Convert board RLZ code from ASCII to hex
|
|
rlz="0x$(echo -n ${bid_params[0]} | hexdump -ve '/1 "%02x"')"
|
|
|
|
# Prepare text of all three board ID related nodes
|
|
sub="$(printf "\\\n\"board_id\": %s,\\\n" "${rlz}")"
|
|
sub+="$(printf "\"board_id_mask\": %s,\\\n" "0x${bid_params[1]}")"
|
|
sub+="$(printf "\"board_id_flags\": %s,\\\n" "0x${bid_params[2]}")"
|
|
sed -i "s/\"fuses\": {/${sub}\"fuses\": {/" "${tmpf}"
|
|
}
|
|
|
|
# This function accepts two arguments, names of two binary files.
|
|
#
|
|
# It searches the first passed in file for the first 8 bytes of the second
|
|
# passed in file. The od utility is used to generate full hex dump of the
|
|
# first file (16 bytes per line) and the first 8 bytes of the second file.
|
|
#
|
|
# grep is used to check if the pattern is present in the full dump. If the
|
|
# pattern is not found, the first file is dumped again, this time with an 8
|
|
# byte offset into the file. This makes sure that if the match is present, but
|
|
# is spanning two lines of the original hex dump, it is in a single dump line
|
|
# the second time around.
|
|
find_blob_in_blob() {
|
|
local main_blob="${1}"
|
|
local pattern_blob="${2}"
|
|
local pattern
|
|
local od_options="-An -tx1"
|
|
|
|
# Get the first 8 bytes of the pattern blob.
|
|
pattern="$(${OD} ${od_options} -N8 "${pattern_blob}")"
|
|
|
|
if "${OD}" ${od_options} "${main_blob}" | grep "${pattern}" > /dev/null; then
|
|
return 0
|
|
fi
|
|
|
|
# Just in case pattern was wrapped in the previous od output, let's do it
|
|
# again with an 8 bytes offset
|
|
if "${OD}" ${od_options} -j8 "${main_blob}" |
|
|
grep "${pattern}" > /dev/null; then
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
SIGNER="cr50-codesigner"
|
|
if ! which "${SIGNER}" 2>/dev/null > /dev/null; then
|
|
echo "${SIGNER} is not available, try running 'sudo emerge cr50-utils'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# This is where the new signed image will be pasted into.
|
|
: ${RESULT_FILE=build/cr50/ec.bin}
|
|
TMP_RESULT_FILE="${RESULT_FILE}.tmp"
|
|
|
|
if [[ -z "${CROS_WORKON_SRCROOT}" ]]; then
|
|
echo "${progname}: This script must run inside Chrome OS chroot" >&2
|
|
exit 1
|
|
fi
|
|
|
|
: ${CR50_BOARD_ID=}
|
|
: ${H1_DEVIDS=}
|
|
EC_ROOT="${CROS_WORKON_SRCROOT}/src/platform/ec"
|
|
EC_BIN_ROOT="${EC_ROOT}/util/signer"
|
|
|
|
do_hex=
|
|
do_b1=
|
|
do_prod=
|
|
|
|
# Prepare the default manifest.
|
|
cp "${EC_BIN_ROOT}/ec_RW-manifest-dev.json" "${tmpf}"
|
|
|
|
elves=( build/cr50/RW/ec.RW.elf build/cr50/RW/ec.RW_B.elf )
|
|
cd "${EC_ROOT}"
|
|
while (( $# )); do
|
|
param="${1}"
|
|
case "${param}" in
|
|
(hex) do_hex='true';;
|
|
(b1)
|
|
do_b1='true'
|
|
sed -i 's/\(.*FW_DEFINED_DATA_BLK0.*\): 2/\1: 0/' "${tmpf}"
|
|
;;
|
|
(elves)
|
|
if [[ (( $# < 3 )) ]]; then
|
|
echo "two elf file names are required" >&2
|
|
exit 1
|
|
fi
|
|
elves=( $2 $3 )
|
|
shift
|
|
shift
|
|
;;
|
|
(prod)
|
|
do_prod='true'
|
|
;;
|
|
(help)
|
|
usage 0
|
|
;;
|
|
(*)
|
|
usage 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [[ -z "${do_hex}" && ! -f "${RESULT_FILE}" ]]; then
|
|
echo "${RESULT_FILE} not found. Run 'make BOARD=cr50' first" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -n "${do_prod}" && -n "${do_b1}" ]]; then
|
|
echo "can not build prod images for B1, sorry..."
|
|
exit 1
|
|
fi
|
|
|
|
RMA_KEY_BASE="${EC_ROOT}/board/cr50/rma_key_blob"
|
|
|
|
signer_command_params=()
|
|
signer_command_params+=(--b -x ${EC_BIN_ROOT}/fuses.xml)
|
|
if [[ -z "${do_prod}" ]]; then
|
|
signer_command_params+=(-k ${EC_BIN_ROOT}/cr50_rom0-dev-blsign.pem.pub)
|
|
else
|
|
cp "${EC_BIN_ROOT}/ec_RW-manifest-prod.json" "${tmpf}"
|
|
signer_command_params+=(-k ${EC_BIN_ROOT}/cr50_RW-prod.pem.pub)
|
|
# Swap test public RMA server key with the prod version.
|
|
signer_command_params+=(-S "${RMA_KEY_BASE}.test","${RMA_KEY_BASE}.prod")
|
|
fi
|
|
signer_command_params+=(-j ${tmpf})
|
|
|
|
if [[ -n "${do_hex}" ]]; then
|
|
dst_suffix='signed.hex'
|
|
else
|
|
signer_command_params+=(--format=bin)
|
|
dst_suffix='flat'
|
|
fi
|
|
|
|
tweak_manifest
|
|
|
|
count=0
|
|
for elf in ${elves[@]}; do
|
|
if [[ -n "${do_prod}" ]]; then
|
|
if strings "${elf}" | grep -q "DBG/cr50"; then
|
|
echo "Will not sign debug image with prod keys" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
signed_file="${count}.${dst_suffix}"
|
|
|
|
# Make sure output file is not owned by root
|
|
touch "${signed_file}"
|
|
if ! "${SIGNER}" ${signer_command_params[@]} \
|
|
-i ${elf} -o "${signed_file}"; then
|
|
echo "${progname}: ${SIGNER} failed" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if find_blob_in_blob "${signed_file}" "${RMA_KEY_BASE}.test"; then
|
|
echo "${progname}: test RMA key in the signed image!" >&2
|
|
rm *."${dst_suffix}"
|
|
exit 1
|
|
fi
|
|
|
|
if ! find_blob_in_blob "${signed_file}" "${RMA_KEY_BASE}.prod"; then
|
|
echo "${progname}: prod RMA key not in the signed image!" >&2
|
|
rm *."${dst_suffix}"
|
|
exit 1
|
|
fi
|
|
: $(( count++ ))
|
|
done
|
|
|
|
if [[ -z "${do_hex}" ]]; then
|
|
# Full binary image is required, paste the newly signed blobs into the
|
|
# output image, preserving it in case dd fails for whatever reason.
|
|
cp "${RESULT_FILE}" "${TMP_RESULT_FILE}"
|
|
dd if="0.flat" of="${TMP_RESULT_FILE}" seek=16384 bs=1 conv=notrunc
|
|
dd if="1.flat" of="${TMP_RESULT_FILE}" seek=278528 bs=1 conv=notrunc
|
|
rm [01].flat
|
|
mv "${TMP_RESULT_FILE}" "${RESULT_FILE}"
|
|
fi
|
|
|
|
echo "SUCCESS!!!"
|