update_engine: Update the TPM with max_rollforward on rollback

- Determines the value from max_rollforward_(kernel|firmware)
  based on the list of the last N release values from stable.
- Sets the TPM values once it has been determined that the new
  image will boot and be installed.

BUG=chromium:840432
TEST=cros_run_unit_tests --board=samus --packages update_engine

Change-Id: I9620fe01cfea49e798e1397dada55ec6bec93047
Reviewed-on: https://chromium-review.googlesource.com/1419006
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Bailey Berro <baileyberro@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index b47040b..0ebf848 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -38,6 +38,7 @@
 using chromeos_update_engine::test_utils::WriteFileString;
 using chromeos_update_manager::EvalStatus;
 using chromeos_update_manager::FakeUpdateManager;
+using chromeos_update_manager::kRollforwardInfinity;
 using chromeos_update_manager::MockPolicy;
 using std::string;
 using testing::_;
@@ -534,21 +535,44 @@
                          .size = 1,
                          .hash = kPayloadHashHex});
   in.is_rollback = true;
-  in.rollback_key_version.kernel = 1;
-  in.rollback_key_version.kernel = 2;
-  in.rollback_key_version.firmware_key = 3;
-  in.rollback_key_version.firmware = 4;
+
+  // The rollback payload is 2 versions behind stable.
+  in.rollback_key_version.kernel = 24;
+  in.rollback_key_version.kernel = 23;
+  in.rollback_key_version.firmware_key = 22;
+  in.rollback_key_version.firmware = 21;
+
+  OmahaResponse::RollbackKeyVersion m4;
+  m4.firmware_key = 16;
+  m4.firmware = 15;
+  m4.kernel_key = 14;
+  m4.kernel = 13;
+
+  in.past_rollback_key_version = m4;
 
   fake_system_state_.fake_hardware()->SetMinKernelKeyVersion(0x00010002);
   fake_system_state_.fake_hardware()->SetMinFirmwareKeyVersion(0x00030004);
 
+  fake_system_state_.fake_hardware()->SetMaxKernelKeyRollforward(0xaaaaaaaa);
+  // TODO(crbug/783998): Add support for firmware when implemented.
+
   OmahaRequestParams params(&fake_system_state_);
   params.set_rollback_allowed(true);
+  params.set_rollback_allowed_milestones(4);
 
   fake_system_state_.set_request_params(&params);
   InstallPlan install_plan;
   EXPECT_TRUE(DoTest(in, "", &install_plan));
   EXPECT_TRUE(install_plan.is_rollback);
+
+  // The max rollforward should be set the values of the image
+  // rollback_allowed_milestones (4 for this test) in the past.
+  const uint32_t expected_max_kernel_rollforward =
+      static_cast<uint32_t>(m4.kernel_key) << 16 |
+      static_cast<uint32_t>(m4.kernel);
+  EXPECT_EQ(expected_max_kernel_rollforward,
+            fake_system_state_.fake_hardware()->GetMaxKernelKeyRollforward());
+  // TODO(crbug/783998): Add support for firmware when implemented.
 }
 
 TEST_F(OmahaResponseHandlerActionTest, RollbackKernelVersionErrorTest) {
@@ -563,18 +587,36 @@
   in.rollback_key_version.firmware_key = 3;
   in.rollback_key_version.firmware = 4;
 
+  OmahaResponse::RollbackKeyVersion m4;
+  m4.firmware_key = 16;
+  m4.firmware = 15;
+  m4.kernel_key = 14;
+  m4.kernel = 13;
+  in.past_rollback_key_version = m4;
+
   fake_system_state_.fake_hardware()->SetMinKernelKeyVersion(0x00010002);
   fake_system_state_.fake_hardware()->SetMinFirmwareKeyVersion(0x00030004);
+  const uint32_t current_kernel_max_rollforward = 0xaaaaaaaa;
+  fake_system_state_.fake_hardware()->SetMaxKernelKeyRollforward(
+      current_kernel_max_rollforward);
 
   OmahaRequestParams params(&fake_system_state_);
   params.set_rollback_allowed(true);
+  params.set_rollback_allowed_milestones(4);
 
   fake_system_state_.set_request_params(&params);
   InstallPlan install_plan;
   EXPECT_FALSE(DoTest(in, "", &install_plan));
+
+  // Max rollforward is not changed in error cases.
+  EXPECT_EQ(current_kernel_max_rollforward,
+            fake_system_state_.fake_hardware()->GetMaxKernelKeyRollforward());
+  // TODO(crbug/783998): Add support for firmware when implemented.
 }
 
 TEST_F(OmahaResponseHandlerActionTest, RollbackFirmwareVersionErrorTest) {
+  // TODO(crbug/783998): Add handling for max_firmware_rollforward when
+  // implemented.
   OmahaResponse in;
   in.update_exists = true;
   in.packages.push_back({.payload_urls = {"https://RollbackTest"},
@@ -591,6 +633,7 @@
 
   OmahaRequestParams params(&fake_system_state_);
   params.set_rollback_allowed(true);
+  params.set_rollback_allowed_milestones(4);
 
   fake_system_state_.set_request_params(&params);
   InstallPlan install_plan;
@@ -605,13 +648,23 @@
                          .hash = kPayloadHashHex});
   in.is_rollback = false;
 
+  const uint32_t current_kernel_max_rollforward = 0xaaaaaaaa;
+  fake_system_state_.fake_hardware()->SetMaxKernelKeyRollforward(
+      current_kernel_max_rollforward);
+
   OmahaRequestParams params(&fake_system_state_);
   params.set_rollback_allowed(true);
+  params.set_rollback_allowed_milestones(4);
 
   fake_system_state_.set_request_params(&params);
   InstallPlan install_plan;
   EXPECT_TRUE(DoTest(in, "", &install_plan));
   EXPECT_FALSE(install_plan.is_rollback);
+
+  // Max rollforward is not changed for non-rollback cases.
+  EXPECT_EQ(current_kernel_max_rollforward,
+            fake_system_state_.fake_hardware()->GetMaxKernelKeyRollforward());
+  // TODO(crbug/783998): Add support for firmware when implemented.
 }
 
 TEST_F(OmahaResponseHandlerActionTest, RollbackNotAllowedTest) {
@@ -624,10 +677,46 @@
 
   OmahaRequestParams params(&fake_system_state_);
   params.set_rollback_allowed(false);
+  params.set_rollback_allowed_milestones(4);
+
+  const uint32_t current_kernel_max_rollforward = 0xaaaaaaaa;
+  fake_system_state_.fake_hardware()->SetMaxKernelKeyRollforward(
+      current_kernel_max_rollforward);
 
   fake_system_state_.set_request_params(&params);
   InstallPlan install_plan;
   EXPECT_FALSE(DoTest(in, "", &install_plan));
+
+  // This case generates an error so, do not update max rollforward.
+  EXPECT_EQ(current_kernel_max_rollforward,
+            fake_system_state_.fake_hardware()->GetMaxKernelKeyRollforward());
+  // TODO(crbug/783998): Add support for firmware when implemented.
+}
+
+TEST_F(OmahaResponseHandlerActionTest, NormalUpdateWithZeroMilestonesAllowed) {
+  OmahaResponse in;
+  in.update_exists = true;
+  in.packages.push_back({.payload_urls = {"https://RollbackTest"},
+                         .size = 1,
+                         .hash = kPayloadHashHex});
+  in.is_rollback = false;
+
+  OmahaRequestParams params(&fake_system_state_);
+  params.set_rollback_allowed(true);
+  params.set_rollback_allowed_milestones(0);
+
+  const uint32_t current_kernel_max_rollforward = 0xaaaaaaaa;
+  fake_system_state_.fake_hardware()->SetMaxKernelKeyRollforward(
+      current_kernel_max_rollforward);
+
+  fake_system_state_.set_request_params(&params);
+  InstallPlan install_plan;
+  EXPECT_TRUE(DoTest(in, "", &install_plan));
+
+  // When allowed_milestones is 0, this is set to infinity.
+  EXPECT_EQ(kRollforwardInfinity,
+            fake_system_state_.fake_hardware()->GetMaxKernelKeyRollforward());
+  // TODO(crbug/783998): Add support for firmware when implemented.
 }
 
 TEST_F(OmahaResponseHandlerActionTest, SystemVersionTest) {