Implement Rust-owned Android Keystore secure storage (#93)
Dependency security audit / rustsec (push) Failing after 23s

This commit is contained in:
hugo committed 2026-10-08 16:22:57 +02:00
1 parent 874c8139a4
commit 1abd75282e
36 files changed
+4380 -37

No files matched your search

+1
View File
@@ -92,6 +92,7 @@ zbus-secret-service-keyring-store = { workspace = true, optional = true }
arboard = { workspace = true, optional = true }
[dev-dependencies]
aes-gcm = "0.11.1"
hex = "0.4"
keepass = { workspace = true, features = ["save_kdbx4"] }
nix = { version = "0.31", features = ["fs"] }
+6 -3
View File
@@ -107,11 +107,14 @@ impl MobileAuthenticationError {
"IronStorage Locked",
"The authentication lease expired.",
),
AuthenticationError::SecretStore(SecretStoreError::Missing) => {
Self::passphrase_required("Enter the GPG key passphrase to continue.")
}
AuthenticationError::SecretStore(
SecretStoreError::Missing
| SecretStoreError::DeviceKeyMissing
| SecretStoreError::Invalidated,
) => Self::passphrase_required("Enter the GPG key passphrase to continue."),
AuthenticationError::SecretStore(
SecretStoreError::Denied
| SecretStoreError::Lockout
| SecretStoreError::UnsupportedProtection
| SecretStoreError::Unavailable,
) => Self::new(
+14 -2
View File
@@ -275,6 +275,14 @@ impl PrivateStorage {
Ok(storage)
}
pub fn android_secret_backend(
&self,
keystore: std::sync::Arc<dyn crate::secret_store::android::AndroidKeystore>,
) -> Result<crate::secret_store::android::AndroidSecretBackend, PrivateStorageError> {
let directory = private_directory(&self.data, "secrets")?;
crate::secret_store::android::AndroidSecretBackend::open(directory, keystore)
.map_err(secret_error)
}
pub fn root(&self) -> &Path {
&self.root
}
@@ -476,8 +484,12 @@ fn secret_error(error: SecretStoreError) -> PrivateStorageError {
SecretStoreError::Locked | SecretStoreError::Denied | SecretStoreError::Cancelled => {
PrivateStorageError::SecureStorageLocked
}
SecretStoreError::Missing => PrivateStorageError::RestoredWithoutKeystore,
SecretStoreError::Corrupted => PrivateStorageError::InvalidSecureBinding,
SecretStoreError::Missing | SecretStoreError::DeviceKeyMissing => {
PrivateStorageError::RestoredWithoutKeystore
}
SecretStoreError::Corrupted | SecretStoreError::Invalidated => {
PrivateStorageError::InvalidSecureBinding
}
_ => PrivateStorageError::SecureStorageUnavailable,
}
}
+9
View File
@@ -16,6 +16,7 @@ use crate::{
repository::SecretBytes,
};
pub mod android;
mod platform;
pub(crate) use platform::NativeSecretBackend;
@@ -283,6 +284,9 @@ impl SecretCachePolicy {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SecretStoreError {
DeviceKeyMissing,
Invalidated,
Lockout,
InvalidReference,
InvalidCachePolicy,
AlreadyExists,
@@ -298,6 +302,11 @@ pub enum SecretStoreError {
impl fmt::Display for SecretStoreError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match self {
Self::DeviceKeyMissing => {
"the device key is missing; recover the protected secret manually"
}
Self::Invalidated => "the protected key was invalidated; recover the secret manually",
Self::Lockout => "biometric authentication is locked out",
Self::InvalidReference => "the secret reference is invalid",
Self::InvalidCachePolicy => "the secret cache policy is invalid",
Self::AlreadyExists => "the referenced secret already exists",
File diff suppressed because it is too large. Load diff