From 478b6d34afb9fd98daf0663dd6093d8f058a9f34 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Wed, 13 Jan 2016 14:49:03 -0800 Subject: sign_nv_cbootimage: Update signing scripts for nv bootloader and lp0 Currently, nvidia tools do not provide the support to perform signing of bootloader or lp0 image. Thus, the signing script is updated to support this. Once, we have the required tools, this script can be simplified again. CQ-DEPEND=CL:*244234 BUG=chrome-os-partner:43018 BRANCH=none TEST=Verified that signed bootloader and lp0 work fine on dev-PKC fused devices. Reference: https://code.google.com/p/chrome-os-partner/issues/attachmentText?id=43018&aid=430180067000&name=sign-lp0.sh&token=ABZ6GAcjz4b2mEk55WqREzwTnWWpEyE_7A%3A1452631308268 https://code.google.com/p/chrome-os-partner/issues/attachmentText?id=43018&aid=430180060000&name=sign.sh&token=ABZ6GAcRky67XrzMOgKZfkJxr70qm-tTAg%3A1452631308240 Change-Id: Icb024a1d9a61714df6e52d94c96cf43481cac869 Signed-off-by: Furquan Shaikh Reviewed-on: https://chromium-review.googlesource.com/321459 Commit-Ready: Furquan Shaikh Tested-by: Furquan Shaikh Reviewed-by: Mike Frysinger --- scripts/image_signing/sign_nv_cbootimage.sh | 239 ++++++++++++++++++++++++---- 1 file 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 </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 < "${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 "$@" -- cgit v1.2.1