blob: 19539201c35b6194da95358b678219ed5693eb3c [file] [log] [blame]
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +00001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000015//! This module implements IKeystoreAuthorization AIDL interface.
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000016
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000017use crate::ks_err;
Hasini Gunasinghea020b532021-01-07 21:42:35 +000018use crate::error::Error as KeystoreError;
Janis Danisevskisea03cff2021-12-16 08:10:17 -080019use crate::error::anyhow_error_to_cstring;
Janis Danisevskis0ffb8a82022-02-06 22:37:21 -080020use crate::globals::{ENFORCEMENTS, SUPER_KEY, DB, LEGACY_IMPORTER};
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000021use crate::permission::KeystorePerm;
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +000022use crate::super_key::UserState;
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +000023use crate::utils::{check_keystore_permission, watchdog as wd};
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000024use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Hasini Gunasingheda895552021-01-27 19:34:37 +000025 HardwareAuthToken::HardwareAuthToken,
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000026};
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000027use android_security_authorization::binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult,
28 Strong, Status as BinderStatus};
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000029use android_security_authorization::aidl::android::security::authorization::{
30 IKeystoreAuthorization::BnKeystoreAuthorization, IKeystoreAuthorization::IKeystoreAuthorization,
31 LockScreenEvent::LockScreenEvent, AuthorizationTokens::AuthorizationTokens,
32 ResponseCode::ResponseCode,
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000033};
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000034use android_system_keystore2::aidl::android::system::keystore2::{
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000035 ResponseCode::ResponseCode as KsResponseCode};
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000036use anyhow::{Context, Result};
Paul Crowleyf61fee72021-03-17 14:38:44 -070037use keystore2_crypto::Password;
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000038use keystore2_selinux as selinux;
39
40/// This is the Authorization error type, it wraps binder exceptions and the
41/// Authorization ResponseCode
Chris Wailes263de9f2022-08-11 15:00:51 -070042#[derive(Debug, thiserror::Error, PartialEq, Eq)]
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000043pub enum Error {
44 /// Wraps an IKeystoreAuthorization response code as defined by
45 /// android.security.authorization AIDL interface specification.
46 #[error("Error::Rc({0:?})")]
47 Rc(ResponseCode),
48 /// Wraps a Binder exception code other than a service specific exception.
49 #[error("Binder exception code {0:?}, {1:?}")]
50 Binder(ExceptionCode, i32),
51}
52
53/// This function should be used by authorization service calls to translate error conditions
54/// into service specific exceptions.
55///
56/// All error conditions get logged by this function.
57///
58/// `Error::Rc(x)` variants get mapped onto a service specific error code of `x`.
59/// Certain response codes may be returned from keystore/ResponseCode.aidl by the keystore2 modules,
60/// which are then converted to the corresponding response codes of android.security.authorization
61/// AIDL interface specification.
62///
63/// `selinux::Error::perm()` is mapped on `ResponseCode::PERMISSION_DENIED`.
64///
65/// All non `Error` error conditions get mapped onto ResponseCode::SYSTEM_ERROR`.
66///
67/// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
68/// as argument to `handle_ok`. `handle_ok` must generate a `BinderResult<T>`, but it
69/// typically returns Ok(value).
70pub fn map_or_log_err<T, U, F>(result: Result<U>, handle_ok: F) -> BinderResult<T>
71where
72 F: FnOnce(U) -> BinderResult<T>,
73{
74 result.map_or_else(
75 |e| {
76 log::error!("{:#?}", e);
77 let root_cause = e.root_cause();
78 if let Some(KeystoreError::Rc(ks_rcode)) = root_cause.downcast_ref::<KeystoreError>() {
79 let rc = match *ks_rcode {
80 // Although currently keystore2/ResponseCode.aidl and
81 // authorization/ResponseCode.aidl share the same integer values for the
82 // common response codes, this may deviate in the future, hence the
83 // conversion here.
84 KsResponseCode::SYSTEM_ERROR => ResponseCode::SYSTEM_ERROR.0,
85 KsResponseCode::KEY_NOT_FOUND => ResponseCode::KEY_NOT_FOUND.0,
86 KsResponseCode::VALUE_CORRUPTED => ResponseCode::VALUE_CORRUPTED.0,
87 KsResponseCode::INVALID_ARGUMENT => ResponseCode::INVALID_ARGUMENT.0,
88 // If the code paths of IKeystoreAuthorization aidl's methods happen to return
89 // other error codes from KsResponseCode in the future, they should be converted
90 // as well.
91 _ => ResponseCode::SYSTEM_ERROR.0,
92 };
Janis Danisevskisea03cff2021-12-16 08:10:17 -080093 return Err(BinderStatus::new_service_specific_error(
94 rc,
95 anyhow_error_to_cstring(&e).as_deref(),
96 ));
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000097 }
98 let rc = match root_cause.downcast_ref::<Error>() {
99 Some(Error::Rc(rcode)) => rcode.0,
100 Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
101 None => match root_cause.downcast_ref::<selinux::Error>() {
102 Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
103 _ => ResponseCode::SYSTEM_ERROR.0,
104 },
105 };
Janis Danisevskisea03cff2021-12-16 08:10:17 -0800106 Err(BinderStatus::new_service_specific_error(
107 rc,
108 anyhow_error_to_cstring(&e).as_deref(),
109 ))
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000110 },
111 handle_ok,
112 )
113}
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000114
115/// This struct is defined to implement the aforementioned AIDL interface.
116/// As of now, it is an empty struct.
117pub struct AuthorizationManager;
118
119impl AuthorizationManager {
120 /// Create a new instance of Keystore Authorization service.
Stephen Crane221bbb52020-12-16 15:52:10 -0800121 pub fn new_native_binder() -> Result<Strong<dyn IKeystoreAuthorization>> {
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000122 Ok(BnKeystoreAuthorization::new_binder(
123 Self,
124 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
125 ))
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000126 }
127
128 fn add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()> {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700129 // Check keystore permission.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000130 check_keystore_permission(KeystorePerm::AddAuth).context(ks_err!())?;
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000131
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700132 ENFORCEMENTS.add_auth_token(auth_token.clone());
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000133 Ok(())
134 }
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000135
136 fn on_lock_screen_event(
137 &self,
138 lock_screen_event: LockScreenEvent,
139 user_id: i32,
Paul Crowleyf61fee72021-03-17 14:38:44 -0700140 password: Option<Password>,
Paul Crowley618869e2021-04-08 20:30:54 -0700141 unlocking_sids: Option<&[i64]>,
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000142 ) -> Result<()> {
Paul Crowley618869e2021-04-08 20:30:54 -0700143 log::info!(
144 "on_lock_screen_event({:?}, user_id={:?}, password.is_some()={}, unlocking_sids={:?})",
145 lock_screen_event,
146 user_id,
147 password.is_some(),
148 unlocking_sids
149 );
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000150 match (lock_screen_event, password) {
Paul Crowleyf61fee72021-03-17 14:38:44 -0700151 (LockScreenEvent::UNLOCK, Some(password)) => {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700152 // This corresponds to the unlock() method in legacy keystore API.
153 // check permission
Janis Danisevskisa916d992021-10-19 15:46:09 -0700154 check_keystore_permission(KeystorePerm::Unlock)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000155 .context(ks_err!("Unlock with password."))?;
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000156 ENFORCEMENTS.set_device_locked(user_id, false);
Paul Crowley7a658392021-03-18 17:08:20 -0700157
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800158 let mut skm = SUPER_KEY.write().unwrap();
159
Paul Crowley7a658392021-03-18 17:08:20 -0700160 DB.with(|db| {
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800161 skm.unlock_screen_lock_bound_key(
Paul Crowley7a658392021-03-18 17:08:20 -0700162 &mut db.borrow_mut(),
163 user_id as u32,
164 &password,
165 )
166 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000167 .context(ks_err!("unlock_screen_lock_bound_key failed"))?;
Paul Crowley7a658392021-03-18 17:08:20 -0700168
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000169 // Unlock super key.
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000170 if let UserState::Uninitialized = DB
171 .with(|db| {
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800172 skm.unlock_and_get_user_state(
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000173 &mut db.borrow_mut(),
Janis Danisevskis0ffb8a82022-02-06 22:37:21 -0800174 &LEGACY_IMPORTER,
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000175 user_id as u32,
Paul Crowleyf61fee72021-03-17 14:38:44 -0700176 &password,
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000177 )
178 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000179 .context(ks_err!("Unlock with password."))?
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000180 {
181 log::info!(
182 "In on_lock_screen_event. Trying to unlock when LSKF is uninitialized."
183 );
184 }
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000185
186 Ok(())
187 }
188 (LockScreenEvent::UNLOCK, None) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000189 check_keystore_permission(KeystorePerm::Unlock).context(ks_err!("Unlock."))?;
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000190 ENFORCEMENTS.set_device_locked(user_id, false);
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800191 let mut skm = SUPER_KEY.write().unwrap();
Paul Crowley618869e2021-04-08 20:30:54 -0700192 DB.with(|db| {
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800193 skm.try_unlock_user_with_biometric(&mut db.borrow_mut(), user_id as u32)
Paul Crowley618869e2021-04-08 20:30:54 -0700194 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000195 .context(ks_err!("try_unlock_user_with_biometric failed"))?;
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000196 Ok(())
197 }
198 (LockScreenEvent::LOCK, None) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000199 check_keystore_permission(KeystorePerm::Lock).context(ks_err!("Lock"))?;
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000200 ENFORCEMENTS.set_device_locked(user_id, true);
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800201 let mut skm = SUPER_KEY.write().unwrap();
Paul Crowley618869e2021-04-08 20:30:54 -0700202 DB.with(|db| {
Janis Danisevskis0fd25a62022-01-04 19:53:37 -0800203 skm.lock_screen_lock_bound_key(
Paul Crowley618869e2021-04-08 20:30:54 -0700204 &mut db.borrow_mut(),
205 user_id as u32,
206 unlocking_sids.unwrap_or(&[]),
207 );
208 });
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000209 Ok(())
210 }
211 _ => {
212 // Any other combination is not supported.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000213 Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(ks_err!("Unknown event."))
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000214 }
215 }
216 }
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000217
218 fn get_auth_tokens_for_credstore(
219 &self,
220 challenge: i64,
221 secure_user_id: i64,
222 auth_token_max_age_millis: i64,
223 ) -> Result<AuthorizationTokens> {
224 // Check permission. Function should return if this failed. Therefore having '?' at the end
225 // is very important.
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000226 check_keystore_permission(KeystorePerm::GetAuthToken).context(ks_err!("GetAuthToken"))?;
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000227
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700228 // If the challenge is zero, return error
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000229 if challenge == 0 {
230 return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000231 .context(ks_err!("Challenge can not be zero."));
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000232 }
233 // Obtain the auth token and the timestamp token from the enforcement module.
234 let (auth_token, ts_token) =
235 ENFORCEMENTS.get_auth_tokens(challenge, secure_user_id, auth_token_max_age_millis)?;
236 Ok(AuthorizationTokens { authToken: auth_token, timestampToken: ts_token })
237 }
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000238}
239
240impl Interface for AuthorizationManager {}
241
242impl IKeystoreAuthorization for AuthorizationManager {
243 fn addAuthToken(&self, auth_token: &HardwareAuthToken) -> BinderResult<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000244 let _wp = wd::watch_millis("IKeystoreAuthorization::addAuthToken", 500);
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000245 map_or_log_err(self.add_auth_token(auth_token), Ok)
246 }
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000247
248 fn onLockScreenEvent(
249 &self,
250 lock_screen_event: LockScreenEvent,
251 user_id: i32,
252 password: Option<&[u8]>,
Paul Crowley618869e2021-04-08 20:30:54 -0700253 unlocking_sids: Option<&[i64]>,
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000254 ) -> BinderResult<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000255 let _wp =
256 wd::watch_millis_with("IKeystoreAuthorization::onLockScreenEvent", 500, move || {
257 format!("lock event: {}", lock_screen_event.0)
258 });
Paul Crowleyf61fee72021-03-17 14:38:44 -0700259 map_or_log_err(
Paul Crowley618869e2021-04-08 20:30:54 -0700260 self.on_lock_screen_event(
261 lock_screen_event,
262 user_id,
263 password.map(|pw| pw.into()),
264 unlocking_sids,
265 ),
Paul Crowleyf61fee72021-03-17 14:38:44 -0700266 Ok,
267 )
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000268 }
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000269
270 fn getAuthTokensForCredStore(
271 &self,
272 challenge: i64,
273 secure_user_id: i64,
274 auth_token_max_age_millis: i64,
Stephen Crane23cf7242022-01-19 17:49:46 +0000275 ) -> binder::Result<AuthorizationTokens> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000276 let _wp = wd::watch_millis("IKeystoreAuthorization::getAuthTokensForCredStore", 500);
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000277 map_or_log_err(
278 self.get_auth_tokens_for_credstore(
279 challenge,
280 secure_user_id,
281 auth_token_max_age_millis,
282 ),
283 Ok,
284 )
285 }
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000286}