sign_nv_cbootimage: Update script to match script from master branch

CQ-DEPEND=CL:325370, CL:325382
BUG=chrome-os-partner:43018
BRANCH=None
TEST=Verified that signed image boots on dev-fused system.

Change-Id: Ice6cfce11fbcababd896a17e9546bcbc75b4a970
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/325381
Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
Tested-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Furquan Shaikh <furquan@chromium.org>
diff --git a/Makefile b/Makefile
index 3314155..f9f5a06 100644
--- a/Makefile
+++ b/Makefile
@@ -590,7 +590,7 @@
 	scripts/image_signing/make_dev_firmware.sh \
 	scripts/image_signing/make_dev_ssd.sh \
 	scripts/image_signing/set_gbb_flags.sh \
-	scripts/image_signing/nv_pkc_signing.sh
+	scripts/image_signing/sign_nv_cbootimage.sh
 
 # Installed, but not made executable.
 SIGNING_COMMON = scripts/image_signing/common_minimal.sh
diff --git a/scripts/image_signing/nv_pkc_signing.sh b/scripts/image_signing/nv_pkc_signing.sh
deleted file mode 100755
index 3495173..0000000
--- a/scripts/image_signing/nv_pkc_signing.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2012 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.
-
-set +e
-
-# If tools are not present, do not continue signing
-if [ ! type nv_bct_dump ] || [ ! type nv_cbootimage ]; then
-    exit 0
-fi
-
-cat >update.cfg <<EOF
-PkcKey = $1/nv_pkc.pem;
-ReSignBl;
-EOF
-
-nv_cbootimage -s tegra210 -u update.cfg $2 $2-final
-cp $2-final $2
-
-exit 0
diff --git a/scripts/image_signing/sign_nv_cbootimage.sh b/scripts/image_signing/sign_nv_cbootimage.sh
new file mode 100755
index 0000000..da978e8
--- /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 "$@"