Merge "Keystore 2.0: Fix loading of unencrypted legacy super keys."
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index c69774d..7d2d8de 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -39,6 +39,7 @@
         "android.system.keystore2-V1-rust",
         "libanyhow",
         "libbinder_rs",
+        "libcutils_bindgen",
         "libkeystore2_aaid-rust",
         "libkeystore2_apc_compat-rust",
         "libkeystore2_crypto_rust",
@@ -54,6 +55,9 @@
         "librusqlite",
         "libthiserror",
     ],
+    shared_libs: [
+        "libcutils",
+    ],
 }
 
 rust_library {
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index 8bec0f7..280500c 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -90,6 +90,16 @@
     UserState getState(in int userId);
 
     /**
+     * This function notifies the Keymint device of the specified securityLevel that
+     * early boot has ended, so that they no longer allow early boot keys to be used.
+     * ## Error conditions:
+     * `ResponseCode::PERMISSION_DENIED` - if the caller does not have the 'EarlyBootEnded'
+     *                                     permission.
+     * A KeyMint ErrorCode may be returned indicating a backend diagnosed error.
+     */
+     void earlyBootEnded();
+
+    /**
      * Informs Keystore 2.0 that the an off body event was detected.
      *
      * ## Error conditions:
diff --git a/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl b/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
index 5c2d0b1..4a092af 100644
--- a/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
+++ b/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
@@ -16,6 +16,7 @@
 
 package android.security.remoteprovisioning;
 
+import android.hardware.security.keymint.DeviceInfo;
 import android.hardware.security.keymint.ProtectedData;
 import android.hardware.security.keymint.SecurityLevel;
 import android.security.remoteprovisioning.AttestationPoolStatus;
@@ -90,7 +91,7 @@
      *                         request.
      */
     byte[] generateCsr(in boolean testMode, in int numCsr, in byte[] eek, in byte[] challenge,
-        in SecurityLevel secLevel, out ProtectedData protectedData);
+        in SecurityLevel secLevel, out ProtectedData protectedData, out DeviceInfo deviceInfo);
 
     /**
      * This method provides a way for the returned attestation certificate chains to be provisioned
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 1c206fc..47bd946 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -14,12 +14,16 @@
 
 //! This module implements IKeystoreMaintenance AIDL interface.
 
+use crate::error::map_km_error;
 use crate::error::Error as KeystoreError;
+use crate::globals::get_keymint_device;
 use crate::globals::{DB, LEGACY_MIGRATOR, SUPER_KEY};
 use crate::permission::KeystorePerm;
 use crate::super_key::UserState;
 use crate::utils::check_keystore_permission;
 use crate::{database::MonotonicRawTime, error::map_or_log_err};
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::IKeyMintDevice::IKeyMintDevice;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_security_maintenance::aidl::android::security::maintenance::{
     IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
     UserState::UserState as AidlUserState,
@@ -117,6 +121,36 @@
         }
     }
 
+    fn early_boot_ended_help(sec_level: &SecurityLevel) -> Result<()> {
+        let (dev, _, _) =
+            get_keymint_device(sec_level).context("In early_boot_ended: getting keymint device")?;
+        let km_dev: Strong<dyn IKeyMintDevice> =
+            dev.get_interface().context("In early_boot_ended: getting keymint device interface")?;
+        map_km_error(km_dev.earlyBootEnded())
+            .context("In keymint device: calling earlyBootEnded")?;
+        Ok(())
+    }
+
+    fn early_boot_ended() -> Result<()> {
+        check_keystore_permission(KeystorePerm::early_boot_ended())
+            .context("In early_boot_ended. Checking permission")?;
+
+        let sec_levels = [
+            (SecurityLevel::TRUSTED_ENVIRONMENT, "TRUSTED_ENVIRONMENT"),
+            (SecurityLevel::STRONGBOX, "STRONGBOX"),
+        ];
+        sec_levels.iter().fold(Ok(()), |result, (sec_level, sec_level_string)| {
+            let curr_result = Maintenance::early_boot_ended_help(sec_level);
+            if curr_result.is_err() {
+                log::error!(
+                    "Call to earlyBootEnded failed for security level {}.",
+                    &sec_level_string
+                );
+            }
+            result.and(curr_result)
+        })
+    }
+
     fn on_device_off_body() -> Result<()> {
         // Security critical permission check. This statement must return on fail.
         check_keystore_permission(KeystorePerm::report_off_body())
@@ -150,6 +184,10 @@
         map_or_log_err(Self::get_state(user_id), Ok)
     }
 
+    fn earlyBootEnded(&self) -> BinderResult<()> {
+        map_or_log_err(Self::early_boot_ended(), Ok)
+    }
+
     fn onDeviceOffBody(&self) -> BinderResult<()> {
         map_or_log_err(Self::on_device_off_body(), Ok)
     }
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index f0a4c87..45c4dc1 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -311,6 +311,8 @@
         ClearUID = 0x200,    selinux name: clear_uid;
         /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
         GetAuthToken = 0x400,  selinux name: get_auth_token;
+        /// Checked when earlyBootEnded() is called.
+        EarlyBootEnded = 0x800,   selinux name: early_boot_ended;
         /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
         ReportOffBody = 0x1000, selinux name: report_off_body;
     }
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index 8c04088..1c757c9 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -23,9 +23,10 @@
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, AttestationKey::AttestationKey, Certificate::Certificate,
-    IRemotelyProvisionedComponent::IRemotelyProvisionedComponent, KeyParameter::KeyParameter,
-    KeyParameterValue::KeyParameterValue, MacedPublicKey::MacedPublicKey,
-    ProtectedData::ProtectedData, SecurityLevel::SecurityLevel, Tag::Tag,
+    DeviceInfo::DeviceInfo, IRemotelyProvisionedComponent::IRemotelyProvisionedComponent,
+    KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue,
+    MacedPublicKey::MacedPublicKey, ProtectedData::ProtectedData, SecurityLevel::SecurityLevel,
+    Tag::Tag,
 };
 use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
     AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
@@ -261,6 +262,7 @@
     /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
     /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
     /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
+    #[allow(clippy::too_many_arguments)]
     pub fn generate_csr(
         &self,
         test_mode: bool,
@@ -269,6 +271,7 @@
         challenge: &[u8],
         sec_level: SecurityLevel,
         protected_data: &mut ProtectedData,
+        device_info: &mut DeviceInfo,
     ) -> Result<Vec<u8>> {
         let dev = self.get_dev_by_sec_level(&sec_level)?;
         let (_, _, uuid) = get_keymint_device(&sec_level)?;
@@ -280,13 +283,12 @@
                 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
                 .collect())
         })?;
-        let mut mac = Vec::<u8>::with_capacity(32);
-        map_rem_prov_error(dev.generateCertificateRequest(
+        let mut mac = map_rem_prov_error(dev.generateCertificateRequest(
             test_mode,
             &keys_to_sign,
             eek,
             challenge,
-            &mut mac,
+            device_info,
             protected_data,
         ))
         .context("In generate_csr: Failed to generate csr")?;
@@ -399,9 +401,18 @@
         challenge: &[u8],
         sec_level: SecurityLevel,
         protected_data: &mut ProtectedData,
+        device_info: &mut DeviceInfo,
     ) -> binder::public_api::Result<Vec<u8>> {
         map_or_log_err(
-            self.generate_csr(test_mode, num_csr, eek, challenge, sec_level, protected_data),
+            self.generate_csr(
+                test_mode,
+                num_csr,
+                eek,
+                challenge,
+                sec_level,
+                protected_data,
+                device_info,
+            ),
             Ok,
         )
     }
diff --git a/keystore2/src/shared_secret_negotiation.rs b/keystore2/src/shared_secret_negotiation.rs
index afce533..fb55f33 100644
--- a/keystore2/src/shared_secret_negotiation.rs
+++ b/keystore2/src/shared_secret_negotiation.rs
@@ -151,8 +151,10 @@
             |(mut connected, mut failed), e| {
                 match e {
                     SharedSecretParticipant::Aidl(instance_name) => {
-                        let service_name =
-                            format!("{}/{}", SHARED_SECRET_PACKAGE_NAME, instance_name);
+                        let service_name = format!(
+                            "{}.{}/{}",
+                            SHARED_SECRET_PACKAGE_NAME, SHARED_SECRET_INTERFACE_NAME, instance_name
+                        );
                         match map_binder_status_code(binder::get_interface(&service_name)) {
                             Err(e) => {
                                 log::warn!(
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 2748025..7b58205 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -215,12 +215,12 @@
 }
 
 /// AID offset for uid space partitioning.
-/// TODO: Replace with bindgen generated from libcutils. b/175619259
-pub const AID_USER_OFFSET: u32 = 100000;
+pub const AID_USER_OFFSET: u32 = cutils_bindgen::AID_USER_OFFSET;
 
 /// Extracts the android user from the given uid.
 pub fn uid_to_android_user(uid: u32) -> u32 {
-    uid / AID_USER_OFFSET
+    // Safety: No memory access
+    unsafe { cutils_bindgen::multiuser_get_user_id(uid) }
 }
 
 #[cfg(test)]