bitwarden_core/client/
encryption_settings.rsuse std::collections::HashMap;
use bitwarden_crypto::{AsymmetricCryptoKey, CryptoError, KeyContainer, SymmetricCryptoKey};
#[cfg(feature = "internal")]
use bitwarden_crypto::{AsymmetricEncString, EncString, MasterKey};
use bitwarden_error::prelude::*;
use thiserror::Error;
use uuid::Uuid;
#[cfg(feature = "internal")]
use crate::error::Result;
use crate::VaultLocked;
#[bitwarden_error(flat)]
#[derive(Debug, Error)]
pub enum EncryptionSettingsError {
#[error("Cryptography error, {0}")]
Crypto(#[from] bitwarden_crypto::CryptoError),
#[error(transparent)]
InvalidBase64(#[from] base64::DecodeError),
#[error(transparent)]
VaultLocked(#[from] VaultLocked),
#[error("Invalid private key")]
InvalidPrivateKey,
#[error("Missing private key")]
MissingPrivateKey,
}
#[derive(Clone)]
pub struct EncryptionSettings {
user_key: SymmetricCryptoKey,
pub(crate) private_key: Option<AsymmetricCryptoKey>,
org_keys: HashMap<Uuid, SymmetricCryptoKey>,
}
impl std::fmt::Debug for EncryptionSettings {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EncryptionSettings").finish()
}
}
impl EncryptionSettings {
#[cfg(feature = "internal")]
pub(crate) fn new(
master_key: MasterKey,
user_key: EncString,
private_key: EncString,
) -> Result<Self, EncryptionSettingsError> {
let user_key = master_key.decrypt_user_key(user_key)?;
Self::new_decrypted_key(user_key, private_key)
}
#[cfg(feature = "internal")]
pub(crate) fn new_decrypted_key(
user_key: SymmetricCryptoKey,
private_key: EncString,
) -> Result<Self, EncryptionSettingsError> {
use bitwarden_crypto::KeyDecryptable;
use log::warn;
let private_key = {
let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
AsymmetricCryptoKey::from_der(&dec)
.map_err(|_| {
warn!("Invalid private key");
})
.ok()
};
Ok(EncryptionSettings {
user_key,
private_key,
org_keys: HashMap::new(),
})
}
#[cfg(feature = "secrets")]
pub(crate) fn new_single_key(key: SymmetricCryptoKey) -> Self {
EncryptionSettings {
user_key: key,
private_key: None,
org_keys: HashMap::new(),
}
}
#[cfg(feature = "internal")]
pub(crate) fn set_org_keys(
&mut self,
org_enc_keys: Vec<(Uuid, AsymmetricEncString)>,
) -> Result<&Self, EncryptionSettingsError> {
use bitwarden_crypto::KeyDecryptable;
self.org_keys.clear();
if org_enc_keys.is_empty() {
return Ok(self);
}
let private_key = self
.private_key
.as_ref()
.ok_or(EncryptionSettingsError::MissingPrivateKey)?;
for (org_id, org_enc_key) in org_enc_keys {
let mut dec: Vec<u8> = org_enc_key.decrypt_with_key(private_key)?;
let org_key = SymmetricCryptoKey::try_from(dec.as_mut_slice())?;
self.org_keys.insert(org_id, org_key);
}
Ok(self)
}
pub fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError> {
if self.private_key.is_none() {
return Ok(&self.user_key);
}
match org_id {
Some(org_id) => self
.org_keys
.get(org_id)
.ok_or(CryptoError::MissingKey(*org_id)),
None => Ok(&self.user_key),
}
}
}
impl KeyContainer for EncryptionSettings {
fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError> {
EncryptionSettings::get_key(self, org_id)
}
}