vboot_reference: sanity check firmware A/B content when resigning

If the FW_A and FW_B contents are the same, we should not resign with
DEV/NORM keyblocks.

BUG=chrome-os-partner:6942
TEST=(to sign) ./resign_firmwarefd.sh bios.bin new.bin \
	       ../../tests/devkeys/firmware_data_key.vbprivk
	       ../../tests/devkeys/firmware.keyblock \
	       ../../tests/devkeys/dev_firmware_data_key.vbprivk \
	       ../../tests/devkeys/dev_firmware.keyblock \
	       ../../tests/devkeys/kernel_subkey.vbpubk
     (to verify) dump_fmap -x new.bin
                 vbutil_keyblock --unpack VBLOCK_A | grep Flags
                 vbutil_keyblock --unpack VBLOCK_B | grep Flags
     When the input (bios.bin) have DEV FW (ex, zgb/alex), then output
     is A=6, B=7; when the input is old or new firmware without DEV
     (ex, mario/s*y/l*y), output is A=7, B=7, and you'lll see
     "Found firmware with same A/B content - ignore DEV keyblock."
     meessage during resign process.

Change-Id: I10cbbf7370f35a40673b328b70c83e7d1213a45d
Reviewed-on: https://gerrit.chromium.org/gerrit/12371
Commit-Ready: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/scripts/image_signing/resign_firmwarefd.sh b/scripts/image_signing/resign_firmwarefd.sh
index 146907b..abee150 100755
--- a/scripts/image_signing/resign_firmwarefd.sh
+++ b/scripts/image_signing/resign_firmwarefd.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2011 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.
 
@@ -55,7 +55,7 @@
 fi
 
 # Make sure the tools we need are available.
-for prog in dump_fmap vbutil_firmware; do
+for prog in cut dump_fmap md5sum vbutil_firmware; do
   type "${prog}" &>/dev/null || \
     { echo "${prog} tool not found."; exit 1; }
 done
@@ -73,6 +73,19 @@
 # firmware" for more information).
 PREAMBLE_FLAG=$9
 
+# Disables using developer keyblocks
+disable_dev_keyblock() {
+  DEV_FIRMWARE_KEYBLOCK=$FIRMWARE_KEYBLOCK
+  DEV_FIRMWARE_DATAKEY=$FIRMWARE_DATAKEY
+}
+
+# Compares if the contents in given files are the same.
+is_the_same_binary_file() {
+  local hash1="$(md5sum -b "$1" | cut -d' ' -f1)"
+  local hash2="$(md5sum -b "$2" | cut -d' ' -f1)"
+  [ "$hash1" = "$hash2" ]
+}
+
 if [ -z "$VERSION" ]; then
   VERSION=1
 fi
@@ -80,8 +93,7 @@
 
 if [ ! -e $DEV_FIRMWARE_KEYBLOCK ] || [ ! -e $DEV_FIRMWARE_DATAKEY ] ; then
   echo "No dev firmware keyblock/datakey found. Reusing normal keys."
-  DEV_FIRMWARE_KEYBLOCK=$FIRMWARE_KEYBLOCK
-  DEV_FIRMWARE_DATAKEY=$FIRMWARE_DATAKEY
+  disable_dev_keyblock
 fi
 
 # Parse offsets and size of firmware data and vblocks
@@ -108,13 +120,15 @@
   eval fw${i}_size=$((size))
 done
 
-temp_fwimage=$(make_temp_file)
+temp_fwimage_a=$(make_temp_file)
+temp_fwimage_b=$(make_temp_file)
 temp_out_vb=$(make_temp_file)
 
-# Extract out Firmware A data and generate signature using the right keys.
-# Firmware A is the dev firmware.
-dd if="${SRC_FD}" of="${temp_fwimage}" skip="${fwA_offset}" bs=1 \
+# Extract out Firmware A and B.
+dd if="${SRC_FD}" of="${temp_fwimage_a}" skip="${fwA_offset}" bs=1 \
   count="${fwA_size}"
+dd if="${SRC_FD}" of="${temp_fwimage_b}" skip="${fwB_offset}" bs=1 \
+  count="${fwB_size}"
 
 # Extract existing preamble flag if not assigned yet.
 if [ -n "$PREAMBLE_FLAG" ]; then
@@ -127,13 +141,20 @@
   flag="$(vbutil_firmware \
     --verify "${temp_out_vb}" \
     --signpubkey "${temp_root_key}" \
-    --fv "${temp_fwimage}" |
+    --fv "${temp_fwimage_a}" |
     grep "Preamble flags:" |
     sed 's/.*: *//')" || flag=""
   [ -z "$flag" ] || PREAMBLE_FLAG="--flag $flag"
 fi
 echo "Using firmware preamble flag: $PREAMBLE_FLAG"
 
+# Sanity check firmware type: "developer key block" should be only used if the
+# content in firmware A/B are different; otherwise always use normal key blocks.
+if is_the_same_binary_file "${temp_fwimage_a}" "${temp_fwimage_b}"; then
+  echo "Found firmware with same A/B content - ignoring DEV keyblock."
+  disable_dev_keyblock
+fi
+
 echo "Re-calculating Firmware A vblock"
 vbutil_firmware \
   --vblock "${temp_out_vb}" \
@@ -141,7 +162,7 @@
   --signprivate "${DEV_FIRMWARE_DATAKEY}" \
   --version "${VERSION}" \
   $PREAMBLE_FLAG \
-  --fv "${temp_fwimage}" \
+  --fv "${temp_fwimage_a}" \
   --kernelkey "${KERNEL_SUBKEY}"
 
 # Create a copy of the input image and put in the new vblock for firmware A
@@ -149,9 +170,6 @@
 dd if="${temp_out_vb}" of="${DST_FD}" seek="${fwA_vblock_offset}" bs=1 \
   count="${fwA_vblock_size}" conv=notrunc
 
-# Firmware B is the normal firmware.
-dd if="${SRC_FD}" of="${temp_fwimage}" skip="${fwB_offset}" bs=1 \
-  count="${fwB_size}"
 echo "Re-calculating Firmware B vblock"
 vbutil_firmware \
   --vblock "${temp_out_vb}" \
@@ -159,7 +177,7 @@
   --signprivate "${FIRMWARE_DATAKEY}" \
   --version "${VERSION}" \
   $PREAMBLE_FLAG \
-  --fv "${temp_fwimage}" \
+  --fv "${temp_fwimage_b}" \
   --kernelkey "${KERNEL_SUBKEY}"
 
 # Destination image has already been created.