Add util methods to get payload vbmeta image hash

The methods will be used later to build avmdtool.

Test: libapexutil_rust.test
Change-Id: I28bde2f57cb2c4e05f4cd4be5abf52cb6f788003
diff --git a/libs/apexutil/src/lib.rs b/libs/apexutil/src/lib.rs
index 63b09de..1183aea 100644
--- a/libs/apexutil/src/lib.rs
+++ b/libs/apexutil/src/lib.rs
@@ -93,6 +93,19 @@
     Err(ApexParseError::DescriptorNotHashtree)
 }
 
+/// Gets the hash of the payload's verified VBMeta image data.
+pub fn get_payload_vbmeta_image_hash(path: &str) -> Result<Vec<u8>, ApexVerificationError> {
+    let apex_file = File::open(path).map_err(ApexParseError::Io)?;
+    let (_, offset, size) = get_public_key_and_image_info(&apex_file)?;
+    let vbmeta = VbMetaImage::verify_reader_region(apex_file, offset, size)?;
+    Ok(vbmeta.hash().ok_or(ApexVerificationError::ApexPubkeyMistmatch)?.to_vec())
+}
+
+/// Converts the buffer to a Hex String
+pub fn to_hex_string(buf: &[u8]) -> String {
+    buf.iter().map(|b| format!("{:02x}", b)).collect()
+}
+
 fn get_public_key_and_image_info(apex_file: &File) -> Result<(Vec<u8>, u64, u64), ApexParseError> {
     let mut z = ZipArchive::new(apex_file).map_err(|err| match err {
         ZipError::Io(err) => ApexParseError::Io(err),
@@ -130,9 +143,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    fn to_hex_string(buf: &[u8]) -> String {
-        buf.iter().map(|b| format!("{:02x}", b)).collect()
-    }
+
     #[test]
     fn test_open_apex() {
         let res = verify("tests/data/test.apex").unwrap();
@@ -141,4 +152,13 @@
             "fe11ab17da0a3a738b54bdc3a13f6139cbdf91ec32f001f8d4bbbf8938e04e39"
         );
     }
+
+    #[test]
+    fn test_payload_vbmeta_image_hash() {
+        let result = get_payload_vbmeta_image_hash("tests/data/test.apex").unwrap();
+        assert_eq!(
+            to_hex_string(&result),
+            "296e32a76544de9da01713e471403ab4667705ad527bb4f1fac0cf61e7ce122d"
+        );
+    }
 }
diff --git a/libs/vbmeta/src/lib.rs b/libs/vbmeta/src/lib.rs
index 2d3463c..887844c 100644
--- a/libs/vbmeta/src/lib.rs
+++ b/libs/vbmeta/src/lib.rs
@@ -138,6 +138,18 @@
         Some(&self.data[begin..end])
     }
 
+    /// Get the hash of the verified data in the VBMeta image from the authentication block. If the
+    /// image was not signed, there might not be a hash and, if there is, it's not known to be
+    /// correct.
+    pub fn hash(&self) -> Option<&[u8]> {
+        if self.header.algorithm_type == AvbAlgorithmType_AVB_ALGORITHM_TYPE_NONE {
+            return None;
+        }
+        let begin = size_of::<AvbVBMetaImageHeader>() + self.header.hash_offset as usize;
+        let end = begin + self.header.hash_size as usize;
+        Some(&self.data[begin..end])
+    }
+
     /// Get the descriptors of the VBMeta image.
     pub fn descriptors(&self) -> Result<Descriptors<'_>, VbMetaImageParseError> {
         Descriptors::from_image(&self.data)