summaryrefslogtreecommitdiff
path: root/scripts/image_signing/sign_nv_cbootimage.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/image_signing/sign_nv_cbootimage.sh')
-rwxr-xr-xscripts/image_signing/sign_nv_cbootimage.sh262
1 files changed, 262 insertions, 0 deletions
diff --git a/scripts/image_signing/sign_nv_cbootimage.sh b/scripts/image_signing/sign_nv_cbootimage.sh
new file mode 100755
index 00000000..da978e84
--- /dev/null
+++ b/scripts/image_signing/sign_nv_cbootimage.sh
@@ -0,0 +1,262 @@
+#!/bin/bash
+# Copyright 2015 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.
+
+# Wrapper script for signing firmware image using cbootimage.
+
+# Determine script directory.
+SCRIPT_DIR=$(dirname "$0")
+
+# Load common constants and variables.
+. "${SCRIPT_DIR}/common_minimal.sh"
+
+# Abort on error.
+set -e
+
+usage() {
+ cat<<EOF
+Usage: $0 <type> <pkc_key> <firmware_image> <soc>
+
+Signs <firmware_image> of <type> with <pkc_key> using cbootimage for <soc>.
+where type is one of
+ bootloader = sign bootloader image
+ lp0_firmware = sign lp0 firmware
+EOF
+ exit 1
+}
+
+# Signs bootloader image using pkc_key provided for given soc
+# Args: TYPE=bootloader PKC_KEY FIRMWARE_IMAGE SOC
+sign_bootloader() {
+ local type=$1
+ local pkc_key="$(readlink -f "$2")"
+ local firmware_image="$(readlink -f "$3")"
+ local soc=$4
+
+ local work_dir=$(make_temp_dir)
+ local config_file=$(make_temp_file)
+ local signed_fw=$(make_temp_file)
+
+ pushd "${work_dir}" >/dev/null
+
+ # Get bootloader length.
+ #
+ # Example:
+ # $ bct_dump image.fastboot.bin
+ # Version = 0x00210001;
+ # BlockSize = 0x00008000;
+ # ...
+ # ...
+ # # Bootloader[0].Length = 69324;
+ # ...
+ # ...
+ #
+ # then, bl_length=69324 (size of bootloader that needs to be signed)
+ local bl_length=$(bct_dump "${firmware_image}" | \
+ sed -n '/Bootloader\[0\].Length/{ s/.*=\s*//; s/;//; p; q}')
+
+ # Extract bootloader to sign.
+ dd \
+ if="${firmware_image}" \
+ of="${signed_fw}.bl.tosig" \
+ count="${bl_length}" \
+ ibs=1 \
+ skip=32768 >/dev/null 2>&1
+
+ # Calculate rsa signature for bootloader.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.bl.sig" \
+ "${signed_fw}.bl.tosig"
+
+ # Update bootloader's rsa signature, aes hash and bct's aes hash.
+ echo "RsaPssSigBlFile = ${signed_fw}.bl.sig;" > "${config_file}"
+ echo "RehashBl;" >> "${config_file}"
+ cbootimage \
+ -s "${soc}" \
+ -u "${config_file}" \
+ "${firmware_image}" \
+ "${signed_fw}.tmp" >/dev/null
+
+ # Extract the part of bct which needs to be rsa signed.
+ dd \
+ if="${signed_fw}.tmp" \
+ of="${signed_fw}.bct.tosig" \
+ count=8944 \
+ ibs=1 \
+ skip=1296 >/dev/null 2>&1
+
+ # Calculate rsa signature for bct.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.bct.sig" \
+ "${signed_fw}.bct.tosig"
+
+ # Create public key modulus from key file.
+ openssl \
+ rsa -in "${pkc_key}" \
+ -noout \
+ -modulus \
+ -out "${signed_fw}.key.mod"
+
+ # Remove prefix.
+ cut \
+ -d= \
+ -f2 "${signed_fw}.key.mod" > "${signed_fw}.key.mod.tmp1"
+ dd \
+ if="${signed_fw}.key.mod.tmp1" \
+ of="${signed_fw}.key.mod.tmp" \
+ count=512 \
+ ibs=1 >/dev/null 2>&1
+
+ # Convert from hexdecimal to binary.
+ perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' \
+ < "${signed_fw}.key.mod.tmp" \
+ > "${signed_fw}.key.mod.bin"
+
+ # Update bct's rsa signature and modulus.
+ echo "RsaPssSigBctFile = ${signed_fw}.bct.sig;" > "${config_file}"
+ echo "RsaKeyModulusFile = ${signed_fw}.key.mod.bin;" >> "${config_file}"
+ cbootimage \
+ -s "${soc}" \
+ -u "${config_file}" \
+ "${signed_fw}.tmp" \
+ "${signed_fw}" >/dev/null
+
+ # Calculate hash of public key modulus.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.key.mod.bin" \
+ "${signed_fw}.key.mod.bin.rev"
+ openssl \
+ dgst -sha256 \
+ -binary \
+ -out "${signed_fw}.key.sha" \
+ "${signed_fw}.key.mod.bin.rev"
+
+ popd >/dev/null
+
+ # Copy signed firmware image and public key hash to current directory..
+ mv "${signed_fw}" "${firmware_image}"
+ mv "${signed_fw}.key.sha" "${firmware_image}.pubkey.sha"
+}
+
+# Signs lp0 firmware image using pkc_key provided for given soc
+# Args: TYPE=lp0_firmware PKC_KEY FIRMWARE_IMAGE SOC
+sign_lp0_firmware() {
+ local type=$1
+ local pkc_key="$(readlink -f "$2")"
+ local firmware_image="$(readlink -f "$3")"
+ local soc=$4
+
+ local work_dir=$(make_temp_dir)
+ local signed_fw=$(make_temp_file)
+
+ pushd "${work_dir}" >/dev/null
+
+ cp "${firmware_image}" "${signed_fw}"
+
+ # Extract the part of the binary which needs to be signed.
+ dd \
+ if="${firmware_image}" \
+ of="${signed_fw}.tosig" \
+ ibs=1 \
+ skip=544 >/dev/null 2>&1
+
+ # Calculate rsa-pss signature.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.rsa.sig" \
+ "${signed_fw}.tosig"
+
+ # Reverse rsa signature to meet tegra soc ordering requirement.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.rsa.sig" \
+ "${signed_fw}.rsa.sig.rev"
+
+ # Inject rsa-pss signature into the binary image's header.
+ dd \
+ if="${signed_fw}.rsa.sig.rev" \
+ of="${signed_fw}" \
+ count=256 \
+ obs=1 \
+ seek=288 \
+ conv=notrunc >/dev/null 2>&1
+
+ # Generate public key modulus from key file.
+ openssl \
+ rsa -in "${pkc_key}" \
+ -noout \
+ -modulus \
+ -out "${signed_fw}.key.mod"
+
+ # Remove prefix.
+ cut \
+ -d= \
+ -f2 "${signed_fw}.key.mod" > "${signed_fw}.key.mod.tmp1"
+
+ dd \
+ if="${signed_fw}.key.mod.tmp1" \
+ of="${signed_fw}.key.mod.tmp" \
+ count=512 \
+ ibs=1 >/dev/null 2>&1
+
+ # Convert from hexdecimal to binary.
+ perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' \
+ < "${signed_fw}.key.mod.tmp" \
+ > "${signed_fw}.key.mod.bin"
+
+ # Reverse byte order.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.key.mod.bin" \
+ "${signed_fw}.key.mod.bin.rev"
+
+ # Inject public key modulus into the binary image's header.
+ dd \
+ if="${signed_fw}.key.mod.bin.rev" \
+ of="${signed_fw}" \
+ count=256 \
+ obs=1 \
+ seek=16 \
+ conv=notrunc >/dev/null 2>&1
+
+ popd >/dev/null
+ mv "${signed_fw}" "${firmware_image}"
+}
+
+main() {
+ if [[ $# -ne 4 ]]; then
+ usage
+ fi
+
+ local type=$1
+
+ case ${type} in
+ bootloader)
+ sign_bootloader "$@"
+ ;;
+ lp0_firmware)
+ sign_lp0_firmware "$@"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+}
+
+main "$@"