提交 4e72737a 编写于 作者: T Tomas Weinfurt 提交者: Jeremy Barton

Eliminate X509Extension allocations during ssl handshake with OpenSSL

Moves policydata to a PAL struct so it can be passed without creating and discarding the X509Extension objects.
上级 4c5edb6f
......@@ -4,12 +4,24 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace Internal.Cryptography
{
[StructLayout(LayoutKind.Sequential)]
internal struct PolicyData
{
internal byte[] ApplicationCertPolicies;
internal byte[] CertPolicies;
internal byte[] CertPolicyMappings;
internal byte[] CertPolicyConstraints;
internal byte[] EnhancedKeyUsage;
internal byte[] InhibitAnyPolicyExtension;
}
/// <summary>Provides specific implementation for X509Certificate2.</summary>
internal interface ICertificatePal : ICertificatePalCore
{
......@@ -27,5 +39,6 @@ internal interface ICertificatePal : ICertificatePalCore
ICertificatePal CopyWithPrivateKey(DSA privateKey);
ICertificatePal CopyWithPrivateKey(ECDsa privateKey);
ICertificatePal CopyWithPrivateKey(RSA privateKey);
PolicyData GetPolicyData();
}
}
......@@ -277,6 +277,39 @@ public X500DistinguishedName IssuerName
}
}
public PolicyData GetPolicyData()
{
PolicyData policyData = default;
EnsureCertData();
foreach (X509Extension extension in _certData.Extensions)
{
switch (extension.Oid.Value)
{
case Oids.ApplicationCertPolicies:
policyData.ApplicationCertPolicies = extension.RawData;
break;
case Oids.CertPolicies:
policyData.CertPolicies = extension.RawData;
break;
case Oids.CertPolicyMappings:
policyData.CertPolicyMappings = extension.RawData;
break;
case Oids.CertPolicyConstraints:
policyData.CertPolicyConstraints = extension.RawData;
break;
case Oids.EnhancedKeyUsage:
policyData.EnhancedKeyUsage = extension.RawData;
break;
case Oids.InhibitAnyPolicyExtension:
policyData.InhibitAnyPolicyExtension = extension.RawData;
break;
}
}
return policyData;
}
public IEnumerable<X509Extension> Extensions {
get
{
......
......@@ -236,34 +236,37 @@ private static CertificatePolicy ReadPolicy(X509Certificate2 cert)
ISet<string> ekus = null;
CertificatePolicy policy = new CertificatePolicy();
foreach (X509Extension extension in cert.Extensions)
PolicyData policyData = cert.Pal.GetPolicyData();
if (policyData.ApplicationCertPolicies != null)
{
switch (extension.Oid.Value)
{
case Oids.ApplicationCertPolicies:
applicationCertPolicies = ReadCertPolicyExtension(extension);
break;
case Oids.CertPolicies:
policy.DeclaredCertificatePolicies = ReadCertPolicyExtension(extension);
break;
case Oids.CertPolicyMappings:
policy.PolicyMapping = ReadCertPolicyMappingsExtension(extension);
break;
case Oids.CertPolicyConstraints:
ReadCertPolicyConstraintsExtension(extension, policy);
break;
case Oids.EnhancedKeyUsage:
if (applicationCertPolicies == null)
{
// No reason to do this if the applicationCertPolicies was already read
ekus = ReadExtendedKeyUsageExtension(extension);
}
applicationCertPolicies = ReadCertPolicyExtension(policyData.ApplicationCertPolicies);
}
break;
case Oids.InhibitAnyPolicyExtension:
policy.InhibitAnyDepth = ReadInhibitAnyPolicyExtension(extension);
break;
}
if (policyData.CertPolicies != null)
{
policy.DeclaredCertificatePolicies = ReadCertPolicyExtension(policyData.CertPolicies);
}
if (policyData.CertPolicyMappings!= null)
{
policy.PolicyMapping = ReadCertPolicyMappingsExtension(policyData.CertPolicyMappings);
}
if (policyData.CertPolicyConstraints != null)
{
ReadCertPolicyConstraintsExtension(policyData.CertPolicyConstraints, policy);
}
if (policyData.EnhancedKeyUsage != null && applicationCertPolicies == null)
{
// No reason to do this if the applicationCertPolicies was already read
ekus = ReadExtendedKeyUsageExtension(policyData.EnhancedKeyUsage);
}
if (policyData.InhibitAnyPolicyExtension != null)
{
policy.InhibitAnyDepth = ReadInhibitAnyPolicyExtension(policyData.InhibitAnyPolicyExtension);
}
policy.DeclaredApplicationPolicies = applicationCertPolicies ?? ekus;
......@@ -287,41 +290,45 @@ private static bool CheckExplicitAnyPolicy(ISet<string> declaredPolicies)
return declaredPolicies.Remove(Oids.AnyCertPolicy);
}
private static int ReadInhibitAnyPolicyExtension(X509Extension extension)
private static int ReadInhibitAnyPolicyExtension(byte[] rawData)
{
AsnReader reader = new AsnReader(extension.RawData, AsnEncodingRules.DER);
AsnReader reader = new AsnReader(rawData, AsnEncodingRules.DER);
int inhibitAnyPolicy;
reader.TryReadInt32(out inhibitAnyPolicy);
reader.ThrowIfNotEmpty();
return inhibitAnyPolicy;
}
private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy)
private static void ReadCertPolicyConstraintsExtension(byte[] rawData, CertificatePolicy policy)
{
PolicyConstraintsAsn constraints = PolicyConstraintsAsn.Decode(
extension.RawData,
rawData,
AsnEncodingRules.DER);
policy.RequireExplicitPolicyDepth = constraints.RequireExplicitPolicyDepth;
policy.InhibitMappingDepth = constraints.InhibitMappingDepth;
}
private static ISet<string> ReadExtendedKeyUsageExtension(X509Extension extension)
private static ISet<string> ReadExtendedKeyUsageExtension(byte[] rawData)
{
X509EnhancedKeyUsageExtension ekusExtension = (X509EnhancedKeyUsageExtension)extension;
HashSet<string> oids = new HashSet<string>();
foreach (Oid oid in ekusExtension.EnhancedKeyUsages)
AsnReader reader = new AsnReader(rawData, AsnEncodingRules.DER);
AsnReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
//OidCollection usages
while (sequenceReader.HasData)
{
oids.Add(oid.Value);
oids.Add(sequenceReader.ReadObjectIdentifierAsString());
}
return oids;
}
internal static ISet<string> ReadCertPolicyExtension(X509Extension extension)
internal static ISet<string> ReadCertPolicyExtension(byte[] rawData)
{
AsnReader reader = new AsnReader(extension.RawData, AsnEncodingRules.DER);
AsnReader reader = new AsnReader(rawData, AsnEncodingRules.DER);
AsnReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
......@@ -341,9 +348,9 @@ internal static ISet<string> ReadCertPolicyExtension(X509Extension extension)
return policies;
}
private static List<CertificatePolicyMappingAsn> ReadCertPolicyMappingsExtension(X509Extension extension)
private static List<CertificatePolicyMappingAsn> ReadCertPolicyMappingsExtension(byte[] rawData)
{
AsnReader reader = new AsnReader(extension.RawData, AsnEncodingRules.DER);
AsnReader reader = new AsnReader(rawData, AsnEncodingRules.DER);
AsnReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
......
......@@ -203,7 +203,7 @@ public void FindByCertificatePolicy(string oidValue)
return false;
}
ISet<string> policyOids = CertificatePolicyChain.ReadCertPolicyExtension(ext);
ISet<string> policyOids = CertificatePolicyChain.ReadCertPolicyExtension(ext.RawData);
return policyOids.Contains(oidValue);
});
}
......
......@@ -11,7 +11,6 @@
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace Internal.Cryptography.Pal
......@@ -411,6 +410,50 @@ public X500DistinguishedName IssuerName
}
}
public PolicyData GetPolicyData()
{
PolicyData policyData = default;
int extensionCount = Interop.Crypto.X509GetExtCount(_cert);
for (int i = 0; i < extensionCount; i++)
{
IntPtr ext = Interop.Crypto.X509GetExt(_cert, i);
Interop.Crypto.CheckValidOpenSslHandle(ext);
IntPtr oidPtr = Interop.Crypto.X509ExtensionGetOid(ext);
Interop.Crypto.CheckValidOpenSslHandle(oidPtr);
string oidValue = Interop.Crypto.GetOidValue(oidPtr);
IntPtr dataPtr = Interop.Crypto.X509ExtensionGetData(ext);
Interop.Crypto.CheckValidOpenSslHandle(dataPtr);
switch (oidValue)
{
case Oids.ApplicationCertPolicies:
policyData.ApplicationCertPolicies = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
case Oids.CertPolicies:
policyData.CertPolicies = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
case Oids.CertPolicyMappings:
policyData.CertPolicyMappings = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
case Oids.CertPolicyConstraints:
policyData.CertPolicyConstraints = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
case Oids.EnhancedKeyUsage:
policyData.EnhancedKeyUsage = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
case Oids.InhibitAnyPolicyExtension:
policyData.InhibitAnyPolicyExtension = Interop.Crypto.GetAsn1StringBytes(dataPtr);
break;
}
}
return policyData;
}
public IEnumerable<X509Extension> Extensions
{
get
......
......@@ -360,6 +360,11 @@ public X500DistinguishedName IssuerName
}
}
public PolicyData GetPolicyData()
{
throw new PlatformNotSupportedException();
}
public IEnumerable<X509Extension> Extensions
{
get
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册