• 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 utility functions used by the Keystore 2.0 service
16 //! implementation.
17 
18 use crate::error::{map_binder_status, Error, ErrorCode};
19 use crate::permission;
20 use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
21 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
22     KeyCharacteristics::KeyCharacteristics, Tag::Tag,
23 };
24 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
25 use android_security_apc::aidl::android::security::apc::{
26     IProtectedConfirmation::{FLAG_UI_OPTION_INVERTED, FLAG_UI_OPTION_MAGNIFIED},
27     ResponseCode::ResponseCode as ApcResponseCode,
28 };
29 use android_system_keystore2::aidl::android::system::keystore2::{
30     Authorization::Authorization, KeyDescriptor::KeyDescriptor,
31 };
32 use anyhow::{anyhow, Context};
33 use binder::{FromIBinder, SpIBinder, ThreadState};
34 use keystore2_apc_compat::{
35     ApcCompatUiOptions, APC_COMPAT_ERROR_ABORTED, APC_COMPAT_ERROR_CANCELLED,
36     APC_COMPAT_ERROR_IGNORED, APC_COMPAT_ERROR_OK, APC_COMPAT_ERROR_OPERATION_PENDING,
37     APC_COMPAT_ERROR_SYSTEM_ERROR,
38 };
39 use std::sync::Mutex;
40 
41 /// This function uses its namesake in the permission module and in
42 /// combination with with_calling_sid from the binder crate to check
43 /// if the caller has the given keystore permission.
check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()>44 pub fn check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()> {
45     ThreadState::with_calling_sid(|calling_sid| {
46         permission::check_keystore_permission(
47             &calling_sid.ok_or_else(Error::sys).context(
48                 "In check_keystore_permission: Cannot check permission without calling_sid.",
49             )?,
50             perm,
51         )
52     })
53 }
54 
55 /// This function uses its namesake in the permission module and in
56 /// combination with with_calling_sid from the binder crate to check
57 /// if the caller has the given grant permission.
check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()>58 pub fn check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()> {
59     ThreadState::with_calling_sid(|calling_sid| {
60         permission::check_grant_permission(
61             &calling_sid.ok_or_else(Error::sys).context(
62                 "In check_grant_permission: Cannot check permission without calling_sid.",
63             )?,
64             access_vec,
65             key,
66         )
67     })
68 }
69 
70 /// This function uses its namesake in the permission module and in
71 /// combination with with_calling_sid from the binder crate to check
72 /// if the caller has the given key permission.
check_key_permission( perm: KeyPerm, key: &KeyDescriptor, access_vector: &Option<KeyPermSet>, ) -> anyhow::Result<()>73 pub fn check_key_permission(
74     perm: KeyPerm,
75     key: &KeyDescriptor,
76     access_vector: &Option<KeyPermSet>,
77 ) -> anyhow::Result<()> {
78     ThreadState::with_calling_sid(|calling_sid| {
79         permission::check_key_permission(
80             ThreadState::get_calling_uid(),
81             &calling_sid
82                 .ok_or_else(Error::sys)
83                 .context("In check_key_permission: Cannot check permission without calling_sid.")?,
84             perm,
85             key,
86             access_vector,
87         )
88     })
89 }
90 
91 /// This function checks whether a given tag corresponds to the access of device identifiers.
is_device_id_attestation_tag(tag: Tag) -> bool92 pub fn is_device_id_attestation_tag(tag: Tag) -> bool {
93     matches!(
94         tag,
95         Tag::ATTESTATION_ID_IMEI
96             | Tag::ATTESTATION_ID_MEID
97             | Tag::ATTESTATION_ID_SERIAL
98             | Tag::DEVICE_UNIQUE_ATTESTATION
99     )
100 }
101 
102 /// This function checks whether the calling app has the Android permissions needed to attest device
103 /// identifiers. It throws an error if the permissions cannot be verified, or if the caller doesn't
104 /// have the right permissions, and returns silently otherwise.
check_device_attestation_permissions() -> anyhow::Result<()>105 pub fn check_device_attestation_permissions() -> anyhow::Result<()> {
106     let permission_controller: binder::Strong<dyn IPermissionController::IPermissionController> =
107         binder::get_interface("permission")?;
108 
109     let binder_result = {
110         let _wp = watchdog::watch_millis(
111             "In check_device_attestation_permissions: calling checkPermission.",
112             500,
113         );
114         permission_controller.checkPermission(
115             "android.permission.READ_PRIVILEGED_PHONE_STATE",
116             ThreadState::get_calling_pid(),
117             ThreadState::get_calling_uid() as i32,
118         )
119     };
120     let has_permissions = map_binder_status(binder_result)
121         .context("In check_device_attestation_permissions: checkPermission failed")?;
122     match has_permissions {
123         true => Ok(()),
124         false => Err(Error::Km(ErrorCode::CANNOT_ATTEST_IDS)).context(concat!(
125             "In check_device_attestation_permissions: ",
126             "caller does not have the permission to attest device IDs"
127         )),
128     }
129 }
130 
131 /// Thread safe wrapper around SpIBinder. It is safe to have SpIBinder smart pointers to the
132 /// same object in multiple threads, but cloning a SpIBinder is not thread safe.
133 /// Keystore frequently hands out binder tokens to the security level interface. If this
134 /// is to happen from a multi threaded thread pool, the SpIBinder needs to be protected by a
135 /// Mutex.
136 #[derive(Debug)]
137 pub struct Asp(Mutex<SpIBinder>);
138 
139 impl Asp {
140     /// Creates a new instance owning a SpIBinder wrapped in a Mutex.
new(i: SpIBinder) -> Self141     pub fn new(i: SpIBinder) -> Self {
142         Self(Mutex::new(i))
143     }
144 
145     /// Clones the owned SpIBinder and attempts to convert it into the requested interface.
get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<binder::Strong<T>>146     pub fn get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<binder::Strong<T>> {
147         // We can use unwrap here because we never panic when locked, so the mutex
148         // can never be poisoned.
149         let lock = self.0.lock().unwrap();
150         (*lock)
151             .clone()
152             .into_interface()
153             .map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
154     }
155 }
156 
157 impl Clone for Asp {
clone(&self) -> Self158     fn clone(&self) -> Self {
159         let lock = self.0.lock().unwrap();
160         Self(Mutex::new((*lock).clone()))
161     }
162 }
163 
164 /// Converts a set of key characteristics as returned from KeyMint into the internal
165 /// representation of the keystore service.
key_characteristics_to_internal( key_characteristics: Vec<KeyCharacteristics>, ) -> Vec<crate::key_parameter::KeyParameter>166 pub fn key_characteristics_to_internal(
167     key_characteristics: Vec<KeyCharacteristics>,
168 ) -> Vec<crate::key_parameter::KeyParameter> {
169     key_characteristics
170         .into_iter()
171         .flat_map(|aidl_key_char| {
172             let sec_level = aidl_key_char.securityLevel;
173             aidl_key_char.authorizations.into_iter().map(move |aidl_kp| {
174                 crate::key_parameter::KeyParameter::new(aidl_kp.into(), sec_level)
175             })
176         })
177         .collect()
178 }
179 
180 /// Converts a set of key characteristics from the internal representation into a set of
181 /// Authorizations as they are used to convey key characteristics to the clients of keystore.
key_parameters_to_authorizations( parameters: Vec<crate::key_parameter::KeyParameter>, ) -> Vec<Authorization>182 pub fn key_parameters_to_authorizations(
183     parameters: Vec<crate::key_parameter::KeyParameter>,
184 ) -> Vec<Authorization> {
185     parameters.into_iter().map(|p| p.into_authorization()).collect()
186 }
187 
188 /// This returns the current time (in milliseconds) as an instance of a monotonic clock,
189 /// by invoking the system call since Rust does not support getting monotonic time instance
190 /// as an integer.
get_current_time_in_milliseconds() -> i64191 pub fn get_current_time_in_milliseconds() -> i64 {
192     let mut current_time = libc::timespec { tv_sec: 0, tv_nsec: 0 };
193     // Following unsafe block includes one system call to get monotonic time.
194     // Therefore, it is not considered harmful.
195     unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_RAW, &mut current_time) };
196     current_time.tv_sec as i64 * 1000 + (current_time.tv_nsec as i64 / 1_000_000)
197 }
198 
199 /// Converts a response code as returned by the Android Protected Confirmation HIDL compatibility
200 /// module (keystore2_apc_compat) into a ResponseCode as defined by the APC AIDL
201 /// (android.security.apc) spec.
compat_2_response_code(rc: u32) -> ApcResponseCode202 pub fn compat_2_response_code(rc: u32) -> ApcResponseCode {
203     match rc {
204         APC_COMPAT_ERROR_OK => ApcResponseCode::OK,
205         APC_COMPAT_ERROR_CANCELLED => ApcResponseCode::CANCELLED,
206         APC_COMPAT_ERROR_ABORTED => ApcResponseCode::ABORTED,
207         APC_COMPAT_ERROR_OPERATION_PENDING => ApcResponseCode::OPERATION_PENDING,
208         APC_COMPAT_ERROR_IGNORED => ApcResponseCode::IGNORED,
209         APC_COMPAT_ERROR_SYSTEM_ERROR => ApcResponseCode::SYSTEM_ERROR,
210         _ => ApcResponseCode::SYSTEM_ERROR,
211     }
212 }
213 
214 /// Converts the UI Options flags as defined by the APC AIDL (android.security.apc) spec into
215 /// UI Options flags as defined by the Android Protected Confirmation HIDL compatibility
216 /// module (keystore2_apc_compat).
ui_opts_2_compat(opt: i32) -> ApcCompatUiOptions217 pub fn ui_opts_2_compat(opt: i32) -> ApcCompatUiOptions {
218     ApcCompatUiOptions {
219         inverted: (opt & FLAG_UI_OPTION_INVERTED) != 0,
220         magnified: (opt & FLAG_UI_OPTION_MAGNIFIED) != 0,
221     }
222 }
223 
224 /// AID offset for uid space partitioning.
225 pub const AID_USER_OFFSET: u32 = cutils_bindgen::AID_USER_OFFSET;
226 
227 /// AID of the keystore process itself, used for keys that
228 /// keystore generates for its own use.
229 pub const AID_KEYSTORE: u32 = cutils_bindgen::AID_KEYSTORE;
230 
231 /// Extracts the android user from the given uid.
uid_to_android_user(uid: u32) -> u32232 pub fn uid_to_android_user(uid: u32) -> u32 {
233     // Safety: No memory access
234     unsafe { cutils_bindgen::multiuser_get_user_id(uid) }
235 }
236 
237 /// This module provides helpers for simplified use of the watchdog module.
238 #[cfg(feature = "watchdog")]
239 pub mod watchdog {
240     pub use crate::watchdog::WatchPoint;
241     use crate::watchdog::Watchdog;
242     use lazy_static::lazy_static;
243     use std::sync::Arc;
244     use std::time::Duration;
245 
246     lazy_static! {
247         /// A Watchdog thread, that can be used to create watch points.
248         static ref WD: Arc<Watchdog> = Watchdog::new(Duration::from_secs(10));
249     }
250 
251     /// Sets a watch point with `id` and a timeout of `millis` milliseconds.
watch_millis(id: &'static str, millis: u64) -> Option<WatchPoint>252     pub fn watch_millis(id: &'static str, millis: u64) -> Option<WatchPoint> {
253         Watchdog::watch(&WD, id, Duration::from_millis(millis))
254     }
255 
256     /// Like `watch_millis` but with a callback that is called every time a report
257     /// is printed about this watch point.
watch_millis_with( id: &'static str, millis: u64, callback: impl Fn() -> String + Send + 'static, ) -> Option<WatchPoint>258     pub fn watch_millis_with(
259         id: &'static str,
260         millis: u64,
261         callback: impl Fn() -> String + Send + 'static,
262     ) -> Option<WatchPoint> {
263         Watchdog::watch_with(&WD, id, Duration::from_millis(millis), callback)
264     }
265 }
266 
267 /// This module provides empty/noop implementations of the watch dog utility functions.
268 #[cfg(not(feature = "watchdog"))]
269 pub mod watchdog {
270     /// Noop watch point.
271     pub struct WatchPoint();
272     /// Sets a Noop watch point.
watch_millis(_: &'static str, _: u64) -> Option<WatchPoint>273     fn watch_millis(_: &'static str, _: u64) -> Option<WatchPoint> {
274         None
275     }
276 
watch_millis_with( _: &'static str, _: u64, _: impl Fn() -> String + Send + 'static, ) -> Option<WatchPoint>277     pub fn watch_millis_with(
278         _: &'static str,
279         _: u64,
280         _: impl Fn() -> String + Send + 'static,
281     ) -> Option<WatchPoint> {
282         None
283     }
284 }
285 
286 #[cfg(test)]
287 mod tests {
288     use super::*;
289     use anyhow::Result;
290 
291     #[test]
check_device_attestation_permissions_test() -> Result<()>292     fn check_device_attestation_permissions_test() -> Result<()> {
293         check_device_attestation_permissions().or_else(|error| {
294             match error.root_cause().downcast_ref::<Error>() {
295                 // Expected: the context for this test might not be allowed to attest device IDs.
296                 Some(Error::Km(ErrorCode::CANNOT_ATTEST_IDS)) => Ok(()),
297                 // Other errors are unexpected
298                 _ => Err(error),
299             }
300         })
301     }
302 }
303