Remove direct access to the sealing CDI from the payload
Change the API from offering the raw sealing CDI to offering VM instance
secrets that happend to be derived from the sealing CDI. This makes it
harder for the payload to leak its sealing CDI and losing the ability to
have secrets in the VM.
Bug: 243514248
Test: atest MicrodroidTests
Test: atest ComposHostTestCases
Change-Id: I0e72dabe7daca4d72a35788412d2ee19a3b446a5
diff --git a/microdroid/vm_payload/include/vm_payload.h b/microdroid/vm_payload/include/vm_payload.h
index 6dba760..4b77b43 100644
--- a/microdroid/vm_payload/include/vm_payload.h
+++ b/microdroid/vm_payload/include/vm_payload.h
@@ -16,6 +16,10 @@
#pragma once
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -27,6 +31,20 @@
bool notify_payload_ready();
/**
+ * Get a secret that is uniquely bound to this VM instance. The secrets are 32-byte values and the
+ * value associated with an identifier will not change over the lifetime of the VM instance.
+ *
+ * \param identifier identifier of the secret to return.
+ * \param identifier_size size of the secret identifier.
+ * \param secret pointer to size bytes where the secret is written.
+ * \param size number of bytes of the secret to get, up to the secret size.
+ *
+ * \return true on success and false on failure.
+ */
+bool get_vm_instance_secret(const void *identifier, size_t identifier_size, void *secret,
+ size_t size);
+
+/**
* 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
@@ -41,13 +59,6 @@
*/
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 e3da227..74dd8f4 100644
--- a/microdroid/vm_payload/src/lib.rs
+++ b/microdroid/vm_payload/src/lib.rs
@@ -17,6 +17,6 @@
mod vm_service;
pub use vm_service::{
- get_dice_attestation_cdi, get_dice_attestation_chain, get_dice_sealing_cdi,
+ get_dice_attestation_cdi, get_dice_attestation_chain, get_vm_instance_secret,
notify_payload_ready,
};
diff --git a/microdroid/vm_payload/src/vm_service.rs b/microdroid/vm_payload/src/vm_service.rs
index 18d8222..cfc3884 100644
--- a/microdroid/vm_payload/src/vm_service.rs
+++ b/microdroid/vm_payload/src/vm_service.rs
@@ -42,6 +42,40 @@
get_vm_payload_service()?.notifyPayloadReady().context("Cannot notify payload ready")
}
+/// Get a secret that is uniquely bound to this VM instance.
+///
+/// # Safety
+///
+/// The identifier must be identifier_size bytes and secret must be size bytes.
+#[no_mangle]
+pub unsafe extern "C" fn get_vm_instance_secret(
+ identifier: *const u8,
+ identifier_size: usize,
+ secret: *mut u8,
+ size: usize,
+) -> bool {
+ let identifier = std::slice::from_raw_parts(identifier, identifier_size);
+ match try_get_vm_instance_secret(identifier, size) {
+ Err(e) => {
+ error!("{:?}", e);
+ false
+ }
+ Ok(vm_secret) => {
+ if vm_secret.len() != size {
+ return false;
+ }
+ std::ptr::copy_nonoverlapping(vm_secret.as_ptr(), secret, size);
+ true
+ }
+ }
+}
+
+fn try_get_vm_instance_secret(identifier: &[u8], size: usize) -> Result<Vec<u8>> {
+ get_vm_payload_service()?
+ .getVmInstanceSecret(identifier, i32::try_from(size)?)
+ .context("Cannot get VM instance secret")
+}
+
/// Get the VM's attestation chain.
/// Returns the size of data or 0 on failure.
///
@@ -98,34 +132,6 @@
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))