Optimize public key imports for OpenSSL and Common Crypto
authorFilip Navara <filip.navara@gmail.com>
Thu, 13 Sep 2018 16:19:12 +0000 (18:19 +0200)
committerJeremy Barton <jbarton@microsoft.com>
Thu, 13 Sep 2018 16:19:12 +0000 (09:19 -0700)
* Optimize RSA and DSA key imports for Common Crypto and OpenSSL.
* Convert key imports to use ReadOnlySpan.

Commit migrated from https://github.com/dotnet/corefx/commit/713420b9fbe2a86be3a8032c8185a7f5ef308290

12 files changed:
src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs
src/libraries/Common/src/System/Security/Cryptography/DSAKeyFormatHelper.cs
src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs
src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs
src/libraries/Common/src/System/Security/Cryptography/EccKeyFormatHelper.cs
src/libraries/Common/src/System/Security/Cryptography/EccSecurityTransforms.cs
src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs
src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs
src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/X509Pal.cs
src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509Encoder.cs

index 37dd66d..e7be585 100644 (file)
@@ -13,9 +13,21 @@ internal static partial class Interop
 {
     internal static partial class AppleCrypto
     {
+        private static int AppleCryptoNative_SecKeyImportEphemeral(
+            ReadOnlySpan<byte> pbKeyBlob,
+            int isPrivateKey,
+            out SafeSecKeyRefHandle ppKeyOut,
+            out int pOSStatus) =>
+            AppleCryptoNative_SecKeyImportEphemeral(
+                ref MemoryMarshal.GetReference(pbKeyBlob),
+                pbKeyBlob.Length,
+                isPrivateKey,
+                out ppKeyOut,
+                out pOSStatus);
+
         [DllImport(Libraries.AppleCryptoNative)]
         private static extern int AppleCryptoNative_SecKeyImportEphemeral(
-            byte[] pbKeyBlob,
+            ref byte pbKeyBlob,
             int cbKeyBlob,
             int isPrivateKey,
             out SafeSecKeyRefHandle ppKeyOut,
@@ -24,11 +36,14 @@ internal static partial class Interop
         private static int AppleCryptoNative_GenerateSignature(
             SafeSecKeyRefHandle privateKey,
             ReadOnlySpan<byte> pbDataHash,
-            int cbDataHash,
             out SafeCFDataHandle pSignatureOut,
             out SafeCFErrorHandle pErrorOut) =>
             AppleCryptoNative_GenerateSignature(
-                privateKey, ref MemoryMarshal.GetReference(pbDataHash), cbDataHash, out pSignatureOut, out pErrorOut);
+                privateKey,
+                ref MemoryMarshal.GetReference(pbDataHash),
+                pbDataHash.Length,
+                out pSignatureOut,
+                out pErrorOut);
 
         [DllImport(Libraries.AppleCryptoNative)]
         private static extern int AppleCryptoNative_GenerateSignature(
@@ -41,12 +56,16 @@ internal static partial class Interop
         private static int AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
             SafeSecKeyRefHandle privateKey,
             ReadOnlySpan<byte> pbDataHash,
-            int cbDataHash,
             PAL_HashAlgorithm hashAlgorithm,
             out SafeCFDataHandle pSignatureOut,
             out SafeCFErrorHandle pErrorOut) =>
             AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
-                privateKey, ref MemoryMarshal.GetReference(pbDataHash), cbDataHash, hashAlgorithm, out pSignatureOut, out pErrorOut);
+                privateKey,
+                ref MemoryMarshal.GetReference(pbDataHash),
+                pbDataHash.Length,
+                hashAlgorithm,
+                out pSignatureOut,
+                out pErrorOut);
 
         [DllImport(Libraries.AppleCryptoNative)]
         private static extern int AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
@@ -60,16 +79,14 @@ internal static partial class Interop
         private static int AppleCryptoNative_VerifySignature(
             SafeSecKeyRefHandle publicKey,
             ReadOnlySpan<byte> pbDataHash,
-            int cbDataHash,
             ReadOnlySpan<byte> pbSignature,
-            int cbSignature,
             out SafeCFErrorHandle pErrorOut) =>
             AppleCryptoNative_VerifySignature(
                 publicKey,
                 ref MemoryMarshal.GetReference(pbDataHash),
-                cbDataHash,
+                pbDataHash.Length,
                 ref MemoryMarshal.GetReference(pbSignature),
-                cbSignature,
+                pbSignature.Length,
                 out pErrorOut);
 
         [DllImport(Libraries.AppleCryptoNative)]
@@ -84,17 +101,15 @@ internal static partial class Interop
         private static int AppleCryptoNative_VerifySignatureWithHashAlgorithm(
             SafeSecKeyRefHandle publicKey,
             ReadOnlySpan<byte> pbDataHash,
-            int cbDataHash,
             ReadOnlySpan<byte> pbSignature,
-            int cbSignature,
             PAL_HashAlgorithm hashAlgorithm,
             out SafeCFErrorHandle pErrorOut) =>
             AppleCryptoNative_VerifySignatureWithHashAlgorithm(
                 publicKey,
                 ref MemoryMarshal.GetReference(pbDataHash),
-                cbDataHash,
+                pbDataHash.Length,
                 ref MemoryMarshal.GetReference(pbSignature),
-                cbSignature,
+                pbSignature.Length,
                 hashAlgorithm,
                 out pErrorOut);
 
@@ -180,7 +195,7 @@ internal static partial class Interop
             }
         }
 
-        internal static SafeSecKeyRefHandle ImportEphemeralKey(byte[] keyBlob, bool hasPrivateKey)
+        internal static SafeSecKeyRefHandle ImportEphemeralKey(ReadOnlySpan<byte> keyBlob, bool hasPrivateKey)
         {
             Debug.Assert(keyBlob != null);
 
@@ -189,7 +204,6 @@ internal static partial class Interop
 
             int ret = AppleCryptoNative_SecKeyImportEphemeral(
                 keyBlob,
-                keyBlob.Length,
                 hasPrivateKey ? 1 : 0,
                 out keyHandle,
                 out osStatus);
@@ -218,7 +232,6 @@ internal static partial class Interop
                     AppleCryptoNative_GenerateSignature(
                         privateKey,
                         source,
-                        source.Length,
                         out signature,
                         out error));
         }
@@ -237,7 +250,6 @@ internal static partial class Interop
                     AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
                         privateKey,
                         source,
-                        source.Length,
                         hashAlgorithm,
                         out signature,
                         out error));
@@ -260,7 +272,7 @@ internal static partial class Interop
                 delegate (ReadOnlySpan<byte> innerSource, out SafeCFDataHandle outputHandle, out SafeCFErrorHandle errorHandle)
                 {
                     return AppleCryptoNative_GenerateSignatureWithHashAlgorithm(
-                        privateKey, innerSource, innerSource.Length, hashAlgorithm, out outputHandle, out errorHandle);
+                        privateKey, innerSource, hashAlgorithm, out outputHandle, out errorHandle);
                 });
         }
 
@@ -276,9 +288,7 @@ internal static partial class Interop
             int ret = AppleCryptoNative_VerifySignature(
                 publicKey,
                 dataHash,
-                dataHash.Length,
                 signature,
-                signature.Length,
                 out error);
 
             const int True = 1;
@@ -316,9 +326,7 @@ internal static partial class Interop
             int ret = AppleCryptoNative_VerifySignatureWithHashAlgorithm(
                 publicKey,
                 dataHash,
-                dataHash.Length,
                 signature,
-                signature.Length,
                 hashAlgorithm,
                 out error);
 
index 296b9f1..a7b85ae 100644 (file)
@@ -22,8 +22,11 @@ internal static partial class Interop
         [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaDestroy")]
         internal static extern void RsaDestroy(IntPtr rsa);
 
+        internal static SafeRsaHandle DecodeRsaPublicKey(ReadOnlySpan<byte> buf) =>
+            DecodeRsaPublicKey(ref MemoryMarshal.GetReference(buf), buf.Length);
+
         [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeRsaPublicKey")]
-        internal static extern SafeRsaHandle DecodeRsaPublicKey(byte[] buf, int len);
+        private static extern SafeRsaHandle DecodeRsaPublicKey(ref byte buf, int len);
 
         internal static int RsaPublicEncrypt(
             int flen,
index 3de051e..9e7e9a5 100644 (file)
@@ -88,6 +88,16 @@ namespace System.Security.Cryptography
                 out key);
         }
 
+       internal static ReadOnlyMemory<byte> ReadSubjectPublicKeyInfo(
+            ReadOnlyMemory<byte> source,
+            out int bytesRead)
+        {
+            return KeyFormatHelper.ReadSubjectPublicKeyInfo(
+                s_validOids,
+                source,
+                out bytesRead);
+        }
+
         internal static void ReadPkcs8(
             ReadOnlySpan<byte> source,
             out int bytesRead,
index f34d780..a5d796c 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Buffers;
 using System.Diagnostics;
 using System.IO;
 using System.Numerics;
+using System.Runtime.InteropServices;
 using System.Security.Cryptography.Apple;
 using System.Security.Cryptography.Asn1;
 using Internal.Cryptography;
@@ -179,13 +181,8 @@ namespace System.Security.Cryptography
 
                 private static SafeSecKeyRefHandle ImportKey(DSAParameters parameters)
                 {
-                    bool hasPrivateKey = parameters.X != null;
-                    byte[] blob;
-                    
-                    if (hasPrivateKey)
+                    if (parameters.X != null)
                     {
-                        Debug.Assert(parameters.X != null);
-
                         // DSAPrivateKey ::= SEQUENCE(
                         //   version INTEGER,
                         //   p INTEGER,
@@ -205,18 +202,37 @@ namespace System.Security.Cryptography
                             privateKeyWriter.WriteKeyParameterInteger(parameters.Y);
                             privateKeyWriter.WriteKeyParameterInteger(parameters.X);
                             privateKeyWriter.PopSequence();
-                            blob = privateKeyWriter.Encode();
+                            return Interop.AppleCrypto.ImportEphemeralKey(privateKeyWriter.EncodeAsSpan(), true);
                         }
                     }
                     else
                     {
                         using (AsnWriter writer = DSAKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
                         {
-                            blob = writer.Encode();
+                            return Interop.AppleCrypto.ImportEphemeralKey(writer.EncodeAsSpan(), false);
                         }
                     }
+                }
+
+                public override unsafe void ImportSubjectPublicKeyInfo(
+                    ReadOnlySpan<byte> source,
+                    out int bytesRead)
+                {
+                    fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+                    {
+                        using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+                        {
+                            // Validate the DER value and get the number of bytes.
+                            DSAKeyFormatHelper.ReadSubjectPublicKeyInfo(
+                                manager.Memory,
+                                out int localRead);
 
-                    return Interop.AppleCrypto.ImportEphemeralKey(blob, hasPrivateKey);
+                            SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+                            SetKey(SecKeyPair.PublicOnly(publicKey));
+
+                            bytesRead = localRead;
+                        }
+                    }
                 }
 
                 public override byte[] CreateSignature(byte[] rgbHash)
index 5728264..1b7f928 100644 (file)
@@ -80,6 +80,13 @@ namespace System.Security.Cryptography
                 KeySizeValue = _ecc.ImportParameters(parameters);
             }
 
+            public override void ImportSubjectPublicKeyInfo(
+                ReadOnlySpan<byte> source,
+                out int bytesRead)
+            {
+                KeySizeValue = _ecc.ImportSubjectPublicKeyInfo(source, out bytesRead);
+            }
+
             public override void GenerateKey(ECCurve curve)
             {
                 KeySizeValue = _ecc.GenerateKey(curve);
index 04463b7..2a856f3 100644 (file)
@@ -31,6 +31,16 @@ namespace System.Security.Cryptography
                 out key);
         }
 
+       internal static ReadOnlyMemory<byte> ReadSubjectPublicKeyInfo(
+            ReadOnlyMemory<byte> source,
+            out int bytesRead)
+        {
+            return KeyFormatHelper.ReadSubjectPublicKeyInfo(
+                s_validOids,
+                source,
+                out bytesRead);
+        }
+
         internal static void ReadEncryptedPkcs8(
             ReadOnlySpan<byte> source,
             ReadOnlySpan<char> password,
index 2fb8d4d..bd2f4a9 100644 (file)
@@ -2,7 +2,9 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Buffers;
 using System.Diagnostics;
+using System.Runtime.InteropServices;
 using System.Security.Cryptography.Apple;
 using System.Security.Cryptography.Asn1;
 using Internal.Cryptography;
@@ -132,7 +134,7 @@ namespace System.Security.Cryptography
             }
         }
 
-        public int ImportParameters(ECParameters parameters)
+        internal int ImportParameters(ECParameters parameters)
         {
             parameters.Validate();
 
@@ -184,25 +186,44 @@ namespace System.Security.Cryptography
 
         private static SafeSecKeyRefHandle ImportKey(ECParameters parameters)
         {
-            bool isPrivateKey = parameters.D != null;
-            byte[] blob;
-
-            if (isPrivateKey)
+            if (parameters.D != null)
             {
                 using (AsnWriter privateKey = EccKeyFormatHelper.WriteECPrivateKey(parameters))
                 {
-                    blob = privateKey.Encode();
+                    return Interop.AppleCrypto.ImportEphemeralKey(privateKey.EncodeAsSpan(), true);
                 }
             }
             else
             {
                 using (AsnWriter publicKey = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
                 {
-                    blob = publicKey.Encode();
+                    return Interop.AppleCrypto.ImportEphemeralKey(publicKey.EncodeAsSpan(), false);
                 }
             }
+        }
+
+        internal unsafe int ImportSubjectPublicKeyInfo(
+            ReadOnlySpan<byte> source,
+            out int bytesRead)
+        {
+            fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+            {
+                using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+                {
+                    // Validate the DER value and get the number of bytes.
+                    EccKeyFormatHelper.ReadSubjectPublicKeyInfo(
+                        manager.Memory,
+                        out int localRead);
 
-            return Interop.AppleCrypto.ImportEphemeralKey(blob, isPrivateKey);
+                    SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+                    SecKeyPair newKeys = SecKeyPair.PublicOnly(publicKey);
+                    int size = GetKeySize(newKeys);
+                    SetKey(newKeys);
+
+                    bytesRead = localRead;
+                    return size;
+                }
+            }
         }
     }
 }
index 2fe3666..3c0e4ac 100644 (file)
@@ -5,7 +5,8 @@
 using System.Buffers;
 using System.Diagnostics;
 using System.IO;
-
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.Asn1;
 using Microsoft.Win32.SafeHandles;
 using Internal.Cryptography;
 
@@ -395,6 +396,31 @@ namespace System.Security.Cryptography
             ForceSetKeySize(BitsPerByte * Interop.Crypto.RsaSize(key));
         }
 
+        public override unsafe void ImportRSAPublicKey(ReadOnlySpan<byte> source, out int bytesRead)
+        {
+            fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+            {
+                using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+                {
+                    AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER);
+                    ReadOnlyMemory<byte> firstElement = reader.PeekEncodedValue();
+
+                    SafeRsaHandle key = Interop.Crypto.DecodeRsaPublicKey(firstElement.Span);
+
+                    Interop.Crypto.CheckValidOpenSslHandle(key);
+
+                    FreeKey();
+                    _key = new Lazy<SafeRsaHandle>(key);
+
+                    // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere
+                    // with the already loaded key.
+                    ForceSetKeySize(BitsPerByte * Interop.Crypto.RsaSize(key));
+
+                    bytesRead = firstElement.Length;
+                }
+            }
+        }
+
         protected override void Dispose(bool disposing)
         {
             if (disposing)
index f598dc6..b6a0518 100644 (file)
@@ -6,6 +6,7 @@ using System.Buffers;
 using System.Diagnostics;
 using System.IO;
 using System.Numerics;
+using System.Runtime.InteropServices;
 using System.Security.Cryptography.Apple;
 using System.Security.Cryptography.Asn1;
 using Internal.Cryptography;
@@ -185,6 +186,57 @@ namespace System.Security.Cryptography
                 }
             }
 
+            public override unsafe void ImportSubjectPublicKeyInfo(
+                ReadOnlySpan<byte> source,
+                out int bytesRead)
+            {
+                fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+                {
+                    using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+                    {
+                        // Validate the DER value and get the number of bytes.
+                        RSAKeyFormatHelper.ReadSubjectPublicKeyInfo(
+                            manager.Memory,
+                            out int localRead);
+
+                        SafeSecKeyRefHandle publicKey = Interop.AppleCrypto.ImportEphemeralKey(source.Slice(0, localRead), false);
+                        SetKey(SecKeyPair.PublicOnly(publicKey));
+
+                        bytesRead = localRead;
+                    }
+                }
+            }
+
+            public override unsafe void ImportRSAPublicKey(ReadOnlySpan<byte> source, out int bytesRead)
+            {
+                fixed (byte* ptr = &MemoryMarshal.GetReference(source))
+                {
+                    using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, source.Length))
+                    {
+                        AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER);
+                        ReadOnlyMemory<byte> firstElement = reader.PeekEncodedValue();
+
+                        SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
+                        {
+                            Algorithm = new AlgorithmIdentifierAsn
+                            {
+                                Algorithm = new Oid(Oids.Rsa),
+                                Parameters = AlgorithmIdentifierAsn.ExplicitDerNull,
+                            },
+                            SubjectPublicKey = firstElement,
+                        };
+
+                        using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
+                        {
+                            spki.Encode(writer);
+                            ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+                        }
+
+                        bytesRead = firstElement.Length;
+                    }
+                }
+            }
+
             public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding)
             {
                 if (data == null)
@@ -718,25 +770,20 @@ namespace System.Security.Cryptography
 
             private static SafeSecKeyRefHandle ImportKey(RSAParameters parameters)
             {
-                bool isPrivateKey = parameters.D != null;
-                byte[] pkcs1Blob;
-
-                if (isPrivateKey)
+                if (parameters.D != null)
                 {
                     using (AsnWriter pkcs1PrivateKey = RSAKeyFormatHelper.WritePkcs1PrivateKey(parameters))
                     {
-                        pkcs1Blob = pkcs1PrivateKey.Encode();
+                        return Interop.AppleCrypto.ImportEphemeralKey(pkcs1PrivateKey.EncodeAsSpan(), true);
                     }
                 }
                 else
                 {
                     using (AsnWriter pkcs1PublicKey = RSAKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
                     {
-                        pkcs1Blob = pkcs1PublicKey.Encode();
+                        return Interop.AppleCrypto.ImportEphemeralKey(pkcs1PublicKey.EncodeAsSpan(), false);
                     }
                 }
-
-                return Interop.AppleCrypto.ImportEphemeralKey(pkcs1Blob, isPrivateKey);
             }
         }
 
index a89fc60..1ba0513 100644 (file)
@@ -98,6 +98,9 @@
     <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeEvpPKeyHandle.Unix.cs">
       <Link>Common\Microsoft\Win32\SafeHandles\SafeEvpPKeyHandle.Unix.cs</Link>
     </Compile>
+    <Compile Include="$(CommonPath)\System\Memory\PointerMemoryManager.cs">
+      <Link>Common\System\Memory\PointerMemoryManager.cs</Link>
+    </Compile>
     <Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1V2.cs">
       <Link>Common\System\Security\Cryptography\Asn1V2.cs</Link>
     </Compile>
index b195c12..dbbf108 100644 (file)
@@ -84,16 +84,10 @@ namespace Internal.Cryptography.Pal
 
             private static AsymmetricAlgorithm DecodeRsaPublicKey(byte[] encodedKeyValue)
             {
-                AlgorithmIdentifierAsn ignored = default;
-                RSAKeyFormatHelper.ReadRsaPublicKey(
-                    encodedKeyValue,
-                    ignored,
-                    out RSAParameters rsaParameters);
-
                 RSA rsa = RSA.Create();
                 try
                 {
-                    rsa.ImportParameters(rsaParameters);
+                    rsa.ImportRSAPublicKey(encodedKeyValue.AsSpan(), out _);
                     return rsa;
                 }
                 catch (Exception)
@@ -105,21 +99,26 @@ namespace Internal.Cryptography.Pal
 
             private static AsymmetricAlgorithm DecodeDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters)
             {
-                DSAKeyFormatHelper.ReadDsaPublicKey(
-                    encodedKeyValue,
-                    new AlgorithmIdentifierAsn { Parameters = encodedParameters },
-                    out DSAParameters dsaParameters);
-
-                DSA dsa = DSA.Create();
-                try
+                SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
                 {
-                    dsa.ImportParameters(dsaParameters);
-                    return dsa;
-                }
-                catch (Exception)
+                    Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa, null), Parameters = encodedParameters },
+                    SubjectPublicKey = encodedKeyValue,
+                };
+
+                using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
                 {
-                    dsa.Dispose();
-                    throw;
+                    spki.Encode(writer);
+                    DSA dsa = DSA.Create();
+                    try
+                    {
+                        dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+                        return dsa;
+                    }
+                    catch (Exception)
+                    {
+                        dsa.Dispose();
+                        throw;
+                    }
                 }
             }
 
index 1fc4ee9..ca2b9a9 100644 (file)
@@ -255,31 +255,41 @@ namespace Internal.Cryptography.Pal
 
         private static RSA BuildRsaPublicKey(byte[] encodedData)
         {
-            using (SafeRsaHandle rsaHandle = Interop.Crypto.DecodeRsaPublicKey(encodedData, encodedData.Length))
+            RSA rsa = new RSAOpenSsl();
+            try
             {
-                Interop.Crypto.CheckValidOpenSslHandle(rsaHandle);
-
-                RSAParameters rsaParameters = Interop.Crypto.ExportRsaParameters(rsaHandle, false);
-                RSA rsa = new RSAOpenSsl();
-                rsa.ImportParameters(rsaParameters);
-                return rsa;
+                rsa.ImportRSAPublicKey(encodedData.AsSpan(), out _);
+            }
+            catch (Exception)
+            {
+                rsa.Dispose();
+                throw;
             }
+            return rsa;
         }
 
-        private static DSA BuildDsaPublicKey(byte[] encodedKey, byte[] encodedParameters)
+        private static DSA BuildDsaPublicKey(byte[] encodedKeyValue, byte[] encodedParameters)
         {
             SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn
             {
-                Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa), Parameters = encodedParameters },
-                SubjectPublicKey = encodedKey,
+                Algorithm = new AlgorithmIdentifierAsn { Algorithm = new Oid(Oids.Dsa, null), Parameters = encodedParameters },
+                SubjectPublicKey = encodedKeyValue,
             };
 
             using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
             {
-                DSA dsa = new DSAOpenSsl();
                 spki.Encode(writer);
-                dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
-                return dsa;
+                DSA dsa = new DSAOpenSsl();
+                try
+                {
+                    dsa.ImportSubjectPublicKeyInfo(writer.EncodeAsSpan(), out _);
+                    return dsa;
+                }
+                catch (Exception)
+                {
+                    dsa.Dispose();
+                    throw;
+                }
             }
         }
     }