blob: 4636a6650686251795444f83352c7271e650dccc [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
Janis Danisevskisea03cff2021-12-16 08:10:17 -080017use crate::error::anyhow_error_to_cstring;
James Willcoxd215da82023-10-03 21:31:31 +000018use crate::error::Error as KeystoreError;
19use crate::globals::{DB, ENFORCEMENTS, LEGACY_IMPORTER, SUPER_KEY};
20use crate::ks_err;
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000021use crate::permission::KeystorePerm;
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +000022use crate::utils::{check_keystore_permission, watchdog as wd};
James Willcoxd215da82023-10-03 21:31:31 +000023use aconfig_android_hardware_biometrics_rust;
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000024use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
James Willcoxd215da82023-10-03 21:31:31 +000025 HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000026};
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000027use android_security_authorization::aidl::android::security::authorization::{
James Willcoxd215da82023-10-03 21:31:31 +000028 AuthorizationTokens::AuthorizationTokens, IKeystoreAuthorization::BnKeystoreAuthorization,
Eric Biggers10afa962023-12-01 23:05:24 +000029 IKeystoreAuthorization::IKeystoreAuthorization, ResponseCode::ResponseCode,
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +000030};
James Willcoxd215da82023-10-03 21:31:31 +000031use android_security_authorization::binder::{
32 BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status as BinderStatus,
33 Strong,
34};
35use android_system_keystore2::aidl::android::system::keystore2::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;
James Willcoxd215da82023-10-03 21:31:31 +000039use std::ffi::CString;
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000040
41/// This is the Authorization error type, it wraps binder exceptions and the
42/// Authorization ResponseCode
Chris Wailes263de9f2022-08-11 15:00:51 -070043#[derive(Debug, thiserror::Error, PartialEq, Eq)]
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000044pub enum Error {
45 /// Wraps an IKeystoreAuthorization response code as defined by
46 /// android.security.authorization AIDL interface specification.
47 #[error("Error::Rc({0:?})")]
48 Rc(ResponseCode),
49 /// Wraps a Binder exception code other than a service specific exception.
50 #[error("Binder exception code {0:?}, {1:?}")]
51 Binder(ExceptionCode, i32),
52}
53
54/// This function should be used by authorization service calls to translate error conditions
55/// into service specific exceptions.
56///
57/// All error conditions get logged by this function.
58///
59/// `Error::Rc(x)` variants get mapped onto a service specific error code of `x`.
60/// Certain response codes may be returned from keystore/ResponseCode.aidl by the keystore2 modules,
61/// which are then converted to the corresponding response codes of android.security.authorization
62/// AIDL interface specification.
63///
64/// `selinux::Error::perm()` is mapped on `ResponseCode::PERMISSION_DENIED`.
65///
66/// All non `Error` error conditions get mapped onto ResponseCode::SYSTEM_ERROR`.
David Drysdale5238d772024-06-07 15:12:10 +010067pub fn map_or_log_err<T>(result: Result<T>) -> BinderResult<T> {
68 result.map_err(|e| {
69 log::error!("{:#?}", e);
70 let root_cause = e.root_cause();
71 if let Some(KeystoreError::Rc(ks_rcode)) = root_cause.downcast_ref::<KeystoreError>() {
72 let rc = match *ks_rcode {
73 // Although currently keystore2/ResponseCode.aidl and
74 // authorization/ResponseCode.aidl share the same integer values for the
75 // common response codes, this may deviate in the future, hence the
76 // conversion here.
77 KsResponseCode::SYSTEM_ERROR => ResponseCode::SYSTEM_ERROR.0,
78 KsResponseCode::KEY_NOT_FOUND => ResponseCode::KEY_NOT_FOUND.0,
79 KsResponseCode::VALUE_CORRUPTED => ResponseCode::VALUE_CORRUPTED.0,
80 KsResponseCode::INVALID_ARGUMENT => ResponseCode::INVALID_ARGUMENT.0,
81 // If the code paths of IKeystoreAuthorization aidl's methods happen to return
82 // other error codes from KsResponseCode in the future, they should be converted
83 // as well.
84 _ => ResponseCode::SYSTEM_ERROR.0,
85 };
86 BinderStatus::new_service_specific_error(rc, anyhow_error_to_cstring(&e).as_deref())
87 } else {
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000088 let rc = match root_cause.downcast_ref::<Error>() {
89 Some(Error::Rc(rcode)) => rcode.0,
90 Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
91 None => match root_cause.downcast_ref::<selinux::Error>() {
92 Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
93 _ => ResponseCode::SYSTEM_ERROR.0,
94 },
95 };
David Drysdale5238d772024-06-07 15:12:10 +010096 BinderStatus::new_service_specific_error(rc, anyhow_error_to_cstring(&e).as_deref())
97 }
98 })
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000099}
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000100
101/// This struct is defined to implement the aforementioned AIDL interface.
102/// As of now, it is an empty struct.
103pub struct AuthorizationManager;
104
105impl AuthorizationManager {
106 /// Create a new instance of Keystore Authorization service.
Stephen Crane221bbb52020-12-16 15:52:10 -0800107 pub fn new_native_binder() -> Result<Strong<dyn IKeystoreAuthorization>> {
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000108 Ok(BnKeystoreAuthorization::new_binder(
109 Self,
110 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
111 ))
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000112 }
113
114 fn add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()> {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700115 // Check keystore permission.
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000116 check_keystore_permission(KeystorePerm::AddAuth)
117 .context(ks_err!("caller missing AddAuth permissions"))?;
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000118
David Drysdalebf2d72f2023-06-15 13:38:36 +0100119 log::info!(
120 "add_auth_token(challenge={}, userId={}, authId={}, authType={:#x}, timestamp={}ms)",
121 auth_token.challenge,
122 auth_token.userId,
123 auth_token.authenticatorId,
124 auth_token.authenticatorType.0,
125 auth_token.timestamp.milliSeconds,
126 );
127
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700128 ENFORCEMENTS.add_auth_token(auth_token.clone());
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000129 Ok(())
130 }
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000131
Eric Biggers10afa962023-12-01 23:05:24 +0000132 fn on_device_unlocked(&self, user_id: i32, password: Option<Password>) -> Result<()> {
Paul Crowley618869e2021-04-08 20:30:54 -0700133 log::info!(
Eric Biggers10afa962023-12-01 23:05:24 +0000134 "on_device_unlocked(user_id={}, password.is_some()={})",
Paul Crowley618869e2021-04-08 20:30:54 -0700135 user_id,
136 password.is_some(),
Paul Crowley618869e2021-04-08 20:30:54 -0700137 );
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000138 check_keystore_permission(KeystorePerm::Unlock)
139 .context(ks_err!("caller missing Unlock permissions"))?;
Eric Biggers10afa962023-12-01 23:05:24 +0000140 ENFORCEMENTS.set_device_locked(user_id, false);
Paul Crowley7a658392021-03-18 17:08:20 -0700141
Eric Biggers10afa962023-12-01 23:05:24 +0000142 let mut skm = SUPER_KEY.write().unwrap();
143 if let Some(password) = password {
144 DB.with(|db| {
145 skm.unlock_user(&mut db.borrow_mut(), &LEGACY_IMPORTER, user_id as u32, &password)
146 })
147 .context(ks_err!("Unlock with password."))
148 } else {
149 DB.with(|db| skm.try_unlock_user_with_biometric(&mut db.borrow_mut(), user_id as u32))
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000150 .context(ks_err!("try_unlock_user_with_biometric failed user_id={user_id}"))
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000151 }
152 }
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000153
Eric Biggers6946daa2024-01-17 22:51:37 +0000154 fn on_device_locked(
155 &self,
156 user_id: i32,
157 unlocking_sids: &[i64],
158 mut weak_unlock_enabled: bool,
159 ) -> Result<()> {
160 log::info!(
161 "on_device_locked(user_id={}, unlocking_sids={:?}, weak_unlock_enabled={})",
162 user_id,
163 unlocking_sids,
164 weak_unlock_enabled
165 );
166 if !android_security_flags::fix_unlocked_device_required_keys_v2() {
167 weak_unlock_enabled = false;
168 }
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000169 check_keystore_permission(KeystorePerm::Lock)
170 .context(ks_err!("caller missing Lock permission"))?;
Eric Biggers10afa962023-12-01 23:05:24 +0000171 ENFORCEMENTS.set_device_locked(user_id, true);
172 let mut skm = SUPER_KEY.write().unwrap();
173 DB.with(|db| {
174 skm.lock_unlocked_device_required_keys(
175 &mut db.borrow_mut(),
176 user_id as u32,
177 unlocking_sids,
Eric Biggers6946daa2024-01-17 22:51:37 +0000178 weak_unlock_enabled,
Eric Biggers10afa962023-12-01 23:05:24 +0000179 );
180 });
181 Ok(())
182 }
183
Eric Biggers6946daa2024-01-17 22:51:37 +0000184 fn on_weak_unlock_methods_expired(&self, user_id: i32) -> Result<()> {
185 log::info!("on_weak_unlock_methods_expired(user_id={})", user_id);
186 if !android_security_flags::fix_unlocked_device_required_keys_v2() {
187 return Ok(());
188 }
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000189 check_keystore_permission(KeystorePerm::Lock)
190 .context(ks_err!("caller missing Lock permission"))?;
Eric Biggers6946daa2024-01-17 22:51:37 +0000191 SUPER_KEY.write().unwrap().wipe_plaintext_unlocked_device_required_keys(user_id as u32);
192 Ok(())
193 }
194
195 fn on_non_lskf_unlock_methods_expired(&self, user_id: i32) -> Result<()> {
196 log::info!("on_non_lskf_unlock_methods_expired(user_id={})", user_id);
197 if !android_security_flags::fix_unlocked_device_required_keys_v2() {
198 return Ok(());
199 }
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000200 check_keystore_permission(KeystorePerm::Lock)
201 .context(ks_err!("caller missing Lock permission"))?;
Eric Biggers6946daa2024-01-17 22:51:37 +0000202 SUPER_KEY.write().unwrap().wipe_all_unlocked_device_required_keys(user_id as u32);
203 Ok(())
204 }
205
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000206 fn get_auth_tokens_for_credstore(
207 &self,
208 challenge: i64,
209 secure_user_id: i64,
210 auth_token_max_age_millis: i64,
211 ) -> Result<AuthorizationTokens> {
212 // Check permission. Function should return if this failed. Therefore having '?' at the end
213 // is very important.
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000214 check_keystore_permission(KeystorePerm::GetAuthToken)
215 .context(ks_err!("caller missing GetAuthToken permission"))?;
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000216
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700217 // If the challenge is zero, return error
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000218 if challenge == 0 {
219 return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000220 .context(ks_err!("Challenge can not be zero."));
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000221 }
222 // Obtain the auth token and the timestamp token from the enforcement module.
223 let (auth_token, ts_token) =
224 ENFORCEMENTS.get_auth_tokens(challenge, secure_user_id, auth_token_max_age_millis)?;
225 Ok(AuthorizationTokens { authToken: auth_token, timestampToken: ts_token })
226 }
James Willcoxd215da82023-10-03 21:31:31 +0000227
228 fn get_last_auth_time(
229 &self,
230 secure_user_id: i64,
231 auth_types: &[HardwareAuthenticatorType],
232 ) -> Result<i64> {
233 // Check keystore permission.
Shaquille Johnsona4d10db2024-02-28 20:39:14 +0000234 check_keystore_permission(KeystorePerm::GetLastAuthTime)
235 .context(ks_err!("caller missing GetLastAuthTime permission"))?;
James Willcoxd215da82023-10-03 21:31:31 +0000236
237 let mut max_time: i64 = -1;
238 for auth_type in auth_types.iter() {
239 if let Some(time) = ENFORCEMENTS.get_last_auth_time(secure_user_id, *auth_type) {
240 if time.milliseconds() > max_time {
241 max_time = time.milliseconds();
242 }
243 }
244 }
245
246 if max_time >= 0 {
247 Ok(max_time)
248 } else {
249 Err(Error::Rc(ResponseCode::NO_AUTH_TOKEN_FOUND))
250 .context(ks_err!("No auth token found"))
251 }
252 }
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000253}
254
255impl Interface for AuthorizationManager {}
256
257impl IKeystoreAuthorization for AuthorizationManager {
258 fn addAuthToken(&self, auth_token: &HardwareAuthToken) -> BinderResult<()> {
David Drysdale541846b2024-05-23 13:16:07 +0100259 let _wp = wd::watch("IKeystoreAuthorization::addAuthToken");
David Drysdale5238d772024-06-07 15:12:10 +0100260 map_or_log_err(self.add_auth_token(auth_token))
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000261 }
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000262
Eric Biggers10afa962023-12-01 23:05:24 +0000263 fn onDeviceUnlocked(&self, user_id: i32, password: Option<&[u8]>) -> BinderResult<()> {
David Drysdale541846b2024-05-23 13:16:07 +0100264 let _wp = wd::watch("IKeystoreAuthorization::onDeviceUnlocked");
David Drysdale5238d772024-06-07 15:12:10 +0100265 map_or_log_err(self.on_device_unlocked(user_id, password.map(|pw| pw.into())))
Eric Biggers10afa962023-12-01 23:05:24 +0000266 }
267
Eric Biggers6946daa2024-01-17 22:51:37 +0000268 fn onDeviceLocked(
269 &self,
270 user_id: i32,
271 unlocking_sids: &[i64],
272 weak_unlock_enabled: bool,
273 ) -> BinderResult<()> {
David Drysdale541846b2024-05-23 13:16:07 +0100274 let _wp = wd::watch("IKeystoreAuthorization::onDeviceLocked");
David Drysdale5238d772024-06-07 15:12:10 +0100275 map_or_log_err(self.on_device_locked(user_id, unlocking_sids, weak_unlock_enabled))
Eric Biggers6946daa2024-01-17 22:51:37 +0000276 }
277
278 fn onWeakUnlockMethodsExpired(&self, user_id: i32) -> BinderResult<()> {
David Drysdale541846b2024-05-23 13:16:07 +0100279 let _wp = wd::watch("IKeystoreAuthorization::onWeakUnlockMethodsExpired");
David Drysdale5238d772024-06-07 15:12:10 +0100280 map_or_log_err(self.on_weak_unlock_methods_expired(user_id))
Eric Biggers6946daa2024-01-17 22:51:37 +0000281 }
282
283 fn onNonLskfUnlockMethodsExpired(&self, user_id: i32) -> BinderResult<()> {
David Drysdale541846b2024-05-23 13:16:07 +0100284 let _wp = wd::watch("IKeystoreAuthorization::onNonLskfUnlockMethodsExpired");
David Drysdale5238d772024-06-07 15:12:10 +0100285 map_or_log_err(self.on_non_lskf_unlock_methods_expired(user_id))
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000286 }
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000287
288 fn getAuthTokensForCredStore(
289 &self,
290 challenge: i64,
291 secure_user_id: i64,
292 auth_token_max_age_millis: i64,
Stephen Crane23cf7242022-01-19 17:49:46 +0000293 ) -> binder::Result<AuthorizationTokens> {
David Drysdale541846b2024-05-23 13:16:07 +0100294 let _wp = wd::watch("IKeystoreAuthorization::getAuthTokensForCredStore");
David Drysdale5238d772024-06-07 15:12:10 +0100295 map_or_log_err(self.get_auth_tokens_for_credstore(
296 challenge,
297 secure_user_id,
298 auth_token_max_age_millis,
299 ))
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000300 }
James Willcoxd215da82023-10-03 21:31:31 +0000301
302 fn getLastAuthTime(
303 &self,
304 secure_user_id: i64,
305 auth_types: &[HardwareAuthenticatorType],
306 ) -> binder::Result<i64> {
307 if aconfig_android_hardware_biometrics_rust::last_authentication_time() {
David Drysdale5238d772024-06-07 15:12:10 +0100308 map_or_log_err(self.get_last_auth_time(secure_user_id, auth_types))
James Willcoxd215da82023-10-03 21:31:31 +0000309 } else {
310 Err(BinderStatus::new_service_specific_error(
311 ResponseCode::PERMISSION_DENIED.0,
312 Some(CString::new("Feature is not enabled.").unwrap().as_c_str()),
313 ))
314 }
315 }
Janis Danisevskis9f10a6a2021-01-18 16:45:21 +0000316}