From dd33b1eb28dea68342418536721a1e63ad570b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garci=CC=81a?= Date: Wed, 11 Oct 2023 15:39:13 +0200 Subject: [PATCH 1/2] [PM-4270] Individual cipher key encryption --- crates/bitwarden/src/vault/cipher/cipher.rs | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index b01f17136..36fcf71c8 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -43,6 +43,8 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, + pub key: Option, + pub name: EncString, pub notes: Option, @@ -77,6 +79,8 @@ pub struct CipherView { pub folder_id: Option, pub collection_ids: Vec, + pub key: Option, + pub name: String, pub notes: Option, @@ -131,11 +135,15 @@ pub struct CipherListView { impl KeyEncryptable for CipherView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + let key_owned = Cipher::get_cipher_key(key, &self.key)?; + let key = key_owned.as_ref().unwrap_or(key); + Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, + key: self.key, name: self.name.encrypt_with_key(key)?, notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, @@ -161,11 +169,15 @@ impl KeyEncryptable for CipherView { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let key_owned = Cipher::get_cipher_key(key, &self.key)?; + let key = key_owned.as_ref().unwrap_or(key); + Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), + key: self.key.clone(), name: self.name.decrypt_with_key(key)?, notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, @@ -190,6 +202,19 @@ impl KeyDecryptable for Cipher { } impl Cipher { + fn get_cipher_key( + key: &SymmetricCryptoKey, + inner_key: &Option, + ) -> Result> { + inner_key + .as_ref() + .map(|k| { + let key: Vec = k.decrypt_with_key(key)?; + SymmetricCryptoKey::try_from(key.as_slice()) + }) + .transpose() + } + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { @@ -257,6 +282,9 @@ impl Cipher { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let key_owned = Cipher::get_cipher_key(key, &self.key)?; + let key = key_owned.as_ref().unwrap_or(key); + Ok(CipherListView { id: self.id, organization_id: self.organization_id, From ff7d4b0be46bbe3623670b5361d561d971b52ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garci=CC=81a?= Date: Thu, 2 Nov 2023 16:43:33 +0100 Subject: [PATCH 2/2] Fix PR comments --- crates/bitwarden/src/vault/cipher/cipher.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 36fcf71c8..b95a2f090 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -43,6 +43,7 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, + /// More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. pub key: Option, pub name: EncString, @@ -135,8 +136,8 @@ pub struct CipherListView { impl KeyEncryptable for CipherView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { - let key_owned = Cipher::get_cipher_key(key, &self.key)?; - let key = key_owned.as_ref().unwrap_or(key); + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); Ok(Cipher { id: self.id, @@ -169,8 +170,8 @@ impl KeyEncryptable for CipherView { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { - let key_owned = Cipher::get_cipher_key(key, &self.key)?; - let key = key_owned.as_ref().unwrap_or(key); + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); Ok(CipherView { id: self.id, @@ -202,11 +203,15 @@ impl KeyDecryptable for Cipher { } impl Cipher { + /// Get the decrypted individual encryption key for this cipher. + /// Note that some ciphers do not have individual encryption keys, + /// in which case this will return Ok(None) and the key associated + /// with this cipher's user or organization must be used instead fn get_cipher_key( key: &SymmetricCryptoKey, - inner_key: &Option, + ciphers_key: &Option, ) -> Result> { - inner_key + ciphers_key .as_ref() .map(|k| { let key: Vec = k.decrypt_with_key(key)?; @@ -282,8 +287,8 @@ impl Cipher { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { - let key_owned = Cipher::get_cipher_key(key, &self.key)?; - let key = key_owned.as_ref().unwrap_or(key); + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); Ok(CipherListView { id: self.id,