summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@google.com>2020-12-03 11:19:09 -0800
committerCommit Bot <commit-bot@chromium.org>2020-12-11 21:06:50 +0000
commitfb25edf13402ef3be8935c7d3dc1416efff49c5b (patch)
treec825a3116e75b3c782917c853f24721c645284f3
parente1db52ef9282486117247d178af184e2641904c8 (diff)
downloadvboot-fb25edf13402ef3be8935c7d3dc1416efff49c5b.tar.gz
sign_gsc_firmware: refactor and extend to support D2
The major difference between Cr50 and Ti50 signing is that the RW sections are represented differently: elf files in Cr50 case and ihex files in Ti50 case. Other differences include the produced signed final image size and the offsets of the components in the final image. The signing script is being updated to figure out all these differences at run time. A new optional field is introduced in the signing manifest, the 'generation'. If this field is absent or set to 'h' (for H1), the script proceeds with the Cr50 signing process. If 'generation' is set to 'd' (for D2), the script proceeds with the Ti50 signing process. Instead of using fixed offsets into the final image, the base addresses of the components in ihex format are used, the only fixed value is the base address of the flash image in the chip address space (0x40000 for H1 vs 0x80000 for D2). To make this work for H1 the output format of the signed blob produced by gsc-codesigner is changed from binary to ihex. BRANCH=none BUG=b:173049030 TEST=using this script and the signing_istructions.sh module produced by the real Cr50 signer was able to produce functional images for both Cr50 and Ti50. Change-Id: I845be1101b09c9476fa27fbddb72607dc6cea901 Signed-off-by: Vadim Bendebury <vbendeb@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2570009 Tested-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: George Engelbrecht <engeg@google.com> Auto-Submit: Vadim Bendebury <vbendeb@chromium.org> Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
-rwxr-xr-xscripts/image_signing/sign_gsc_firmware.sh226
1 files changed, 136 insertions, 90 deletions
diff --git a/scripts/image_signing/sign_gsc_firmware.sh b/scripts/image_signing/sign_gsc_firmware.sh
index a464b9b1..30e27950 100755
--- a/scripts/image_signing/sign_gsc_firmware.sh
+++ b/scripts/image_signing/sign_gsc_firmware.sh
@@ -122,6 +122,28 @@ get_hex_base() {
fi
}
+# Paste a binary blob into a larger binary file at a given offset.
+paste_bin() {
+ local file="${1}"
+ local blob="${2}"
+ local image_base="${3}"
+ local hex_base="${4}"
+ local file_size
+ local blob_size
+ local offset
+
+
+ file_size="$(stat -c '%s' "${file}")"
+ blob_size="$(stat -c '%s' "${blob}")"
+ offset="$(( hex_base - image_base ))"
+
+ if [[ $(( blob_size + offset )) -ge ${file_size} ]];then
+ die \
+ "Can't fit ${blob_size} bytes at offset ${offset} into ${file_size} bytes"
+ fi
+ dd if="${blob}" of="${file}" seek="${offset}" bs=1 conv=notrunc
+}
+
# This function accepts one argument, the name of the GSC manifest file which
# needs to be verified and in certain cases altered.
#
@@ -306,30 +328,26 @@ determine_rma_key_base() {
# Sign GSC RW firmware ELF images into a combined GSC firmware image
# using the provided production keys and manifests.
sign_rw() {
- if [[ $# -ne 8 ]]; then
+ if [[ $# -ne 9 ]]; then
die "Usage: sign_rw <key_file> <manifest> <fuses>" \
- "<rma_key_dir> <rw_a> <rw_b> <output> <generation>"
+ "<rma_key_dir> <rw_a> <rw_b> <output> <generation> <image_base>"
fi
local key_file="$1"
local manifest_file="$2"
local fuses_file="$3"
local rma_key_dir="$4"
- local elfs=( "$5" "$6" )
+ local rws=( "$5" "$6" )
local result_file="$7"
local generation="$8"
- local temp_dir
+ local image_base="$9"
+ local base_name
local rma_key_base=""
- local rw_a_offset
- local rw_b_offset
+ local signer_command_params
+ local temp_dir
temp_dir="$(make_temp_dir)"
-
- if [[ ! -f "${result_file}" ]]; then
- die "${result_file} not found."
- fi
-
- local signer_command_params=(-x "${fuses_file}" --key "${key_file}")
+ signer_command_params=(-x "${fuses_file}" --key "${key_file}")
case "${generation}" in
(h)
@@ -342,9 +360,9 @@ sign_rw() {
"${manifest_file}")"
if [[ "${gsc_version}" != "22" ]]; then
- rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${elfs[@]}")"
+ rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${rws[@]}")"
else
- echo "Ignoring RMA keys for factory branch ${gsc_version}"
+ warn "Ignoring RMA keys for factory branch ${gsc_version}"
fi
# Swap test public RMA server key with the prod version.
@@ -355,15 +373,13 @@ sign_rw() {
fi
# Indicate H1 signing.
- signer_command_params+=( '--b' )
- # Fixed offsets into the binary blob where RW sections start.
- rw_a_offset=16384
- rw_b_offset=278528
+ signer_command_params+=( "--b" )
+ base_name="cr50"
;;
(d)
# Indicate D1 signing.
- signer_command_params+=( '--dauntless' )
- die "Need to figure out D2 RW sections offsets"
+ signer_command_params+=( "--dauntless" "--ihex" )
+ base_name="ti50"
;;
(*)
die "Unknown generation value \"${generation}\""
@@ -372,46 +388,46 @@ sign_rw() {
signer_command_params+=(--json "${manifest_file}")
- signer_command_params+=(--format=bin)
- dst_suffix='flat'
if [[ "${FLAGS_override_keyid}" == "${FLAGS_TRUE}" ]]; then
signer_command_params+=(--override-keyid)
fi
- local count=0
- for elf in "${elfs[@]}"; do
- if strings "${elf}" | grep -q "DBG/cr50"; then
- die "Will not sign debug image with prod keys"
- fi
- signed_file="${temp_dir}/${count}.${dst_suffix}"
+ for rw in "${rws[@]}"; do
+ local hex_signed="${temp_dir}/hex_signed"
+ local bin_signed="${temp_dir}/bin_signed"
+ local hex_base
- # Make sure output file is not owned by root.
- touch "${signed_file}"
+ # Make sure output files are not owned by root.
+ touch "${bin_signed}" "${hex_signed}"
if ! gsc-codesigner "${signer_command_params[@]}" \
- -i "${elf}" -o "${signed_file}"; then
+ -i "${rw}" -o "${hex_signed}"; then
die "gsc-codesigner ${signer_command_params[*]}" \
- "-i ${elf} -o ${signed_file} failed"
+ "-i ${rw} -o ${hex_signed} failed"
+ fi
+
+ if ! objcopy -I ihex "${hex_signed}" -O binary "${bin_signed}"; then
+ die "Failed to convert ${rw} from hex to bin"
fi
if [[ -n "${rma_key_base}" ]]; then
- if find_blob_in_blob "${signed_file}" "${rma_key_base}.test"; then
+ if find_blob_in_blob "${bin_signed}" "${rma_key_base}.test"; then
die "test RMA key in the signed image!"
fi
- if ! find_blob_in_blob "${signed_file}" "${rma_key_base}.prod"; then
+ if ! find_blob_in_blob "${bin_signed}" "${rma_key_base}.prod"; then
die "prod RMA key not in the signed image!"
fi
fi
- : $(( count++ ))
+
+ hex_base="$(get_hex_base "${hex_signed}")"
+ paste_bin "${result_file}" "${bin_signed}" "${image_base}" "${hex_base}"
done
- # Full binary image is required, paste the newly signed blobs into the
- # output image.
- dd if="${temp_dir}/0.${dst_suffix}" of="${result_file}" \
- seek="${rw_a_offset}" bs=1 conv=notrunc
- dd if="${temp_dir}/1.${dst_suffix}" of="${result_file}" \
- seek="${rw_b_offset}" bs=1 conv=notrunc
+ if strings "${rw}" | grep -q "DBG/${base_name}"; then
+ die "Will not sign debug image with prod keys"
+ fi
+
}
# A very crude RO verification function. The key signature found at a fixed
@@ -460,13 +476,13 @@ verify_ro() {
# downloading the tarball from the BCS expects the image to be in that
# directory.
sign_gsc_firmware() {
- if [[ $# -ne 9 ]]; then
+ if [[ $# -ne 10 ]]; then
die "Usage: sign_gsc_firmware <key_file> <manifest> <fuses>" \
- "<rma_key_dir> <ro_a> <ro_b> <rw_a> <rw_b> <output>"
+ "<rma_key_dir> <ro_a> <ro_b> <rw_a> <rw_b> <output> <generation>"
fi
local key_file="$1"
- local manifest_source="$2"
+ local manifest_file="$2"
local fuses_file="$3"
local rma_key_dir="$4"
local ro_a_hex="$5"
@@ -474,33 +490,21 @@ sign_gsc_firmware() {
local rw_a="$7"
local rw_b="$8"
local output_file="$9"
- local generation
- local manifest_file
+ local generation="${10}"
local temp_dir
- local ro_b_base
- manifest_file="${manifest_source}.updated"
temp_dir="$(make_temp_dir)"
- # Prepare file for inline editing.
- jq . < "${manifest_source}" > "${manifest_file}" || \
- die "basic validation of ${manifest_json} failed"
-
- # Retrieve chip type from the manifest, if preset, otherwise use h1.
- generation="$(jq '.generation' "${manifest_file}")"
case "${generation}" in
- (h|null)
- generation="h" # Just in case this is a legacy manifest.
-
+ (h)
# H1 flash size, image size must match.
IMAGE_SIZE="$(( 512 * 1024 ))"
+ IMAGE_BASE="0x40000"
;;
(d)
# D2 flash size, image size must match.
- IMAGE_SIZE="$(( 512 * 1024 ))"
- ;;
- (*)
- die "Unknown generation value \"${generation}\" in signing manifest"
+ IMAGE_SIZE="$(( 1024 * 1024 ))"
+ IMAGE_BASE="0x80000"
;;
esac
@@ -512,54 +516,101 @@ sign_gsc_firmware() {
die "Failed creating ${output_file}"
fi
+ if ! sign_rw "${key_file}" "${manifest_file}" "${fuses_file}" \
+ "${rma_key_dir}" "${rw_a}" "${rw_b}" \
+ "${output_file}" "${generation}" "${IMAGE_BASE}"; then
+ die "Failed invoking sign_rw for ${rw_a} and ${rw_b}"
+ fi
+
local f
- local count=0
for f in "${ro_a_hex}" "${ro_b_hex}"; do
- if ! objcopy -I ihex "${f}" -O binary "${temp_dir}/${count}.bin"; then
- die "Failed to convert ${f} from hex to bin"
+ local hex_base
+ local bin
+
+ hex_base="$(get_hex_base "${f}")"
+ bin="${temp_dir}/bin"
+
+ if [[ -z ${hex_base} ]]; then
+ die "Failed retrieving base address from ${f}"
fi
- verify_ro "${temp_dir}/${count}.bin" "${key_file}"
- : $(( count++ ))
- done
- if ! sign_rw "${key_file}" "${manifest_file}" "${fuses_file}" \
- "${rma_key_dir}" "${rw_a}" "${rw_b}" \
- "${output_file}" "${generation}"; then
- die "Failed invoking sign_rw for ELF files ${rw_a} ${rw_b}"
- fi
+ if ! objcopy -I ihex "${f}" -O binary "${bin}"; then
+ die "Failed to convert ${f} from hex to bin"
+ fi
+ if [[ "${generation}" == "h" ]]; then
+ verify_ro "${bin}" "${key_file}"
+ fi
- ro_b_base=$(( IMAGE_SIZE / 2 ))
- dd if="${temp_dir}/0.bin" of="${output_file}" conv=notrunc
- dd if="${temp_dir}/1.bin" of="${output_file}" seek="${ro_b_base}" bs=1 \
- conv=notrunc
+ paste_bin "${output_file}" "${bin}" "${IMAGE_BASE}" "${hex_base}"
+ done
- echo "Image successfully signed to ${output_file}"
+ info "Image successfully signed to ${output_file}"
}
# Sign the directory holding GSC firmware.
sign_gsc_firmware_dir() {
if [[ $# -ne 3 ]]; then
- die "Usage: sign_gsc_firmware_dir <input> <key> <output>"
+ die "Usage: sign_gsc_firmware_dir <input> <key dir> <output>"
fi
local input="${1%/}"
- local key_file="$2"
+ local key_dir="$2"
local output="$3"
+ local generation
+ local rw_a
+ local rw_b
+ local manifest_source
+ local manifest_file
+ local key_file
+ local base_name
+
+ manifest_source="${input}/prod.json"
+ manifest_file="${manifest_source}.updated"
+
+ # Verify signing manifest.
+ jq . < "${manifest_source}" > "${manifest_file}" || \
+ die "basic validation of ${manifest_source} failed"
+
+
+ # Retrieve chip type from the manifest, if present, otherwise use h1.
+ generation="$(jq ".generation" "${input}/prod.json" | sed 's/"//g')"
+ case "${generation}" in
+ (h|null)
+ generation="h"
+ base_name="cr50"
+ rw_a="${input}/ec.RW.elf"
+ rw_b="${input}/ec.RW_B.elf"
+ ;;
+ (d)
+ base_name="ti50"
+ rw_a="${input}/rw_A.hex"
+ rw_b="${input}/rw_B.hex"
+ ;;
+ (*)
+ die "Unknown generation value \"${generation}\" in signing manifest"
+ ;;
+ esac
+
+ key_file="${key_dir}/${base_name}.pem"
+ if [[ ! -e "${key_file}" ]]; then
+ die "Missing key file: ${key_file}"
+ fi
if [[ -d "${output}" ]]; then
- output="${output}/cr50.bin.prod"
+ output="${output}/${base_name}.bin.prod"
fi
sign_gsc_firmware \
"${key_file}" \
- "${input}/prod.json" \
+ "${manifest_file}" \
"${input}/fuses.xml" \
"${input}" \
"${input}/prod.ro.A" \
"${input}/prod.ro.B" \
- "${input}/ec.RW.elf" \
- "${input}/ec.RW_B.elf" \
- "${output}"
+ "${rw_a}" \
+ "${rw_b}" \
+ "${output}" \
+ "${generation}"
}
main() {
@@ -572,7 +623,6 @@ main() {
local key_dir="$2"
local output="$3"
- local key_file="${key_dir}/cr50.pem"
local signing_instructions="${input}/signing_instructions.sh"
if [[ -f ${signing_instructions} ]]; then
@@ -581,14 +631,10 @@ main() {
die "${signing_instructions} not found"
fi
- if [[ ! -e "${key_file}" ]]; then
- die "Missing key file: ${key_file}"
- fi
-
if [[ ! -d "${input}" ]]; then
die "Missing input directory: ${input}"
fi
- sign_gsc_firmware_dir "${input}" "${key_file}" "${output}"
+ sign_gsc_firmware_dir "${input}" "${key_dir}" "${output}"
}
main "$@"