Keystore 2.0: Revise GC.
* Store GC relevant information with blobs.
* Marking a key unreferenced now deletes the main key entry and all
associated artifacts from the database except the blobs and their
associated metadata, which is left to the GC.
* The GC is now automatically called by the DB module and it is now
modular enough to use local test GC.
Test: keystore2_test
Change-Id: Iaf9e851d2895c8c457d160052fcab7f8d20e6555
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 417e3c5..c2170b6 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -16,7 +16,7 @@
//! This crate implements the IKeystoreSecurityLevel interface.
-use crate::{database::Uuid, gc::Gc, globals::get_keymint_device};
+use crate::globals::get_keymint_device;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, HardwareAuthenticatorType::HardwareAuthenticatorType,
IKeyMintDevice::IKeyMintDevice, KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat,
@@ -36,17 +36,17 @@
use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
use crate::utils::{check_key_permission, uid_to_android_user, Asp};
use crate::{
- database::{CertificateInfo, KeyIdGuard},
- globals::DB,
-};
-use crate::{
- database::{DateTime, KeyMetaData, KeyMetaEntry, KeyType},
+ database::{
+ BlobMetaData, BlobMetaEntry, DateTime, KeyEntry, KeyEntryLoadBits, KeyMetaData,
+ KeyMetaEntry, KeyType, SubComponentType, Uuid,
+ },
+ operation::KeystoreOperation,
+ operation::OperationDb,
permission::KeyPerm,
};
use crate::{
- database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
- operation::KeystoreOperation,
- operation::OperationDb,
+ database::{CertificateInfo, KeyIdGuard},
+ globals::DB,
};
use crate::{
error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
@@ -138,23 +138,22 @@
}
_ => DB
.with::<_, Result<KeyDescriptor>>(|db| {
- let mut metadata = KeyMetaData::new();
- metadata.add(KeyMetaEntry::CreationDate(creation_date));
+ let mut key_metadata = KeyMetaData::new();
+ key_metadata.add(KeyMetaEntry::CreationDate(creation_date));
+ let mut blob_metadata = BlobMetaData::new();
+ blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
let mut db = db.borrow_mut();
- let (need_gc, key_id) = db
+ let key_id = db
.store_new_key(
&key,
&key_parameters,
- &key_blob,
+ &(&key_blob, &blob_metadata),
&cert_info,
- &metadata,
+ &key_metadata,
&self.km_uuid,
)
.context("In store_new_key.")?;
- if need_gc {
- Gc::notify_gc();
- }
Ok(KeyDescriptor {
domain: Domain::KEY_ID,
nspace: key_id.id(),
@@ -185,7 +184,7 @@
// so that we can use it by reference like the blob provided by the key descriptor.
// Otherwise, we would have to clone the blob from the key descriptor.
let scoping_blob: Vec<u8>;
- let (km_blob, key_properties, key_id_guard) = match key.domain {
+ let (km_blob, key_properties, key_id_guard, blob_metadata) = match key.domain {
Domain::BLOB => {
check_key_permission(KeyPerm::use_(), key, &None)
.context("In create_operation: checking use permission for Domain::BLOB.")?;
@@ -201,6 +200,7 @@
},
None,
None,
+ None,
)
}
_ => {
@@ -215,19 +215,19 @@
)
})
.context("In create_operation: Failed to load key blob.")?;
- scoping_blob = match key_entry.take_km_blob() {
- Some(blob) => blob,
- None => {
- return Err(Error::sys()).context(concat!(
- "In create_operation: Successfully loaded key entry,",
- " but KM blob was missing."
- ))
- }
- };
+
+ let (blob, blob_metadata) =
+ key_entry.take_key_blob_info().ok_or_else(Error::sys).context(concat!(
+ "In create_operation: Successfully loaded key entry, ",
+ "but KM blob was missing."
+ ))?;
+ scoping_blob = blob;
+
(
&scoping_blob,
Some((key_id_guard.id(), key_entry.into_key_parameters())),
Some(key_id_guard),
+ Some(blob_metadata),
)
}
};
@@ -265,7 +265,7 @@
.upgrade_keyblob_if_required_with(
&*km_dev,
key_id_guard,
- &km_blob,
+ &(km_blob, blob_metadata.as_ref()),
&operation_parameters,
|blob| loop {
match map_km_error(km_dev.begin(
@@ -498,7 +498,7 @@
_ => panic!("Unreachable."),
};
- // import_wrapped_key requires the rebind permission for the new key.
+ // Import_wrapped_key requires the rebind permission for the new key.
check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
let (wrapping_key_id_guard, wrapping_key_entry) = DB
@@ -512,8 +512,8 @@
)
})
.context("Failed to load wrapping key.")?;
- let wrapping_key_blob = match wrapping_key_entry.km_blob() {
- Some(blob) => blob,
+ let (wrapping_key_blob, wrapping_blob_metadata) = match wrapping_key_entry.key_blob_info() {
+ Some((blob, metadata)) => (blob, metadata),
None => {
return Err(error::Error::sys()).context(concat!(
"No km_blob after successfully loading key.",
@@ -549,12 +549,12 @@
.upgrade_keyblob_if_required_with(
&*km_dev,
Some(wrapping_key_id_guard),
- wrapping_key_blob,
+ &(&wrapping_key_blob, Some(&wrapping_blob_metadata)),
&[],
|wrapping_blob| {
let creation_result = map_km_error(km_dev.importWrappedKey(
wrapped_data,
- wrapping_key_blob,
+ wrapping_blob,
masking_key,
¶ms,
pw_sid,
@@ -574,16 +574,16 @@
&self,
km_dev: &dyn IKeyMintDevice,
key_id_guard: Option<KeyIdGuard>,
- blob: &[u8],
+ blob_info: &(&[u8], Option<&BlobMetaData>),
params: &[KeyParameter],
f: F,
) -> Result<(T, Option<Vec<u8>>)>
where
F: Fn(&[u8]) -> Result<T, Error>,
{
- match f(blob) {
+ match f(blob_info.0) {
Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
- let upgraded_blob = map_km_error(km_dev.upgradeKey(blob, params))
+ let upgraded_blob = map_km_error(km_dev.upgradeKey(blob_info.0, params))
.context("In upgrade_keyblob_if_required_with: Upgrade failed.")?;
key_id_guard.map_or(Ok(()), |key_id_guard| {
DB.with(|db| {
@@ -591,6 +591,7 @@
&key_id_guard,
SubComponentType::KEY_BLOB,
Some(&upgraded_blob),
+ blob_info.1,
)
})
.context(concat!(