pvmfw/avb: Add Capability::UefiSupport

Add support for a new VM capability flag in the VBMeta property
"com.android.virt.cap" representing guest kernel support for
the UEFI boot process.

Add unit tests to test the new capability.

Test: atest libpvmfw_avb.integration_test
Change-Id: I4c364909a743d860b9cb68fbda78a4860c136417
diff --git a/guest/pvmfw/avb/Android.bp b/guest/pvmfw/avb/Android.bp
index 558152d..f97a713 100644
--- a/guest/pvmfw/avb/Android.bp
+++ b/guest/pvmfw/avb/Android.bp
@@ -43,6 +43,7 @@
         ":test_image_with_duplicated_capability",
         ":test_image_with_rollback_index_5",
         ":test_image_with_multiple_capabilities",
+        ":test_image_with_all_capabilities",
         ":unsigned_test_image",
     ],
     prefer_rlib: true,
@@ -218,3 +219,17 @@
         },
     ],
 }
+
+avb_add_hash_footer {
+    name: "test_image_with_all_capabilities",
+    src: ":unsigned_test_image",
+    partition_name: "boot",
+    private_key: ":pvmfw_sign_key",
+    salt: "4231",
+    props: [
+        {
+            name: "com.android.virt.cap",
+            value: "remote_attest|secretkeeper_protection|supports_uefi_boot",
+        },
+    ],
+}
diff --git a/guest/pvmfw/avb/src/verify.rs b/guest/pvmfw/avb/src/verify.rs
index 038b1d6..bd700ce 100644
--- a/guest/pvmfw/avb/src/verify.rs
+++ b/guest/pvmfw/avb/src/verify.rs
@@ -70,6 +70,11 @@
     RemoteAttest,
     /// Secretkeeper protected secrets.
     SecretkeeperProtection,
+    /// UEFI support for booting guest kernel.
+    SupportsUefiBoot,
+    /// (internal)
+    #[allow(non_camel_case_types)] // TODO: Use mem::variant_count once stable.
+    _VARIANT_COUNT,
 }
 
 impl Capability {
@@ -77,6 +82,9 @@
     const REMOTE_ATTEST: &'static [u8] = b"remote_attest";
     const SECRETKEEPER_PROTECTION: &'static [u8] = b"secretkeeper_protection";
     const SEPARATOR: u8 = b'|';
+    const SUPPORTS_UEFI_BOOT: &'static [u8] = b"supports_uefi_boot";
+    /// Number of supported capabilites.
+    pub const COUNT: usize = Self::_VARIANT_COUNT as usize;
 
     /// Returns the capabilities indicated in `descriptor`, or error if the descriptor has
     /// unexpected contents.
@@ -91,6 +99,7 @@
             let cap = match v {
                 Self::REMOTE_ATTEST => Self::RemoteAttest,
                 Self::SECRETKEEPER_PROTECTION => Self::SecretkeeperProtection,
+                Self::SUPPORTS_UEFI_BOOT => Self::SupportsUefiBoot,
                 _ => return Err(PvmfwVerifyError::UnknownVbmetaProperty),
             };
             if res.contains(&cap) {
diff --git a/guest/pvmfw/avb/tests/api_test.rs b/guest/pvmfw/avb/tests/api_test.rs
index 8683e69..01c13d4 100644
--- a/guest/pvmfw/avb/tests/api_test.rs
+++ b/guest/pvmfw/avb/tests/api_test.rs
@@ -38,6 +38,7 @@
 const TEST_IMG_WITH_INITRD_AND_NON_INITRD_DESC_PATH: &str =
     "test_image_with_initrd_and_non_initrd_desc.img";
 const TEST_IMG_WITH_MULTIPLE_CAPABILITIES: &str = "test_image_with_multiple_capabilities.img";
+const TEST_IMG_WITH_ALL_CAPABILITIES: &str = "test_image_with_all_capabilities.img";
 const UNSIGNED_TEST_IMG_PATH: &str = "unsigned_test.img";
 
 const RANDOM_FOOTER_POS: usize = 30;
@@ -418,3 +419,22 @@
     assert!(verified_boot_data.has_capability(Capability::SecretkeeperProtection));
     Ok(())
 }
+
+#[test]
+fn payload_with_all_capabilities() -> Result<()> {
+    let public_key = load_trusted_public_key()?;
+    let verified_boot_data = verify_payload(
+        &fs::read(TEST_IMG_WITH_ALL_CAPABILITIES)?,
+        /* initrd= */ None,
+        &public_key,
+    )
+    .map_err(|e| anyhow!("Verification failed. Error: {}", e))?;
+
+    assert!(verified_boot_data.has_capability(Capability::RemoteAttest));
+    assert!(verified_boot_data.has_capability(Capability::SecretkeeperProtection));
+    assert!(verified_boot_data.has_capability(Capability::SupportsUefiBoot));
+    // Fail if this test doesn't actually cover all supported capabilities.
+    assert_eq!(Capability::COUNT, 3);
+
+    Ok(())
+}