futility: updater: Correct HWID digest when preserving HWID

Starting from GBB 1.2, a digest is stored in GBB and must be updated
whenever the HWID string is changed.

In shell script version of updater, the digest is automatically updated
when we do "futility gbb -s --hwid=XXX", but in native updater
implementation we only updated the HWID string and left digest
unchanged, this leaves devices generating wrong PCR1 values.

`cmd_gbb_utility` updates the digest by calling `update_hwid_digest`
using vboot1 structure, so we should introduce a new vboot2 friendly
function, `vb2_change_hwid`, which changes both HWID string and digest
at same time.

Note this has no impact for end user's devices with write protection
enabled. Only changes dogfood units AU results.

BUG=b:122248649
TEST=make futil; tests/futility/run_test_scripts.sh $(pwd)/build/futility
BRANCH=none

Change-Id: I6ad2754e6df3c9dd66d71c560a2afc26d14eae33
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1411932
Reviewed-by: Joel Kitching <kitching@chromium.org>
(cherry picked from commit 859682accb19893803026a28b4c8ca2cd57945a4)
Reviewed-on: https://chromium-review.googlesource.com/c/1423940
Tested-by: James Chen <chienhua@google.com>
Trybot-Ready: James Chen <chienhua@google.com>
Reviewed-by: John  Chen <zuan@chromium.org>
Reviewed-by: Srinivasa duvvuri <sduvvuri@google.com>
Commit-Queue: John  Chen <zuan@chromium.org>
diff --git a/futility/futility.h b/futility/futility.h
index f063575..f5f6877 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -108,6 +108,9 @@
 int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len,
 			   uint32_t *maxlen);
 
+/* Sets the HWID string field inside a GBB header. */
+int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid);
+
 /* For GBB v1.2 and later, update the hwid_digest */
 void update_hwid_digest(GoogleBinaryBlockHeader *gbb);
 
diff --git a/futility/misc.c b/futility/misc.c
index 703033c..af291a4 100644
--- a/futility/misc.c
+++ b/futility/misc.c
@@ -4,6 +4,7 @@
  * found in the LICENSE file.
  */
 
+#include <assert.h>
 #include <errno.h>
 #ifndef HAVE_MACOS
 #include <linux/fs.h>		/* For BLKGETSIZE64 */
@@ -166,6 +167,7 @@
 	return is_valid;
 }
 
+/* Deprecated. Use futil_set_gbb_hwid in future. */
 /* For GBB v1.2 and later, update the hwid_digest field. */
 void update_hwid_digest(GoogleBinaryBlockHeader *gbb)
 {
@@ -181,6 +183,29 @@
 			  gbb->hwid_digest, sizeof(gbb->hwid_digest));
 }
 
+/* Sets the HWID string field inside a GBB header. */
+int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid)
+{
+	uint8_t *to = (uint8_t *)gbb + gbb->hwid_offset;
+	size_t len;
+
+	assert(hwid);
+	len = strlen(hwid);
+	if (len >= gbb->hwid_size)
+		return -1;
+
+	/* Zero whole area so we won't have garbage after NUL. */
+	memset(to, 0, gbb->hwid_size);
+	memcpy(to, hwid, len);
+
+	/* major_version starts from 1 and digest must be updated since v1.2. */
+	if (gbb->major_version == 1 && gbb->minor_version < 2)
+		return 0;
+
+	return vb2_digest_buffer(to, len, VB2_HASH_SHA256, gbb->hwid_digest,
+				 sizeof(gbb->hwid_digest));
+}
+
 /*
  * TODO: All sorts of race conditions likely here, and everywhere this is used.
  * Do we care? If so, fix it.
diff --git a/futility/updater.c b/futility/updater.c
index 0a2e915..ef66e59 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -953,8 +953,6 @@
 			struct firmware_image *image_to,
 			int preserve_flags)
 {
-	int len;
-	uint8_t *hwid_to, *hwid_from;
 	const struct vb2_gbb_header *gbb_from;
 	struct vb2_gbb_header *gbb_to;
 
@@ -969,18 +967,9 @@
 	if (preserve_flags)
 		gbb_to->flags = gbb_from->flags;
 
-	hwid_to = (uint8_t *)gbb_to + gbb_to->hwid_offset;
-	hwid_from = (uint8_t *)gbb_from + gbb_from->hwid_offset;
-
 	/* Preserve HWID. */
-	len = strlen((const char *)hwid_from);
-	if (len >= gbb_to->hwid_size)
-		return -1;
-
-	/* Zero whole area so we won't have garbage after NUL. */
-	memset(hwid_to, 0, gbb_to->hwid_size);
-	memcpy(hwid_to, hwid_from, len);
-	return 0;
+	return futil_set_gbb_hwid(
+			gbb_to, (const char *)gbb_from + gbb_from->hwid_offset);
 }
 
 /*
diff --git a/tests/futility/test_update.sh b/tests/futility/test_update.sh
index 03743f9..934abbe 100755
--- a/tests/futility/test_update.sh
+++ b/tests/futility/test_update.sh
@@ -91,6 +91,17 @@
 cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.large"
 truncate -s $((8388608 * 2)) "${FROM_IMAGE}.large"
 
+# Create GBB v1.2 images (for checking digest)
+GBB_OUTPUT="$("${FUTILITY}" gbb --digest "${TO_IMAGE}")"
+[ "${GBB_OUTPUT}" = "digest: <none>" ]
+TO_IMAGE_GBB12="${TO_IMAGE}.gbb12"
+HWID_DIGEST="adf64d2a434b610506153da42440b0b498d7369c0e98b629ede65eb59f4784fa"
+cp -f "${TO_IMAGE}" "${TO_IMAGE_GBB12}"
+patch_file "${TO_IMAGE_GBB12}" GBB 6 "\x02"
+"${FUTILITY}" gbb -s --hwid="${TO_HWID}" "${TO_IMAGE_GBB12}"
+GBB_OUTPUT="$("${FUTILITY}" gbb --digest "${TO_IMAGE_GBB12}")"
+[ "${GBB_OUTPUT}" = "digest: ${HWID_DIGEST}   valid" ]
+
 # Generate expected results.
 cp -f "${TO_IMAGE}" "${TMP}.expected.full"
 cp -f "${FROM_IMAGE}" "${TMP}.expected.rw"
@@ -112,6 +123,9 @@
 	RW_SECTION_B:${TMP}.to/RW_SECTION_B
 "${FUTILITY}" load_fmap "${TMP}.expected.legacy" \
 	RW_LEGACY:${TMP}.to/RW_LEGACY
+cp -f "${TMP}.expected.full" "${TMP}.expected.full.gbb12"
+patch_file "${TMP}.expected.full.gbb12" GBB 6 "\x02"
+"${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${TMP}.expected.full.gbb12"
 cp -f "${TMP}.expected.full" "${TMP}.expected.full.gbb0"
 "${FUTILITY}" gbb -s --flags=0 "${TMP}.expected.full.gbb0"
 cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.gbb0"
@@ -187,6 +201,10 @@
 	-i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 \
 	--host_only --ec_image non-exist.bin --pd_image non_exist.bin
 
+test_update "Full update (GBB1.2 hwid digest)" \
+	"${FROM_IMAGE}" "${TMP}.expected.full.gbb12" \
+	-i "${TO_IMAGE_GBB12}" --wp=0 --sys_props 0,0x10001,1
+
 # Test RW-only update.
 test_update "RW update" \
 	"${FROM_IMAGE}" "${TMP}.expected.rw" \