Add getSupplementaryAttestationInfo
Allows clients to retrieve information required to interpret certain
attested values found in the attestation certificate.
Currently only relevant for Tag::MODULE_HASH, for which it returns the
encoded structure whose hash ends up in the attestation certificate.
Bug: 369375199
Test: treehugger
Change-Id: Ida8c72fa262d13c01c22bd68fa0bd71b881b876b
diff --git a/keystore2/aconfig/flags.aconfig b/keystore2/aconfig/flags.aconfig
index 2e9659f..b15230e 100644
--- a/keystore2/aconfig/flags.aconfig
+++ b/keystore2/aconfig/flags.aconfig
@@ -48,3 +48,11 @@
bug: "319563050"
is_fixed_read_only: true
}
+
+flag {
+ name: "attest_modules"
+ namespace: "hardware_backed_security"
+ description: "Support attestation of modules"
+ bug: "369375199"
+ is_fixed_read_only: true
+}
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 0e8892b..3b9c631 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -165,6 +165,8 @@
LazyLock::new(|| Arc::new(LegacyImporter::new(Arc::new(Default::default()))));
/// Background thread which handles logging via statsd and logd
pub static LOGS_HANDLER: LazyLock<Arc<AsyncTask>> = LazyLock::new(Default::default);
+/// DER-encoded module information returned by `getSupplementaryAttestationInfo(Tag.MODULE_HASH)`.
+pub static ENCODED_MODULE_INFO: RwLock<Option<Vec<u8>>> = RwLock::new(None);
static GC: LazyLock<Arc<Gc>> = LazyLock::new(|| {
Arc::new(Gc::new_init_with(ASYNC_TASK.clone(), || {
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 95e1744..85ac7bc 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -27,7 +27,10 @@
};
use crate::{
database::Uuid,
- globals::{create_thread_local_db, DB, LEGACY_BLOB_LOADER, LEGACY_IMPORTER, SUPER_KEY},
+ globals::{
+ create_thread_local_db, DB, ENCODED_MODULE_INFO, LEGACY_BLOB_LOADER, LEGACY_IMPORTER,
+ SUPER_KEY,
+ },
};
use crate::{database::KEYSTORE_UUID, permission};
use crate::{
@@ -39,6 +42,7 @@
id_rotation::IdRotationState,
};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::Tag::Tag;
use android_hardware_security_keymint::binder::{BinderFeatures, Strong, ThreadState};
use android_system_keystore2::aidl::android::system::keystore2::{
Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
@@ -314,6 +318,20 @@
DB.with(|db| count_key_entries(&mut db.borrow_mut(), k.domain, k.nspace))
}
+ fn get_supplementary_attestation_info(&self, tag: Tag) -> Result<Vec<u8>> {
+ match tag {
+ Tag::MODULE_HASH => {
+ let info = ENCODED_MODULE_INFO.read().unwrap();
+ (*info)
+ .clone()
+ .ok_or(Error::Rc(ResponseCode::INFO_NOT_AVAILABLE))
+ .context(ks_err!("Module info not received."))
+ }
+ _ => Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
+ .context(ks_err!("Tag {tag:?} not supported for getSupplementaryAttestationInfo.")),
+ }
+ }
+
fn list_entries_batched(
&self,
domain: Domain,
@@ -441,4 +459,14 @@
let _wp = wd::watch("IKeystoreService::getNumberOfEntries");
self.count_num_entries(domain, namespace).map_err(into_logged_binder)
}
+
+ fn getSupplementaryAttestationInfo(&self, tag: Tag) -> binder::Result<Vec<u8>> {
+ if keystore2_flags::attest_modules() {
+ let _wp = wd::watch("IKeystoreService::getSupplementaryAttestationInfo");
+ self.get_supplementary_attestation_info(tag).map_err(into_logged_binder)
+ } else {
+ log::error!("attest_modules flag is not toggled");
+ Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+ }
+ }
}