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