Keystore2: implement getState method in IKeystoreMaintenance AIDL.
Bug: 176123105
Test: TBD
Change-Id: I96a6a2aa8832a5356c7d108e9bc6ac9a5091d272
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index c789bb5..3115e92 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -15,6 +15,7 @@
package android.security.maintenance;
import android.system.keystore2.Domain;
+import android.security.maintenance.UserState;
// TODO: mark the interface with @SensitiveData when the annotation is ready (b/176110256).
@@ -75,4 +76,17 @@
* @hide
*/
void clearNamespace(Domain domain, long nspace);
+
+ /**
+ * Allows querying user state, given user id.
+ * Callers require 'GetState' permission.
+ * ## Error conditions:
+ * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'GetState'
+ * permission.
+ * `ResponseCode::SYSTEM_ERROR` - if an error occurred when querying the user state.
+ *
+ * @param userId - Android user id
+ * @hide
+ */
+ UserState getState(in int userId);
}
diff --git a/keystore2/aidl/android/security/maintenance/UserState.aidl b/keystore2/aidl/android/security/maintenance/UserState.aidl
new file mode 100644
index 0000000..b6fe278
--- /dev/null
+++ b/keystore2/aidl/android/security/maintenance/UserState.aidl
@@ -0,0 +1,22 @@
+// Copyright 2021, 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.
+
+package android.security.maintenance;
+
+@Backing(type="int")
+enum UserState {
+ UNINITIALIZED = 0,
+ LSKF_UNLOCKED = 1,
+ LSKF_LOCKED = 2,
+}
\ No newline at end of file
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 576ac3f..e2ee75f 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -291,7 +291,7 @@
AddAuth = 1, selinux name: add_auth;
/// Checked when an app is uninstalled or wiped.
ClearNs = 2, selinux name: clear_ns;
- /// Checked when Keystore 2.0 gets locked.
+ /// Checked when the user state is queried from Keystore 2.0.
GetState = 4, selinux name: get_state;
/// Checked when Keystore 2.0 is asked to list a namespace that the caller
/// does not have the get_info permission for.
diff --git a/keystore2/src/user_manager.rs b/keystore2/src/user_manager.rs
index b84cb82..c17fa72 100644
--- a/keystore2/src/user_manager.rs
+++ b/keystore2/src/user_manager.rs
@@ -20,8 +20,9 @@
use crate::permission::KeystorePerm;
use crate::super_key::UserState;
use crate::utils::check_keystore_permission;
-use android_security_maintenance::aidl::android::security::maintenance::IKeystoreMaintenance::{
- BnKeystoreMaintenance, IKeystoreMaintenance,
+use android_security_maintenance::aidl::android::security::maintenance::{
+ IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
+ UserState::UserState as AidlUserState,
};
use android_security_maintenance::binder::{Interface, Result as BinderResult};
use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
@@ -97,6 +98,23 @@
DB.with(|db| db.borrow_mut().unbind_keys_for_namespace(domain, nspace))
.context("In clear_namespace: Trying to delete keys from db.")
}
+
+ fn get_state(user_id: i32) -> Result<AidlUserState> {
+ // Check permission. Function should return if this failed. Therefore having '?' at the end
+ // is very important.
+ check_keystore_permission(KeystorePerm::get_state()).context("In get_state.")?;
+ let state = DB
+ .with(|db| {
+ UserState::get(&mut db.borrow_mut(), &LEGACY_MIGRATOR, &SUPER_KEY, user_id as u32)
+ })
+ .context("In get_state. Trying to get UserState.")?;
+
+ match state {
+ UserState::Uninitialized => Ok(AidlUserState::UNINITIALIZED),
+ UserState::LskfUnlocked(_) => Ok(AidlUserState::LSKF_UNLOCKED),
+ UserState::LskfLocked => Ok(AidlUserState::LSKF_LOCKED),
+ }
+ }
}
impl Interface for Maintenance {}
@@ -117,4 +135,8 @@
fn clearNamespace(&self, domain: Domain, nspace: i64) -> BinderResult<()> {
map_or_log_err(Self::clear_namespace(domain, nspace), Ok)
}
+
+ fn getState(&self, user_id: i32) -> binder::public_api::Result<AidlUserState> {
+ map_or_log_err(Self::get_state(user_id), Ok)
+ }
}