blob: 8d3b66e2cff8b9fe7c9c0dc615f3ffd08adec050 [file] [log] [blame]
Janis Danisevskis1af91262020-08-10 14:58:08 -07001// 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
Janis Danisevskis1af91262020-08-10 14:58:08 -070015//! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0
16//! AIDL spec.
17
Max Bires8e93d2b2021-01-14 13:17:59 -080018use std::collections::HashMap;
19
Janis Danisevskise92a5e62020-12-02 12:57:41 -080020use crate::permission::{KeyPerm, KeystorePerm};
Janis Danisevskis1af91262020-08-10 14:58:08 -070021use crate::security_level::KeystoreSecurityLevel;
Janis Danisevskis04b02832020-10-26 09:21:40 -070022use crate::utils::{
Janis Danisevskise92a5e62020-12-02 12:57:41 -080023 check_grant_permission, check_key_permission, check_keystore_permission,
24 key_parameters_to_authorizations, Asp,
Janis Danisevskis04b02832020-10-26 09:21:40 -070025};
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +000026use crate::{
27 database::Uuid,
28 globals::{create_thread_local_db, DB, LEGACY_BLOB_LOADER, LEGACY_MIGRATOR},
29};
Max Bires8e93d2b2021-01-14 13:17:59 -080030use crate::{database::KEYSTORE_UUID, permission};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080031use crate::{
32 database::{KeyEntryLoadBits, KeyType, SubComponentType},
33 error::ResponseCode,
34};
Janis Danisevskis5cb52dc2021-04-07 16:31:18 -070035use crate::{
36 error::{self, map_or_log_err, ErrorCode},
37 id_rotation::IdRotationState,
38};
Shawn Willden708744a2020-12-11 13:05:27 +000039use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
Andrew Walbrande45c8b2021-04-13 14:42:38 +000040use android_hardware_security_keymint::binder::{BinderFeatures, Strong, ThreadState};
Janis Danisevskis1af91262020-08-10 14:58:08 -070041use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis2c7f9622020-09-30 16:30:31 -070042 Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
43 IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
44 KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
Janis Danisevskis1af91262020-08-10 14:58:08 -070045};
Max Bires8e93d2b2021-01-14 13:17:59 -080046use anyhow::{Context, Result};
Janis Danisevskise92a5e62020-12-02 12:57:41 -080047use error::Error;
48use keystore2_selinux as selinux;
Janis Danisevskis1af91262020-08-10 14:58:08 -070049
50/// Implementation of the IKeystoreService.
Max Bires8e93d2b2021-01-14 13:17:59 -080051#[derive(Default)]
Janis Danisevskis1af91262020-08-10 14:58:08 -070052pub struct KeystoreService {
Max Bires8e93d2b2021-01-14 13:17:59 -080053 i_sec_level_by_uuid: HashMap<Uuid, Asp>,
54 uuid_by_sec_level: HashMap<SecurityLevel, Uuid>,
Janis Danisevskis1af91262020-08-10 14:58:08 -070055}
56
57impl KeystoreService {
58 /// Create a new instance of the Keystore 2.0 service.
Janis Danisevskis5cb52dc2021-04-07 16:31:18 -070059 pub fn new_native_binder(
60 id_rotation_state: IdRotationState,
61 ) -> Result<Strong<dyn IKeystoreService>> {
Max Bires8e93d2b2021-01-14 13:17:59 -080062 let mut result: Self = Default::default();
Janis Danisevskis5cb52dc2021-04-07 16:31:18 -070063 let (dev, uuid) = KeystoreSecurityLevel::new_native_binder(
64 SecurityLevel::TRUSTED_ENVIRONMENT,
65 id_rotation_state.clone(),
66 )
67 .context(concat!(
68 "In KeystoreService::new_native_binder: ",
69 "Trying to construct mandatory security level TEE."
70 ))
71 .map(|(dev, uuid)| (Asp::new(dev.as_binder()), uuid))?;
Max Bires8e93d2b2021-01-14 13:17:59 -080072 result.i_sec_level_by_uuid.insert(uuid, dev);
73 result.uuid_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, uuid);
Janis Danisevskisba998992020-12-29 16:08:40 -080074
Max Bires8e93d2b2021-01-14 13:17:59 -080075 // Strongbox is optional, so we ignore errors and turn the result into an Option.
Janis Danisevskis5cb52dc2021-04-07 16:31:18 -070076 if let Ok((dev, uuid)) =
77 KeystoreSecurityLevel::new_native_binder(SecurityLevel::STRONGBOX, id_rotation_state)
78 .map(|(dev, uuid)| (Asp::new(dev.as_binder()), uuid))
Max Bires8e93d2b2021-01-14 13:17:59 -080079 {
80 result.i_sec_level_by_uuid.insert(uuid, dev);
81 result.uuid_by_sec_level.insert(SecurityLevel::STRONGBOX, uuid);
82 }
83
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +000084 let uuid_by_sec_level = result.uuid_by_sec_level.clone();
85 LEGACY_MIGRATOR
86 .set_init(move || {
87 (create_thread_local_db(), uuid_by_sec_level, LEGACY_BLOB_LOADER.clone())
88 })
89 .context(
90 "In KeystoreService::new_native_binder: Trying to initialize the legacy migrator.",
91 )?;
92
Andrew Walbrande45c8b2021-04-13 14:42:38 +000093 Ok(BnKeystoreService::new_binder(
94 result,
95 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
96 ))
Janis Danisevskis1af91262020-08-10 14:58:08 -070097 }
98
Max Bires8e93d2b2021-01-14 13:17:59 -080099 fn uuid_to_sec_level(&self, uuid: &Uuid) -> SecurityLevel {
100 self.uuid_by_sec_level
101 .iter()
102 .find(|(_, v)| **v == *uuid)
103 .map(|(s, _)| *s)
104 .unwrap_or(SecurityLevel::SOFTWARE)
105 }
106
Stephen Crane221bbb52020-12-16 15:52:10 -0800107 fn get_i_sec_level_by_uuid(&self, uuid: &Uuid) -> Result<Strong<dyn IKeystoreSecurityLevel>> {
Max Bires8e93d2b2021-01-14 13:17:59 -0800108 if let Some(dev) = self.i_sec_level_by_uuid.get(uuid) {
109 dev.get_interface().context("In get_i_sec_level_by_uuid.")
110 } else {
111 Err(error::Error::sys())
112 .context("In get_i_sec_level_by_uuid: KeyMint instance for key not found.")
113 }
Janis Danisevskisba998992020-12-29 16:08:40 -0800114 }
115
Janis Danisevskis1af91262020-08-10 14:58:08 -0700116 fn get_security_level(
117 &self,
Max Bires8e93d2b2021-01-14 13:17:59 -0800118 sec_level: SecurityLevel,
Stephen Crane221bbb52020-12-16 15:52:10 -0800119 ) -> Result<Strong<dyn IKeystoreSecurityLevel>> {
Max Bires8e93d2b2021-01-14 13:17:59 -0800120 if let Some(dev) = self
121 .uuid_by_sec_level
122 .get(&sec_level)
123 .and_then(|uuid| self.i_sec_level_by_uuid.get(uuid))
124 {
125 dev.get_interface().context("In get_security_level.")
126 } else {
127 Err(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
128 .context("In get_security_level: No such security level.")
129 }
Janis Danisevskis1af91262020-08-10 14:58:08 -0700130 }
131
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700132 fn get_key_entry(&self, key: &KeyDescriptor) -> Result<KeyEntryResponse> {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000133 let caller_uid = ThreadState::get_calling_uid();
Janis Danisevskisaec14592020-11-12 09:41:49 -0800134 let (key_id_guard, mut key_entry) = DB
Janis Danisevskis1af91262020-08-10 14:58:08 -0700135 .with(|db| {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000136 LEGACY_MIGRATOR.with_try_migrate(&key, caller_uid, || {
137 db.borrow_mut().load_key_entry(
138 &key,
139 KeyType::Client,
140 KeyEntryLoadBits::PUBLIC,
141 caller_uid,
142 |k, av| check_key_permission(KeyPerm::get_info(), k, &av),
143 )
144 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700145 })
146 .context("In get_key_entry, while trying to load key info.")?;
147
Janis Danisevskis377d1002021-01-27 19:07:48 -0800148 let i_sec_level = if !key_entry.pure_cert() {
149 Some(
Max Bires8e93d2b2021-01-14 13:17:59 -0800150 self.get_i_sec_level_by_uuid(key_entry.km_uuid())
151 .context("In get_key_entry: Trying to get security level proxy.")?,
Janis Danisevskis377d1002021-01-27 19:07:48 -0800152 )
153 } else {
154 None
155 };
Janis Danisevskis1af91262020-08-10 14:58:08 -0700156
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700157 Ok(KeyEntryResponse {
Janis Danisevskis377d1002021-01-27 19:07:48 -0800158 iSecurityLevel: i_sec_level,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700159 metadata: KeyMetadata {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700160 key: KeyDescriptor {
161 domain: Domain::KEY_ID,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800162 nspace: key_id_guard.id(),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700163 ..Default::default()
164 },
Max Bires8e93d2b2021-01-14 13:17:59 -0800165 keySecurityLevel: self.uuid_to_sec_level(key_entry.km_uuid()),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700166 certificate: key_entry.take_cert(),
167 certificateChain: key_entry.take_cert_chain(),
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800168 modificationTimeMs: key_entry
169 .metadata()
170 .creation_date()
171 .map(|d| d.to_millis_epoch())
172 .ok_or(Error::Rc(ResponseCode::VALUE_CORRUPTED))
173 .context("In get_key_entry: Trying to get creation date.")?,
Janis Danisevskis04b02832020-10-26 09:21:40 -0700174 authorizations: key_parameters_to_authorizations(key_entry.into_key_parameters()),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700175 },
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700176 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700177 }
178
179 fn update_subcomponent(
180 &self,
181 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700182 public_cert: Option<&[u8]>,
183 certificate_chain: Option<&[u8]>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700184 ) -> Result<()> {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000185 let caller_uid = ThreadState::get_calling_uid();
Janis Danisevskis1af91262020-08-10 14:58:08 -0700186 DB.with::<_, Result<()>>(|db| {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000187 let entry = match LEGACY_MIGRATOR.with_try_migrate(&key, caller_uid, || {
188 db.borrow_mut().load_key_entry(
189 &key,
190 KeyType::Client,
191 KeyEntryLoadBits::NONE,
192 caller_uid,
193 |k, av| {
194 check_key_permission(KeyPerm::update(), k, &av)
195 .context("In update_subcomponent.")
196 },
197 )
198 }) {
Janis Danisevskis377d1002021-01-27 19:07:48 -0800199 Err(e) => match e.root_cause().downcast_ref::<Error>() {
200 Some(Error::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None),
201 _ => Err(e),
202 },
203 Ok(v) => Ok(Some(v)),
204 }
205 .context("Failed to load key entry.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700206
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000207 let mut db = db.borrow_mut();
Paul Crowleyd5653e52021-03-25 09:46:31 -0700208 if let Some((key_id_guard, _key_entry)) = entry {
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800209 db.set_blob(&key_id_guard, SubComponentType::CERT, public_cert, None)
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700210 .context("Failed to update cert subcomponent.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -0800211
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800212 db.set_blob(&key_id_guard, SubComponentType::CERT_CHAIN, certificate_chain, None)
Janis Danisevskis377d1002021-01-27 19:07:48 -0800213 .context("Failed to update cert chain subcomponent.")?;
214 return Ok(());
Janis Danisevskis1af91262020-08-10 14:58:08 -0700215 }
216
Janis Danisevskis377d1002021-01-27 19:07:48 -0800217 // If we reach this point we have to check the special condition where a certificate
218 // entry may be made.
219 if !(public_cert.is_none() && certificate_chain.is_some()) {
220 return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND)).context("No key to update.");
Janis Danisevskis1af91262020-08-10 14:58:08 -0700221 }
Janis Danisevskis377d1002021-01-27 19:07:48 -0800222
223 // So we know that we have a certificate chain and no public cert.
224 // Now check that we have everything we need to make a new certificate entry.
225 let key = match (key.domain, &key.alias) {
226 (Domain::APP, Some(ref alias)) => KeyDescriptor {
227 domain: Domain::APP,
228 nspace: ThreadState::get_calling_uid() as i64,
229 alias: Some(alias.clone()),
230 blob: None,
231 },
232 (Domain::SELINUX, Some(_)) => key.clone(),
233 _ => {
234 return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
235 .context("Domain must be APP or SELINUX to insert a certificate.")
236 }
237 };
238
239 // Security critical: This must return on failure. Do not remove the `?`;
240 check_key_permission(KeyPerm::rebind(), &key, &None)
241 .context("Caller does not have permission to insert this certificate.")?;
242
Janis Danisevskis66784c42021-01-27 08:40:25 -0800243 db.store_new_certificate(&key, certificate_chain.unwrap(), &KEYSTORE_UUID)
Janis Danisevskis377d1002021-01-27 19:07:48 -0800244 .context("Failed to insert new certificate.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700245 Ok(())
246 })
247 .context("In update_subcomponent.")
248 }
249
250 fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800251 let mut k = match domain {
252 Domain::APP => KeyDescriptor {
253 domain,
254 nspace: ThreadState::get_calling_uid() as u64 as i64,
255 ..Default::default()
256 },
257 Domain::SELINUX => KeyDescriptor{domain, nspace: namespace, ..Default::default()},
258 _ => return Err(Error::perm()).context(
259 "In list_entries: List entries is only supported for Domain::APP and Domain::SELINUX."
260 ),
261 };
262
263 // First we check if the caller has the info permission for the selected domain/namespace.
264 // By default we use the calling uid as namespace if domain is Domain::APP.
265 // If the first check fails we check if the caller has the list permission allowing to list
266 // any namespace. In that case we also adjust the queried namespace if a specific uid was
267 // selected.
268 match check_key_permission(KeyPerm::get_info(), &k, &None) {
269 Err(e) => {
270 if let Some(selinux::Error::PermissionDenied) =
271 e.root_cause().downcast_ref::<selinux::Error>()
272 {
273 check_keystore_permission(KeystorePerm::list())
274 .context("In list_entries: While checking keystore permission.")?;
275 if namespace != -1 {
276 k.nspace = namespace;
277 }
278 } else {
279 return Err(e).context("In list_entries: While checking key permission.")?;
280 }
281 }
282 Ok(()) => {}
283 };
284
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000285 let mut result = LEGACY_MIGRATOR
286 .list_uid(k.domain, k.nspace)
287 .context("In list_entries: Trying to list legacy keys.")?;
288
289 result.append(
290 &mut DB
291 .with(|db| {
292 let mut db = db.borrow_mut();
293 db.list(k.domain, k.nspace)
294 })
295 .context("In list_entries: Trying to list keystore database.")?,
296 );
297
298 result.sort_unstable();
299 result.dedup();
300 Ok(result)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700301 }
302
303 fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800304 let caller_uid = ThreadState::get_calling_uid();
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800305 DB.with(|db| {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000306 LEGACY_MIGRATOR.with_try_migrate(&key, caller_uid, || {
307 db.borrow_mut().unbind_key(&key, KeyType::Client, caller_uid, |k, av| {
308 check_key_permission(KeyPerm::delete(), k, &av).context("During delete_key.")
309 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800310 })
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800311 })
312 .context("In delete_key: Trying to unbind the key.")?;
Janis Danisevskisa51ccbc2020-11-25 21:04:24 -0800313 Ok(())
Janis Danisevskis1af91262020-08-10 14:58:08 -0700314 }
315
316 fn grant(
317 &self,
318 key: &KeyDescriptor,
319 grantee_uid: i32,
320 access_vector: permission::KeyPermSet,
321 ) -> Result<KeyDescriptor> {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000322 let caller_uid = ThreadState::get_calling_uid();
Janis Danisevskis1af91262020-08-10 14:58:08 -0700323 DB.with(|db| {
Hasini Gunasinghe3ed5da72021-02-04 15:18:54 +0000324 LEGACY_MIGRATOR.with_try_migrate(&key, caller_uid, || {
325 db.borrow_mut().grant(
326 &key,
327 caller_uid,
328 grantee_uid as u32,
329 access_vector,
330 |k, av| check_grant_permission(*av, k).context("During grant."),
331 )
332 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700333 })
334 .context("In KeystoreService::grant.")
335 }
336
337 fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> {
338 DB.with(|db| {
Janis Danisevskis66784c42021-01-27 08:40:25 -0800339 db.borrow_mut().ungrant(&key, ThreadState::get_calling_uid(), grantee_uid as u32, |k| {
340 check_key_permission(KeyPerm::grant(), k, &None)
341 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700342 })
343 .context("In KeystoreService::ungrant.")
344 }
345}
346
347impl binder::Interface for KeystoreService {}
348
349// Implementation of IKeystoreService. See AIDL spec at
350// system/security/keystore2/binder/android/security/keystore2/IKeystoreService.aidl
351impl IKeystoreService for KeystoreService {
352 fn getSecurityLevel(
353 &self,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700354 security_level: SecurityLevel,
Stephen Crane221bbb52020-12-16 15:52:10 -0800355 ) -> binder::public_api::Result<Strong<dyn IKeystoreSecurityLevel>> {
Max Bires8e93d2b2021-01-14 13:17:59 -0800356 map_or_log_err(self.get_security_level(security_level), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700357 }
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700358 fn getKeyEntry(&self, key: &KeyDescriptor) -> binder::public_api::Result<KeyEntryResponse> {
359 map_or_log_err(self.get_key_entry(key), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700360 }
361 fn updateSubcomponent(
362 &self,
363 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700364 public_cert: Option<&[u8]>,
365 certificate_chain: Option<&[u8]>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700366 ) -> binder::public_api::Result<()> {
367 map_or_log_err(self.update_subcomponent(key, public_cert, certificate_chain), Ok)
368 }
369 fn listEntries(
370 &self,
371 domain: Domain,
372 namespace: i64,
373 ) -> binder::public_api::Result<Vec<KeyDescriptor>> {
374 map_or_log_err(self.list_entries(domain, namespace), Ok)
375 }
376 fn deleteKey(&self, key: &KeyDescriptor) -> binder::public_api::Result<()> {
377 map_or_log_err(self.delete_key(key), Ok)
378 }
379 fn grant(
380 &self,
381 key: &KeyDescriptor,
382 grantee_uid: i32,
383 access_vector: i32,
384 ) -> binder::public_api::Result<KeyDescriptor> {
385 map_or_log_err(self.grant(key, grantee_uid, access_vector.into()), Ok)
386 }
387 fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> binder::public_api::Result<()> {
388 map_or_log_err(self.ungrant(key, grantee_uid), Ok)
389 }
390}