keystore: Remove dead code
Attestation keys are now managed by RKPD. Remove support for attestation
keys in keystore DB.
Test: keystore2_test
Change-Id: Iad7d9297701364eba44bcc60b564c7c7e12b9aea
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 6108221..d7c939c 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -46,11 +46,9 @@
mod versioning;
use crate::gc::Gc;
-use crate::globals::get_keymint_dev_by_uuid;
use crate::impl_metadata; // This is in db_utils.rs
use crate::key_parameter::{KeyParameter, Tag};
use crate::ks_err;
-use crate::metrics_store::log_rkp_error_stats;
use crate::permission::KeyPermSet;
use crate::utils::{get_current_time_in_milliseconds, watchdog as wd, AID_USER_OFFSET};
use crate::{
@@ -67,8 +65,7 @@
SecurityLevel::SecurityLevel,
};
use android_security_metrics::aidl::android::security::metrics::{
- RkpError::RkpError as MetricsRkpError, Storage::Storage as MetricsStorage,
- StorageStats::StorageStats,
+ Storage::Storage as MetricsStorage, StorageStats::StorageStats,
};
use android_system_keystore2::aidl::android::system::keystore2::{
Domain::Domain, KeyDescriptor::KeyDescriptor,
@@ -252,8 +249,6 @@
/// This is a super key type. These keys are created by keystore itself and used to encrypt
/// other key blobs to provide LSKF binding.
Super,
- /// This is an attestation key. These keys are created by the remote provisioning mechanism.
- Attestation,
}
impl ToSql for KeyType {
@@ -261,7 +256,6 @@
Ok(ToSqlOutput::Owned(Value::Integer(match self {
KeyType::Client => 0,
KeyType::Super => 1,
- KeyType::Attestation => 2,
})))
}
}
@@ -271,7 +265,6 @@
match i64::column_result(value)? {
0 => Ok(KeyType::Client),
1 => Ok(KeyType::Super),
- 2 => Ok(KeyType::Attestation),
v => Err(FromSqlError::OutOfRange(v)),
}
}
@@ -321,8 +314,6 @@
0x41, 0xe3, 0xb9, 0xce, 0x27, 0x58, 0x4e, 0x91, 0xbc, 0xfd, 0xa5, 0x5d, 0x91, 0x85, 0xab, 0x11,
]);
-static EXPIRATION_BUFFER_MS: i64 = 12 * 60 * 60 * 1000;
-
/// Indicates how the sensitive part of this key blob is encrypted.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum EncryptedBy {
@@ -1561,48 +1552,6 @@
))
}
- /// Creates a new attestation key entry and allocates a new randomized id for the new key.
- /// The key id gets associated with a domain and namespace later but not with an alias. The
- /// alias will be used to denote if a key has been signed as each key can only be bound to one
- /// domain and namespace pairing so there is no need to use them as a value for indexing into
- /// a key.
- pub fn create_attestation_key_entry(
- &mut self,
- maced_public_key: &[u8],
- raw_public_key: &[u8],
- private_key: &[u8],
- km_uuid: &Uuid,
- ) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::create_attestation_key_entry", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let key_id = KEY_ID_LOCK.get(
- Self::insert_with_retry(|id| {
- tx.execute(
- "INSERT into persistent.keyentry
- (id, key_type, domain, namespace, alias, state, km_uuid)
- VALUES(?, ?, NULL, NULL, NULL, ?, ?);",
- params![id, KeyType::Attestation, KeyLifeCycle::Live, km_uuid],
- )
- })
- .context(ks_err!())?,
- );
- Self::set_blob_internal(
- tx,
- key_id.0,
- SubComponentType::KEY_BLOB,
- Some(private_key),
- None,
- )?;
- let mut metadata = KeyMetaData::new();
- metadata.add(KeyMetaEntry::AttestationMacedPublicKey(maced_public_key.to_vec()));
- metadata.add(KeyMetaEntry::AttestationRawPubKey(raw_public_key.to_vec()));
- metadata.store_in_db(key_id.0, tx)?;
- Ok(()).no_gc()
- })
- .context(ks_err!())
- }
-
/// Set a new blob and associates it with the given key id. Each blob
/// has a sub component type.
/// Each key can have one of each sub component type associated. If more
@@ -1730,375 +1679,6 @@
.context(ks_err!())
}
- /// Stores a signed certificate chain signed by a remote provisioning server, keyed
- /// on the public key.
- pub fn store_signed_attestation_certificate_chain(
- &mut self,
- raw_public_key: &[u8],
- batch_cert: &[u8],
- cert_chain: &[u8],
- expiration_date: i64,
- km_uuid: &Uuid,
- ) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::store_signed_attestation_certificate_chain", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let mut stmt = tx
- .prepare(
- "SELECT keyentryid
- FROM persistent.keymetadata
- WHERE tag = ? AND data = ? AND keyentryid IN
- (SELECT id
- FROM persistent.keyentry
- WHERE
- alias IS NULL AND
- domain IS NULL AND
- namespace IS NULL AND
- key_type = ? AND
- km_uuid = ?);",
- )
- .context("Failed to store attestation certificate chain.")?;
- let mut rows = stmt
- .query(params![
- KeyMetaData::AttestationRawPubKey,
- raw_public_key,
- KeyType::Attestation,
- km_uuid
- ])
- .context("Failed to fetch keyid")?;
- let key_id = db_utils::with_rows_extract_one(&mut rows, |row| {
- row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
- .get(0)
- .context("Failed to unpack id.")
- })
- .context("Failed to get key_id.")?;
- let num_updated = tx
- .execute(
- "UPDATE persistent.keyentry
- SET alias = ?
- WHERE id = ?;",
- params!["signed", key_id],
- )
- .context("Failed to update alias.")?;
- if num_updated != 1 {
- return Err(KsError::sys()).context("Alias not updated for the key.");
- }
- let mut metadata = KeyMetaData::new();
- metadata.add(KeyMetaEntry::AttestationExpirationDate(DateTime::from_millis_epoch(
- expiration_date,
- )));
- metadata.store_in_db(key_id, tx).context("Failed to insert key metadata.")?;
- Self::set_blob_internal(
- tx,
- key_id,
- SubComponentType::CERT_CHAIN,
- Some(cert_chain),
- None,
- )
- .context("Failed to insert cert chain")?;
- Self::set_blob_internal(tx, key_id, SubComponentType::CERT, Some(batch_cert), None)
- .context("Failed to insert cert")?;
- Ok(()).no_gc()
- })
- .context(ks_err!())
- }
-
- /// Assigns the next unassigned attestation key to a domain/namespace combo that does not
- /// currently have a key assigned to it.
- pub fn assign_attestation_key(
- &mut self,
- domain: Domain,
- namespace: i64,
- km_uuid: &Uuid,
- ) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::assign_attestation_key", 500);
-
- match domain {
- Domain::APP | Domain::SELINUX => {}
- _ => {
- return Err(KsError::sys())
- .context(ks_err!("Domain {:?} must be either App or SELinux.", domain));
- }
- }
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let result = tx
- .execute(
- "UPDATE persistent.keyentry
- SET domain=?1, namespace=?2
- WHERE
- id =
- (SELECT MIN(id)
- FROM persistent.keyentry
- WHERE ALIAS IS NOT NULL
- AND domain IS NULL
- AND key_type IS ?3
- AND state IS ?4
- AND km_uuid IS ?5)
- AND
- (SELECT COUNT(*)
- FROM persistent.keyentry
- WHERE domain=?1
- AND namespace=?2
- AND key_type IS ?3
- AND state IS ?4
- AND km_uuid IS ?5) = 0;",
- params![
- domain.0 as u32,
- namespace,
- KeyType::Attestation,
- KeyLifeCycle::Live,
- km_uuid,
- ],
- )
- .context("Failed to assign attestation key")?;
- if result == 0 {
- let (_, hw_info) = get_keymint_dev_by_uuid(km_uuid)
- .context("Error in retrieving keymint device by UUID.")?;
- log_rkp_error_stats(MetricsRkpError::OUT_OF_KEYS, &hw_info.securityLevel);
- return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
- .context("Out of keys.");
- } else if result > 1 {
- return Err(KsError::sys())
- .context(format!("Expected to update 1 entry, instead updated {}", result));
- }
- Ok(()).no_gc()
- })
- .context(ks_err!())
- }
-
- /// Retrieves num_keys number of attestation keys that have not yet been signed by a remote
- /// provisioning server, or the maximum number available if there are not num_keys number of
- /// entries in the table.
- pub fn fetch_unsigned_attestation_keys(
- &mut self,
- num_keys: i32,
- km_uuid: &Uuid,
- ) -> Result<Vec<Vec<u8>>> {
- let _wp = wd::watch_millis("KeystoreDB::fetch_unsigned_attestation_keys", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let mut stmt = tx
- .prepare(
- "SELECT data
- FROM persistent.keymetadata
- WHERE tag = ? AND keyentryid IN
- (SELECT id
- FROM persistent.keyentry
- WHERE
- alias IS NULL AND
- domain IS NULL AND
- namespace IS NULL AND
- key_type = ? AND
- km_uuid = ?
- LIMIT ?);",
- )
- .context("Failed to prepare statement")?;
- let rows = stmt
- .query_map(
- params![
- KeyMetaData::AttestationMacedPublicKey,
- KeyType::Attestation,
- km_uuid,
- num_keys
- ],
- |row| row.get(0),
- )?
- .collect::<rusqlite::Result<Vec<Vec<u8>>>>()
- .context("Failed to execute statement")?;
- Ok(rows).no_gc()
- })
- .context(ks_err!())
- }
-
- /// Removes any keys that have expired as of the current time. Returns the number of keys
- /// marked unreferenced that are bound to be garbage collected.
- pub fn delete_expired_attestation_keys(&mut self) -> Result<i32> {
- let _wp = wd::watch_millis("KeystoreDB::delete_expired_attestation_keys", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let mut stmt = tx
- .prepare(
- "SELECT keyentryid, data
- FROM persistent.keymetadata
- WHERE tag = ? AND keyentryid IN
- (SELECT id
- FROM persistent.keyentry
- WHERE key_type = ?);",
- )
- .context("Failed to prepare query")?;
- let key_ids_to_check = stmt
- .query_map(
- params![KeyMetaData::AttestationExpirationDate, KeyType::Attestation],
- |row| Ok((row.get(0)?, row.get(1)?)),
- )?
- .collect::<rusqlite::Result<Vec<(i64, DateTime)>>>()
- .context("Failed to get date metadata")?;
- // Calculate curr_time with a discount factor to avoid a key that's milliseconds away
- // from expiration dodging this delete call.
- let curr_time = DateTime::from_millis_epoch(
- SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64
- + EXPIRATION_BUFFER_MS,
- );
- let mut num_deleted = 0;
- for id in key_ids_to_check.iter().filter(|kt| kt.1 < curr_time).map(|kt| kt.0) {
- if Self::mark_unreferenced(tx, id)? {
- num_deleted += 1;
- }
- }
- Ok(num_deleted).do_gc(num_deleted != 0)
- })
- .context(ks_err!())
- }
-
- /// Deletes all remotely provisioned attestation keys in the system, regardless of the state
- /// they are in. This is useful primarily as a testing mechanism.
- pub fn delete_all_attestation_keys(&mut self) -> Result<i64> {
- let _wp = wd::watch_millis("KeystoreDB::delete_all_attestation_keys", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let mut stmt = tx
- .prepare(
- "SELECT id FROM persistent.keyentry
- WHERE key_type IS ?;",
- )
- .context("Failed to prepare statement")?;
- let keys_to_delete = stmt
- .query_map(params![KeyType::Attestation], |row| row.get(0))?
- .collect::<rusqlite::Result<Vec<i64>>>()
- .context("Failed to execute statement")?;
- let num_deleted = keys_to_delete
- .iter()
- .map(|id| Self::mark_unreferenced(tx, *id))
- .collect::<Result<Vec<bool>>>()
- .context("Failed to execute mark_unreferenced on a keyid")?
- .into_iter()
- .filter(|result| *result)
- .count() as i64;
- Ok(num_deleted).do_gc(num_deleted != 0)
- })
- .context(ks_err!())
- }
-
- fn query_kid_for_attestation_key_and_cert_chain(
- &self,
- tx: &Transaction,
- domain: Domain,
- namespace: i64,
- km_uuid: &Uuid,
- ) -> Result<Option<i64>> {
- let mut stmt = tx.prepare(
- "SELECT id
- FROM persistent.keyentry
- WHERE key_type = ?
- AND domain = ?
- AND namespace = ?
- AND state = ?
- AND km_uuid = ?;",
- )?;
- let rows = stmt
- .query_map(
- params![
- KeyType::Attestation,
- domain.0 as u32,
- namespace,
- KeyLifeCycle::Live,
- km_uuid
- ],
- |row| row.get(0),
- )?
- .collect::<rusqlite::Result<Vec<i64>>>()
- .context("query failed.")?;
- if rows.is_empty() {
- return Ok(None);
- }
- Ok(Some(rows[0]))
- }
-
- /// Fetches the private key and corresponding certificate chain assigned to a
- /// domain/namespace pair. Will either return nothing if the domain/namespace is
- /// not assigned, or one CertificateChain.
- pub fn retrieve_attestation_key_and_cert_chain(
- &mut self,
- domain: Domain,
- namespace: i64,
- km_uuid: &Uuid,
- ) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
- let _wp = wd::watch_millis("KeystoreDB::retrieve_attestation_key_and_cert_chain", 500);
-
- match domain {
- Domain::APP | Domain::SELINUX => {}
- _ => {
- return Err(KsError::sys())
- .context(format!("Domain {:?} must be either App or SELinux.", domain));
- }
- }
-
- self.delete_expired_attestation_keys()
- .context(ks_err!("Failed to prune expired attestation keys",))?;
- let tx = self
- .conn
- .unchecked_transaction()
- .context(ks_err!("Failed to initialize transaction."))?;
- let key_id: i64 = match self
- .query_kid_for_attestation_key_and_cert_chain(&tx, domain, namespace, km_uuid)?
- {
- None => return Ok(None),
- Some(kid) => kid,
- };
- tx.commit().context(ks_err!("Failed to commit keyid query"))?;
- let key_id_guard = KEY_ID_LOCK.get(key_id);
- let tx = self
- .conn
- .unchecked_transaction()
- .context(ks_err!("Failed to initialize transaction."))?;
- let mut stmt = tx.prepare(
- "SELECT subcomponent_type, blob
- FROM persistent.blobentry
- WHERE keyentryid = ?;",
- )?;
- let rows = stmt
- .query_map(params![key_id_guard.id()], |row| Ok((row.get(0)?, row.get(1)?)))?
- .collect::<rusqlite::Result<Vec<(SubComponentType, Vec<u8>)>>>()
- .context("query failed.")?;
- if rows.is_empty() {
- return Ok(None);
- } else if rows.len() != 3 {
- return Err(KsError::sys()).context(format!(
- concat!(
- "Expected to get a single attestation",
- "key, cert, and cert chain for a total of 3 entries, but instead got {}."
- ),
- rows.len()
- ));
- }
- let mut km_blob: Vec<u8> = Vec::new();
- let mut cert_chain_blob: Vec<u8> = Vec::new();
- let mut batch_cert_blob: Vec<u8> = Vec::new();
- for row in rows {
- let sub_type: SubComponentType = row.0;
- match sub_type {
- SubComponentType::KEY_BLOB => {
- km_blob = row.1;
- }
- SubComponentType::CERT_CHAIN => {
- cert_chain_blob = row.1;
- }
- SubComponentType::CERT => {
- batch_cert_blob = row.1;
- }
- _ => Err(KsError::sys()).context("Unknown or incorrect subcomponent type.")?,
- }
- }
- Ok(Some((
- key_id_guard,
- CertificateChain {
- private_key: ZVec::try_from(km_blob)?,
- batch_cert: batch_cert_blob,
- cert_chain: cert_chain_blob,
- },
- )))
- }
-
/// Updates the alias column of the given key id `newid` with the given alias,
/// and atomically, removes the alias, domain, and namespace from another row
/// with the same alias-domain-namespace tuple if such row exits.
@@ -2808,33 +2388,33 @@
"DELETE FROM persistent.keymetadata
WHERE keyentryid IN (
SELECT id FROM persistent.keyentry
- WHERE domain = ? AND namespace = ? AND (key_type = ? OR key_type = ?)
+ WHERE domain = ? AND namespace = ? AND key_type = ?
);",
- params![domain.0, namespace, KeyType::Client, KeyType::Attestation],
+ params![domain.0, namespace, KeyType::Client],
)
.context("Trying to delete keymetadata.")?;
tx.execute(
"DELETE FROM persistent.keyparameter
WHERE keyentryid IN (
SELECT id FROM persistent.keyentry
- WHERE domain = ? AND namespace = ? AND (key_type = ? OR key_type = ?)
+ WHERE domain = ? AND namespace = ? AND key_type = ?
);",
- params![domain.0, namespace, KeyType::Client, KeyType::Attestation],
+ params![domain.0, namespace, KeyType::Client],
)
.context("Trying to delete keyparameters.")?;
tx.execute(
"DELETE FROM persistent.grant
WHERE keyentryid IN (
SELECT id FROM persistent.keyentry
- WHERE domain = ? AND namespace = ? AND (key_type = ? OR key_type = ?)
+ WHERE domain = ? AND namespace = ? AND key_type = ?
);",
- params![domain.0, namespace, KeyType::Client, KeyType::Attestation],
+ params![domain.0, namespace, KeyType::Client],
)
.context("Trying to delete grants.")?;
tx.execute(
"DELETE FROM persistent.keyentry
- WHERE domain = ? AND namespace = ? AND (key_type = ? OR key_type = ?);",
- params![domain.0, namespace, KeyType::Client, KeyType::Attestation],
+ WHERE domain = ? AND namespace = ? AND key_type = ?;",
+ params![domain.0, namespace, KeyType::Client],
)
.context("Trying to delete keyentry.")?;
Ok(()).need_gc()
@@ -3285,7 +2865,7 @@
use std::collections::BTreeMap;
use std::fmt::Write;
use std::sync::atomic::{AtomicU8, Ordering};
- use std::sync::{Arc, RwLock};
+ use std::sync::Arc;
use std::thread;
use std::time::{Duration, SystemTime};
use crate::utils::AesGcm;
@@ -3302,18 +2882,6 @@
Ok(db)
}
- fn new_test_db_with_gc<F>(path: &Path, cb: F) -> Result<KeystoreDB>
- where
- F: Fn(&Uuid, &[u8]) -> Result<()> + Send + 'static,
- {
- let super_key: Arc<RwLock<SuperKeyManager>> = Default::default();
-
- let gc_db = KeystoreDB::new(path, None).expect("Failed to open test gc db_connection.");
- let gc = Gc::new_init_with(Default::default(), move || (Box::new(cb), gc_db, super_key));
-
- KeystoreDB::new(path, Some(Arc::new(gc)))
- }
-
fn rebind_alias(
db: &mut KeystoreDB,
newid: &KeyIdGuard,
@@ -3491,195 +3059,6 @@
}
#[test]
- fn test_add_unsigned_key() -> Result<()> {
- let mut db = new_test_db()?;
- let public_key: Vec<u8> = vec![0x01, 0x02, 0x03];
- let private_key: Vec<u8> = vec![0x04, 0x05, 0x06];
- let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09];
- db.create_attestation_key_entry(
- &public_key,
- &raw_public_key,
- &private_key,
- &KEYSTORE_UUID,
- )?;
- let keys = db.fetch_unsigned_attestation_keys(5, &KEYSTORE_UUID)?;
- assert_eq!(keys.len(), 1);
- assert_eq!(keys[0], public_key);
- Ok(())
- }
-
- #[test]
- fn test_store_signed_attestation_certificate_chain() -> Result<()> {
- let mut db = new_test_db()?;
- let expiration_date: i64 =
- SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64
- + EXPIRATION_BUFFER_MS
- + 10000;
- let namespace: i64 = 30;
- let base_byte: u8 = 1;
- let loaded_values =
- load_attestation_key_pool(&mut db, expiration_date, namespace, base_byte)?;
- let chain =
- db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?;
- assert!(chain.is_some());
- let (_, cert_chain) = chain.unwrap();
- assert_eq!(cert_chain.private_key.to_vec(), loaded_values.priv_key);
- assert_eq!(cert_chain.batch_cert, loaded_values.batch_cert);
- assert_eq!(cert_chain.cert_chain, loaded_values.cert_chain);
- Ok(())
- }
-
- #[test]
- fn test_remove_expired_certs() -> Result<()> {
- let temp_dir =
- TempDir::new("test_remove_expired_certs_").expect("Failed to create temp dir.");
- let mut db = new_test_db_with_gc(temp_dir.path(), |_, _| Ok(()))?;
- let expiration_date: i64 =
- SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64
- + EXPIRATION_BUFFER_MS
- + 10000;
- let namespace: i64 = 30;
- let namespace_del1: i64 = 45;
- let namespace_del2: i64 = 60;
- let entry_values = load_attestation_key_pool(
- &mut db,
- expiration_date,
- namespace,
- 0x01, /* base_byte */
- )?;
- load_attestation_key_pool(&mut db, 45, namespace_del1, 0x02)?;
- load_attestation_key_pool(&mut db, expiration_date - 10001, namespace_del2, 0x03)?;
-
- let blob_entry_row_count: u32 = db
- .conn
- .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0))
- .expect("Failed to get blob entry row count.");
- // We expect 9 rows here because there are three blobs per attestation key, i.e.,
- // one key, one certificate chain, and one certificate.
- assert_eq!(blob_entry_row_count, 9);
-
- assert_eq!(db.delete_expired_attestation_keys()?, 2);
-
- let mut cert_chain =
- db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?;
- assert!(cert_chain.is_some());
- let (_, value) = cert_chain.unwrap();
- assert_eq!(entry_values.batch_cert, value.batch_cert);
- assert_eq!(entry_values.cert_chain, value.cert_chain);
- assert_eq!(entry_values.priv_key, value.private_key.to_vec());
-
- cert_chain = db.retrieve_attestation_key_and_cert_chain(
- Domain::APP,
- namespace_del1,
- &KEYSTORE_UUID,
- )?;
- assert!(cert_chain.is_none());
- cert_chain = db.retrieve_attestation_key_and_cert_chain(
- Domain::APP,
- namespace_del2,
- &KEYSTORE_UUID,
- )?;
- assert!(cert_chain.is_none());
-
- // Give the garbage collector half a second to catch up.
- std::thread::sleep(Duration::from_millis(500));
-
- let blob_entry_row_count: u32 = db
- .conn
- .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0))
- .expect("Failed to get blob entry row count.");
- // There shound be 3 blob entries left, because we deleted two of the attestation
- // key entries with three blobs each.
- assert_eq!(blob_entry_row_count, 3);
-
- Ok(())
- }
-
- fn compare_rem_prov_values(
- expected: &RemoteProvValues,
- actual: Option<(KeyIdGuard, CertificateChain)>,
- ) {
- assert!(actual.is_some());
- let (_, value) = actual.unwrap();
- assert_eq!(expected.batch_cert, value.batch_cert);
- assert_eq!(expected.cert_chain, value.cert_chain);
- assert_eq!(expected.priv_key, value.private_key.to_vec());
- }
-
- #[test]
- fn test_dont_remove_valid_certs() -> Result<()> {
- let temp_dir =
- TempDir::new("test_remove_expired_certs_").expect("Failed to create temp dir.");
- let mut db = new_test_db_with_gc(temp_dir.path(), |_, _| Ok(()))?;
- let expiration_date: i64 =
- SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64
- + EXPIRATION_BUFFER_MS
- + 10000;
- let namespace1: i64 = 30;
- let namespace2: i64 = 45;
- let namespace3: i64 = 60;
- let entry_values1 = load_attestation_key_pool(
- &mut db,
- expiration_date,
- namespace1,
- 0x01, /* base_byte */
- )?;
- let entry_values2 =
- load_attestation_key_pool(&mut db, expiration_date + 40000, namespace2, 0x02)?;
- let entry_values3 =
- load_attestation_key_pool(&mut db, expiration_date - 9000, namespace3, 0x03)?;
-
- let blob_entry_row_count: u32 = db
- .conn
- .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0))
- .expect("Failed to get blob entry row count.");
- // We expect 9 rows here because there are three blobs per attestation key, i.e.,
- // one key, one certificate chain, and one certificate.
- assert_eq!(blob_entry_row_count, 9);
-
- let mut cert_chain =
- db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace1, &KEYSTORE_UUID)?;
- compare_rem_prov_values(&entry_values1, cert_chain);
-
- cert_chain =
- db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace2, &KEYSTORE_UUID)?;
- compare_rem_prov_values(&entry_values2, cert_chain);
-
- cert_chain =
- db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace3, &KEYSTORE_UUID)?;
- compare_rem_prov_values(&entry_values3, cert_chain);
-
- // Give the garbage collector half a second to catch up.
- std::thread::sleep(Duration::from_millis(500));
-
- let blob_entry_row_count: u32 = db
- .conn
- .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0))
- .expect("Failed to get blob entry row count.");
- // There shound be 9 blob entries left, because all three keys are valid with
- // three blobs each.
- assert_eq!(blob_entry_row_count, 9);
-
- Ok(())
- }
- #[test]
- fn test_delete_all_attestation_keys() -> Result<()> {
- let mut db = new_test_db()?;
- load_attestation_key_pool(&mut db, 45 /* expiration */, 1 /* namespace */, 0x02)?;
- load_attestation_key_pool(&mut db, 80 /* expiration */, 2 /* namespace */, 0x03)?;
- db.create_key_entry(&Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?;
- let result = db.delete_all_attestation_keys()?;
-
- // Give the garbage collector half a second to catch up.
- std::thread::sleep(Duration::from_millis(500));
-
- // Attestation keys should be deleted, and the regular key should remain.
- assert_eq!(result, 2);
-
- Ok(())
- }
-
- #[test]
fn test_rebind_alias() -> Result<()> {
fn extractor(
ke: &KeyEntryRow,
@@ -5048,35 +4427,6 @@
.collect::<Result<Vec<_>>>()
}
- struct RemoteProvValues {
- cert_chain: Vec<u8>,
- priv_key: Vec<u8>,
- batch_cert: Vec<u8>,
- }
-
- fn load_attestation_key_pool(
- db: &mut KeystoreDB,
- expiration_date: i64,
- namespace: i64,
- base_byte: u8,
- ) -> Result<RemoteProvValues> {
- let public_key: Vec<u8> = vec![base_byte, 0x02 * base_byte];
- let cert_chain: Vec<u8> = vec![0x03 * base_byte, 0x04 * base_byte];
- let priv_key: Vec<u8> = vec![0x05 * base_byte, 0x06 * base_byte];
- let raw_public_key: Vec<u8> = vec![0x0b * base_byte, 0x0c * base_byte];
- let batch_cert: Vec<u8> = vec![base_byte * 0x0d, base_byte * 0x0e];
- db.create_attestation_key_entry(&public_key, &raw_public_key, &priv_key, &KEYSTORE_UUID)?;
- db.store_signed_attestation_certificate_chain(
- &raw_public_key,
- &batch_cert,
- &cert_chain,
- expiration_date,
- &KEYSTORE_UUID,
- )?;
- db.assign_attestation_key(Domain::APP, namespace, &KEYSTORE_UUID)?;
- Ok(RemoteProvValues { cert_chain, priv_key, batch_cert })
- }
-
// Note: The parameters and SecurityLevel associations are nonsensical. This
// collection is only used to check if the parameters are preserved as expected by the
// database.