vboot2: Add more precise recovery reasons to firmware verification

vboot1 kept track of an internal "LoadFirmware() check" value for both
firmware slots and encoded the value for the slot that managed to go
further in the verification flow into a special range of recovery
reasons. vboot2 instead uses the generic "invalid RW" reason for all
firmware verification failures and communicates further information
through the subcode.

While the subcode may be good enough for developers, it's difficult to
communicate failure reasons to "normal" users (like non-firmware
developers) on the TAB screen. Currently we just display a couple of
numbers that people won't know how to interpret and "RW firmware failed
signature check" for any verification error (including rollback, which
might be the most commonly encountered in practice).

Since our recovery reason space is big enough (and we don't reuse old
numbers anyway), we might as well reuse the more precise numbers (and
strings) from vboot1 to communicate the failure reason, even if we don't
implement its "which slot came further" algorithm. This patch translates
the most common/useful VBSD_LF_CHECK numbers into plain VB2_RECOVERY
reasons and uses them where appropriate.

CQ-DEPEND=CL:248400
BRANCH=veyron
BUG=None
TEST=make runtests VBOOT2=1
test_that my_jerry firmware_CorruptBothFwSigAB
firmware_CorruptBothFwBodyAB firmware_RollbackFirmware
(Confirmed that matched recovery reasons are the more precise ones in
the 0x10-0x1F range.)

Change-Id: I51ecf1b820d1faa40405cb84377380d6f3f6ca1d
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/248392
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
diff --git a/firmware/2lib/include/2recovery_reasons.h b/firmware/2lib/include/2recovery_reasons.h
index c305dd6..3633fe1 100644
--- a/firmware/2lib/include/2recovery_reasons.h
+++ b/firmware/2lib/include/2recovery_reasons.h
@@ -48,15 +48,20 @@
 	/* Test error from LoadFirmware() (deprecated) */
 	VB2_RECOVERY_RO_TEST_LF = 0x09,
 
-	/*
-	 * RW firmware failed signature check (neither RW firmware slot was
-	 * valid).  Recovery reason is VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN +
-	 * the check value for the slot which came closest to validating; see
-	 * VBSD_LF_CHECK_* in vboot_struct.h.
-	 */
-	// TODO: pass back those codes from vboot2?
-	VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN = 0x10,
-	VB2_RECOVERY_RO_INVALID_RW_CHECK_MAX = 0x1F,
+	/* Latest tried RW firmware keyblock verification failed */
+	VB2_RECOVERY_FW_KEYBLOCK = 0x13,
+
+	/* Latest tried RW firmware key version too old */
+	VB2_RECOVERY_FW_KEY_ROLLBACK = 0x14,
+
+	/* Latest tried RW firmware preamble verification failed */
+	VB2_RECOVERY_FW_PREAMBLE = 0x16,
+
+	/* Latest tried RW firmware version too old */
+	VB2_RECOVERY_FW_ROLLBACK = 0x17,
+
+	/* Latest tried RW firmware body verification failed */
+	VB2_RECOVERY_FW_BODY = 0x1b,
 
 	/*
 	 * Firmware boot failure outside of verified boot (RAM init, missing
diff --git a/firmware/lib20/api.c b/firmware/lib20/api.c
index 3fa492e..55c59ea 100644
--- a/firmware/lib20/api.c
+++ b/firmware/lib20/api.c
@@ -189,7 +189,7 @@
 	 */
 	rv = vb2_verify_digest(&key, &pre->body_signature, digest, &wb);
 	if (rv)
-		vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
+		vb2_fail(ctx, VB2_RECOVERY_FW_BODY, rv);
 
 	return rv;
 }
diff --git a/firmware/lib20/misc.c b/firmware/lib20/misc.c
index 815d5eb..a446022 100644
--- a/firmware/lib20/misc.c
+++ b/firmware/lib20/misc.c
@@ -74,14 +74,20 @@
 
 	/* Verify the keyblock */
 	rv = vb2_verify_keyblock(kb, block_size, &root_key, &wb);
-	if (rv)
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv);
 		return rv;
+	}
 
 	/* Key version is the upper 16 bits of the composite firmware version */
 	if (kb->data_key.key_version > 0xffff)
-		return VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE;
-	if (kb->data_key.key_version < (sd->fw_version_secdata >> 16))
-		return VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
+		rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE;
+	if (!rv && kb->data_key.key_version < (sd->fw_version_secdata >> 16))
+		rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv);
+		return rv;
+	}
 
 	sd->fw_version = kb->data_key.key_version << 16;
 
@@ -174,20 +180,25 @@
 
 	/* Verify the preamble */
 	rv = vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb);
-	if (rv)
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv);
 		return rv;
+	}
 
 	/*
 	 * Firmware version is the lower 16 bits of the composite firmware
 	 * version.
 	 */
 	if (pre->firmware_version > 0xffff)
-		return VB2_ERROR_FW_PREAMBLE_VERSION_RANGE;
-
+		rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE;
 	/* Combine with the key version from vb2_load_fw_keyblock() */
 	sd->fw_version |= pre->firmware_version;
-	if (sd->fw_version < sd->fw_version_secdata)
-		return VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
+	if (!rv && sd->fw_version < sd->fw_version_secdata)
+		rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv);
+		return rv;
+	}
 
 	/*
 	 * If this is a newer version than in secure storage, and we
diff --git a/firmware/lib21/misc.c b/firmware/lib21/misc.c
index f29b6e4..92322a9 100644
--- a/firmware/lib21/misc.c
+++ b/firmware/lib21/misc.c
@@ -104,8 +104,10 @@
 
 	/* Verify the keyblock */
 	rv = vb2_verify_keyblock(kb, kb->c.total_size, &root_key, &wb);
-	if (rv)
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv);
 		return rv;
+	}
 
 	/* Preamble follows the keyblock in the vblock */
 	sd->vblock_preamble_offset = kb->c.total_size;
@@ -114,9 +116,13 @@
 
 	/* Key version is the upper 16 bits of the composite firmware version */
 	if (packed_key->key_version > 0xffff)
-		return VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE;
-	if (packed_key->key_version < (sd->fw_version_secdata >> 16))
-		return VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
+		rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE;
+	if (!rv && packed_key->key_version < (sd->fw_version_secdata >> 16))
+		rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv);
+		return rv;
+	}
 
 	sd->fw_version = packed_key->key_version << 16;
 
@@ -179,8 +185,10 @@
 
 	/* Verify the preamble */
 	rv = vb2_verify_fw_preamble(pre, pre->c.total_size, &data_key, &wb);
-	if (rv)
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv);
 		return rv;
+	}
 
 	/* Move the preamble down now that the data key is no longer used */
 	memmove(key_data, pre, pre->c.total_size);
@@ -194,12 +202,15 @@
 	 * version.
 	 */
 	if (pre->fw_version > 0xffff)
-		return VB2_ERROR_FW_PREAMBLE_VERSION_RANGE;
-
+		rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE;
 	/* Combine with the key version from vb2_load_fw_keyblock() */
 	sd->fw_version |= pre->fw_version;
-	if (sd->fw_version < sd->fw_version_secdata)
-		return VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
+	if (!rv && sd->fw_version < sd->fw_version_secdata)
+		rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
+	if (rv) {
+		vb2_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv);
+		return rv;
+	}
 
 	/*
 	 * If this is a newer version than in secure storage, and we