Migrate DICE access to IVmPayloadService

Take control of the microdroid interface to DICE so we can eventually
expose only what we need to with a simple interface.

Merge the DICE logic into microdroid_manager, removing a process,
removing IDiceMaintenance, and replacing IDiceNode with
IVmPayloadService for access to the DICE values. The current interface
is just meant to be enough to migrate current payload but it will need
to be refined.

The new interface is exposed in the vm_payload library and clients are
updated to use the new library functions.

Bug: 243133253
Bug: 243514248
Test: atest MicrodroidTests
Test: atest ComposHostTestCases
Change-Id: I2d659576ca3ccdb8f8ffd9d22ff0d1b96e85a3b8
diff --git a/microdroid/ueventd.rc b/microdroid/ueventd.rc
index fc165c8..268d3a2 100644
--- a/microdroid/ueventd.rc
+++ b/microdroid/ueventd.rc
@@ -28,4 +28,4 @@
 # Virtual console for logcat
 /dev/hvc2                 0666   system     system
 
-/dev/open-dice0           0660   diced      diced
+/dev/open-dice0           0660   root       root
diff --git a/microdroid/vm_payload/include/vm_payload.h b/microdroid/vm_payload/include/vm_payload.h
index 36480da..6dba760 100644
--- a/microdroid/vm_payload/include/vm_payload.h
+++ b/microdroid/vm_payload/include/vm_payload.h
@@ -20,10 +20,34 @@
 extern "C" {
 #endif
 
-/// Notifies the host that the payload is ready.
-/// Returns true if the notification succeeds else false.
+/**
+ * Notifies the host that the payload is ready.
+ * Returns true if the notification succeeds else false.
+ */
 bool notify_payload_ready();
 
+/**
+ * Get the VM's attestation chain.
+ * Returns the size of data or 0 on failure.
+ * TODO: don't expose the contained privacy breaking identifiers to the payload
+ * TODO: keep the DICE chain as an internal detail for as long as possible
+ */
+size_t get_dice_attestation_chain(void *data, size_t size);
+
+/**
+ * Get the VM's attestation CDI.
+ * Returns the size of data or 0 on failure.
+ * TODO: don't expose the raw CDI, only derived values
+ */
+size_t get_dice_attestation_cdi(void *data, size_t size);
+
+/**
+ * Get the VM's sealing CDI.
+ * Returns the size of data or 0 on failure.
+ * TODO: don't expose the raw CDI, only derived values
+ */
+size_t get_dice_sealing_cdi(void *data, size_t size);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/microdroid/vm_payload/src/lib.rs b/microdroid/vm_payload/src/lib.rs
index 394578a..e3da227 100644
--- a/microdroid/vm_payload/src/lib.rs
+++ b/microdroid/vm_payload/src/lib.rs
@@ -16,4 +16,7 @@
 
 mod vm_service;
 
-pub use vm_service::notify_payload_ready;
+pub use vm_service::{
+    get_dice_attestation_cdi, get_dice_attestation_chain, get_dice_sealing_cdi,
+    notify_payload_ready,
+};
diff --git a/microdroid/vm_payload/src/vm_service.rs b/microdroid/vm_payload/src/vm_service.rs
index 7414827..18d8222 100644
--- a/microdroid/vm_payload/src/vm_service.rs
+++ b/microdroid/vm_payload/src/vm_service.rs
@@ -28,7 +28,7 @@
         android_logger::Config::default().with_tag("vm_payload").with_min_level(Level::Debug),
     );
     if let Err(e) = try_notify_payload_ready() {
-        error!("Failed to notify ready: {}", e);
+        error!("{:?}", e);
         false
     } else {
         info!("Notified host payload ready successfully");
@@ -42,6 +42,90 @@
     get_vm_payload_service()?.notifyPayloadReady().context("Cannot notify payload ready")
 }
 
+/// Get the VM's attestation chain.
+/// Returns the size of data or 0 on failure.
+///
+/// # Safety
+///
+/// The data must be size bytes big.
+#[no_mangle]
+pub unsafe extern "C" fn get_dice_attestation_chain(data: *mut u8, size: usize) -> usize {
+    match try_get_dice_attestation_chain() {
+        Err(e) => {
+            error!("{:?}", e);
+            0
+        }
+        Ok(chain) => {
+            if size < chain.len() {
+                0
+            } else {
+                std::ptr::copy_nonoverlapping(chain.as_ptr(), data, chain.len());
+                chain.len()
+            }
+        }
+    }
+}
+
+fn try_get_dice_attestation_chain() -> Result<Vec<u8>> {
+    get_vm_payload_service()?.getDiceAttestationChain().context("Cannot get attestation chain")
+}
+
+/// Get the VM's attestation CDI.
+/// Returns the size of data or 0 on failure.
+///
+/// # Safety
+///
+/// The data must be size bytes big.
+#[no_mangle]
+pub unsafe extern "C" fn get_dice_attestation_cdi(data: *mut u8, size: usize) -> usize {
+    match try_get_dice_attestation_cdi() {
+        Err(e) => {
+            error!("{:?}", e);
+            0
+        }
+        Ok(cdi) => {
+            if size < cdi.len() {
+                0
+            } else {
+                std::ptr::copy_nonoverlapping(cdi.as_ptr(), data, cdi.len());
+                cdi.len()
+            }
+        }
+    }
+}
+
+fn try_get_dice_attestation_cdi() -> Result<Vec<u8>> {
+    get_vm_payload_service()?.getDiceAttestationCdi().context("Cannot get attestation CDI")
+}
+
+/// Get the VM's sealing CDI.
+/// Returns the size of data or 0 on failure.
+///
+/// # Safety
+///
+/// The data must be size bytes big.
+#[no_mangle]
+pub unsafe extern "C" fn get_dice_sealing_cdi(data: *mut u8, size: usize) -> usize {
+    match try_get_dice_sealing_cdi() {
+        Err(e) => {
+            error!("{:?}", e);
+            0
+        }
+        Ok(cdi) => {
+            if size < cdi.len() {
+                0
+            } else {
+                std::ptr::copy_nonoverlapping(cdi.as_ptr(), data, cdi.len());
+                cdi.len()
+            }
+        }
+    }
+}
+
+fn try_get_dice_sealing_cdi() -> Result<Vec<u8>> {
+    get_vm_payload_service()?.getDiceSealingCdi().context("Cannot get sealing CDI")
+}
+
 fn get_vm_payload_service() -> Result<Strong<dyn IVmPayloadService>> {
     wait_for_interface(VM_PAYLOAD_SERVICE_NAME)
         .context(format!("Failed to connect to service: {}", VM_PAYLOAD_SERVICE_NAME))