pvmfw: Rollback index of kernel & security_version

Capture rollback_index of guest kernel. Rollback indexes are available
in AvbSlotVerifyData returned from avb_slot_verify(). This is a slice of
uint64 where the position of the rollback_index is determined by
rollback_index_location (which defaults to 0).

This is then used as the 'security_version' in the dice config, that
can be used by guests OS to provide AntiRollback protection to secrets.

Note on TrunkStableFlagging - This is guarded by flag llpvm_changes,
based on which security_version is added to  dice.

Test: #payload_with_rollback_index
Test: flash pvmfw => get dice chain from Compos => verify-dice-chain
contaisn security version = 1 for guest OS
Bug: 296830692

Change-Id: I0d6d993d8b2d1b98dcc39fb90895a59c7a699d7d
diff --git a/pvmfw/avb/src/ops.rs b/pvmfw/avb/src/ops.rs
index 539291b..c7b8b01 100644
--- a/pvmfw/avb/src/ops.rs
+++ b/pvmfw/avb/src/ops.rs
@@ -229,10 +229,14 @@
     _rollback_index_location: usize,
     out_rollback_index: *mut u64,
 ) -> AvbIOResult {
-    // Rollback protection is not yet implemented, but this method is required by
-    // `avb_slot_verify()`.
-    // We set `out_rollback_index` to 0 to ensure that the default rollback index (0)
-    // is never smaller than it, thus the rollback index check will pass.
+    // This method is used by `avb_slot_verify()` to read the stored_rollback_index at
+    // rollback_index_location.
+
+    // TODO(291213394) : Refine this comment once capability for rollback protection is defined.
+    // pvmfw does not compare stored_rollback_index with rollback_index for Antirollback protection
+    // Hence, we set `out_rollback_index` to 0 to ensure that the
+    // rollback_index (including default: 0) is never smaller than it,
+    // thus the rollback index check will pass.
     result_to_io_enum(write(out_rollback_index, 0))
 }
 
@@ -334,4 +338,8 @@
             unsafe { slice::from_raw_parts(data.loaded_partitions, data.num_loaded_partitions) };
         Ok(loaded_partitions)
     }
+
+    pub(crate) fn rollback_indexes(&self) -> &[u64] {
+        &self.as_ref().rollback_indexes
+    }
 }
diff --git a/pvmfw/avb/src/verify.rs b/pvmfw/avb/src/verify.rs
index ac945e2..1a16f9d 100644
--- a/pvmfw/avb/src/verify.rs
+++ b/pvmfw/avb/src/verify.rs
@@ -23,6 +23,9 @@
 use avb_bindgen::{AvbPartitionData, AvbVBMetaData};
 use core::ffi::c_char;
 
+// We use this for the rollback_index field if AvbSlotVerifyDataWrap has empty rollback_indexes
+const DEFAULT_ROLLBACK_INDEX: u64 = 0;
+
 /// Verified data returned when the payload verification succeeds.
 #[derive(Debug, PartialEq, Eq)]
 pub struct VerifiedBootData<'a> {
@@ -36,6 +39,8 @@
     pub public_key: &'a [u8],
     /// VM capabilities.
     pub capabilities: Vec<Capability>,
+    /// Rollback index of kernel.
+    pub rollback_index: u64,
 }
 
 /// This enum corresponds to the `DebugLevel` in `VirtualMachineConfig`.
@@ -153,6 +158,10 @@
     let kernel_verify_result = ops.verify_partition(PartitionName::Kernel.as_cstr())?;
 
     let vbmeta_images = kernel_verify_result.vbmeta_images()?;
+    // TODO(b/302093437): Use explicit rollback_index_location instead of default
+    // location (first element).
+    let rollback_index =
+        *kernel_verify_result.rollback_indexes().first().unwrap_or(&DEFAULT_ROLLBACK_INDEX);
     verify_only_one_vbmeta_exists(vbmeta_images)?;
     let vbmeta_image = vbmeta_images[0];
     verify_vbmeta_is_from_kernel_partition(&vbmeta_image)?;
@@ -171,6 +180,7 @@
             initrd_digest: None,
             public_key: trusted_public_key,
             capabilities,
+            rollback_index,
         });
     }
 
@@ -196,5 +206,6 @@
         initrd_digest: Some(*initrd_descriptor.digest),
         public_key: trusted_public_key,
         capabilities,
+        rollback_index,
     })
 }