Skip to content

Commit c57e3a7

Browse files
quextenHinton
andauthored
[PM-12023] Enforce hmac when mac key is present (#1041)
## 🎟️ Tracking https://bitwarden.atlassian.net/issues/PM-12023 (https://bitwarden.atlassian.net/issues/PM-4185) ## 📔 Objective Prevent downgrading of encstring types to hmac-less by enforcing hmac when the symmetric key used has a mac key. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes --------- Co-authored-by: Oscar Hinton <[email protected]>
1 parent d23ec73 commit c57e3a7

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

crates/bitwarden-crypto/src/enc_string/symmetric.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ impl KeyDecryptable<SymmetricCryptoKey, Vec<u8>> for EncString {
237237
fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result<Vec<u8>> {
238238
match self {
239239
EncString::AesCbc256_B64 { iv, data } => {
240+
if key.mac_key.is_some() {
241+
return Err(CryptoError::MacNotProvided);
242+
}
243+
240244
let dec = crate::aes::decrypt_aes256(iv, data.clone(), &key.key)?;
241245
Ok(dec)
242246
}
@@ -296,7 +300,9 @@ mod tests {
296300
use schemars::schema_for;
297301

298302
use super::EncString;
299-
use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey};
303+
use crate::{
304+
derive_symmetric_key, CryptoError, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey,
305+
};
300306

301307
#[test]
302308
fn test_enc_string_roundtrip() {
@@ -418,6 +424,24 @@ mod tests {
418424
assert_eq!(dec_str, "EncryptMe!");
419425
}
420426

427+
#[test]
428+
fn test_decrypt_downgrade_encstring_prevention() {
429+
// Simulate a potential downgrade attack by removing the mac portion of the `EncString` and
430+
// attempt to decrypt it using a `SymmetricCryptoKey` with a mac key.
431+
let key = "hvBMMb1t79YssFZkpetYsM3deyVuQv4r88Uj9gvYe0+G8EwxvW3v1iywVmSl61iwzd17JW5C/ivzxSP2C9h7Tw==".to_string();
432+
let key = SymmetricCryptoKey::try_from(key).unwrap();
433+
434+
// A "downgraded" `EncString` from `EncString::AesCbc256_HmacSha256_B64` (2) to
435+
// `EncString::AesCbc256_B64` (0), with the mac portion removed.
436+
// <enc_string>
437+
let enc_str = "0.NQfjHLr6za7VQVAbrpL81w==|wfrjmyJ0bfwkQlySrhw8dA==";
438+
let enc_string: EncString = enc_str.parse().unwrap();
439+
assert_eq!(enc_string.enc_type(), 0);
440+
441+
let result: Result<String, CryptoError> = enc_string.decrypt_with_key(&key);
442+
assert!(matches!(result, Err(CryptoError::MacNotProvided)));
443+
}
444+
421445
#[test]
422446
fn test_decrypt_cbc128_hmac() {
423447
let key = "Gt1aZ8kTTgkF80bLtb7LiMZBcxEA2FA5mbvV4x7K208=".to_string();

crates/bitwarden-crypto/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub enum CryptoError {
1111
InvalidKey,
1212
#[error("The cipher's MAC doesn't match the expected value")]
1313
InvalidMac,
14+
#[error("The key provided expects mac protected encstrings, but the mac is missing")]
15+
MacNotProvided,
1416
#[error("Error while decrypting EncString")]
1517
KeyDecrypt,
1618
#[error("The cipher key has an invalid length")]

0 commit comments

Comments
 (0)