Merge "Revert "Add dependency on keymint cpp lib""
diff --git a/diced/Android.bp b/diced/Android.bp
index 525828e..e13d863 100644
--- a/diced/Android.bp
+++ b/diced/Android.bp
@@ -138,6 +138,24 @@
init_rc: ["diced.rc"],
}
+rust_binary {
+ name: "diced.microdroid",
+ srcs: ["src/diced_main.rs"],
+ prefer_rlib: true,
+ rustlibs: [
+ "android.hardware.security.dice-V1-rust",
+ "libandroid_logger",
+ "libbinder_rs",
+ "libdiced",
+ "libdiced_open_dice_cbor",
+ "libdiced_sample_inputs",
+ "libdiced_utils",
+ "liblog_rust",
+ ],
+ init_rc: ["diced.microdroid.rc"],
+ bootstrap: true,
+}
+
rust_test {
name: "diced_test",
crate_name: "diced_test",
diff --git a/diced/diced.microdroid.rc b/diced/diced.microdroid.rc
new file mode 100644
index 0000000..2226f47
--- /dev/null
+++ b/diced/diced.microdroid.rc
@@ -0,0 +1,13 @@
+# Start the Diced service.
+#
+# See system/core/init/README.md for information on the init.rc language.
+
+service diced /system/bin/diced.microdroid
+ class main
+ user diced
+ group diced
+ # The diced service must not be allowed to restart.
+ # If it crashes for any reason security critical state is lost.
+ # The only remedy is to restart the device.
+ oneshot
+ writepid /dev/cpuset/foreground/tasks
diff --git a/fsverity/Android.bp b/fsverity/Android.bp
index 5c3d6a0..2fc3c01 100644
--- a/fsverity/Android.bp
+++ b/fsverity/Android.bp
@@ -53,3 +53,14 @@
"com.android.compos",
],
}
+
+cc_library_static {
+ name: "libfsverity_digests_proto_cc",
+ proto: {
+ type: "lite",
+ static: true,
+ canonical_path_from_root: false,
+ export_proto_headers: true,
+ },
+ srcs: ["fsverity_digests.proto"],
+}
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index 6a37c78..3df5936 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -23,10 +23,15 @@
* user's password.
* @hide
*/
- @SensitiveData
+@SensitiveData
interface IKeystoreMaintenance {
/**
+ * Special value indicating the callers uid.
+ */
+ const int UID_SELF = -1;
+
+ /**
* Allows LockSettingsService to inform keystore about adding a new user.
* Callers require 'AddUser' permission.
*
@@ -115,6 +120,10 @@
* The source may be specified by Domain::APP, Domain::SELINUX, or Domain::KEY_ID. The target
* may be specified by Domain::APP or Domain::SELINUX.
*
+ * If Domain::APP is selected in either source or destination, nspace must be set to UID_SELF,
+ * implying the caller's UID. If the caller has the MIGRATE_ANY_KEY permission, Domain::APP may
+ * be used with other nspace values which then indicates the UID of a different application.
+ *
* ## Error conditions:
* `ResponseCode::PERMISSION_DENIED` - If the caller lacks any of the required permissions.
* `ResponseCode::KEY_NOT_FOUND` - If the source did not exist.
@@ -131,4 +140,22 @@
* Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
*/
void deleteAllKeys();
+
+ /**
+ * List all entries accessible by the caller in the given `domain` and `nspace`.
+ *
+ * Callers either has to have the `GET_INFO` permission for the requested namespace or `LIST`
+ * permission to list all the entries.
+ *
+ * ## Error conditions
+ * `ResponseCode::INVALID_ARGUMENT` if `domain` is other than `Domain::APP` or `Domain::SELINUX`
+ * `ResponseCode::PERMISSION_DENIED` if the caller does not have the permission
+ *
+ * @param domain `Domain::APP` or `Domain::SELINUX`.
+ *
+ * @param nspace The SELinux keystore2_key namespace.
+ *
+ * @return List of KeyDescriptors.
+ */
+ KeyDescriptor[] listEntries(in Domain domain, in long nspace);
}
diff --git a/keystore2/legacykeystore/lib.rs b/keystore2/legacykeystore/lib.rs
index da60297..13a9143 100644
--- a/keystore2/legacykeystore/lib.rs
+++ b/keystore2/legacykeystore/lib.rs
@@ -25,8 +25,8 @@
};
use anyhow::{Context, Result};
use keystore2::{
- async_task::AsyncTask, legacy_blob::LegacyBlobLoader, maintenance::DeleteListener,
- maintenance::Domain, utils::watchdog as wd,
+ async_task::AsyncTask, error::anyhow_error_to_cstring, legacy_blob::LegacyBlobLoader,
+ maintenance::DeleteListener, maintenance::Domain, utils::watchdog as wd,
};
use rusqlite::{
params, Connection, OptionalExtension, Transaction, TransactionBehavior, NO_PARAMS,
@@ -226,7 +226,10 @@
if log_error {
log::error!("{:?}", e);
}
- Err(BinderStatus::new_service_specific_error(rc, None))
+ Err(BinderStatus::new_service_specific_error(
+ rc,
+ anyhow_error_to_cstring(&e).as_deref(),
+ ))
},
handle_ok,
)
diff --git a/keystore2/src/apc.rs b/keystore2/src/apc.rs
index 0096686..7d56dc9 100644
--- a/keystore2/src/apc.rs
+++ b/keystore2/src/apc.rs
@@ -21,6 +21,7 @@
sync::{mpsc::Sender, Arc, Mutex},
};
+use crate::error::anyhow_error_to_cstring;
use crate::utils::{compat_2_response_code, ui_opts_2_compat, watchdog as wd};
use android_security_apc::aidl::android::security::apc::{
IConfirmationCallback::IConfirmationCallback,
@@ -110,7 +111,10 @@
_ => ResponseCode::SYSTEM_ERROR.0,
},
};
- Err(BinderStatus::new_service_specific_error(rc, None))
+ Err(BinderStatus::new_service_specific_error(
+ rc,
+ anyhow_error_to_cstring(&e).as_deref(),
+ ))
},
handle_ok,
)
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 516a860..64b498f 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -15,6 +15,7 @@
//! This module implements IKeystoreAuthorization AIDL interface.
use crate::error::Error as KeystoreError;
+use crate::error::anyhow_error_to_cstring;
use crate::globals::{ENFORCEMENTS, SUPER_KEY, DB, LEGACY_MIGRATOR};
use crate::permission::KeystorePerm;
use crate::super_key::UserState;
@@ -88,7 +89,10 @@
// as well.
_ => ResponseCode::SYSTEM_ERROR.0,
};
- return Err(BinderStatus::new_service_specific_error(rc, None));
+ return Err(BinderStatus::new_service_specific_error(
+ rc,
+ anyhow_error_to_cstring(&e).as_deref(),
+ ));
}
let rc = match root_cause.downcast_ref::<Error>() {
Some(Error::Rc(rcode)) => rcode.0,
@@ -98,7 +102,10 @@
_ => ResponseCode::SYSTEM_ERROR.0,
},
};
- Err(BinderStatus::new_service_specific_error(rc, None))
+ Err(BinderStatus::new_service_specific_error(
+ rc,
+ anyhow_error_to_cstring(&e).as_deref(),
+ ))
},
handle_ok,
)
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index 84d741f..f34c5da 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -37,6 +37,7 @@
};
use keystore2_selinux as selinux;
use std::cmp::PartialEq;
+use std::ffi::CString;
/// This is the main Keystore error type. It wraps the Keystore `ResponseCode` generated
/// from AIDL in the `Rc` variant and Keymint `ErrorCode` in the Km variant.
@@ -189,6 +190,20 @@
)
}
+/// This function turns an anyhow error into an optional CString.
+/// This is especially useful to add a message string to a service specific error.
+/// If the formatted string was not convertible because it contained a nul byte,
+/// None is returned and a warning is logged.
+pub fn anyhow_error_to_cstring(e: &anyhow::Error) -> Option<CString> {
+ match CString::new(format!("{:?}", e)) {
+ Ok(msg) => Some(msg),
+ Err(_) => {
+ log::warn!("Cannot convert error message to CStr. It contained a nul byte.");
+ None
+ }
+ }
+}
+
/// This function behaves similar to map_or_log_error, but it does not log the errors, instead
/// it calls map_err on the error before mapping it to a binder result allowing callers to
/// log or transform the error before mapping it.
@@ -205,7 +220,10 @@
|e| {
let e = map_err(e);
let rc = get_error_code(&e);
- Err(BinderStatus::new_service_specific_error(rc, None))
+ Err(BinderStatus::new_service_specific_error(
+ rc,
+ anyhow_error_to_cstring(&e).as_deref(),
+ ))
},
handle_ok,
)
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index ca73820..d5feee1 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -22,12 +22,14 @@
use crate::globals::{DB, LEGACY_MIGRATOR, SUPER_KEY};
use crate::permission::{KeyPerm, KeystorePerm};
use crate::super_key::UserState;
-use crate::utils::{check_key_permission, check_keystore_permission, watchdog as wd};
+use crate::utils::{
+ check_key_permission, check_keystore_permission, list_key_entries, watchdog as wd,
+};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
};
use android_security_maintenance::aidl::android::security::maintenance::{
- IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
+ IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance, UID_SELF},
UserState::UserState as AidlUserState,
};
use android_security_maintenance::binder::{
@@ -37,6 +39,7 @@
use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
use anyhow::{Context, Result};
use keystore2_crypto::Password;
+use keystore2_selinux as selinux;
/// Reexport Domain for the benefit of DeleteListener
pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
@@ -214,46 +217,64 @@
}
fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
- let caller_uid = ThreadState::get_calling_uid();
let migrate_any_key_permission =
check_keystore_permission(KeystorePerm::MigrateAnyKey).is_ok();
- DB.with(|db| {
- let key_id_guard = match source.domain {
- Domain::APP | Domain::SELINUX | Domain::KEY_ID => {
- let (key_id_guard, _) = LEGACY_MIGRATOR
- .with_try_migrate(source, caller_uid, || {
- db.borrow_mut().load_key_entry(
- source,
- KeyType::Client,
- KeyEntryLoadBits::NONE,
- caller_uid,
- |k, av| {
- if !migrate_any_key_permission {
- check_key_permission(KeyPerm::Use, k, &av)?;
- check_key_permission(KeyPerm::Delete, k, &av)?;
- check_key_permission(KeyPerm::Grant, k, &av)?;
- }
- Ok(())
- },
- )
- })
- .context("In migrate_key_namespace: Failed to load key blob.")?;
- key_id_guard
- }
- _ => {
- return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(concat!(
- "In migrate_key_namespace: ",
- "Source domain must be one of APP, SELINUX, or KEY_ID."
- ))
- }
- };
+ let src_uid = match source.domain {
+ Domain::SELINUX | Domain::KEY_ID => ThreadState::get_calling_uid(),
+ Domain::APP if source.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
+ Domain::APP if source.nspace != UID_SELF.into() && migrate_any_key_permission => {
+ source.nspace as u32
+ }
+ _ => {
+ return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
+ "In migrate_key_namespace:
+ Source domain must be one of APP, SELINUX, or KEY_ID.",
+ )
+ }
+ };
- db.borrow_mut().migrate_key_namespace(key_id_guard, destination, caller_uid, |k| {
- if !migrate_any_key_permission {
- check_key_permission(KeyPerm::Rebind, k, &None)?;
+ let dest_uid = match destination.domain {
+ Domain::SELINUX => ThreadState::get_calling_uid(),
+ Domain::APP if destination.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
+ Domain::APP if destination.nspace != UID_SELF.into() && migrate_any_key_permission => {
+ destination.nspace as u32
+ }
+ _ => {
+ return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
+ "In migrate_key_namespace:
+ Destination domain must be one of APP or SELINUX.",
+ )
+ }
+ };
+
+ DB.with(|db| {
+ let (key_id_guard, _) = LEGACY_MIGRATOR
+ .with_try_migrate(source, src_uid, || {
+ db.borrow_mut().load_key_entry(
+ source,
+ KeyType::Client,
+ KeyEntryLoadBits::NONE,
+ src_uid,
+ |k, av| {
+ if migrate_any_key_permission {
+ Ok(())
+ } else {
+ check_key_permission(KeyPerm::Use, k, &av)?;
+ check_key_permission(KeyPerm::Delete, k, &av)?;
+ check_key_permission(KeyPerm::Grant, k, &av)
+ }
+ },
+ )
+ })
+ .context("In migrate_key_namespace: Failed to load key blob.")?;
+
+ db.borrow_mut().migrate_key_namespace(key_id_guard, destination, dest_uid, |k| {
+ if migrate_any_key_permission {
+ Ok(())
+ } else {
+ check_key_permission(KeyPerm::Rebind, k, &None)
}
- Ok(())
})
})
}
@@ -266,6 +287,30 @@
Maintenance::call_on_all_security_levels("deleteAllKeys", |dev| dev.deleteAllKeys())
}
+
+ fn list_entries(domain: Domain, nspace: i64) -> Result<Vec<KeyDescriptor>> {
+ let k = match domain {
+ Domain::APP | Domain::SELINUX => KeyDescriptor{domain, nspace, ..Default::default()},
+ _ => return Err(Error::perm()).context(
+ "In list_entries: List entries is only supported for Domain::APP and Domain::SELINUX."
+ ),
+ };
+
+ // The caller has to have either GetInfo for the namespace or List permission
+ check_key_permission(KeyPerm::GetInfo, &k, &None)
+ .or_else(|e| {
+ if Some(&selinux::Error::PermissionDenied)
+ == e.root_cause().downcast_ref::<selinux::Error>()
+ {
+ check_keystore_permission(KeystorePerm::List)
+ } else {
+ Err(e)
+ }
+ })
+ .context("In list_entries: While checking key and keystore permission.")?;
+
+ DB.with(|db| list_key_entries(&mut db.borrow_mut(), domain, nspace))
+ }
}
impl Interface for Maintenance {}
@@ -315,6 +360,11 @@
map_or_log_err(Self::migrate_key_namespace(source, destination), Ok)
}
+ fn listEntries(&self, domain: Domain, namespace: i64) -> BinderResult<Vec<KeyDescriptor>> {
+ let _wp = wd::watch_millis("IKeystoreMaintenance::listEntries", 500);
+ map_or_log_err(Self::list_entries(domain, namespace), Ok)
+ }
+
fn deleteAllKeys(&self) -> BinderResult<()> {
let _wp = wd::watch_millis("IKeystoreMaintenance::deleteAllKeys", 500);
map_or_log_err(Self::delete_all_keys(), Ok)
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 4697481..2725dc2 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -22,7 +22,7 @@
use crate::security_level::KeystoreSecurityLevel;
use crate::utils::{
check_grant_permission, check_key_permission, check_keystore_permission,
- key_parameters_to_authorizations, watchdog as wd,
+ key_parameters_to_authorizations, list_key_entries, watchdog as wd,
};
use crate::{
database::Uuid,
@@ -286,22 +286,7 @@
Ok(()) => {}
};
- let mut result = LEGACY_MIGRATOR
- .list_uid(k.domain, k.nspace)
- .context("In list_entries: Trying to list legacy keys.")?;
-
- result.append(
- &mut DB
- .with(|db| {
- let mut db = db.borrow_mut();
- db.list(k.domain, k.nspace, KeyType::Client)
- })
- .context("In list_entries: Trying to list keystore database.")?,
- );
-
- result.sort_unstable();
- result.dedup();
- Ok(result)
+ DB.with(|db| list_key_entries(&mut db.borrow_mut(), k.domain, k.nspace))
}
fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index f6d92ee..82e6700 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -18,6 +18,10 @@
use crate::error::{map_binder_status, Error, ErrorCode};
use crate::permission;
use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
+use crate::{
+ database::{KeyType, KeystoreDB},
+ globals::LEGACY_MIGRATOR,
+};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
KeyCharacteristics::KeyCharacteristics, Tag::Tag,
};
@@ -27,9 +31,9 @@
ResponseCode::ResponseCode as ApcResponseCode,
};
use android_system_keystore2::aidl::android::system::keystore2::{
- Authorization::Authorization, KeyDescriptor::KeyDescriptor,
+ Authorization::Authorization, Domain::Domain, KeyDescriptor::KeyDescriptor,
};
-use anyhow::Context;
+use anyhow::{Context, Result};
use binder::{Strong, ThreadState};
use keystore2_apc_compat::{
ApcCompatUiOptions, APC_COMPAT_ERROR_ABORTED, APC_COMPAT_ERROR_CANCELLED,
@@ -199,6 +203,28 @@
rustutils::users::multiuser_get_user_id(uid)
}
+/// List all key aliases for a given domain + namespace.
+pub fn list_key_entries(
+ db: &mut KeystoreDB,
+ domain: Domain,
+ namespace: i64,
+) -> Result<Vec<KeyDescriptor>> {
+ let mut result = Vec::new();
+ result.append(
+ &mut LEGACY_MIGRATOR
+ .list_uid(domain, namespace)
+ .context("In list_key_entries: Trying to list legacy keys.")?,
+ );
+ result.append(
+ &mut db
+ .list(domain, namespace, KeyType::Client)
+ .context("In list_key_entries: Trying to list keystore database.")?,
+ );
+ result.sort_unstable();
+ result.dedup();
+ Ok(result)
+}
+
/// This module provides helpers for simplified use of the watchdog module.
#[cfg(feature = "watchdog")]
pub mod watchdog {