Merge "Adding AVB-specific kernel patches for reference"
diff --git a/libavb_atx/avb_atx_ops.h b/libavb_atx/avb_atx_ops.h
index e05ce99..06c989f 100644
--- a/libavb_atx/avb_atx_ops.h
+++ b/libavb_atx/avb_atx_ops.h
@@ -59,6 +59,13 @@
    */
   AvbIOResult (*read_permanent_attributes_hash)(
       AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
+
+  /* Provides the key version of a key used during verification. This may be
+   * useful for managing the minimum key version.
+   */
+  void (*set_key_version)(AvbAtxOps* atx_ops,
+                          size_t rollback_index_location,
+                          uint64_t key_version);
 };
 
 #ifdef __cplusplus
diff --git a/libavb_atx/avb_atx_validate.c b/libavb_atx/avb_atx_validate.c
index fb200c1..7708277 100644
--- a/libavb_atx/avb_atx_validate.c
+++ b/libavb_atx/avb_atx_validate.c
@@ -241,6 +241,16 @@
     return AVB_IO_RESULT_OK;
   }
 
+  /* Report the key versions used during verification. */
+  ops->atx_ops->set_key_version(
+      ops->atx_ops,
+      AVB_ATX_PIK_VERSION_LOCATION,
+      metadata.product_intermediate_key_certificate.signed_data.key_version);
+  ops->atx_ops->set_key_version(
+      ops->atx_ops,
+      AVB_ATX_PSK_VERSION_LOCATION,
+      metadata.product_signing_key_certificate.signed_data.key_version);
+
   *out_is_trusted = true;
   return AVB_IO_RESULT_OK;
 }
diff --git a/test/avb_atx_validate_unittest.cc b/test/avb_atx_validate_unittest.cc
index 8dd60a3..4db238f 100644
--- a/test/avb_atx_validate_unittest.cc
+++ b/test/avb_atx_validate_unittest.cc
@@ -179,6 +179,11 @@
     return ops_.read_permanent_attributes_hash(hash);
   }
 
+  void set_key_version(size_t rollback_index_location,
+                       uint64_t key_version) override {
+    ops_.set_key_version(rollback_index_location, key_version);
+  }
+
  protected:
   virtual AvbIOResult Validate(bool* is_trusted) {
     return avb_atx_validate_vbmeta_public_key(
@@ -236,6 +241,14 @@
   bool is_trusted = false;
   EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
   EXPECT_TRUE(is_trusted);
+
+  // Check that the key versions were reported correctly.
+  EXPECT_EQ(
+      ops_.get_verified_rollback_indexes()[AVB_ATX_PIK_VERSION_LOCATION],
+      metadata_.product_intermediate_key_certificate.signed_data.key_version);
+  EXPECT_EQ(ops_.get_verified_rollback_indexes()[AVB_ATX_PSK_VERSION_LOCATION],
+            metadata_.product_signing_key_certificate.signed_data.key_version);
+  EXPECT_EQ(2UL, ops_.get_verified_rollback_indexes().size());
 }
 
 TEST_F(AvbAtxValidateTest, SuccessAfterNewSign) {
@@ -627,6 +640,11 @@
     return ops_.read_permanent_attributes_hash(hash);
   }
 
+  void set_key_version(size_t rollback_index_location,
+                       uint64_t key_version) override {
+    return ops_.set_key_version(rollback_index_location, key_version);
+  }
+
  protected:
   FakeAvbOps ops_;
   AvbAtxPermanentAttributes attributes_;
diff --git a/test/fake_avb_ops.cc b/test/fake_avb_ops.cc
index 4b38dcc..34b896d 100644
--- a/test/fake_avb_ops.cc
+++ b/test/fake_avb_ops.cc
@@ -264,6 +264,11 @@
   return AVB_IO_RESULT_OK;
 }
 
+void FakeAvbOps::set_key_version(size_t rollback_index_location,
+                                 uint64_t key_version) {
+  verified_rollback_indexes_[rollback_index_location] = key_version;
+}
+
 static AvbIOResult my_ops_read_from_partition(AvbOps* ops,
                                               const char* partition,
                                               int64_t offset,
@@ -355,6 +360,14 @@
       ->read_permanent_attributes_hash(hash);
 }
 
+static void my_ops_set_key_version(AvbAtxOps* atx_ops,
+                                   size_t rollback_index_location,
+                                   uint64_t key_version) {
+  return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
+      ->delegate()
+      ->set_key_version(rollback_index_location, key_version);
+}
+
 FakeAvbOps::FakeAvbOps() {
   avb_ops_.ab_ops = &avb_ab_ops_;
   avb_ops_.atx_ops = &avb_atx_ops_;
@@ -377,6 +390,7 @@
   avb_atx_ops_.read_permanent_attributes = my_ops_read_permanent_attributes;
   avb_atx_ops_.read_permanent_attributes_hash =
       my_ops_read_permanent_attributes_hash;
+  avb_atx_ops_.set_key_version = my_ops_set_key_version;
 
   delegate_ = this;
 }
diff --git a/test/fake_avb_ops.h b/test/fake_avb_ops.h
index 53775d4..35abffa 100644
--- a/test/fake_avb_ops.h
+++ b/test/fake_avb_ops.h
@@ -84,6 +84,9 @@
 
   virtual AvbIOResult read_permanent_attributes_hash(
       uint8_t hash[AVB_SHA256_DIGEST_SIZE]) = 0;
+
+  virtual void set_key_version(size_t rollback_index_location,
+                               uint64_t key_version) = 0;
 };
 
 // Provides fake implementations of AVB ops. All instances of this class must be
@@ -143,6 +146,10 @@
     return stored_rollback_indexes_;
   }
 
+  std::map<size_t, uint64_t> get_verified_rollback_indexes() {
+    return verified_rollback_indexes_;
+  }
+
   void set_stored_is_device_unlocked(bool stored_is_device_unlocked) {
     stored_is_device_unlocked_ = stored_is_device_unlocked;
   }
@@ -204,6 +211,9 @@
   AvbIOResult read_permanent_attributes_hash(
       uint8_t hash[AVB_SHA256_DIGEST_SIZE]) override;
 
+  void set_key_version(size_t rollback_index_location,
+                       uint64_t key_version) override;
+
  private:
   AvbOps avb_ops_;
   AvbABOps avb_ab_ops_;
@@ -217,6 +227,7 @@
   std::string expected_public_key_metadata_;
 
   std::map<size_t, uint64_t> stored_rollback_indexes_;
+  std::map<size_t, uint64_t> verified_rollback_indexes_;
 
   bool stored_is_device_unlocked_;