Add Keystore 2.0 service.
This patch adds a boilerplate Keystore 2.0 service. It is configured to
run on the device but does not provide any useful service yet.
It provides basic functionality for generating, importing and using
keys, but it still lacks full Keystore functionality.
Test: VtsKeystore2V1_0TargetTest (in followup CL)
Bug: 160623310
Bug: 160930114
Bug: 160930117
Bug: 160930331
Bug: 159465122
Change-Id: I7dfa2f2f63f4da3af620aff2ec99c0cba3bda6fd
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
new file mode 100644
index 0000000..ea17766
--- /dev/null
+++ b/keystore2/src/service.rs
@@ -0,0 +1,254 @@
+// 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)
+ }
+}