| // Copyright 2020, The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // TODO remove when fully implemented. |
| #![allow(unused_variables)] |
| |
| //! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0 |
| //! AIDL spec. |
| |
| use crate::database::{KeyEntry, KeyEntryLoadBits, SubComponentType}; |
| use crate::error::{self, map_or_log_err, ErrorCode}; |
| use crate::globals::DB; |
| use crate::permission; |
| use crate::permission::KeyPerm; |
| use crate::security_level::KeystoreSecurityLevel; |
| use crate::utils::{check_grant_permission, check_key_permission, Asp}; |
| use android_system_keystore2::aidl::android::system::keystore2::{ |
| Certificate::Certificate, CertificateChain::CertificateChain, Domain::Domain, |
| IKeystoreSecurityLevel::IKeystoreSecurityLevel, IKeystoreService::BnKeystoreService, |
| IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor, KeyMetadata::KeyMetadata, |
| SecurityLevel::SecurityLevel, |
| }; |
| use anyhow::{anyhow, Context, Result}; |
| use binder::{IBinder, Interface, ThreadState}; |
| |
| /// Implementation of the IKeystoreService. |
| pub struct KeystoreService { |
| sec_level: Asp, |
| } |
| |
| impl KeystoreService { |
| /// Create a new instance of the Keystore 2.0 service. |
| pub fn new_native_binder() -> Result<impl IKeystoreService> { |
| let result = BnKeystoreService::new_binder(Self { |
| sec_level: Asp::new({ |
| let sec_level = |
| KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT) |
| .context("While trying to create IKeystoreSecurityLevel")?; |
| sec_level.as_binder() |
| }), |
| }); |
| result.as_binder().set_requesting_sid(true); |
| Ok(result) |
| } |
| |
| fn get_security_level( |
| &self, |
| security_level: SecurityLevel, |
| ) -> Result<Box<dyn IKeystoreSecurityLevel>> { |
| match security_level { |
| SecurityLevel::TRUSTED_ENVIRONMENT => self |
| .sec_level |
| .get_interface() |
| .context("In get_security_level: Failed to get IKeystoreSecurityLevel."), |
| _ => Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))), |
| } |
| } |
| |
| fn get_key_entry( |
| &self, |
| key: &KeyDescriptor, |
| ) -> Result<( |
| KeyMetadata, |
| Option<Certificate>, |
| Option<CertificateChain>, |
| Box<dyn IKeystoreSecurityLevel>, |
| )> { |
| let mut key_entry: KeyEntry = DB |
| .with(|db| { |
| db.borrow_mut().load_key_entry( |
| key.clone(), |
| KeyEntryLoadBits::PUBLIC, |
| ThreadState::get_calling_uid(), |
| |k, av| check_key_permission(KeyPerm::get_info(), k, &av), |
| ) |
| }) |
| .context("In get_key_entry, while trying to load key info.")?; |
| |
| let i_sec_level = match key_entry.sec_level() { |
| SecurityLevel::TRUSTED_ENVIRONMENT => self |
| .sec_level |
| .get_interface() |
| .context("In get_key_entry: Failed to get IKeystoreSecurityLevel.")?, |
| _ => return Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))), |
| }; |
| |
| Ok(( |
| KeyMetadata { |
| key: KeyDescriptor { |
| domain: Domain::KEY_ID, |
| nspace: key_entry.id(), |
| ..Default::default() |
| }, |
| securityLevel: key_entry.sec_level(), |
| // TODO add key characteristics here. |
| ..Default::default() |
| }, |
| key_entry.take_cert().map(|v| Certificate { data: v }), |
| key_entry.take_cert_chain().map(|v| CertificateChain { data: v }), |
| i_sec_level, |
| )) |
| } |
| |
| fn update_subcomponent( |
| &self, |
| key: &KeyDescriptor, |
| public_cert: Option<&Certificate>, |
| certificate_chain: Option<&CertificateChain>, |
| ) -> Result<()> { |
| DB.with::<_, Result<()>>(|db| { |
| let mut db = db.borrow_mut(); |
| let key_entry = db |
| .load_key_entry( |
| key.clone(), |
| KeyEntryLoadBits::NONE, |
| ThreadState::get_calling_uid(), |
| |k, av| { |
| check_key_permission(KeyPerm::update(), k, &av) |
| .context("In update_subcomponent.") |
| }, |
| ) |
| .context("Failed to load key_entry.")?; |
| |
| if let Some(cert) = public_cert { |
| db.insert_blob( |
| key_entry.id(), |
| SubComponentType::CERT, |
| &cert.data, |
| key_entry.sec_level(), |
| ) |
| .context("Failed to update cert subcomponent.")?; |
| } |
| |
| if let Some(cert_chain) = certificate_chain { |
| db.insert_blob( |
| key_entry.id(), |
| SubComponentType::CERT_CHAIN, |
| &cert_chain.data, |
| key_entry.sec_level(), |
| ) |
| .context("Failed to update cert chain subcomponent.")?; |
| } |
| Ok(()) |
| }) |
| .context("In update_subcomponent.") |
| } |
| |
| fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> { |
| // TODO implement. |
| Err(anyhow!(error::Error::sys())) |
| } |
| |
| fn delete_key(&self, key: &KeyDescriptor) -> Result<()> { |
| // TODO implement. |
| Err(anyhow!(error::Error::sys())) |
| } |
| |
| fn grant( |
| &self, |
| key: &KeyDescriptor, |
| grantee_uid: i32, |
| access_vector: permission::KeyPermSet, |
| ) -> Result<KeyDescriptor> { |
| DB.with(|db| { |
| db.borrow_mut().grant( |
| key.clone(), |
| ThreadState::get_calling_uid(), |
| grantee_uid as u32, |
| access_vector, |
| |k, av| check_grant_permission(*av, k).context("During grant."), |
| ) |
| }) |
| .context("In KeystoreService::grant.") |
| } |
| |
| fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> { |
| DB.with(|db| { |
| db.borrow_mut().ungrant( |
| key.clone(), |
| ThreadState::get_calling_uid(), |
| grantee_uid as u32, |
| |k| check_key_permission(KeyPerm::grant(), k, &None), |
| ) |
| }) |
| .context("In KeystoreService::ungrant.") |
| } |
| } |
| |
| impl binder::Interface for KeystoreService {} |
| |
| // Implementation of IKeystoreService. See AIDL spec at |
| // system/security/keystore2/binder/android/security/keystore2/IKeystoreService.aidl |
| impl IKeystoreService for KeystoreService { |
| fn getSecurityLevel( |
| &self, |
| security_level: SecurityLevel, |
| ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> { |
| map_or_log_err(self.get_security_level(security_level), Ok) |
| } |
| fn getKeyEntry( |
| &self, |
| key: &KeyDescriptor, |
| metadata: &mut KeyMetadata, |
| public_cert: &mut Option<Certificate>, |
| certificate_chain: &mut Option<CertificateChain>, |
| ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> { |
| map_or_log_err(self.get_key_entry(key), |v| { |
| *metadata = v.0; |
| *public_cert = v.1; |
| *certificate_chain = v.2; |
| Ok(v.3) |
| }) |
| } |
| fn updateSubcomponent( |
| &self, |
| key: &KeyDescriptor, |
| public_cert: Option<&Certificate>, |
| certificate_chain: Option<&CertificateChain>, |
| ) -> binder::public_api::Result<()> { |
| map_or_log_err(self.update_subcomponent(key, public_cert, certificate_chain), Ok) |
| } |
| fn listEntries( |
| &self, |
| domain: Domain, |
| namespace: i64, |
| ) -> binder::public_api::Result<Vec<KeyDescriptor>> { |
| map_or_log_err(self.list_entries(domain, namespace), Ok) |
| } |
| fn deleteKey(&self, key: &KeyDescriptor) -> binder::public_api::Result<()> { |
| map_or_log_err(self.delete_key(key), Ok) |
| } |
| fn grant( |
| &self, |
| key: &KeyDescriptor, |
| grantee_uid: i32, |
| access_vector: i32, |
| ) -> binder::public_api::Result<KeyDescriptor> { |
| map_or_log_err(self.grant(key, grantee_uid, access_vector.into()), Ok) |
| } |
| fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> binder::public_api::Result<()> { |
| map_or_log_err(self.ungrant(key, grantee_uid), Ok) |
| } |
| } |