From 4389df6728661d8feb127e211e7375305e313e85 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 8 Oct 2019 12:57:21 -0400 Subject: [PATCH] Remove System.Linq dependency from System.Security.Cryptography.X509Certificates System.Linq was only being used in two places: - In Pkcs10CertificateRequestInfo, it was using Collection<>.Select(...).ToArray(). We can replace it with a simple for loop, which is both faster (e.g. fewer delegate invocations) and fewer generic instantiations (no one else is going to have an instantiation with AttributeAsn). - In LoadMachineStores on Linux, it was using Prepend. We can avoid the need for Prepend (and the associated allocations) entirely by slightly reorganizing the method and using a local function. Commit migrated from https://github.com/dotnet/corefx/commit/5ad15fcb189a9c232051d03c1e889f985f62232b --- .../Pal.Unix/CachedSystemStoreProvider.cs | 41 ++++++++++------------ ...m.Security.Cryptography.X509Certificates.csproj | 1 - .../Pkcs10CertificationRequestInfo.cs | 9 +++-- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs index edaf573..d25711d 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CachedSystemStoreProvider.cs @@ -129,35 +129,33 @@ namespace Internal.Cryptography.Pal Monitor.IsEntered(s_recheckStopwatch), "LoadMachineStores assumes a lock(s_recheckStopwatch)"); - IEnumerable trustedCertFiles; + SafeX509StackHandle rootStore = Interop.Crypto.NewX509Stack(); + Interop.Crypto.CheckValidOpenSslHandle(rootStore); + SafeX509StackHandle intermedStore = Interop.Crypto.NewX509Stack(); + Interop.Crypto.CheckValidOpenSslHandle(intermedStore); + DateTime newFileTime = default; DateTime newDirTime = default; - if (rootStorePath != null && rootStorePath.Exists) - { - trustedCertFiles = rootStorePath.EnumerateFiles(); - newDirTime = rootStorePath.LastWriteTimeUtc; - } - else - { - trustedCertFiles = Array.Empty(); - } + var uniqueRootCerts = new HashSet(); + var uniqueIntermediateCerts = new HashSet(); if (rootStoreFile != null && rootStoreFile.Exists) { - trustedCertFiles = trustedCertFiles.Prepend(rootStoreFile); newFileTime = rootStoreFile.LastWriteTimeUtc; + ProcessFile(rootStoreFile); } - SafeX509StackHandle rootStore = Interop.Crypto.NewX509Stack(); - Interop.Crypto.CheckValidOpenSslHandle(rootStore); - SafeX509StackHandle intermedStore = Interop.Crypto.NewX509Stack(); - Interop.Crypto.CheckValidOpenSslHandle(intermedStore); - - HashSet uniqueRootCerts = new HashSet(); - HashSet uniqueIntermediateCerts = new HashSet(); + if (rootStorePath != null && rootStorePath.Exists) + { + newDirTime = rootStorePath.LastWriteTimeUtc; + foreach (FileInfo file in rootStorePath.EnumerateFiles()) + { + ProcessFile(file); + } + } - foreach (FileInfo file in trustedCertFiles) + void ProcessFile(FileInfo file) { using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file.FullName, "rb")) { @@ -165,17 +163,16 @@ namespace Internal.Cryptography.Pal if (fileBio.IsInvalid) { Interop.Crypto.ErrClearError(); - continue; + return; } - ICertificatePal pal; - // Some distros ship with two variants of the same certificate. // One is the regular format ('BEGIN CERTIFICATE') and the other // contains additional AUX-data ('BEGIN TRUSTED CERTIFICATE'). // The additional data contains the appropriate usage (e.g. emailProtection, serverAuth, ...). // Because corefx doesn't validate for a specific usage, derived certificates are rejected. // For now, we skip the certificates with AUX data and use the regular certificates. + ICertificatePal pal; while (OpenSslX509CertificateReader.TryReadX509PemNoAux(fileBio, out pal) || OpenSslX509CertificateReader.TryReadX509Der(fileBio, out pal)) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj index 56efaeb..68b4b68 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj @@ -687,7 +687,6 @@ - diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs index 47c61391..522a1fa 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/Pkcs10CertificationRequestInfo.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Linq; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.X509Certificates.Asn1; using Internal.Cryptography; @@ -58,12 +57,18 @@ namespace System.Security.Cryptography.X509Certificates spki.Algorithm = new AlgorithmIdentifierAsn { Algorithm = PublicKey.Oid, Parameters = PublicKey.EncodedParameters.RawData }; spki.SubjectPublicKey = PublicKey.EncodedKeyValue.RawData; + var attributes = new AttributeAsn[Attributes.Count]; + for (int i = 0; i < attributes.Length; i++) + { + attributes[i] = new AttributeAsn(Attributes[i]); + } + CertificationRequestInfoAsn requestInfo = new CertificationRequestInfoAsn { Version = 0, Subject = this.Subject.RawData, SubjectPublicKeyInfo = spki, - Attributes = Attributes.Select(a => new AttributeAsn(a)).ToArray(), + Attributes = attributes }; using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER)) -- 2.7.4