#!/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< Signs of with using cbootimage for . 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 "$@"