Encryption-at-rest: Support for AES-256-GCM and ChaCha20-Poly1305 for S/MIME (closes #161)
This commit is contained in:
@@ -16,6 +16,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use common::{
|
||||
Server,
|
||||
auth::{
|
||||
AccessToken, Permissions, PermissionsGroup,
|
||||
credential::{ApiKey, AppPassword},
|
||||
@@ -23,6 +24,7 @@ use common::{
|
||||
},
|
||||
cache::invalidate::CacheInvalidationBuilder,
|
||||
ipc::CacheInvalidation,
|
||||
storage::encryption::{EncryptionMethod, parse_public_key},
|
||||
};
|
||||
use directory::core::secret::{SecretVerificationResult, hash_secret, verify_mfa_secret_hash};
|
||||
use jmap_proto::{error::set::SetError, request::MaybeInvalid, types::state::State};
|
||||
@@ -33,8 +35,8 @@ use registry::{
|
||||
enums::{CredentialType, StorageQuota},
|
||||
prelude::{MASKED_PASSWORD, Object, ObjectInner, ObjectType, Property},
|
||||
structs::{
|
||||
Account, AccountPassword, AccountSettings, Credential, CredentialPermissions, OtpAuth,
|
||||
SecondaryCredential,
|
||||
Account, AccountPassword, AccountSettings, Credential, CredentialPermissions,
|
||||
EncryptionAtRest, OtpAuth, PublicKey, SecondaryCredential,
|
||||
},
|
||||
},
|
||||
types::{datetime::UTCDateTime, id::ObjectId},
|
||||
@@ -105,6 +107,22 @@ pub(crate) async fn account_set(
|
||||
}
|
||||
}
|
||||
|
||||
if account.encryption_at_rest != old_account.encryption_at_rest
|
||||
&& let Some(algorithm) =
|
||||
unsupported_pgp_algorithm(set.server, &account.encryption_at_rest).await?
|
||||
{
|
||||
account = old_account.clone();
|
||||
set.response.not_updated.append(
|
||||
id,
|
||||
SetError::invalid_properties()
|
||||
.with_property(Property::EncryptionAtRest)
|
||||
.with_description(format!(
|
||||
"{algorithm} is only supported for S/MIME encryption, but the selected public key is an OpenPGP key."
|
||||
)),
|
||||
);
|
||||
break 'outer;
|
||||
}
|
||||
|
||||
set.response.updated.append(id, None);
|
||||
}
|
||||
}
|
||||
@@ -897,6 +915,32 @@ pub(crate) async fn credential_query(
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
async fn unsupported_pgp_algorithm(
|
||||
server: &Server,
|
||||
encryption_at_rest: &EncryptionAtRest,
|
||||
) -> trc::Result<Option<&'static str>> {
|
||||
let (settings, algorithm) = match encryption_at_rest {
|
||||
EncryptionAtRest::Aes256Gcm(settings) => (settings, "AES-256-GCM"),
|
||||
EncryptionAtRest::ChaCha20Poly1305(settings) => (settings, "ChaCha20-Poly1305"),
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
||||
if let Some(public_key) = server
|
||||
.registry()
|
||||
.object::<PublicKey>(settings.public_key)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
&& matches!(
|
||||
parse_public_key(&public_key),
|
||||
Ok(Some(params)) if params.method == EncryptionMethod::PGP
|
||||
)
|
||||
{
|
||||
Ok(Some(algorithm))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate_credential_permissions(
|
||||
access_token: &AccessToken,
|
||||
credential: &SecondaryCredential,
|
||||
|
||||
Reference in New Issue
Block a user