vboot/vboot_kernel: rewrite kernel version checking code

This CL is part of a series to merge vboot1 and vboot2.0
kernel verification code; see b/181739551.

BUG=b:181739551
TEST=make clean && make runtests
BRANCH=none

Signed-off-by: Joel Kitching <kitching@google.com>
Change-Id: I18790fefe7c4bf2126978c7a9bf1d412dfc8ac78
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2785809
Tested-by: Joel Kitching <kitching@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Commit-Queue: Joel Kitching <kitching@chromium.org>
diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c
index 5ba8614..781868b 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/lib/vboot_kernel.c
@@ -281,23 +281,23 @@
 	}
 
 	/*
-	 * If the keyblock is valid and we're not in recovery mode, check for
-	 * rollback of the kernel version.
+	 * Kernel preamble version is the lower 16 bits of the composite
+	 * kernel version.
 	 */
-	uint32_t combined_version = (key_version << 16) |
-			(preamble->kernel_version & 0xFFFF);
-	shpart->combined_version = combined_version;
-	if (keyblock_valid && boot_mode != VB2_BOOT_MODE_RECOVERY) {
-		if (combined_version < sd->kernel_version_secdata) {
-			VB2_DEBUG("Kernel version too low.\n");
-			shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK;
-			/*
-			 * If not in developer mode, kernel version
-			 * must be valid.
-			 */
-			if (boot_mode != VB2_BOOT_MODE_DEVELOPER)
-				return VB2_ERROR_UNKNOWN;
-		}
+	if (preamble->kernel_version > VB2_MAX_PREAMBLE_VERSION)
+		return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE;
+
+	/* Combine with the key version. */
+	sd->kernel_version = key_version << 16 | preamble->kernel_version;
+	shpart->combined_version = sd->kernel_version;
+
+	/* If not in recovery mode, check for rollback of the kernel version. */
+	if (need_keyblock_valid &&
+	    boot_mode != VB2_BOOT_MODE_RECOVERY &&
+	    sd->kernel_version < sd->kernel_version_secdata) {
+		VB2_DEBUG("Kernel version too low.\n");
+		shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK;
+		return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK;
 	}
 
 	VB2_DEBUG("Kernel preamble is good.\n");
@@ -577,11 +577,11 @@
 		if (keyblock_valid) {
 			sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED;
 			/* Track lowest version from a valid header. */
-			if (lowest_version > shpart->combined_version)
-				lowest_version = shpart->combined_version;
+			if (lowest_version > sd->kernel_version)
+				lowest_version = sd->kernel_version;
 		}
 		VB2_DEBUG("Keyblock valid: %d\n", keyblock_valid);
-		VB2_DEBUG("Combined version: %u\n", shpart->combined_version);
+		VB2_DEBUG("Combined version: %u\n", sd->kernel_version);
 
 		/*
 		 * If we're only looking at headers, we're done with this
@@ -630,7 +630,7 @@
 		 * Otherwise, we'll check all the other headers to see if they
 		 * contain a newer key.
 		 */
-		if (shpart->combined_version == sd->kernel_version_secdata) {
+		if (sd->kernel_version == sd->kernel_version_secdata) {
 			VB2_DEBUG("Same kernel version\n");
 			break;
 		}