diff options
-rwxr-xr-x | scripts/image_signing/sign_nv_cbootimage.sh | 239 |
1 files changed, 210 insertions, 29 deletions
diff --git a/scripts/image_signing/sign_nv_cbootimage.sh b/scripts/image_signing/sign_nv_cbootimage.sh index 71be794d..da978e84 100755 --- a/scripts/image_signing/sign_nv_cbootimage.sh +++ b/scripts/image_signing/sign_nv_cbootimage.sh @@ -26,11 +26,132 @@ EOF exit 1 } -main() { - if [[ $# -ne 4 ]]; then - usage - fi +# 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")" @@ -39,43 +160,103 @@ main() { local work_dir=$(make_temp_dir) local signed_fw=$(make_temp_file) - if [[ "${type}" == "bootloader" ]]; then + pushd "${work_dir}" >/dev/null - pushd "${work_dir}" >/dev/null + cp "${firmware_image}" "${signed_fw}" - cat >update.cfg <<EOF -PkcKey = ${pkc_key}, --save; -ReSignBl; -EOF + # 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 - # This also generates a file pubkey.sha which contains the hash of public - # key required by factory to burn into PKC fuses. Move pubkey.sha into - # ${firmware_image}.pubkey.sha. - cbootimage -s "${soc}" -u update.cfg "${firmware_image}" \ - "${signed_fw}" + # 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" - popd >/dev/null - # Copy signed firmware image and public key hash to current directory. - mv "${work_dir}/pubkey.sha" "${firmware_image}.pubkey.sha" - mv "${signed_fw}" "${firmware_image}" + # Reverse rsa signature to meet tegra soc ordering requirement. + objcopy \ + -I binary \ + --reverse-bytes=256 \ + "${signed_fw}.rsa.sig" \ + "${signed_fw}.rsa.sig.rev" - elif [[ "${type}" == "lp0_firmware" ]]; then + # 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 - pushd "${work_dir}" >/dev/null + # Generate public key modulus from key file. + openssl \ + rsa -in "${pkc_key}" \ + -noout \ + -modulus \ + -out "${signed_fw}.key.mod" - cat >update.cfg <<EOF -PkcKey = ${pkc_key}; -RsaSign = 0x220,, 288, 16, Complete; -EOF + # Remove prefix. + cut \ + -d= \ + -f2 "${signed_fw}.key.mod" > "${signed_fw}.key.mod.tmp1" - cbootimage --sign update.cfg "${firmware_image}" "${signed_fw}" + dd \ + if="${signed_fw}.key.mod.tmp1" \ + of="${signed_fw}.key.mod.tmp" \ + count=512 \ + ibs=1 >/dev/null 2>&1 - popd >/dev/null - mv "${signed_fw}" "${firmware_image}" + # 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" - else + # 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 "$@" |