1 // 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 
15 //! This module implements IKeystoreAuthorization AIDL interface.
16 
17 use crate::error::Error as KeystoreError;
18 use crate::globals::{ENFORCEMENTS, SUPER_KEY, DB, LEGACY_MIGRATOR};
19 use crate::permission::KeystorePerm;
20 use crate::super_key::UserState;
21 use crate::utils::{check_keystore_permission, watchdog as wd};
22 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
23     HardwareAuthToken::HardwareAuthToken,
24 };
25 use android_security_authorization::binder::{BinderFeatures,ExceptionCode, Interface, Result as BinderResult,
26      Strong, Status as BinderStatus};
27 use android_security_authorization::aidl::android::security::authorization::{
28     IKeystoreAuthorization::BnKeystoreAuthorization, IKeystoreAuthorization::IKeystoreAuthorization,
29     LockScreenEvent::LockScreenEvent, AuthorizationTokens::AuthorizationTokens,
30     ResponseCode::ResponseCode,
31 };
32 use android_system_keystore2::aidl::android::system::keystore2::{
33     ResponseCode::ResponseCode as KsResponseCode };
34 use anyhow::{Context, Result};
35 use keystore2_crypto::Password;
36 use keystore2_selinux as selinux;
37 
38 /// This is the Authorization error type, it wraps binder exceptions and the
39 /// Authorization ResponseCode
40 #[derive(Debug, thiserror::Error, PartialEq)]
41 pub enum Error {
42     /// Wraps an IKeystoreAuthorization response code as defined by
43     /// android.security.authorization AIDL interface specification.
44     #[error("Error::Rc({0:?})")]
45     Rc(ResponseCode),
46     /// Wraps a Binder exception code other than a service specific exception.
47     #[error("Binder exception code {0:?}, {1:?}")]
48     Binder(ExceptionCode, i32),
49 }
50 
51 /// This function should be used by authorization service calls to translate error conditions
52 /// into service specific exceptions.
53 ///
54 /// All error conditions get logged by this function.
55 ///
56 /// `Error::Rc(x)` variants get mapped onto a service specific error code of `x`.
57 /// Certain response codes may be returned from keystore/ResponseCode.aidl by the keystore2 modules,
58 /// which are then converted to the corresponding response codes of android.security.authorization
59 /// AIDL interface specification.
60 ///
61 /// `selinux::Error::perm()` is mapped on `ResponseCode::PERMISSION_DENIED`.
62 ///
63 /// All non `Error` error conditions get mapped onto ResponseCode::SYSTEM_ERROR`.
64 ///
65 /// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
66 /// as argument to `handle_ok`. `handle_ok` must generate a `BinderResult<T>`, but it
67 /// typically returns Ok(value).
map_or_log_err<T, U, F>(result: Result<U>, handle_ok: F) -> BinderResult<T> where F: FnOnce(U) -> BinderResult<T>,68 pub fn map_or_log_err<T, U, F>(result: Result<U>, handle_ok: F) -> BinderResult<T>
69 where
70     F: FnOnce(U) -> BinderResult<T>,
71 {
72     result.map_or_else(
73         |e| {
74             log::error!("{:#?}", e);
75             let root_cause = e.root_cause();
76             if let Some(KeystoreError::Rc(ks_rcode)) = root_cause.downcast_ref::<KeystoreError>() {
77                 let rc = match *ks_rcode {
78                     // Although currently keystore2/ResponseCode.aidl and
79                     // authorization/ResponseCode.aidl share the same integer values for the
80                     // common response codes, this may deviate in the future, hence the
81                     // conversion here.
82                     KsResponseCode::SYSTEM_ERROR => ResponseCode::SYSTEM_ERROR.0,
83                     KsResponseCode::KEY_NOT_FOUND => ResponseCode::KEY_NOT_FOUND.0,
84                     KsResponseCode::VALUE_CORRUPTED => ResponseCode::VALUE_CORRUPTED.0,
85                     KsResponseCode::INVALID_ARGUMENT => ResponseCode::INVALID_ARGUMENT.0,
86                     // If the code paths of IKeystoreAuthorization aidl's methods happen to return
87                     // other error codes from KsResponseCode in the future, they should be converted
88                     // as well.
89                     _ => ResponseCode::SYSTEM_ERROR.0,
90                 };
91                 return Err(BinderStatus::new_service_specific_error(rc, None));
92             }
93             let rc = match root_cause.downcast_ref::<Error>() {
94                 Some(Error::Rc(rcode)) => rcode.0,
95                 Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
96                 None => match root_cause.downcast_ref::<selinux::Error>() {
97                     Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
98                     _ => ResponseCode::SYSTEM_ERROR.0,
99                 },
100             };
101             Err(BinderStatus::new_service_specific_error(rc, None))
102         },
103         handle_ok,
104     )
105 }
106 
107 /// This struct is defined to implement the aforementioned AIDL interface.
108 /// As of now, it is an empty struct.
109 pub struct AuthorizationManager;
110 
111 impl AuthorizationManager {
112     /// Create a new instance of Keystore Authorization service.
new_native_binder() -> Result<Strong<dyn IKeystoreAuthorization>>113     pub fn new_native_binder() -> Result<Strong<dyn IKeystoreAuthorization>> {
114         Ok(BnKeystoreAuthorization::new_binder(
115             Self,
116             BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
117         ))
118     }
119 
add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()>120     fn add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()> {
121         // Check keystore permission.
122         check_keystore_permission(KeystorePerm::add_auth()).context("In add_auth_token.")?;
123 
124         ENFORCEMENTS.add_auth_token(auth_token.clone());
125         Ok(())
126     }
127 
on_lock_screen_event( &self, lock_screen_event: LockScreenEvent, user_id: i32, password: Option<Password>, unlocking_sids: Option<&[i64]>, ) -> Result<()>128     fn on_lock_screen_event(
129         &self,
130         lock_screen_event: LockScreenEvent,
131         user_id: i32,
132         password: Option<Password>,
133         unlocking_sids: Option<&[i64]>,
134     ) -> Result<()> {
135         log::info!(
136             "on_lock_screen_event({:?}, user_id={:?}, password.is_some()={}, unlocking_sids={:?})",
137             lock_screen_event,
138             user_id,
139             password.is_some(),
140             unlocking_sids
141         );
142         match (lock_screen_event, password) {
143             (LockScreenEvent::UNLOCK, Some(password)) => {
144                 // This corresponds to the unlock() method in legacy keystore API.
145                 // check permission
146                 check_keystore_permission(KeystorePerm::unlock())
147                     .context("In on_lock_screen_event: Unlock with password.")?;
148                 ENFORCEMENTS.set_device_locked(user_id, false);
149 
150                 DB.with(|db| {
151                     SUPER_KEY.unlock_screen_lock_bound_key(
152                         &mut db.borrow_mut(),
153                         user_id as u32,
154                         &password,
155                     )
156                 })
157                 .context("In on_lock_screen_event: unlock_screen_lock_bound_key failed")?;
158 
159                 // Unlock super key.
160                 if let UserState::Uninitialized = DB
161                     .with(|db| {
162                         UserState::get_with_password_unlock(
163                             &mut db.borrow_mut(),
164                             &LEGACY_MIGRATOR,
165                             &SUPER_KEY,
166                             user_id as u32,
167                             &password,
168                         )
169                     })
170                     .context("In on_lock_screen_event: Unlock with password.")?
171                 {
172                     log::info!(
173                         "In on_lock_screen_event. Trying to unlock when LSKF is uninitialized."
174                     );
175                 }
176 
177                 Ok(())
178             }
179             (LockScreenEvent::UNLOCK, None) => {
180                 check_keystore_permission(KeystorePerm::unlock())
181                     .context("In on_lock_screen_event: Unlock.")?;
182                 ENFORCEMENTS.set_device_locked(user_id, false);
183                 DB.with(|db| {
184                     SUPER_KEY.try_unlock_user_with_biometric(&mut db.borrow_mut(), user_id as u32)
185                 })
186                 .context("In on_lock_screen_event: try_unlock_user_with_biometric failed")?;
187                 Ok(())
188             }
189             (LockScreenEvent::LOCK, None) => {
190                 check_keystore_permission(KeystorePerm::lock())
191                     .context("In on_lock_screen_event: Lock")?;
192                 ENFORCEMENTS.set_device_locked(user_id, true);
193                 DB.with(|db| {
194                     SUPER_KEY.lock_screen_lock_bound_key(
195                         &mut db.borrow_mut(),
196                         user_id as u32,
197                         unlocking_sids.unwrap_or(&[]),
198                     );
199                 });
200                 Ok(())
201             }
202             _ => {
203                 // Any other combination is not supported.
204                 Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
205                     .context("In on_lock_screen_event: Unknown event.")
206             }
207         }
208     }
209 
get_auth_tokens_for_credstore( &self, challenge: i64, secure_user_id: i64, auth_token_max_age_millis: i64, ) -> Result<AuthorizationTokens>210     fn get_auth_tokens_for_credstore(
211         &self,
212         challenge: i64,
213         secure_user_id: i64,
214         auth_token_max_age_millis: i64,
215     ) -> Result<AuthorizationTokens> {
216         // Check permission. Function should return if this failed. Therefore having '?' at the end
217         // is very important.
218         check_keystore_permission(KeystorePerm::get_auth_token())
219             .context("In get_auth_tokens_for_credstore.")?;
220 
221         // If the challenge is zero, return error
222         if challenge == 0 {
223             return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
224                 .context("In get_auth_tokens_for_credstore. Challenge can not be zero.");
225         }
226         // Obtain the auth token and the timestamp token from the enforcement module.
227         let (auth_token, ts_token) =
228             ENFORCEMENTS.get_auth_tokens(challenge, secure_user_id, auth_token_max_age_millis)?;
229         Ok(AuthorizationTokens { authToken: auth_token, timestampToken: ts_token })
230     }
231 }
232 
233 impl Interface for AuthorizationManager {}
234 
235 impl IKeystoreAuthorization for AuthorizationManager {
addAuthToken(&self, auth_token: &HardwareAuthToken) -> BinderResult<()>236     fn addAuthToken(&self, auth_token: &HardwareAuthToken) -> BinderResult<()> {
237         let _wp = wd::watch_millis("IKeystoreAuthorization::addAuthToken", 500);
238         map_or_log_err(self.add_auth_token(auth_token), Ok)
239     }
240 
onLockScreenEvent( &self, lock_screen_event: LockScreenEvent, user_id: i32, password: Option<&[u8]>, unlocking_sids: Option<&[i64]>, ) -> BinderResult<()>241     fn onLockScreenEvent(
242         &self,
243         lock_screen_event: LockScreenEvent,
244         user_id: i32,
245         password: Option<&[u8]>,
246         unlocking_sids: Option<&[i64]>,
247     ) -> BinderResult<()> {
248         let _wp =
249             wd::watch_millis_with("IKeystoreAuthorization::onLockScreenEvent", 500, move || {
250                 format!("lock event: {}", lock_screen_event.0)
251             });
252         map_or_log_err(
253             self.on_lock_screen_event(
254                 lock_screen_event,
255                 user_id,
256                 password.map(|pw| pw.into()),
257                 unlocking_sids,
258             ),
259             Ok,
260         )
261     }
262 
getAuthTokensForCredStore( &self, challenge: i64, secure_user_id: i64, auth_token_max_age_millis: i64, ) -> binder::public_api::Result<AuthorizationTokens>263     fn getAuthTokensForCredStore(
264         &self,
265         challenge: i64,
266         secure_user_id: i64,
267         auth_token_max_age_millis: i64,
268     ) -> binder::public_api::Result<AuthorizationTokens> {
269         let _wp = wd::watch_millis("IKeystoreAuthorization::getAuthTokensForCredStore", 500);
270         map_or_log_err(
271             self.get_auth_tokens_for_credstore(
272                 challenge,
273                 secure_user_id,
274                 auth_token_max_age_millis,
275             ),
276             Ok,
277         )
278     }
279 }
280