image_signing: use GSC nomenclature instead of Cr50

This patch does not yet provide the ability to sign Ti50 images, but
prepares the signing scripts for further modifications to support a
variety of security chip signing flows.

BRANCH=none
BUG=b:173049030
TEST=verified successful signing of a Cr50 image in a test signer
     setup
     also created a functional Cr50 image invoking
     sign_official_build.sh by hand.

Change-Id: Ic103c9fdf7d1c4ea160c7f6849d5ae5a8303c343
Signed-off-by: Vadim Bendebury <vbendeb@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2537078
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-by: George Engelbrecht <engeg@google.com>
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Auto-Submit: Vadim Bendebury <vbendeb@chromium.org>
diff --git a/scripts/image_signing/sign_cr50_firmware.sh b/scripts/image_signing/sign_gsc_firmware.sh
similarity index 75%
rename from scripts/image_signing/sign_cr50_firmware.sh
rename to scripts/image_signing/sign_gsc_firmware.sh
index d11afbb..768844a 100755
--- a/scripts/image_signing/sign_cr50_firmware.sh
+++ b/scripts/image_signing/sign_gsc_firmware.sh
@@ -36,11 +36,11 @@
            print (struct.unpack('i', d)[0])"
 }
 
-# This function accepts one argument, the name of the Cr50 manifest file which
+# This function accepts one argument, the name of the GSC manifest file which
 # needs to be verified and in certain cases altered.
 #
 # The function verifies that the input manifest is a proper json file, and
-# that the manifest conforms to Cr50 version numbering and board ID flags
+# that the manifest conforms to GSC version numbering and board ID flags
 # conventions for various build images:
 #
 # - only factory version binaries can be converted to node locked images,
@@ -52,9 +52,9 @@
 #
 # - when signing mp images (major version number is odd), the 0x10000 flags
 #   bit must be set (this can be overridden by signing instructions).
-verify_and_prepare_cr50_manifest() {
+verify_and_prepare_gsc_manifest() {
   if [[ $# -ne 1 ]]; then
-    die "Usage: verify_and_prepare_cr50_manifest <manifest .json file>"
+    die "Usage: verify_and_prepare_gsc_manifest <manifest .json file>"
   fi
 
   local manifest_json="$1"
@@ -66,8 +66,8 @@
   local minor
   local values
 
-  values=( $(jq '.config1,.epoch,.major,.minor,.board_id_flags' \
-             "${manifest_json}") )
+  mapfile -t values < <(jq '.config1,.epoch,.major,.minor,.board_id_flags' \
+             "${manifest_json}")
 
   config1="${values[0]}"
   epoch="${values[1]}"
@@ -90,7 +90,7 @@
         die "Node locked target without Device ID value"
       fi
       # Case of a node locked image, it must have the fixed factory version.
-      if [[ $epoch.$major.$minor != $CR50_FACTORY_VERSION ]];then
+      if [[ "${epoch}.${major}.${minor}" != "${CR50_FACTORY_VERSION}" ]];then
         die "Won't create node locked images for version $epoch.$major.$minor"
       fi
 
@@ -100,7 +100,7 @@
 
       devid0="$(to_int32 "0x${INSN_DEVICE_ID/-*}")"
       devid1="$(to_int32 "0x${INSN_DEVICE_ID/*-}")"
-      cf1="$(to_int32 $(( 0x80000000 + ${config1} )))"
+      cf1="$(to_int32 $(( 0x80000000 + config1 )))"
       sub="$(printf "   \"DEV_ID0\": %s,\\\n  \"DEV_ID1\": %s," \
                               "${devid0}" "${devid1}")"
 
@@ -217,12 +217,12 @@
   echo "${base_name}.${curve}"
 }
 
-# Sign cr50 RW firmware ELF images into a combined cr50 firmware image
+# Sign GSC RW firmware ELF images into a combined GSC firmware image
 # using the provided production keys and manifests.
 sign_rw() {
-  if [[ $# -ne 7 ]]; then
+  if [[ $# -ne 8 ]]; then
     die "Usage: sign_rw <key_file> <manifest> <fuses>" \
-        "<rma_key_dir> <rw_a> <rw_b> <output>"
+        "<rma_key_dir> <rw_a> <rw_b> <output> <generation>"
   fi
 
   local key_file="$1"
@@ -231,32 +231,59 @@
   local rma_key_dir="$4"
   local elfs=( "$5" "$6" )
   local result_file="$7"
-  local temp_dir="$(make_temp_dir)"
-  local rma_key_base
+  local generation="$8"
+  local temp_dir
+  local rma_key_base=""
+  local rw_a_offset
+  local rw_b_offset
+
+  temp_dir="$(make_temp_dir)"
 
   if [[ ! -f "${result_file}" ]]; then
     die "${result_file} not found."
   fi
 
-  # If signing a chip factory image (version 0.0.22) do not try figuring out the
-  # RMA keys.
-  local cr50_version="$(jq '.epoch * 10000 + .major * 100 + .minor' \
-     "${manifest_file}")"
+  local signer_command_params=(-x "${fuses_file}" --key "${key_file}")
 
-  if [[ "${cr50_version}" != "22" ]]; then
-    rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${elfs[@]}")"
-  else
-    echo "Ignoring RMA keys for factory branch ${cr50_version}"
-  fi
+  case "${generation}"  in
+    (h)
+      # H1 image might require some tweaking.
+      # If signing a chip factory image (version 0.0.22) do not try figuring
+      # out the RMA keys.
+      local gsc_version
 
-  local signer_command_params=(--b -x "${fuses_file}" --key "${key_file}")
+      gsc_version="$(jq '.epoch * 10000 + .major * 100 + .minor' \
+        "${manifest_file}")"
 
-  # Swap test public RMA server key with the prod version.
-  if [[ -n "${rma_key_base}" ]]; then
-    signer_command_params+=(
-      --swap "${rma_key_base}.test","${rma_key_base}.prod"
-    )
-  fi
+      if [[ "${gsc_version}" != "22" ]]; then
+        rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${elfs[@]}")"
+      else
+        echo "Ignoring RMA keys for factory branch ${gsc_version}"
+      fi
+
+      # Swap test public RMA server key with the prod version.
+      if [[ -n "${rma_key_base}" ]]; then
+        signer_command_params+=(
+          --swap "${rma_key_base}.test,${rma_key_base}.prod"
+        )
+      fi
+
+      # Indicate H1 signing.
+      signer_command_params+=( '--b' )
+      # Fixed offsets into the binary blob where RW sections start.
+      rw_a_offset=16384
+      rw_b_offset=278528
+      ;;
+    (d)
+      # Indicate D1 signing.
+      signer_command_params+=( '--dauntless' )
+      die "Need to figure out D2 RW sections offsets"
+      ;;
+    (*)
+      die "Unknown generation value \"${generation}\""
+      ;;
+  esac
+
   signer_command_params+=(--json "${manifest_file}")
 
   signer_command_params+=(--format=bin)
@@ -275,9 +302,9 @@
 
     # Make sure output file is not owned by root.
     touch "${signed_file}"
-    if ! cr50-codesigner "${signer_command_params[@]}" \
+    if ! gsc-codesigner "${signer_command_params[@]}" \
         -i "${elf}" -o "${signed_file}"; then
-      die "cr50-codesigner ${signer_command_params[@]}" \
+      die "gsc-codesigner ${signer_command_params[*]}" \
         "-i ${elf} -o ${signed_file} failed"
     fi
 
@@ -296,9 +323,9 @@
   # Full binary image is required, paste the newly signed blobs into the
   # output image.
   dd if="${temp_dir}/0.${dst_suffix}" of="${result_file}" \
-    seek=16384 bs=1 conv=notrunc
+    seek="${rw_a_offset}" bs=1 conv=notrunc
   dd if="${temp_dir}/1.${dst_suffix}" of="${result_file}" \
-    seek=278528 bs=1 conv=notrunc
+    seek="${rw_b_offset}" bs=1 conv=notrunc
 }
 
 # A very crude RO verification function. The key signature found at a fixed
@@ -337,7 +364,7 @@
   die "RO key (${key_byte}) in ${ro_bin} does not match type prod"
 }
 
-# This function prepares a full CR50 image, consisting of two ROs and two RWs
+# This function prepares a full GSC image, consisting of two ROs and two RWs
 # placed at their respective offsets into the resulting blob. It invokes the
 # bs (binary signer) script to actually convert ELF versions of RWs into
 # binaries and sign them.
@@ -346,9 +373,9 @@
 # RW version numbers and board ID fields, if set to non-default. The ebuild
 # downloading the tarball from the BCS expects the image to be in that
 # directory.
-sign_cr50_firmware() {
+sign_gsc_firmware() {
   if [[ $# -ne 9 ]]; then
-    die "Usage: sign_cr50_firmware <key_file> <manifest> <fuses>" \
+    die "Usage: sign_gsc_firmware <key_file> <manifest> <fuses>" \
         "<rma_key_dir> <ro_a> <ro_b> <rw_a> <rw_b> <output>"
   fi
 
@@ -361,19 +388,37 @@
   local rw_a="$7"
   local rw_b="$8"
   local output_file="$9"
+  local generation
+  local manifest_file
+  local temp_dir
+  local ro_b_base
 
-  local manifest_file="${manifest_source}.updated"
-  local temp_dir="$(make_temp_dir)"
+  manifest_file="${manifest_source}.updated"
+  temp_dir="$(make_temp_dir)"
 
-  # The H1 chip where Cr50 firmware runs has 512K of flash, the generated
-  # image must match the flash size.
-  IMAGE_SIZE="$(( 512 * 1024 ))"
-
-    # Prepare file for inline editing.
+  # Prepare file for inline editing.
   jq . < "${manifest_source}" > "${manifest_file}" || \
     die "basic validation of ${manifest_json} failed"
 
-  verify_and_prepare_cr50_manifest "${manifest_file}"
+  # Retrieve chip type from the manifest, if preset, otherwise use h1.
+  generation="$(jq '.generation' "${manifest_file}")"
+  case "${generation}"  in
+    (h|null)
+      generation="h"  # Just in case this is a legacy manifest.
+
+      # H1 flash size, image size must match.
+      IMAGE_SIZE="$(( 512 * 1024 ))"
+      ;;
+    (d)
+      # D2 flash size, image size must match.
+      IMAGE_SIZE="$(( 512 * 1024 ))"
+      ;;
+    (*)
+      die "Unknown generation value \"${generation}\" in signing manifest"
+      ;;
+  esac
+
+  verify_and_prepare_gsc_manifest "${manifest_file}"
 
   dd if=/dev/zero bs="${IMAGE_SIZE}" count=1 status=none |
     tr '\000' '\377' > "${output_file}"
@@ -392,20 +437,23 @@
   done
 
   if ! sign_rw "${key_file}" "${manifest_file}" "${fuses_file}" \
-               "${rma_key_dir}" "${rw_a}" "${rw_b}" "${output_file}"; then
+       "${rma_key_dir}" "${rw_a}" "${rw_b}" \
+       "${output_file}" "${generation}"; then
     die "Failed invoking sign_rw for ELF files ${rw_a} ${rw_b}"
   fi
 
+  ro_b_base=$(( IMAGE_SIZE / 2 ))
   dd if="${temp_dir}/0.bin" of="${output_file}" conv=notrunc
-  dd if="${temp_dir}/1.bin" of="${output_file}" seek=262144 bs=1 conv=notrunc
+  dd if="${temp_dir}/1.bin" of="${output_file}" seek="${ro_b_base}" bs=1 \
+     conv=notrunc
 
   echo "Image successfully signed to ${output_file}"
 }
 
-# Sign the directory holding cr50 firmware.
-sign_cr50_firmware_dir() {
+# Sign the directory holding GSC firmware.
+sign_gsc_firmware_dir() {
   if [[ $# -ne 3 ]]; then
-    die "Usage: sign_cr50_firmware_dir <input> <key> <output>"
+    die "Usage: sign_gsc_firmware_dir <input> <key> <output>"
   fi
 
   local input="${1%/}"
@@ -416,7 +464,7 @@
     output="${output}/cr50.bin.prod"
   fi
 
-  sign_cr50_firmware \
+  sign_gsc_firmware \
           "${key_file}" \
           "${input}/prod.json" \
           "${input}/fuses.xml" \
@@ -455,6 +503,6 @@
     die "Missing input directory: ${input}"
   fi
 
-  sign_cr50_firmware_dir "${input}" "${key_file}" "${output}"
+  sign_gsc_firmware_dir "${input}" "${key_file}" "${output}"
 }
 main "$@"
diff --git a/scripts/image_signing/sign_official_build.sh b/scripts/image_signing/sign_official_build.sh
index 9a1a405..6167f0b 100755
--- a/scripts/image_signing/sign_official_build.sh
+++ b/scripts/image_signing/sign_official_build.sh
@@ -39,7 +39,7 @@
              verify (verify an image including rootfs hashes)
              accessory_usbpd (sign USB-PD accessory firmware)
              accessory_rwsig (sign accessory RW firmware)
-             cr50_firmware (sign a cr50 firmware image)
+             gsc_firmware (sign a GSC firmware image)
 
 output_image: File name of the signed output image
 version_file: File name of where to read the kernel and firmware versions.
@@ -817,14 +817,14 @@
   fi
 }
 
-# Sign a cr50 firmware image with the given keys.
+# Sign a GSC firmware image with the given keys.
 # Args: CONTAINER KEY_DIR [OUTPUT_CONTAINER]
-sign_cr50_firmware() {
+sign_gsc_firmware() {
   local image=$1
   local key_dir=$2
   local output=$3
 
-  "${SCRIPT_DIR}/sign_cr50_firmware.sh" \
+  "${SCRIPT_DIR}/sign_gsc_firmware.sh" \
     "${image}" "${key_dir}" "${output}"
 }
 
@@ -1140,8 +1140,8 @@
   cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
   futility sign --type rwsig --prikey "${KEY_NAME}" \
            --version "${FIRMWARE_VERSION}" "${OUTPUT_IMAGE}"
-elif [[ "${TYPE}" == "cr50_firmware" ]]; then
-  sign_cr50_firmware "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}"
+elif [[ "${TYPE}" == "gsc_firmware" ]]; then
+  sign_gsc_firmware "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}"
 else
   die "Invalid type ${TYPE}"
 fi