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