summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasini Gunasinghe <hasinitg@google.com>2021-07-01 21:36:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-07-01 21:36:23 +0000
commit691d4d4dfb8fb174c336761b66c6b79fb08dbac4 (patch)
treedd74432bc61e66a887b659de939223d26e2addf9
parent664ea465c24f19118fb9deedb24d2cf2675885b8 (diff)
parenta3444f867b8ee07dcbc911de22fc3804bb83cf87 (diff)
downloadsecurity-691d4d4dfb8fb174c336761b66c6b79fb08dbac4.tar.gz
Merge "Log metrics related to Remote Key Provisioning (RKP)." into sc-dev
-rw-r--r--keystore2/aidl/android/security/metrics/RkpPoolStats.aidl11
-rw-r--r--keystore2/src/database.rs3
-rw-r--r--keystore2/src/metrics_store.rs52
-rw-r--r--keystore2/src/remote_provisioning.rs38
4 files changed, 77 insertions, 27 deletions
diff --git a/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl b/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
index b2338423..016b6ff3 100644
--- a/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
+++ b/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
@@ -16,14 +16,17 @@
package android.security.metrics;
-import android.security.metrics.PoolStatus;
+import android.security.metrics.SecurityLevel;
/**
- * Count of keys in the key pool related to Remote Key Provisioning (RKP).
+ * Count of keys in the attestation key pool related to Remote Key Provisioning (RKP).
* @hide
*/
@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
parcelable RkpPoolStats {
- PoolStatus pool_status;
- int count_of_keys;
+ SecurityLevel security_level;
+ int expiring;
+ int unassigned;
+ int attested;
+ int total;
} \ No newline at end of file
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index ca346e0a..c7887200 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -47,6 +47,7 @@ mod versioning;
use crate::impl_metadata; // This is in db_utils.rs
use crate::key_parameter::{KeyParameter, Tag};
+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::{
@@ -72,6 +73,7 @@ use android_security_remoteprovisioning::aidl::android::security::remoteprovisio
use android_security_metrics::aidl::android::security::metrics::{
StorageStats::StorageStats,
Storage::Storage as MetricsStorage,
+ RkpError::RkpError as MetricsRkpError,
};
use keystore2_crypto::ZVec;
@@ -1829,6 +1831,7 @@ impl KeystoreDB {
)
.context("Failed to assign attestation key")?;
if result == 0 {
+ log_rkp_error_stats(MetricsRkpError::OUT_OF_KEYS);
return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS)).context("Out of keys.");
} else if result > 1 {
return Err(KsError::sys())
diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs
index e3de0352..32fe353e 100644
--- a/keystore2/src/metrics_store.rs
+++ b/keystore2/src/metrics_store.rs
@@ -21,6 +21,7 @@ use crate::error::get_error_code;
use crate::globals::DB;
use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
use crate::operation::Outcome;
+use crate::remote_provisioning::get_pool_status;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
@@ -38,12 +39,15 @@ use android_security_metrics::aidl::android::security::metrics::{
KeyOrigin::KeyOrigin as MetricsKeyOrigin, Keystore2AtomWithOverflow::Keystore2AtomWithOverflow,
KeystoreAtom::KeystoreAtom, KeystoreAtomPayload::KeystoreAtomPayload,
Outcome::Outcome as MetricsOutcome, Purpose::Purpose as MetricsPurpose,
- SecurityLevel::SecurityLevel as MetricsSecurityLevel, Storage::Storage as MetricsStorage,
+ RkpError::RkpError as MetricsRkpError, RkpErrorStats::RkpErrorStats,
+ RkpPoolStats::RkpPoolStats, SecurityLevel::SecurityLevel as MetricsSecurityLevel,
+ Storage::Storage as MetricsStorage,
};
use anyhow::Result;
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::sync::Mutex;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
lazy_static! {
/// Singleton for MetricsStore.
@@ -83,7 +87,10 @@ impl MetricsStore {
return pull_storage_stats();
}
- // TODO (b/184301651): process and return RKP pool stats.
+ // Process and return RKP pool stats.
+ if AtomID::RKP_POOL_STATS == atom_id {
+ return pull_attestation_pool_stats();
+ }
// It is safe to call unwrap here since the lock can not be poisoned based on its usage
// in this module and the lock is not acquired in the same thread before.
@@ -534,6 +541,47 @@ fn pull_storage_stats() -> Result<Vec<KeystoreAtom>> {
Ok(atom_vec)
}
+fn pull_attestation_pool_stats() -> Result<Vec<KeystoreAtom>> {
+ let mut atoms = Vec::<KeystoreAtom>::new();
+ for sec_level in &[SecurityLevel::TRUSTED_ENVIRONMENT, SecurityLevel::STRONGBOX] {
+ let expired_by = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap_or_else(|_| Duration::new(0, 0))
+ .as_secs() as i64;
+
+ let result = get_pool_status(expired_by, *sec_level);
+
+ if let Ok(pool_status) = result {
+ let rkp_pool_stats = RkpPoolStats {
+ security_level: process_security_level(*sec_level),
+ expiring: pool_status.expiring,
+ unassigned: pool_status.unassigned,
+ attested: pool_status.attested,
+ total: pool_status.total,
+ };
+ atoms.push(KeystoreAtom {
+ payload: KeystoreAtomPayload::RkpPoolStats(rkp_pool_stats),
+ ..Default::default()
+ });
+ } else {
+ log::error!(
+ concat!(
+ "In pull_attestation_pool_stats: Failed to retrieve pool status",
+ " for security level: {:?}"
+ ),
+ sec_level
+ );
+ }
+ }
+ Ok(atoms)
+}
+
+/// Log error events related to Remote Key Provisioning (RKP).
+pub fn log_rkp_error_stats(rkp_error: MetricsRkpError) {
+ let rkp_error_stats = KeystoreAtomPayload::RkpErrorStats(RkpErrorStats { rkpError: rkp_error });
+ METRICS_STORE.insert_atom(AtomID::RKP_ERROR_STATS, rkp_error_stats);
+}
+
/// Enum defining the bit position for each padding mode. Since padding mode can be repeatable, it
/// is represented using a bitmap.
#[allow(non_camel_case_types)]
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index 40ffd0ca..6666f416 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -234,26 +234,6 @@ impl RemoteProvisioningService {
Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
}
- /// Populates the AttestationPoolStatus parcelable with information about how many
- /// certs will be expiring by the date provided in `expired_by` along with how many
- /// keys have not yet been assigned.
- pub fn get_pool_status(
- &self,
- expired_by: i64,
- sec_level: SecurityLevel,
- ) -> Result<AttestationPoolStatus> {
- let (_, _, uuid) = get_keymint_device(&sec_level)?;
- DB.with::<_, Result<AttestationPoolStatus>>(|db| {
- let mut db = db.borrow_mut();
- // delete_expired_attestation_keys is always safe to call, and will remove anything
- // older than the date at the time of calling. No work should be done on the
- // attestation keys unless the pool status is checked first, so this call should be
- // enough to routinely clean out expired keys.
- db.delete_expired_attestation_keys()?;
- db.get_attestation_pool_status(expired_by, &uuid)
- })
- }
-
/// Generates a CBOR blob which will be assembled by the calling code into a larger
/// CBOR blob intended for delivery to a provisioning serever. This blob will contain
/// `num_csr` certificate signing requests for attestation keys generated in the TEE,
@@ -389,6 +369,22 @@ impl RemoteProvisioningService {
}
}
+/// Populates the AttestationPoolStatus parcelable with information about how many
+/// certs will be expiring by the date provided in `expired_by` along with how many
+/// keys have not yet been assigned.
+pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
+ let (_, _, uuid) = get_keymint_device(&sec_level)?;
+ DB.with::<_, Result<AttestationPoolStatus>>(|db| {
+ let mut db = db.borrow_mut();
+ // delete_expired_attestation_keys is always safe to call, and will remove anything
+ // older than the date at the time of calling. No work should be done on the
+ // attestation keys unless the pool status is checked first, so this call should be
+ // enough to routinely clean out expired keys.
+ db.delete_expired_attestation_keys()?;
+ db.get_attestation_pool_status(expired_by, &uuid)
+ })
+}
+
impl binder::Interface for RemoteProvisioningService {}
// Implementation of IRemoteProvisioning. See AIDL spec at
@@ -400,7 +396,7 @@ impl IRemoteProvisioning for RemoteProvisioningService {
sec_level: SecurityLevel,
) -> binder::public_api::Result<AttestationPoolStatus> {
let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
- map_or_log_err(self.get_pool_status(expired_by, sec_level), Ok)
+ map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
}
fn generateCsr(