[avb] Add library libpvmfw_avb_nostd and test it in presubmit

Bug: 237373557
Test: m pvmfw_img && atest libpvmfw_avb.test
Change-Id: I80c19d4081b97ae57d0b50c04d3368b417a6411a
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 318c7fe..5ed7bd6 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -13,11 +13,11 @@
     ],
     rustlibs: [
         "libaarch64_paging",
-        "libavb_nostd",
         "libbuddy_system_allocator",
         "libdice_nostd",
         "liblibfdt",
         "liblog_rust_nostd",
+        "libpvmfw_avb_nostd",
         "libpvmfw_embedded_key",
         "libtinyvec_nostd",
         "libvirtio_drivers",
diff --git a/pvmfw/TEST_MAPPING b/pvmfw/TEST_MAPPING
new file mode 100644
index 0000000..8a2d352
--- /dev/null
+++ b/pvmfw/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "avf-presubmit" : [
+    {
+      "name" : "libpvmfw_avb.test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/pvmfw/avb/Android.bp b/pvmfw/avb/Android.bp
new file mode 100644
index 0000000..65259a5
--- /dev/null
+++ b/pvmfw/avb/Android.bp
@@ -0,0 +1,28 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "libpvmfw_avb_nostd_defaults",
+    crate_name: "pvmfw_avb",
+    srcs: ["src/lib.rs"],
+    prefer_rlib: true,
+    rustlibs: [
+        "libavb_bindgen",
+    ],
+}
+
+rust_library_rlib {
+    name: "libpvmfw_avb_nostd",
+    defaults: ["libpvmfw_avb_nostd_defaults"],
+    no_stdlibs: true,
+    stdlibs: [
+        "libcore.rust_sysroot",
+    ],
+}
+
+rust_test {
+    name: "libpvmfw_avb.test",
+    defaults: ["libpvmfw_avb_nostd_defaults"],
+    test_suites: ["general-tests"],
+}
diff --git a/pvmfw/avb/src/lib.rs b/pvmfw/avb/src/lib.rs
new file mode 100644
index 0000000..eb1f918
--- /dev/null
+++ b/pvmfw/avb/src/lib.rs
@@ -0,0 +1,21 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A library implementing the payload verification for pvmfw with libavb
+
+#![cfg_attr(not(test), no_std)]
+
+mod verify;
+
+pub use verify::{verify_payload, AvbImageVerifyError};
diff --git a/pvmfw/avb/src/verify.rs b/pvmfw/avb/src/verify.rs
new file mode 100644
index 0000000..7f3ba3d
--- /dev/null
+++ b/pvmfw/avb/src/verify.rs
@@ -0,0 +1,112 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module handles the pvmfw payload verification.
+
+use avb_bindgen::AvbSlotVerifyResult;
+use core::fmt;
+
+/// Error code from AVB image verification.
+#[derive(Clone, Debug)]
+pub enum AvbImageVerifyError {
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
+    InvalidArgument,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
+    InvalidMetadata,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_IO
+    Io,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_OOM
+    Oom,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
+    PublicKeyRejected,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
+    RollbackIndex,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
+    UnsupportedVersion,
+    /// AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
+    Verification,
+}
+
+impl fmt::Display for AvbImageVerifyError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Self::InvalidArgument => write!(f, "Invalid parameters."),
+            Self::InvalidMetadata => write!(f, "Invalid metadata."),
+            Self::Io => write!(f, "I/O error while trying to load data or get a rollback index."),
+            Self::Oom => write!(f, "Unable to allocate memory."),
+            Self::PublicKeyRejected => write!(f, "Public key rejected or data not signed."),
+            Self::RollbackIndex => write!(f, "Rollback index is less than its stored value."),
+            Self::UnsupportedVersion => write!(
+                f,
+                "Some of the metadata requires a newer version of libavb than what is in use."
+            ),
+            Self::Verification => write!(f, "Data does not verify."),
+        }
+    }
+}
+
+fn to_avb_verify_result(result: AvbSlotVerifyResult) -> Result<(), AvbImageVerifyError> {
+    match result {
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_OK => Ok(()),
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT => {
+            Err(AvbImageVerifyError::InvalidArgument)
+        }
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA => {
+            Err(AvbImageVerifyError::InvalidMetadata)
+        }
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_IO => Err(AvbImageVerifyError::Io),
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_OOM => Err(AvbImageVerifyError::Oom),
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED => {
+            Err(AvbImageVerifyError::PublicKeyRejected)
+        }
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX => {
+            Err(AvbImageVerifyError::RollbackIndex)
+        }
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION => {
+            Err(AvbImageVerifyError::UnsupportedVersion)
+        }
+        AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION => {
+            Err(AvbImageVerifyError::Verification)
+        }
+    }
+}
+
+/// Verifies the payload (signed kernel + initrd) against the trusted public key.
+pub fn verify_payload(_public_key: &[u8]) -> Result<(), AvbImageVerifyError> {
+    // TODO(b/256148034): Verify the kernel image with avb_slot_verify()
+    // let result = unsafe {
+    //     avb_slot_verify(
+    //         &mut avb_ops,
+    //         requested_partitions.as_ptr(),
+    //         ab_suffix.as_ptr(),
+    //         flags,
+    //         hashtree_error_mode,
+    //         null_mut(),
+    //     )
+    // };
+    let result = AvbSlotVerifyResult::AVB_SLOT_VERIFY_RESULT_OK;
+    to_avb_verify_result(result)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    // TODO(b/256148034): Test verification succeeds with valid payload later.
+    #[test]
+    fn verification_succeeds_with_placeholder_input() {
+        let fake_public_key = [0u8; 2];
+        assert!(verify_payload(&fake_public_key).is_ok());
+    }
+}
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 79b6f57..039e674 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -38,10 +38,10 @@
     memory::MemoryTracker,
     pci::{allocate_all_virtio_bars, PciError, PciInfo, PciMemory32Allocator},
 };
-use ::avb::verify_image;
 use dice::bcc;
 use libfdt::Fdt;
 use log::{debug, error, info, trace};
+use pvmfw_avb::verify_payload;
 
 fn main(
     fdt: &Fdt,
@@ -71,7 +71,7 @@
     let mut pci_root = unsafe { pci_info.make_pci_root() };
     allocate_all_virtio_bars(&mut pci_root, &mut bar_allocator).map_err(handle_pci_error)?;
 
-    verify_image(signed_kernel, PUBLIC_KEY).map_err(|e| {
+    verify_payload(PUBLIC_KEY).map_err(|e| {
         error!("Failed to verify the payload: {e}");
         RebootReason::PayloadVerificationError
     })?;