Merge changes If575a1fe,I929cb995

* changes:
  [avb][test] Add verification tests to check tampered vbmeta
  [avb] Test latest debug initrd passes the payload verification
diff --git a/pvmfw/avb/Android.bp b/pvmfw/avb/Android.bp
index 120a720..1c5e91a 100644
--- a/pvmfw/avb/Android.bp
+++ b/pvmfw/avb/Android.bp
@@ -34,6 +34,7 @@
         ":avb_testkey_rsa4096_pub_bin",
         ":microdroid_kernel_signed",
         ":microdroid_initrd_normal",
+        ":microdroid_initrd_debuggable",
         ":test_image_with_one_hashdesc",
         ":unsigned_test_image",
     ],
diff --git a/pvmfw/avb/tests/api_test.rs b/pvmfw/avb/tests/api_test.rs
index b48ea8b..945c838 100644
--- a/pvmfw/avb/tests/api_test.rs
+++ b/pvmfw/avb/tests/api_test.rs
@@ -15,12 +15,19 @@
  */
 
 use anyhow::Result;
-use avb_bindgen::AvbFooter;
+use avb_bindgen::{
+    avb_footer_validate_and_byteswap, avb_vbmeta_image_header_to_host_byte_order, AvbFooter,
+    AvbVBMetaImageHeader,
+};
 use pvmfw_avb::{verify_payload, AvbSlotVerifyError};
-use std::{fs, mem::size_of};
+use std::{
+    fs,
+    mem::{size_of, transmute, MaybeUninit},
+};
 
 const MICRODROID_KERNEL_IMG_PATH: &str = "microdroid_kernel";
 const INITRD_NORMAL_IMG_PATH: &str = "microdroid_initrd_normal.img";
+const INITRD_DEBUG_IMG_PATH: &str = "microdroid_initrd_debuggable.img";
 const TEST_IMG_WITH_ONE_HASHDESC_PATH: &str = "test_image_with_one_hashdesc.img";
 const UNSIGNED_TEST_IMG_PATH: &str = "unsigned_test.img";
 
@@ -31,19 +38,27 @@
 /// This test uses the Microdroid payload compiled on the fly to check that
 /// the latest payload can be verified successfully.
 #[test]
-fn latest_valid_payload_passes_verification() -> Result<()> {
-    let kernel = load_latest_signed_kernel()?;
-    let initrd_normal = fs::read(INITRD_NORMAL_IMG_PATH)?;
-    let public_key = fs::read(PUBLIC_KEY_RSA4096_PATH)?;
+fn latest_normal_payload_passes_verification() -> Result<()> {
+    assert_payload_verification_succeeds(
+        &load_latest_signed_kernel()?,
+        &load_latest_initrd_normal()?,
+        &load_trusted_public_key()?,
+    )
+}
 
-    assert_eq!(Ok(()), verify_payload(&kernel, Some(&initrd_normal[..]), &public_key));
-    Ok(())
+#[test]
+fn latest_debug_payload_passes_verification() -> Result<()> {
+    assert_payload_verification_succeeds(
+        &load_latest_signed_kernel()?,
+        &load_latest_initrd_debug()?,
+        &load_trusted_public_key()?,
+    )
 }
 
 #[test]
 fn payload_expecting_no_initrd_passes_verification_with_no_initrd() -> Result<()> {
     let kernel = fs::read(TEST_IMG_WITH_ONE_HASHDESC_PATH)?;
-    let public_key = fs::read(PUBLIC_KEY_RSA4096_PATH)?;
+    let public_key = load_trusted_public_key()?;
 
     assert_eq!(Ok(()), verify_payload(&kernel, None, &public_key));
     Ok(())
@@ -87,7 +102,7 @@
     assert_payload_verification_fails(
         &fs::read(UNSIGNED_TEST_IMG_PATH)?,
         &load_latest_initrd_normal()?,
-        &fs::read(PUBLIC_KEY_RSA4096_PATH)?,
+        &load_trusted_public_key()?,
         AvbSlotVerifyError::Io,
     )
 }
@@ -100,7 +115,7 @@
     assert_payload_verification_fails(
         &kernel,
         &load_latest_initrd_normal()?,
-        &fs::read(PUBLIC_KEY_RSA4096_PATH)?,
+        &load_trusted_public_key()?,
         AvbSlotVerifyError::Verification,
     )
 }
@@ -114,11 +129,85 @@
     assert_payload_verification_fails(
         &kernel,
         &load_latest_initrd_normal()?,
-        &fs::read(PUBLIC_KEY_RSA4096_PATH)?,
+        &load_trusted_public_key()?,
         AvbSlotVerifyError::InvalidMetadata,
     )
 }
 
+#[test]
+fn tampered_vbmeta_fails_verification() -> Result<()> {
+    let mut kernel = load_latest_signed_kernel()?;
+    let footer = extract_avb_footer(&kernel)?;
+    let vbmeta_index: usize = (footer.vbmeta_offset + 1).try_into()?;
+
+    kernel[vbmeta_index] = !kernel[vbmeta_index]; // Flip the bits
+
+    assert_payload_verification_fails(
+        &kernel,
+        &load_latest_initrd_normal()?,
+        &load_trusted_public_key()?,
+        AvbSlotVerifyError::InvalidMetadata,
+    )
+}
+
+#[test]
+fn vbmeta_with_public_key_overwritten_fails_verification() -> Result<()> {
+    let mut kernel = load_latest_signed_kernel()?;
+    let footer = extract_avb_footer(&kernel)?;
+    let vbmeta_header = extract_vbmeta_header(&kernel, &footer)?;
+    let public_key_offset = footer.vbmeta_offset as usize
+        + size_of::<AvbVBMetaImageHeader>()
+        + vbmeta_header.authentication_data_block_size as usize
+        + vbmeta_header.public_key_offset as usize;
+    let public_key_size: usize = vbmeta_header.public_key_size.try_into()?;
+    let empty_public_key = vec![0u8; public_key_size];
+
+    kernel[public_key_offset..(public_key_offset + public_key_size)]
+        .copy_from_slice(&empty_public_key);
+
+    assert_payload_verification_fails(
+        &kernel,
+        &load_latest_initrd_normal()?,
+        &empty_public_key,
+        AvbSlotVerifyError::Verification,
+    )?;
+    assert_payload_verification_fails(
+        &kernel,
+        &load_latest_initrd_normal()?,
+        &load_trusted_public_key()?,
+        AvbSlotVerifyError::Verification,
+    )
+}
+
+// TODO(b/256148034): Test that vbmeta with its verification flag overwritten fails verification.
+
+fn extract_avb_footer(kernel: &[u8]) -> Result<AvbFooter> {
+    let footer_start = kernel.len() - size_of::<AvbFooter>();
+    // SAFETY: The slice is the same size as the struct which only contains simple data types.
+    let mut footer = unsafe {
+        transmute::<[u8; size_of::<AvbFooter>()], AvbFooter>(kernel[footer_start..].try_into()?)
+    };
+    // SAFETY: The function updates the struct in-place.
+    unsafe {
+        avb_footer_validate_and_byteswap(&footer, &mut footer);
+    }
+    Ok(footer)
+}
+
+fn extract_vbmeta_header(kernel: &[u8], footer: &AvbFooter) -> Result<AvbVBMetaImageHeader> {
+    let vbmeta_offset: usize = footer.vbmeta_offset.try_into()?;
+    let vbmeta_size: usize = footer.vbmeta_size.try_into()?;
+    let vbmeta_src = &kernel[vbmeta_offset..(vbmeta_offset + vbmeta_size)];
+    // SAFETY: The latest kernel has a valid VBMeta header at the position specified in footer.
+    let vbmeta_header = unsafe {
+        let mut header = MaybeUninit::uninit();
+        let src = vbmeta_src.as_ptr() as *const _ as *const AvbVBMetaImageHeader;
+        avb_vbmeta_image_header_to_host_byte_order(src, header.as_mut_ptr());
+        header.assume_init()
+    };
+    Ok(vbmeta_header)
+}
+
 fn assert_payload_verification_fails(
     kernel: &[u8],
     initrd: &[u8],
@@ -129,6 +218,15 @@
     Ok(())
 }
 
+fn assert_payload_verification_succeeds(
+    kernel: &[u8],
+    initrd: &[u8],
+    trusted_public_key: &[u8],
+) -> Result<()> {
+    assert_eq!(Ok(()), verify_payload(kernel, Some(initrd), trusted_public_key));
+    Ok(())
+}
+
 fn load_latest_signed_kernel() -> Result<Vec<u8>> {
     Ok(fs::read(MICRODROID_KERNEL_IMG_PATH)?)
 }
@@ -136,3 +234,11 @@
 fn load_latest_initrd_normal() -> Result<Vec<u8>> {
     Ok(fs::read(INITRD_NORMAL_IMG_PATH)?)
 }
+
+fn load_latest_initrd_debug() -> Result<Vec<u8>> {
+    Ok(fs::read(INITRD_DEBUG_IMG_PATH)?)
+}
+
+fn load_trusted_public_key() -> Result<Vec<u8>> {
+    Ok(fs::read(PUBLIC_KEY_RSA4096_PATH)?)
+}