Skip to content

Commit 6a02d5d

Browse files
authored
Enable AES encryption on Browser WASM (#70915)
* Copy RijndaelManagedTransform from reference source Copied from https://github.com/microsoft/referencesource/blob/5697c29004a34d80acdaf5742d7e699022c64ecd/mscorlib/system/security/cryptography/rijndaelmanagedtransform.cs * Format document * Clean up RijndaelManagedTransform 1. Add copyright 2. Remove unnecessary attributes 3. Mark class as internal 4. Remove FEATURE_CRYPTO define. Only support CipherMode.CBC and PaddingMode.PKCS7. 5. Remove Contracts and replace with Debug.Assert. * Get RijndaelManagedTransform to compile successfully. * Make RijndaelManagedTransform implement ILiteSymmetricCipher And hook it up to AesImplementation for Browser. * Enable all the Aes tests on Browser. Mark Aes APIs as supported on Browser. * Mark all CipherModes and PaddingModes other than CBC and PKCS7 as unsupported on Browser * Make fields readonly and rename according to code style. * Replace RijndaelManagedTransformMode with bool encrypting. * Throw PNSE for unsupported CipherMode and PaddingMode. Remove unnecessary parameters and fields that aren't supported. * Fix DecryptorReuse_LeadsToSameResults test so it works on Browser and passes for all CipherModes on other platforms * Spanify the input buffer in RijndaelManagedTransform Transform and TransformFinal. * First round of PR feedback * Make _Nb constant BlockSizeInts * Get rid of unnecessary allocations * Remove unsafe pointers from RijndaelManagedTransform. * PR feedback Encrypt and Decrypt index arrays are constant values. Use CopyTo in more places. * Rename RijndaelManagedTransform => AesManagedTransform * Change AesManagedTransform to no longer do padding. Instead, reuse the UniversalCrypto infrastructure to do padding. * Remove UnsupportedPlatform for PaddingMode * PR feedback - clean up unnecessary changes * PR feedback Remove UnsupportedOSPlatform("browser") from CipherMode and the SymmetricAlgorithm base class. These create too many false positives and aren't technically accurate since other implementations may support these on browser.
1 parent c389356 commit 6a02d5d

29 files changed

+1818
-645
lines changed

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherOneShotTests.cs

Lines changed: 529 additions & 527 deletions
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs

Lines changed: 68 additions & 16 deletions
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
88
{
99
using Aes = System.Security.Cryptography.Aes;
1010

11-
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
1211
public class AesContractTests
1312
{
1413
[Fact]
@@ -107,6 +106,7 @@ public static void InvalidKeySizes(int invalidKeySize, bool skipOnNetfx)
107106
[InlineData(64, false)]
108107
[InlineData(256, true)]
109108
[InlineData(127, true)]
109+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
110110
public static void InvalidCFBFeedbackSizes(int feedbackSize, bool discoverableInSetter)
111111
{
112112
using (Aes aes = AesFactory.Create())
@@ -139,6 +139,7 @@ public static void InvalidCFBFeedbackSizes(int feedbackSize, bool discoverableIn
139139
[Theory]
140140
[InlineData(8)]
141141
[InlineData(128)]
142+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
142143
public static void ValidCFBFeedbackSizes(int feedbackSize)
143144
{
144145
// Windows 7 only supports CFB8.
@@ -302,25 +303,28 @@ public static void CreateTransformExceptions()
302303
Assert.Throws<CryptographicException>(() => aes.CreateDecryptor(key, null));
303304
}
304305

305-
using (Aes aes = AesFactory.Create())
306+
if (PlatformDetection.IsNotBrowser)
306307
{
307-
aes.Mode = CipherMode.ECB;
308+
using (Aes aes = AesFactory.Create())
309+
{
310+
aes.Mode = CipherMode.ECB;
308311

309-
Assert.Throws<ArgumentNullException>(() => aes.CreateEncryptor(null, iv));
310-
Assert.Throws<ArgumentNullException>(() => aes.CreateEncryptor(null, null));
312+
Assert.Throws<ArgumentNullException>(() => aes.CreateEncryptor(null, iv));
313+
Assert.Throws<ArgumentNullException>(() => aes.CreateEncryptor(null, null));
311314

312-
Assert.Throws<ArgumentNullException>(() => aes.CreateDecryptor(null, iv));
313-
Assert.Throws<ArgumentNullException>(() => aes.CreateDecryptor(null, null));
315+
Assert.Throws<ArgumentNullException>(() => aes.CreateDecryptor(null, iv));
316+
Assert.Throws<ArgumentNullException>(() => aes.CreateDecryptor(null, null));
314317

315-
// ECB will accept an IV (but ignore it), and doesn't require it.
316-
using (ICryptoTransform didNotThrow = aes.CreateEncryptor(key, null))
317-
{
318-
Assert.NotNull(didNotThrow);
319-
}
318+
// ECB will accept an IV (but ignore it), and doesn't require it.
319+
using (ICryptoTransform didNotThrow = aes.CreateEncryptor(key, null))
320+
{
321+
Assert.NotNull(didNotThrow);
322+
}
320323

321-
using (ICryptoTransform didNotThrow = aes.CreateDecryptor(key, null))
322-
{
323-
Assert.NotNull(didNotThrow);
324+
using (ICryptoTransform didNotThrow = aes.CreateDecryptor(key, null))
325+
{
326+
Assert.NotNull(didNotThrow);
327+
}
324328
}
325329
}
326330
}
@@ -382,6 +386,7 @@ public static void ValidateOffsetAndCount()
382386
}
383387

384388
[Fact]
389+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
385390
public static void Cfb8ModeCanDepadCfb128Padding()
386391
{
387392
using (Aes aes = AesFactory.Create())

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
1212
{
1313
using Aes = System.Security.Cryptography.Aes;
1414

15-
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
1615
public static class AesCornerTests
1716
{
1817
[Fact]

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
77
{
88
using Aes = System.Security.Cryptography.Aes;
99

10-
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
1110
public class AesModeTests
1211
{
1312
[Fact]
@@ -17,24 +16,28 @@ public static void SupportsCBC()
1716
}
1817

1918
[Fact]
19+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")]
2020
public static void SupportsECB()
2121
{
2222
SupportsMode(CipherMode.ECB);
2323
}
2424

2525
[Fact]
26+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
2627
public static void SupportsCFB8()
2728
{
2829
SupportsMode(CipherMode.CFB, feedbackSize: 8);
2930
}
3031

3132
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))]
33+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
3234
public static void SupportsCFB128()
3335
{
3436
SupportsMode(CipherMode.CFB, feedbackSize: 128);
3537
}
3638

3739
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows7))]
40+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
3841
public static void Windows7DoesNotSupportCFB128()
3942
{
4043
DoesNotSupportMode(CipherMode.CFB, feedbackSize: 128);

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
77
{
88
using Aes = System.Security.Cryptography.Aes;
99

10-
[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
1110
public static class DecryptorReusability
1211
{
1312
// See https://github.com/dotnet/runtime/issues/21354 for details

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/Symmetric/SymmetricOneShotBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ public void DerivedTypesDefineTest()
410410
}
411411

412412
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))]
413+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
413414
public void DecryptOneShot_Cfb8_ToleratesExtraPadding()
414415
{
415416
using (SymmetricAlgorithm alg = CreateAlgorithm())
@@ -469,6 +470,7 @@ public void DecryptOneShot_Cbc_InvalidPadding_DoesNotContainPlaintext(PaddingMod
469470
[InlineData(PaddingMode.PKCS7, 2048)]
470471
[InlineData(PaddingMode.ANSIX923, 2048)]
471472
[InlineData(PaddingMode.ISO10126, 2048)]
473+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.ECB is not supported on Browser")]
472474
public void DecryptOneShot_Ecb_InvalidPadding_DoesNotContainPlaintext(PaddingMode paddingMode, int ciphertextSize)
473475
{
474476
using (SymmetricAlgorithm alg = CreateAlgorithm())
@@ -495,6 +497,7 @@ public void DecryptOneShot_Ecb_InvalidPadding_DoesNotContainPlaintext(PaddingMod
495497
[InlineData(PaddingMode.PKCS7, 2048)]
496498
[InlineData(PaddingMode.ANSIX923, 2048)]
497499
[InlineData(PaddingMode.ISO10126, 2048)]
500+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
498501
public void DecryptOneShot_Cfb_InvalidPadding_DoesNotContainPlaintext(PaddingMode paddingMode, int ciphertextSize)
499502
{
500503
using (SymmetricAlgorithm alg = CreateAlgorithm())
@@ -547,6 +550,7 @@ public void DecryptOneShot_Cbc_TooShortDoesNotContainPlaintext(PaddingMode paddi
547550
[InlineData(PaddingMode.PKCS7)]
548551
[InlineData(PaddingMode.ANSIX923)]
549552
[InlineData(PaddingMode.ISO10126)]
553+
[SkipOnPlatform(TestPlatforms.Browser, "CipherMode.CFB is not supported on Browser")]
550554
public void DecryptOneShot_Cfb8_TooShortDoesNotContainPlaintext(PaddingMode paddingMode)
551555
{
552556
using (SymmetricAlgorithm alg = CreateAlgorithm())

src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ namespace System.Security.Cryptography
4747
public abstract partial class Aes : System.Security.Cryptography.SymmetricAlgorithm
4848
{
4949
protected Aes() { }
50-
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
5150
public static new System.Security.Cryptography.Aes Create() { throw null; }
5251
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")]
5352
public static new System.Security.Cryptography.Aes? Create(string algorithmName) { throw null; }
@@ -98,7 +97,6 @@ public override void GenerateKey() { }
9897
[System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId="SYSLIB0021", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
9998
public sealed partial class AesCryptoServiceProvider : System.Security.Cryptography.Aes
10099
{
101-
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
102100
public AesCryptoServiceProvider() { }
103101
public override int BlockSize { get { throw null; } set { } }
104102
public override int FeedbackSize { get { throw null; } set { } }
@@ -135,7 +133,6 @@ public void Encrypt(byte[] nonce, byte[] plaintext, byte[] ciphertext, byte[] ta
135133
}
136134
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
137135
[System.ObsoleteAttribute("Derived cryptographic types are obsolete. Use the Create method on the base type instead.", DiagnosticId="SYSLIB0021", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
138-
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
139136
public sealed partial class AesManaged : System.Security.Cryptography.Aes
140137
{
141138
public AesManaged() { }
@@ -1747,14 +1744,12 @@ public override void Reset() { }
17471744
public abstract partial class Rijndael : System.Security.Cryptography.SymmetricAlgorithm
17481745
{
17491746
protected Rijndael() { }
1750-
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
17511747
public static new System.Security.Cryptography.Rijndael Create() { throw null; }
17521748
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The default algorithm implementations might be removed, use strong type references like 'RSA.Create()' instead.")]
17531749
public static new System.Security.Cryptography.Rijndael? Create(string algName) { throw null; }
17541750
}
17551751
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
17561752
[System.ObsoleteAttribute("The Rijndael and RijndaelManaged types are obsolete. Use Aes instead.", DiagnosticId="SYSLIB0022", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
1757-
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
17581753
public sealed partial class RijndaelManaged : System.Security.Cryptography.Rijndael
17591754
{
17601755
public RijndaelManaged() { }

src/libraries/System.Security.Cryptography/src/Resources/Strings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,4 +753,7 @@
753753
<data name="Unknown_Error" xml:space="preserve">
754754
<value>Unknown error.</value>
755755
</data>
756+
<data name="PlatformNotSupported_CipherModeBrowser" xml:space="preserve">
757+
<value>Only CipherMode.CBC is supported on this platform.</value>
758+
</data>
756759
</root>

src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,8 @@
547547
Link="Common\Interop\Browser\System.Security.Cryptography.Native.Browser\Interop.Sign.cs" />
548548
<Compile Include="System\Security\Cryptography\AesCcm.NotSupported.cs" />
549549
<Compile Include="System\Security\Cryptography\AesGcm.NotSupported.cs" />
550-
<Compile Include="System\Security\Cryptography\AesImplementation.NotSupported.cs" />
550+
<Compile Include="System\Security\Cryptography\AesImplementation.Browser.cs" />
551+
<Compile Include="System\Security\Cryptography\AesManagedTransform.Browser.cs" />
551552
<Compile Include="System\Security\Cryptography\AsnFormatter.Managed.cs" />
552553
<Compile Include="System\Security\Cryptography\CapiHelper.Browser.cs" />
553554
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.NotSupported.cs" />

0 commit comments

Comments
 (0)