Repository: chipsalliance/caliptra-sw (rust)

Issue:
Auto-initialize DPE with Caliptra's own locality (PAUSER)
When DPE is auto-initialized, the RTJM measurement should probably say it was made by Caliptra. So I think in `execute`, locality should be Caliptra's locality (rather than the PL0 PAUSER).

The only thing I'm not sure about is what Caliptra's locality is (I assume it is SoC dependent, and I'm not sure whether Caliptra can introspect that value). 

Pull request:
Make DPE auto-init locality 0xFFFFFFF
We do this since the auto init measurement is provided by Caliptra itself, and not the pl0 pauser.

Fixes #1093 

Patch:
diff --git a/drivers/src/soc_ifc.rs b/drivers/src/soc_ifc.rs
index c346eb78..e3290fe9 100644
--- a/drivers/src/soc_ifc.rs
+++ b/drivers/src/soc_ifc.rs
@@ -74,6 +74,23 @@ impl SocIfc {
         soc_ifc_regs.cptra_security_state().read().debug_locked()
     }
 
+    pub fn mbox_valid_pauser(&self) -> [u32; 5] {
+        let soc_ifc_regs = self.soc_ifc.regs();
+        soc_ifc_regs.cptra_mbox_valid_pauser().read()
+    }
+
+    pub fn mbox_pauser_lock(&self) -> [bool; 5] {
+        let soc_ifc_regs = self.soc_ifc.regs();
+        let pauser_lock = soc_ifc_regs.cptra_mbox_pauser_lock();
+        [
+            pauser_lock.at(0).read().lock(),
+            pauser_lock.at(1).read().lock(),
+            pauser_lock.at(2).read().lock(),
+            pauser_lock.at(3).read().lock(),
+            pauser_lock.at(4).read().lock(),
+        ]
+    }
+
     /// Locks or unlocks the ICCM.
     ///
     /// # Arguments
diff --git a/error/src/lib.rs b/error/src/lib.rs
index 44d8813a..db4c7be9 100644
--- a/error/src/lib.rs
+++ b/error/src/lib.rs
@@ -358,6 +358,8 @@ impl CaliptraError {
         CaliptraError::new_const(0x000E0021);
     pub const RUNTIME_ADD_ROM_MEASUREMENTS_TO_DPE_FAILED: CaliptraError =
         CaliptraError::new_const(0x000E0022);
+    pub const RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED: CaliptraError =
+        CaliptraError::new_const(0x000E0023);
 
     /// FMC Errors
     pub const FMC_GLOBAL_NMI: CaliptraError = CaliptraError::new_const(0x000F0001);
diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs
index b13ffe88..da58bf35 100644
--- a/runtime/src/drivers.rs
+++ b/runtime/src/drivers.rs
@@ -33,6 +33,7 @@ use dpe::{
 };
 
 use crypto::{AlgLen, Crypto, CryptoBuf};
+use zerocopy::AsBytes;
 
 pub struct Drivers {
     pub mbox: Mailbox,
@@ -240,7 +241,8 @@ impl Drivers {
     }
 
     fn initialize_dpe(drivers: &mut Drivers) -> CaliptraResult<()> {
-        let locality = drivers.persistent_data.get().manifest1.header.pl0_pauser;
+        let caliptra_locality = 0xFFFFFFFF;
+        let pl0_pauser_locality = drivers.persistent_data.get().manifest1.header.pl0_pauser;
         let hashed_rt_pub_key = drivers.compute_rt_alias_sn()?;
         let mut crypto = DpeCrypto::new(
             &mut drivers.sha384,
@@ -251,9 +253,36 @@ impl Drivers {
             drivers.persistent_data.get().fht.rt_dice_pub_key,
         );
 
+        // create a hash of all the mailbox valid pausers
+        const PAUSER_COUNT: usize = 5;
+        let mbox_valid_pauser: [u32; PAUSER_COUNT] = drivers.soc_ifc.mbox_valid_pauser();
+        let mbox_pauser_lock: [bool; PAUSER_COUNT] = drivers.soc_ifc.mbox_pauser_lock();
+        let mut valid_pausers = [0u32; PAUSER_COUNT];
+        let mut num_valid_pausers = 0;
+        for i in 0..PAUSER_COUNT {
+            if num_valid_pausers >= PAUSER_COUNT {
+                // Prevent panic; compiler doesn't realize this is impossible.
+                return Err(CaliptraError::RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED);
+            }
+            if mbox_pauser_lock[i] {
+                valid_pausers[num_valid_pausers] = mbox_valid_pauser[i];
+                num_valid_pausers += 1;
+            }
+        }
+        let valid_pauser_hash = crypto
+            .hash(
+                AlgLen::Bit384,
+                valid_pausers[..num_valid_pausers].as_bytes(),
+            )
+            .map_err(|_| CaliptraError::RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED)?;
+
         let mut env = DpeEnv::<CptraDpeTypes> {
             crypto,
-            platform: DpePlatform::new(locality, hashed_rt_pub_key, &mut drivers.cert_chain),
+            platform: DpePlatform::new(
+                caliptra_locality,
+                hashed_rt_pub_key,
+                &mut drivers.cert_chain,
+            ),
         };
         let mut dpe = DpeInstance::new(&mut env, DPE_SUPPORT)
             .map_err(|_| CaliptraError::RUNTIME_INITIALIZE_DPE_FAILED)?;
@@ -270,11 +299,28 @@ impl Drivers {
                 | DeriveChildFlags::INPUT_ALLOW_CA
                 | DeriveChildFlags::INPUT_ALLOW_X509,
             tci_type: u32::from_be_bytes(*b"RTJM"),
-            target_locality: locality,
+            target_locality: caliptra_locality,
         }
-        .execute(&mut dpe, &mut env, locality)
+        .execute(&mut dpe, &mut env, caliptra_locality)
         .map_err(|_| CaliptraError::RUNTIME_INITIALIZE_DPE_FAILED)?;
 
+        // Call DeriveChild to create a measurement for the mailbox valid pausers and change locality to the pl0 pauser locality
+        DeriveChildCmd {
+            handle: ContextHandle::default(),
+            data: valid_pauser_hash
+                .bytes()
+                .try_into()
+                .map_err(|_| CaliptraError::RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED)?,
+            flags: DeriveChildFlags::MAKE_DEFAULT
+                | DeriveChildFlags::CHANGE_LOCALITY
+                | DeriveChildFlags::INPUT_ALLOW_CA
+                | DeriveChildFlags::INPUT_ALLOW_X509,
+            tci_type: u32::from_be_bytes(*b"MBVP"),
+            target_locality: pl0_pauser_locality,
+        }
+        .execute(&mut dpe, &mut env, caliptra_locality)
+        .map_err(|_| CaliptraError::RUNTIME_ADD_VALID_PAUSER_MEASUREMENT_TO_DPE_FAILED)?;
+
         // Call DeriveChild to create TCIs for each measurement added in ROM
         let num_measurements = drivers.persistent_data.get().fht.meas_log_index as usize;
         let measurement_log = drivers.persistent_data.get().measurement_log;
@@ -291,9 +337,9 @@ impl Drivers {
                     | DeriveChildFlags::INPUT_ALLOW_CA
                     | DeriveChildFlags::INPUT_ALLOW_X509,
                 tci_type,
-                target_locality: locality,
+                target_locality: pl0_pauser_locality,
             }
-            .execute(&mut dpe, &mut env, locality)
+            .execute(&mut dpe, &mut env, pl0_pauser_locality)
             .map_err(|_| CaliptraError::RUNTIME_ADD_ROM_MEASUREMENTS_TO_DPE_FAILED)?;
         }
 


Test patch:
diff --git a/runtime/tests/runtime_integration_tests/integration_tests.rs b/runtime/tests/runtime_integration_tests/integration_tests.rs
index cb9d7b90..cc6c5c1f 100644
--- a/runtime/tests/runtime_integration_tests/integration_tests.rs
+++ b/runtime/tests/runtime_integration_tests/integration_tests.rs
@@ -669,12 +669,10 @@ fn test_pauser_privilege_level_dpe_context_thresholds() {
     let mut handle = rotate_ctx_resp.handle;
 
     // Call DeriveChild with PL0 enough times to breach the threshold on the last iteration.
-    // Note that this loop runs exactly PL0_DPE_ACTIVE_CONTEXT_THRESHOLD - 1 times. Due to
-    // auto initialization of DPE, context[0] has a default context. When we initialize drivers,
-    // we also call derive child once without setting RETAINS_PARENT, so context[1] will be
-    // active. Thus, we can call derive child from PL0 exactly 6 times, and the last iteration
-    // of this loop, is expected to throw a threshold breached error.
-    let num_iterations = InvokeDpeCmd::PL0_DPE_ACTIVE_CONTEXT_THRESHOLD - 1;
+    // Note that this loop runs exactly PL0_DPE_ACTIVE_CONTEXT_THRESHOLD times. When we initialize
+    // DPE, we measure mailbox valid pausers in pl0_pauser's locality. Thus, we can call derive child
+    // from PL0 exactly 7 times, and the last iteration of this loop, is expected to throw a threshold breached error.
+    let num_iterations = InvokeDpeCmd::PL0_DPE_ACTIVE_CONTEXT_THRESHOLD;
     for i in 0..num_iterations {
         let mut cmd_data: [u8; 512] = [0u8; InvokeDpeReq::DATA_MAX_SIZE];
         let derive_child_cmd = DeriveChildCmd {