From cddbb7badbf63a5a9a83e8483462ad9ffcca5fc1 Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Sun, 16 Jul 2023 15:46:04 -0400 Subject: [PATCH] Add MAC Validation --- .../src/Types/EncryptedString.cs | 19 +++++++++++++++++-- .../src/Types/SymmetricCryptoKey.cs | 8 ++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/extensions/Bitwarden.Core/src/Types/EncryptedString.cs b/extensions/Bitwarden.Core/src/Types/EncryptedString.cs index 3dfbab6..4468a53 100644 --- a/extensions/Bitwarden.Core/src/Types/EncryptedString.cs +++ b/extensions/Bitwarden.Core/src/Types/EncryptedString.cs @@ -61,8 +61,6 @@ private static byte[] DecryptAes256(ReadOnlySpan encryptionPart, Symmetric throw new FormatException(); } - // TODO: Validate mac - Span data = stackalloc byte[dataPart.Length]; converted = Convert.TryFromBase64Chars(dataPart, data, out bytesWritten); if (!converted) @@ -71,6 +69,15 @@ private static byte[] DecryptAes256(ReadOnlySpan encryptionPart, Symmetric } data = data[..bytesWritten]; + + Span validatedMac = stackalloc byte[32]; + ValidateMac(symmetricCryptoKey.Mac, iv, data, validatedMac); + + if (!validatedMac.SequenceEqual(mac)) + { + throw new FormatException("Invalid MAC"); + } + Span output = stackalloc byte[data.Length]; using var aes = Aes.Create(); @@ -105,6 +112,14 @@ public static EncryptedString Parse(ReadOnlySpan s) return new EncryptedString(type, encryptionPart); } + private static void ValidateMac(Span macKey, ReadOnlySpan iv, ReadOnlySpan data, Span destination) + { + var hmac = IncrementalHash.CreateHMAC(HashAlgorithmName.SHA256, macKey); + hmac.AppendData(iv); + hmac.AppendData(data); + hmac.TryGetCurrentHash(destination, out _); + } + public static bool TryParse(ReadOnlySpan s, [MaybeNullWhen(false)] out EncryptedString result) { try diff --git a/extensions/Bitwarden.Core/src/Types/SymmetricCryptoKey.cs b/extensions/Bitwarden.Core/src/Types/SymmetricCryptoKey.cs index 6d21860..fc52cc4 100644 --- a/extensions/Bitwarden.Core/src/Types/SymmetricCryptoKey.cs +++ b/extensions/Bitwarden.Core/src/Types/SymmetricCryptoKey.cs @@ -16,10 +16,10 @@ public class SymmetricCryptoKey : ISpanParsable const int KeyLength = 32; const int MacLength = 32; - private readonly ReadOnlyMemory _rawData; + private readonly byte[] _rawData; - public ReadOnlyMemory Key => _rawData[..KeyLength]; - public ReadOnlyMemory Mac => _rawData.Length == KeyLength + MacLength ? _rawData[KeyLength..] : default; + public byte[] Key => _rawData[..KeyLength]; + public byte[]? Mac => _rawData.Length == KeyLength + MacLength ? _rawData[KeyLength..] : default; private SymmetricCryptoKey(ReadOnlySpan rawData) { @@ -99,6 +99,6 @@ public static bool TryParse(ReadOnlySpan s, [MaybeNullWhen(false)] out Sym public override string ToString() { - return Convert.ToBase64String(_rawData.Span); + return Convert.ToBase64String(_rawData); } }