vboot2: Add sd->fw_version_secdata field to communicate to crossystem

This patchs adds a new vb2_shared_data field to store the current
rollback prevention version number stored in secdata (TPM). This
information needs to be retrieved from there by coreboot (current
hack) or vboot2 kernel verification (bright shiny future) so it can be
passed along to the operating system and user space.

BRANCH=veyron
BUG=chrome-os-partner:35941
TEST=make runtests. Booted Jerry in recovery mode (with corresponding
coreboot patch), ensured that crossystem tpm_fwver still shows the
correct value.

Change-Id: I2a0c3e51b158a35ac129d2abce19b40c6c6381a6
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/244601
Reviewed-by: Randall Spangler <rspangler@chromium.org>
diff --git a/firmware/2lib/2secdata.c b/firmware/2lib/2secdata.c
index 2987e03..0c5a34e 100644
--- a/firmware/2lib/2secdata.c
+++ b/firmware/2lib/2secdata.c
@@ -53,6 +53,12 @@
 	if (rv)
 		return rv;
 
+	/* Read this now to make sure crossystem has it even in rec mode. */
+	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS,
+			     &sd->fw_version_secdata);
+	if (rv)
+		return rv;
+
 	/* Set status flag */
 	sd->status |= VB2_SD_STATUS_SECDATA_INIT;
 	// TODO: unit test for that
diff --git a/firmware/2lib/include/2struct.h b/firmware/2lib/include/2struct.h
index 95cf73c..3339a30 100644
--- a/firmware/2lib/include/2struct.h
+++ b/firmware/2lib/include/2struct.h
@@ -88,6 +88,9 @@
 	 */
 	uint32_t fw_version;
 
+	/* Version stored in secdata (must be <= fw_version to boot). */
+	uint32_t fw_version_secdata;
+
 	/*
 	 * Status flags for this boot; see enum vb2_shared_data_status.  Status
 	 * is "what we've done"; flags above are "decisions we've made".
diff --git a/firmware/lib20/misc.c b/firmware/lib20/misc.c
index 89e46ec..815d5eb 100644
--- a/firmware/lib20/misc.c
+++ b/firmware/lib20/misc.c
@@ -27,7 +27,6 @@
 	struct vb2_keyblock *kb;
 	uint32_t block_size;
 
-	uint32_t sec_version;
 	int rv;
 
 	vb2_workbuf_from_ctx(ctx, &wb);
@@ -78,15 +77,10 @@
 	if (rv)
 		return rv;
 
-	/* Read the secure key version */
-	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS, &sec_version);
-	if (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 < (sec_version >> 16))
+	if (kb->data_key.key_version < (sd->fw_version_secdata >> 16))
 		return VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
 
 	sd->fw_version = kb->data_key.key_version << 16;
@@ -140,7 +134,6 @@
 	struct vb2_fw_preamble *pre;
 	uint32_t pre_size;
 
-	uint32_t sec_version;
 	int rv;
 
 	vb2_workbuf_from_ctx(ctx, &wb);
@@ -184,11 +177,6 @@
 	if (rv)
 		return rv;
 
-	/* Read the secure key version */
-	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS, &sec_version);
-	if (rv)
-		return rv;
-
 	/*
 	 * Firmware version is the lower 16 bits of the composite firmware
 	 * version.
@@ -198,7 +186,7 @@
 
 	/* Combine with the key version from vb2_load_fw_keyblock() */
 	sd->fw_version |= pre->firmware_version;
-	if (sd->fw_version < sec_version)
+	if (sd->fw_version < sd->fw_version_secdata)
 		return VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
 
 	/*
@@ -206,10 +194,11 @@
 	 * successfully booted the same slot last boot, roll forward the
 	 * version in secure storage.
 	 */
-	if (sd->fw_version > sec_version &&
+	if (sd->fw_version > sd->fw_version_secdata &&
 	    sd->last_fw_slot == sd->fw_slot &&
 	    sd->last_fw_result == VB2_FW_RESULT_SUCCESS) {
 
+		sd->fw_version_secdata = sd->fw_version;
 		rv = vb2_secdata_set(ctx, VB2_SECDATA_VERSIONS, sd->fw_version);
 		if (rv)
 			return rv;
diff --git a/firmware/lib21/misc.c b/firmware/lib21/misc.c
index 384d44e..f29b6e4 100644
--- a/firmware/lib21/misc.c
+++ b/firmware/lib21/misc.c
@@ -73,7 +73,6 @@
 	struct vb2_public_key root_key;
 	struct vb2_keyblock *kb;
 
-	uint32_t sec_version;
 	int rv;
 
 	vb2_workbuf_from_ctx(ctx, &wb);
@@ -111,17 +110,12 @@
 	/* Preamble follows the keyblock in the vblock */
 	sd->vblock_preamble_offset = kb->c.total_size;
 
-	/* Read the secure key version */
-	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS, &sec_version);
-	if (rv)
-		return rv;
-
 	packed_key = (struct vb2_packed_key *)((uint8_t *)kb + kb->key_offset);
 
 	/* 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 < (sec_version >> 16))
+	if (packed_key->key_version < (sd->fw_version_secdata >> 16))
 		return VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
 
 	sd->fw_version = packed_key->key_version << 16;
@@ -162,7 +156,6 @@
 	/* Preamble goes in the next unused chunk of work buffer */
 	struct vb2_fw_preamble *pre;
 
-	uint32_t sec_version;
 	int rv;
 
 	vb2_workbuf_from_ctx(ctx, &wb);
@@ -196,11 +189,6 @@
 	/* Data key is now gone */
 	sd->workbuf_data_key_offset = sd->workbuf_data_key_size = 0;
 
-	/* Read the secure key version */
-	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS, &sec_version);
-	if (rv)
-		return rv;
-
 	/*
 	 * Firmware version is the lower 16 bits of the composite firmware
 	 * version.
@@ -210,7 +198,7 @@
 
 	/* Combine with the key version from vb2_load_fw_keyblock() */
 	sd->fw_version |= pre->fw_version;
-	if (sd->fw_version < sec_version)
+	if (sd->fw_version < sd->fw_version_secdata)
 		return VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
 
 	/*
@@ -218,10 +206,11 @@
 	 * successfully booted the same slot last boot, roll forward the
 	 * version in secure storage.
 	 */
-	if (sd->fw_version > sec_version &&
+	if (sd->fw_version > sd->fw_version_secdata &&
 	    sd->last_fw_slot == sd->fw_slot &&
 	    sd->last_fw_result == VB2_FW_RESULT_SUCCESS) {
 
+		sd->fw_version_secdata = sd->fw_version;
 		rv = vb2_secdata_set(ctx, VB2_SECDATA_VERSIONS, sd->fw_version);
 		if (rv)
 			return rv;
diff --git a/tests/vb20_misc_tests.c b/tests/vb20_misc_tests.c
index 45985dd..65ceea9 100644
--- a/tests/vb20_misc_tests.c
+++ b/tests/vb20_misc_tests.c
@@ -81,7 +81,8 @@
 	mock_verify_preamble_retval = VB2_SUCCESS;
 
 	/* Set up mock data for verifying keyblock */
-	vb2_secdata_set(&cc, VB2_SECDATA_VERSIONS, 0x20002);
+	sd->fw_version_secdata = 0x20002;
+	vb2_secdata_set(&cc, VB2_SECDATA_VERSIONS, sd->fw_version_secdata);
 
 	sd->gbb_rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey);
 	sd->gbb_rootkey_size = sizeof(mock_gbb.rootkey_data);
diff --git a/tests/vb21_misc_tests.c b/tests/vb21_misc_tests.c
index af2c079..826c3fb 100644
--- a/tests/vb21_misc_tests.c
+++ b/tests/vb21_misc_tests.c
@@ -84,7 +84,8 @@
 	mock_verify_preamble_retval = VB2_SUCCESS;
 
 	/* Set up mock data for verifying keyblock */
-	vb2_secdata_set(&ctx, VB2_SECDATA_VERSIONS, 0x20002);
+	sd->fw_version_secdata = 0x20002;
+	vb2_secdata_set(&ctx, VB2_SECDATA_VERSIONS, sd->fw_version_secdata);
 
 	sd->gbb_rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey);
 	sd->gbb_rootkey_size = sizeof(mock_gbb.rootkey_data);