Make DSACryptoServiceProvider set legal key sizes to most restrictive for platform...
authorElinor Fung <elfung@microsoft.com>
Wed, 24 Mar 2021 23:25:26 +0000 (16:25 -0700)
committerGitHub <noreply@github.com>
Wed, 24 Mar 2021 23:25:26 +0000 (16:25 -0700)
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs
src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DSACryptoServiceProvider.Unix.cs

index 0d6f244..3c2b597 100644 (file)
@@ -9,6 +9,7 @@ namespace System.Security.Cryptography.Dsa.Tests
     public partial class DSAKeyGeneration
     {
         public static bool SupportsKeyGeneration => DSAFactory.SupportsKeyGeneration;
+        public static bool HasSecondMinSize { get; } = GetHasSecondMinSize();
 
         [Fact]
         public static void VerifyDefaultKeySize_Fips186_2()
@@ -28,7 +29,7 @@ namespace System.Security.Cryptography.Dsa.Tests
             GenerateKey(dsa => GetMin(dsa.LegalKeySizes));
         }
 
-        [ConditionalFact(nameof(SupportsKeyGeneration))]
+        [ConditionalFact(nameof(SupportsKeyGeneration), nameof(HasSecondMinSize))]
         public static void GenerateSecondMinKey()
         {
             GenerateKey(dsa => GetSecondMin(dsa.LegalKeySizes));
@@ -118,5 +119,13 @@ namespace System.Security.Cryptography.Dsa.Tests
 
             return secondMin;
         }
+
+        private static bool GetHasSecondMinSize()
+        {
+            using (DSA dsa = DSAFactory.Create())
+            {
+                return GetSecondMin(dsa.LegalKeySizes) != int.MaxValue;
+            }
+        }
     }
 }
index 559fa81..b1a8c9e 100644 (file)
@@ -163,7 +163,21 @@ namespace System.Security.Cryptography.Dsa.Tests
             Assert.Throws<ObjectDisposedException>(
                 () =>
                 {
-                    key.KeySize = 576;
+                    try
+                    {
+                        key.KeySize = 576;
+                    }
+                    catch (CryptographicException)
+                    {
+                        // DSACryptoServiceProvider on Android only supports 1024 and does an early check for legal
+                        // key sizes, since it is more restrictive than the wrapped implementation. It will throw
+                        // CryptographicException. SignData should still throw ObjectDisposedException.
+                        if (!PlatformDetection.IsAndroid)
+                        {
+                            throw;
+                        }
+                    }
+
                     SignData(key, data, HashAlgorithmName.SHA1);
                 });
         }
index 575055f..8790cc9 100644 (file)
@@ -12,20 +12,34 @@ namespace System.Security.Cryptography
     public sealed class DSACryptoServiceProvider : DSA, ICspAsymmetricAlgorithm
     {
         private const int SHA1_HASHSIZE = 20;
+        private const int DefaultKeySize = 1024;
 
         private readonly DSA _impl;
         private bool _publicOnly;
 
-        private static KeySizes[] s_legalKeySizes =
+        private static readonly KeySizes[] s_legalKeySizesWindowsCsp =
         {
             new KeySizes(512, 1024, 64)  // Use the same values as Csp Windows because the _impl has different values (512, 3072, 64)
         };
 
-        public DSACryptoServiceProvider() : base()
+        private static readonly KeySizes[] s_legalKeySizesAndroid =
+        {
+            new KeySizes(1024, 1024, 0)  // Intersection of legal sizes on Android and Windows provider
+        };
+
+        // Depending on the platform, _impl's legal key sizes may be more restrictive than Windows provider.
+        //   DSAAndroid : (1024, 3072, 1024)
+        //   DSAOpenSsl : (512, 3072, 64)
+        //   DSASecurityTransforms : (512, 1024, 64)
+        //   Windows CSP : (512, 1024, 64)
+        // Use the most restrictive legal key sizes
+        private static readonly KeySizes[] s_legalKeySizes = OperatingSystem.IsAndroid()
+            ? s_legalKeySizesAndroid
+            : s_legalKeySizesWindowsCsp;
+
+        public DSACryptoServiceProvider()
+            : this(DefaultKeySize)
         {
-            // This class wraps DSA
-            _impl = DSA.Create();
-            KeySize = 1024;
         }
 
         public DSACryptoServiceProvider(int dwKeySize) : base()