Merge changes from topic "apex-aidl" into main
* changes:
Populate apex module info
Include module info in dump output
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 9f27b5a..66b123e 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -3049,4 +3049,11 @@
let app_uids_vec: Vec<i64> = app_uids_affected_by_sid.into_iter().collect();
Ok(app_uids_vec)
}
+
+ /// Retrieve a database PRAGMA config value.
+ pub fn pragma<T: FromSql>(&mut self, name: &str) -> Result<T> {
+ self.conn
+ .query_row(&format!("PRAGMA persistent.{name}"), (), |row| row.get(0))
+ .context(format!("failed to read pragma {name}"))
+ }
}
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 16cc34f..acca942 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -55,6 +55,9 @@
/// Reexport Domain for the benefit of DeleteListener
pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
+#[cfg(test)]
+mod tests;
+
/// Version number of KeyMint V4.
pub const KEYMINT_V4: i32 = 400;
@@ -428,6 +431,34 @@
}
writeln!(f)?;
+ // Display database config information.
+ writeln!(f, "Database configuration:")?;
+ DB.with(|db| -> std::io::Result<()> {
+ let pragma_str = |f: &mut dyn std::io::Write, name| -> std::io::Result<()> {
+ let mut db = db.borrow_mut();
+ let value: String = db
+ .pragma(name)
+ .unwrap_or_else(|e| format!("unknown value for '{name}', failed: {e:?}"));
+ writeln!(f, " {name} = {value}")
+ };
+ let pragma_i32 = |f: &mut dyn std::io::Write, name| -> std::io::Result<()> {
+ let mut db = db.borrow_mut();
+ let value: i32 = db.pragma(name).unwrap_or_else(|e| {
+ log::error!("unknown value for '{name}', failed: {e:?}");
+ -1
+ });
+ writeln!(f, " {name} = {value}")
+ };
+ pragma_i32(f, "auto_vacuum")?;
+ pragma_str(f, "journal_mode")?;
+ pragma_i32(f, "journal_size_limit")?;
+ pragma_i32(f, "synchronous")?;
+ pragma_i32(f, "schema_version")?;
+ pragma_i32(f, "user_version")?;
+ Ok(())
+ })?;
+ writeln!(f)?;
+
// Display accumulated metrics.
writeln!(f, "Metrics information:")?;
writeln!(f)?;
diff --git a/keystore2/src/maintenance/tests.rs b/keystore2/src/maintenance/tests.rs
new file mode 100644
index 0000000..fbafa73
--- /dev/null
+++ b/keystore2/src/maintenance/tests.rs
@@ -0,0 +1,182 @@
+// Copyright 2024, 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.
+
+//! Maintenance tests.
+use super::*;
+use der::ErrorKind;
+
+#[test]
+fn test_encode_module_info_empty() {
+ let expected = vec![0x31, 0x00];
+ assert_eq!(expected, Maintenance::encode_module_info(Vec::new()).unwrap());
+}
+
+#[test]
+fn test_encode_module_info_same_name() {
+ // Same versions
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 25,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 25,
+ },
+ ];
+ let actual = Maintenance::encode_module_info(module_info);
+ assert!(actual.is_err());
+ assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+
+ // Different versions
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 789,
+ },
+ ];
+ let actual = Maintenance::encode_module_info(module_info);
+ assert!(actual.is_err());
+ assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+}
+
+#[test]
+fn test_encode_module_info_same_name_length() {
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+ ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "312e", // SET OF, len 46
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e76697274", // "com.android.virt"
+ "020101", // INTEGER len 1 value 1
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e77696669", // "com.android.wifi"
+ "020102", // INTEGER len 1 value 2
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_version_irrelevant() {
+ // Versions of the modules are irrelevant for determining encoding order since differing names
+ // guarantee a unique ascending order. See Maintenance::ModuleInfo::der_cmp for more detail.
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+ version: 1,
+ },
+ ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "3135", // SET OF, len 53
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e61646264", // "com.android.abdb"
+ "02010e", // INTEGER len 2 value 14
+ "301c", // SEQUENCE, len 28
+ "0417", // OCTET STRING, len 23
+ "636f6d2e616e64726f69642e6578747365727669636573", // "com.android.extservices"
+ "020101", // INTEGER len 1 value 1
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_alphaordering_irrelevant() {
+ // Character ordering of the names of modules is irrelevant for determining encoding order since
+ // differing name lengths guarantee a unique ascending order. See
+ // Maintenance::ModuleInfo::der_cmp for more detail.
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "3137", // SET OF, len 55
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e726b7064", // "com.android.rkpd"
+ "020108", // INTEGER len 1 value 8
+ "301e", // SEQUENCE, len 30
+ "0419", // OCTET STRING, len 25
+ "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+ "020103", // INTEGER len 1 value 3
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info() {
+ // Collection of `ModuleInfo`s from a few of the other test_encode_module_info_* tests
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+ ModuleInfo {
+ name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+ version: 1,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+ ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+ ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "31819a", // SET OF, len 154
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e61646264", // "com.android.abdb"
+ "02010e", // INTEGER len 2 value 14
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e726b7064", // "com.android.rkpd"
+ "020108", // INTEGER len 1 value 8
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e76697274", // "com.android.virt"
+ "020101", // INTEGER len 1 value 1
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e77696669", // "com.android.wifi"
+ "020102", // INTEGER len 1 value 2
+ "301c", // SEQUENCE, len 28
+ "0417", // OCTET STRING, len 23
+ "636f6d2e616e64726f69642e6578747365727669636573", // "com.android.extservices"
+ "020101", // INTEGER len 1 value 1
+ "301e", // SEQUENCE, len 30
+ "0419", // OCTET STRING, len 25
+ "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+ "020103", // INTEGER len 1 value 3
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
diff --git a/keystore2/test_utils/lib.rs b/keystore2/test_utils/lib.rs
index 825657f..8e74f92 100644
--- a/keystore2/test_utils/lib.rs
+++ b/keystore2/test_utils/lib.rs
@@ -21,7 +21,7 @@
use android_system_keystore2::aidl::android::system::keystore2::{
IKeystoreService::IKeystoreService,
- IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+ IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
@@ -193,4 +193,18 @@
0
}
}
+
+ /// Delete a key.
+ pub fn delete_key(&self, key: &KeyDescriptor) -> binder::Result<()> {
+ match self.binder.deleteKey(key) {
+ Ok(()) => Ok(()),
+ Err(s)
+ if s.exception_code() == binder::ExceptionCode::SERVICE_SPECIFIC
+ && s.service_specific_error() == ErrorCode::UNIMPLEMENTED.0 =>
+ {
+ Ok(())
+ }
+ Err(e) => Err(e),
+ }
+ }
}
diff --git a/keystore2/tests/keystore2_client_delete_key_tests.rs b/keystore2/tests/keystore2_client_delete_key_tests.rs
index a0fb9c2..13f8eef 100644
--- a/keystore2/tests/keystore2_client_delete_key_tests.rs
+++ b/keystore2/tests/keystore2_client_delete_key_tests.rs
@@ -100,7 +100,7 @@
)
.unwrap();
- let result = sl.binder.deleteKey(&key_metadata.key);
+ let result = sl.delete_key(&key_metadata.key);
assert!(result.is_ok());
}
@@ -110,7 +110,7 @@
fn keystore2_delete_key_fails_with_missing_key_blob() {
let sl = SecLevel::tee();
- let result = key_generations::map_ks_error(sl.binder.deleteKey(&KeyDescriptor {
+ let result = key_generations::map_ks_error(sl.delete_key(&KeyDescriptor {
domain: Domain::BLOB,
nspace: key_generations::SELINUX_SHELL_NAMESPACE,
alias: None,
@@ -132,7 +132,7 @@
key_generations::generate_ec_p256_signing_key(&sl, Domain::APP, -1, Some(alias), None)
.unwrap();
- let result = key_generations::map_ks_error(sl.binder.deleteKey(&key_metadata.key));
+ let result = key_generations::map_ks_error(sl.delete_key(&key_metadata.key));
assert!(result.is_err());
assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err());
}
diff --git a/keystore2/tests/keystore2_client_ec_key_tests.rs b/keystore2/tests/keystore2_client_ec_key_tests.rs
index 526a339..17a88e7 100644
--- a/keystore2/tests/keystore2_client_ec_key_tests.rs
+++ b/keystore2/tests/keystore2_client_ec_key_tests.rs
@@ -211,7 +211,7 @@
assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
// Delete the generated key blob.
- sl.binder.deleteKey(&key_metadata.key).unwrap();
+ sl.delete_key(&key_metadata.key).unwrap();
}
/// Try to generate a key with invalid Domain. `INVALID_ARGUMENT` error response is expected.
@@ -514,5 +514,5 @@
);
// Delete the generated key blob.
- sl.binder.deleteKey(&key_metadata.key).unwrap();
+ sl.delete_key(&key_metadata.key).unwrap();
}
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
index ede1ae6..6a4dc24 100644
--- a/provisioner/Android.bp
+++ b/provisioner/Android.bp
@@ -36,6 +36,7 @@
],
static_libs: [
"android.hardware.common-V2-ndk",
+ "android.hardware.drm.common-V1-ndk",
"android.hardware.drm-V1-ndk",
"android.hardware.security.rkp-V3-ndk",
"libbase",