From b5f9e91a3f4c77a2fa0c275a0ca639b2c31931f9 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 26 Jan 2021 16:43:59 -0600 Subject: [PATCH] Resolve ILLink warnings in System.Security.Cryptography.Csp (#47439) Contributes to #45623 --- .../ref/System.Security.Cryptography.Csp.cs | 6 ++- .../src/ILLink/ILLink.Suppressions.xml | 11 ----- .../Cryptography/PasswordDeriveBytes.cs | 11 +++++ .../TrimmingTests/PasswordDeriveBytesTest.cs | 43 +++++++++++++++++++ ...curity.Cryptography.Csp.TrimmingTests.proj | 9 ++++ 5 files changed, 68 insertions(+), 12 deletions(-) delete mode 100644 src/libraries/System.Security.Cryptography.Csp/src/ILLink/ILLink.Suppressions.xml create mode 100644 src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/PasswordDeriveBytesTest.cs create mode 100644 src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/System.Security.Cryptography.Csp.TrimmingTests.proj diff --git a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs index ce402e6d386..a992ffcf039 100644 --- a/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs +++ b/src/libraries/System.Security.Cryptography.Csp/ref/System.Security.Cryptography.Csp.cs @@ -144,13 +144,17 @@ public partial class PasswordDeriveBytes : System.Security.Cryptography.DeriveBy { public PasswordDeriveBytes(byte[] password, byte[]? salt) { } public PasswordDeriveBytes(byte[] password, byte[]? salt, System.Security.Cryptography.CspParameters? cspParams) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt) { } public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, System.Security.Cryptography.CspParameters? cspParams) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters? cspParams) { } - public string HashName { get { throw null; } set { } } + public string HashName { get { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed.")] set { } } public int IterationCount { get { throw null; } set { } } public byte[]? Salt { get { throw null; } set { } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] diff --git a/src/libraries/System.Security.Cryptography.Csp/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Security.Cryptography.Csp/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index 0129976fe94..00000000000 --- a/src/libraries/System.Security.Cryptography.Csp/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - ILLink - IL2026 - member - M:System.Security.Cryptography.PasswordDeriveBytes.set_HashName(System.String) - - - \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs index ee79a76f05c..10e52dcf33f 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/PasswordDeriveBytes.cs @@ -14,6 +14,8 @@ namespace System.Security.Cryptography [EditorBrowsable(EditorBrowsableState.Never)] public partial class PasswordDeriveBytes : DeriveBytes { + private const string HashAlgorithmUnreferencedCodeMessage = "The hash implementation might be removed. Ensure the referenced hash algorithm is not trimmed."; + private int _extraCount; private int _prefix; private int _iterations; @@ -30,22 +32,30 @@ public partial class PasswordDeriveBytes : DeriveBytes public PasswordDeriveBytes(byte[] password, byte[]? salt) : this(password, salt, new CspParameters()) { } + [RequiresUnreferencedCode(HashAlgorithmUnreferencedCodeMessage)] public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations) : this(strPassword, rgbSalt, strHashName, iterations, new CspParameters()) { } + [RequiresUnreferencedCode(HashAlgorithmUnreferencedCodeMessage)] public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations) : this(password, salt, hashName, iterations, new CspParameters()) { } #pragma warning restore CA1416 + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The correct hash algorithm is being preserved by the DynamicDependency.")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor, typeof(SHA1CryptoServiceProvider))] public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, CspParameters? cspParams) : this(strPassword, rgbSalt, "SHA1", 100, cspParams) { } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The correct hash algorithm is being preserved by the DynamicDependency.")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor, typeof(SHA1CryptoServiceProvider))] public PasswordDeriveBytes(byte[] password, byte[]? salt, CspParameters? cspParams) : this(password, salt, "SHA1", 100, cspParams) { } + [RequiresUnreferencedCode(HashAlgorithmUnreferencedCodeMessage)] public PasswordDeriveBytes(string strPassword, byte[]? rgbSalt, string strHashName, int iterations, CspParameters? cspParams) : this((new UTF8Encoding(false)).GetBytes(strPassword), rgbSalt, strHashName, iterations, cspParams) { } + [RequiresUnreferencedCode(HashAlgorithmUnreferencedCodeMessage)] public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int iterations, CspParameters? cspParams) { IterationCount = iterations; @@ -58,6 +68,7 @@ public PasswordDeriveBytes(byte[] password, byte[]? salt, string hashName, int i public string HashName { get { return _hashName!; } + [RequiresUnreferencedCode(HashAlgorithmUnreferencedCodeMessage)] set { if (_baseValue != null) diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/PasswordDeriveBytesTest.cs b/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/PasswordDeriveBytesTest.cs new file mode 100644 index 00000000000..4fb327b499d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/PasswordDeriveBytesTest.cs @@ -0,0 +1,43 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Security.Cryptography; + +/// +/// Tests that using PasswordDeriveBytes without specifying a hash algorithm name +/// works correctly in a trimmed application. +/// +class Program +{ + static int Main() + { + string testPassword = "PasswordGoesHere"; + byte[] testSalt = new byte[] { 9, 5, 5, 5, 1, 2, 1, 2 }; + + byte[] expected = HexToByteArray("12F2497EC3EB78B0EA32AABFD8B9515FBC800BEEB6316A4DDF4EA62518341488A116DA3BBC26C685"); + + using (var deriveBytes = new PasswordDeriveBytes(testPassword, testSalt)) + { + byte[] output = deriveBytes.GetBytes(expected.Length); + if (output.SequenceEqual(expected)) + { + return 100; + } + } + + return -1; + } + + private static byte[] HexToByteArray(string hexString) + { + byte[] bytes = new byte[hexString.Length / 2]; + + for (int i = 0; i < hexString.Length; i += 2) + { + ReadOnlySpan s = hexString.AsSpan(i, 2); + bytes[i / 2] = byte.Parse(s, NumberStyles.HexNumber, null); + } + + return bytes; + } +} diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/System.Security.Cryptography.Csp.TrimmingTests.proj b/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/System.Security.Cryptography.Csp.TrimmingTests.proj new file mode 100644 index 00000000000..64b290af04e --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Csp/tests/TrimmingTests/System.Security.Cryptography.Csp.TrimmingTests.proj @@ -0,0 +1,9 @@ + + + + + + + + + -- GitLab