#[cfg(any(feature = "internal", feature = "secrets"))]
use bitwarden_crypto::KeyStore;
#[cfg(feature = "secrets")]
use bitwarden_crypto::SymmetricCryptoKey;
#[cfg(feature = "internal")]
use bitwarden_crypto::UnsignedSharedKey;
use bitwarden_error::bitwarden_error;
use thiserror::Error;
#[cfg(feature = "internal")]
use tracing::{info, instrument};
#[cfg(any(feature = "secrets", feature = "internal"))]
use crate::OrganizationId;
#[cfg(any(feature = "internal", feature = "secrets"))]
use crate::key_management::{KeySlotIds, SymmetricKeySlotId};
use crate::{MissingPrivateKeyError, error::UserIdAlreadySetError};
#[allow(missing_docs)]
#[bitwarden_error(flat)]
#[derive(Debug, Error)]
pub enum EncryptionSettingsError {
#[error("Cryptography error, {0}")]
Crypto(#[from] bitwarden_crypto::CryptoError),
#[error("Cryptography Initialization error")]
CryptoInitialization,
#[error(transparent)]
MissingPrivateKey(#[from] MissingPrivateKeyError),
#[error(transparent)]
UserIdAlreadySet(#[from] UserIdAlreadySetError),
#[error("Wrong Pin")]
WrongPin,
#[error("Unable to set user-key to state")]
UserKeyStateUpdateFailed,
#[error("Unable to retrieve user-key from state")]
UserKeyStateRetrievalFailed,
#[error("Invalid upgrade token")]
InvalidUpgradeToken,
#[error("Key connector retrieval failed")]
KeyConnectorRetrievalFailed,
#[error("Unable to initialize local user data key")]
LocalUserDataKeyInitFailed,
#[error("Unable to load local user data key into key store")]
LocalUserDataKeyLoadFailed,
}
#[allow(missing_docs)]
pub struct EncryptionSettings {}
impl EncryptionSettings {
#[cfg(feature = "secrets")]
pub(crate) fn new_single_org_key(
organization_id: OrganizationId,
key: SymmetricCryptoKey,
store: &KeyStore<KeySlotIds>,
) {
#[allow(deprecated)]
store
.context_mut()
.set_symmetric_key(SymmetricKeySlotId::Organization(organization_id), key)
.expect("Mutable context");
}
#[cfg(feature = "internal")]
#[instrument(err, skip_all)]
pub(crate) fn set_org_keys(
org_enc_keys: Vec<(OrganizationId, UnsignedSharedKey)>,
store: &KeyStore<KeySlotIds>,
) -> Result<(), EncryptionSettingsError> {
use crate::key_management::PrivateKeySlotId;
let mut ctx = store.context_mut();
if org_enc_keys.is_empty() {
info!("No organization keys to set");
return Ok(());
}
if !ctx.has_private_key(PrivateKeySlotId::UserPrivateKey) {
info!("User private key is missing, cannot set organization keys");
return Err(MissingPrivateKeyError.into());
}
ctx.retain_symmetric_keys(|key_ref| {
!matches!(key_ref, SymmetricKeySlotId::Organization(_))
});
info!("Decrypting organization keys");
for (org_id, org_enc_key) in org_enc_keys {
let _span =
tracing::span!(tracing::Level::INFO, "decapsulate_org_key", org_id = %org_id)
.entered();
match org_enc_key.decapsulate(PrivateKeySlotId::UserPrivateKey, &mut ctx) {
Err(e) => {
tracing::error!("Failed to decapsulate organization key: {}", e);
return Err(e.into());
}
Ok(org_symmetric_key) => {
tracing::info!(
org_id = %org_id,
"Successfully decapsulated organization key for org",
);
ctx.persist_symmetric_key(
org_symmetric_key,
SymmetricKeySlotId::Organization(org_id),
)?;
}
}
}
Ok(())
}
}