Skip to content

Commit

Permalink
Change FeedbackSize on Rijndael wrappers to delegate to implementation.
Browse files Browse the repository at this point in the history
The FeedbackSize on RijndaelManaged and RijndaelImplementation were not
accurately reflecting the feedback size that the actual implementation
was using. The FeedbackSize would report 128, however the implementation
defaults to 8, so CFB8 is actually what was being used.

Likewise, the setter for FeedbackSize on the Rijndael types had no
effect. The implementation's default feedback size of 8 would always
be used.
  • Loading branch information
vcsjones committed Jan 7, 2021
1 parent 533a807 commit 595c616
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
Expand Up @@ -23,6 +23,7 @@ internal RijndaelImplementation()

// This class wraps Aes
_impl = Aes.Create();
_impl.FeedbackSize = 128;
}

public override int BlockSize
Expand All @@ -42,6 +43,12 @@ public override int BlockSize
}
}

public override int FeedbackSize
{
get => _impl.FeedbackSize;
set => _impl.FeedbackSize = value;
}

public override byte[] IV
{
get { return _impl.IV; }
Expand Down
Expand Up @@ -19,6 +19,7 @@ public RijndaelManaged()

// This class wraps Aes
_impl = Aes.Create();
_impl.FeedbackSize = 128;
}

public override int BlockSize
Expand All @@ -38,6 +39,12 @@ public override int BlockSize
}
}

public override int FeedbackSize
{
get => _impl.FeedbackSize;
set => _impl.FeedbackSize = value;
}

public override byte[] IV
{
get { return _impl.IV; }
Expand Down
Expand Up @@ -25,13 +25,15 @@ static void test(Rijndael alg)
Assert.Equal(128, alg.LegalBlockSizes[0].MinSize);
Assert.Equal(128, alg.LegalBlockSizes[0].MaxSize);
Assert.Equal(128, alg.BlockSize);
Assert.Equal(128, alg.FeedbackSize);

// Different exception since we have different supported BlockSizes than desktop
Assert.Throws<PlatformNotSupportedException>(() => alg.BlockSize = 192);
Assert.Throws<PlatformNotSupportedException>(() => alg.BlockSize = 256);

// Normal exception for rest
Assert.Throws<CryptographicException>(() => alg.BlockSize = 111);
Assert.Throws<CryptographicException>(() => alg.FeedbackSize = 15);

Assert.Equal(CipherMode.CBC, alg.Mode);
Assert.Equal(PaddingMode.PKCS7, alg.Padding);
Expand Down Expand Up @@ -169,6 +171,9 @@ static void test(Rijndael alg)

alg.Padding = PaddingMode.PKCS7;
Assert.Equal(PaddingMode.PKCS7, alg.Padding);

alg.FeedbackSize = 8;
Assert.Equal(8, alg.FeedbackSize);
}

using (var alg = Rijndael.Create())
Expand Down Expand Up @@ -291,6 +296,51 @@ public static void MultipleBlockDecryptTransform(bool blockAlignedOutput)
Assert.Equal(ExpectedOutput, decrypted);
}

[Theory]
[InlineData(128)]
[InlineData(8)]
[InlineData(null)]
public static void CfbFeedbackSizeIsRespected(int? feedbackSize)
{
// Windows 7 CFB only supports CFB8.
if (PlatformDetection.IsWindows7 && feedbackSize != 8)
return;

void Test(Rijndael alg)
{
alg.Mode = CipherMode.CFB;

if (feedbackSize == null)
{
feedbackSize = alg.FeedbackSize;
}
else
{
alg.FeedbackSize = feedbackSize.Value;
}

int feedbackSizeBytes = feedbackSize.Value / 8;
byte[] input = new byte[feedbackSizeBytes + 1];

using ICryptoTransform transform = alg.CreateEncryptor();

byte[] output = transform.TransformFinalBlock(input, 0, input.Length);
int expectedOutputSize = (input.Length / feedbackSizeBytes) * feedbackSizeBytes + feedbackSizeBytes;

Assert.Equal(expectedOutputSize, output.Length);
}

using (Rijndael alg = new RijndaelManaged())
{
Test(alg);
}

using (Rijndael alg = Rijndael.Create())
{
Test(alg);
}
}

private class RijndaelLegalSizesBreaker : RijndaelMinimal
{
public RijndaelLegalSizesBreaker()
Expand Down

0 comments on commit 595c616

Please sign in to comment.