Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Prevent CFB128 and CFB64 for AES and 3DES persisted keys
  • Loading branch information
vcsjones committed Jul 11, 2021
commit 0596d6d52dee609e8b6c866c9f1e59369ed98a29
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ private CngKey ProduceCngKey()
return CngKey.Open(_keyName!, _provider!, _optionOptions);
}

private bool KeyInPlainText
public bool KeyInPlainText
{
get { return _keyName == null; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,23 @@ protected override bool TryEncryptCfbCore(
}
}

private static void ValidateCFBFeedbackSize(int feedback)
private void ValidateCFBFeedbackSize(int feedback)
{
// only 8bits/128bits feedback would be valid.
if (feedback != 8 && feedback != 128)
if (_core.KeyInPlainText)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
// CFB8 and CFB128 are valid for bcrypt keys.
if (feedback != 8 && feedback != 128)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
}
}
else
{
// CFB8 is only supported for ncrypt keys.
if (feedback != 8)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,23 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}

private static void ValidateCFBFeedbackSize(int feedback)
private void ValidateCFBFeedbackSize(int feedback)
{
// only 8bits/64bits feedback would be valid.
if (feedback != 8 && feedback != 64)
if (_core.KeyInPlainText)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
// CFB8 and CFB164 are valid for bcrypt keys.
if (feedback != 8 && feedback != 64)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
}
}
else
{
// CFB8 is only supported for ncrypt keys.
if (feedback != 8)
{
throw new CryptographicException(string.Format(SR.Cryptography_CipherModeFeedbackNotSupported, feedback, CipherMode.CFB));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ public static class AesCngTests
[InlineData(192, BlockSizeBytes + BlockSizeBytes / 2, CipherMode.CBC, PaddingMode.PKCS7)]
// AES128-CFB8-NoPadding at 2 blocks
[InlineData(128, 2 * BlockSizeBytes, CipherMode.CFB, PaddingMode.None, 8)]
// AES128-CFB128-NoPadding at 2 blocks
[InlineData(128, 2 * BlockSizeBytes, CipherMode.CFB, PaddingMode.None, 128)]
public static void VerifyPersistedKey(
int keySize,
int plainBytesCount,
Expand Down Expand Up @@ -100,6 +98,16 @@ public static void VerifyMachineKey()
() => new AesCng());
}

[OuterLoop("Creates/Deletes a persisted key, limit exposure to key leaking")]
[ConditionalFact(nameof(SupportsPersistedSymmetricKeys))]
public static void VerifyUnsupportedFeedbackSizeForPersistedCfb()
{
SymmetricCngTestHelpers.VerifyOneShotCfbPersistedUnsupportedFeedbackSize(
s_cngAlgorithm,
keyName => new AesCng(keyName),
notSupportedFeedbackSizeInBits: 128);
}

public static bool SupportsPersistedSymmetricKeys
{
get { return SymmetricCngTestHelpers.SupportsPersistedSymmetricKeys; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,32 @@ public static void VerifyMachineKey(
}
}

public static void VerifyOneShotCfbPersistedUnsupportedFeedbackSize(
CngAlgorithm algorithm,
Func<string, SymmetricAlgorithm> persistedFunc,
int notSupportedFeedbackSizeInBits)
{
string keyName = Guid.NewGuid().ToString();

// We try to delete the key later which will also dispose of it, so no need
// to put this in a using.
CngKey cngKey = CngKey.Create(algorithm, keyName);

try
{
using (SymmetricAlgorithm alg = persistedFunc(keyName))
{
byte[] destination = new byte[alg.BlockSize / 8];
Assert.ThrowsAny<CryptographicException>(() =>
alg.EncryptCfb(Array.Empty<byte>(), destination, PaddingMode.None, notSupportedFeedbackSizeInBits));
}
}
finally
{
cngKey.Delete();
}
}

private static bool? s_supportsPersistedSymmetricKeys;
internal static bool SupportsPersistedSymmetricKeys
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public static void VerifyDefaults()
[InlineData(BlockSizeBytes + BlockSizeBytes / 2, CipherMode.CBC, PaddingMode.Zeros)]
// 3DES192-CBC-PKCS7 at 1.5 blocks
[InlineData(BlockSizeBytes + BlockSizeBytes / 2, CipherMode.CBC, PaddingMode.PKCS7)]
// 3DES192-CFB8-NoPadding at 2 blocks
[InlineData(2 * BlockSizeBytes, CipherMode.CFB, PaddingMode.None, 8)]
public static void VerifyPersistedKey(
int plainBytesCount,
CipherMode cipherMode,
Expand Down Expand Up @@ -102,6 +104,16 @@ public static void VerifyMachineKey()
() => new TripleDESCng());
}

[OuterLoop("Creates/Deletes a persisted key, limit exposure to key leaking")]
[ConditionalFact(nameof(SupportsPersistedSymmetricKeys))]
public static void VerifyUnsupportedFeedbackSizeForPersistedCfb()
{
SymmetricCngTestHelpers.VerifyOneShotCfbPersistedUnsupportedFeedbackSize(
s_cngAlgorithm,
keyName => new TripleDESCng(keyName),
notSupportedFeedbackSizeInBits: 64);
}

public static bool SupportsPersistedSymmetricKeys
{
get { return SymmetricCngTestHelpers.SupportsPersistedSymmetricKeys; }
Expand Down