Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace System.Security.Authentication.ExtendedProtection
{
public abstract class ChannelBinding : SafeHandleZeroOrMinusOneIsInvalid
{
protected ChannelBinding()
: base(true)
{
}
protected ChannelBinding(bool ownsHandle)
: base(ownsHandle)
{
}
public abstract int Size
{
get;
}
}
}

View File

@@ -0,0 +1,15 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
namespace System.Security.Authentication.ExtendedProtection
{
// These should match the native SEC_ATTR_*_BINDINGS defines
public enum ChannelBindingKind
{
Unknown = 0,
Unique = 0x19,
Endpoint = 0x1A
}
}

View File

@@ -0,0 +1,17 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
namespace System.Security.Authentication.ExtendedProtection.Configuration
{
internal static class ExtendedProtectionConfigurationStrings
{
internal const string ExtendedProtectionPolicy = "extendedProtectionPolicy";
internal const string PolicyEnforcement = "policyEnforcement";
internal const string ProtectionScenario = "protectionScenario";
internal const string CustomServiceNames = "customServiceNames";
internal const string Name = "name";
}
}

View File

@@ -0,0 +1,102 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Configuration;
namespace System.Security.Authentication.ExtendedProtection.Configuration
{
public sealed class ExtendedProtectionPolicyElement : ConfigurationElement
{
public ExtendedProtectionPolicyElement()
{
this.properties.Add(this.policyEnforcement);
this.properties.Add(this.protectionScenario);
this.properties.Add(this.customServiceNames);
}
protected override ConfigurationPropertyCollection Properties
{
get { return this.properties; }
}
[ConfigurationProperty(ExtendedProtectionConfigurationStrings.PolicyEnforcement)]
public PolicyEnforcement PolicyEnforcement {
get {
return (PolicyEnforcement)this[this.policyEnforcement];
}
set {
this[this.policyEnforcement] = value;
}
}
[ConfigurationProperty(ExtendedProtectionConfigurationStrings.ProtectionScenario, DefaultValue=ProtectionScenario.TransportSelected)]
public ProtectionScenario ProtectionScenario {
get {
return (ProtectionScenario)this[this.protectionScenario];
}
set {
this[this.protectionScenario] = value;
}
}
[ConfigurationProperty(ExtendedProtectionConfigurationStrings.CustomServiceNames)]
public ServiceNameElementCollection CustomServiceNames
{
get {
return (ServiceNameElementCollection)this[this.customServiceNames];
}
}
public ExtendedProtectionPolicy BuildPolicy()
{
if (PolicyEnforcement == PolicyEnforcement.Never)
{
return new ExtendedProtectionPolicy(PolicyEnforcement.Never);
}
ServiceNameCollection spns = null;
ServiceNameElementCollection spnCollection = CustomServiceNames;
if (spnCollection != null && spnCollection.Count > 0)
{
List<string> spnList = new List<string>(spnCollection.Count);
foreach (ServiceNameElement element in spnCollection)
{
spnList.Add(element.Name);
}
spns = new ServiceNameCollection(spnList);
}
return new ExtendedProtectionPolicy(PolicyEnforcement, ProtectionScenario, spns);
}
ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
private static PolicyEnforcement DefaultPolicyEnforcement
{
get
{
return PolicyEnforcement.Never;
}
}
readonly ConfigurationProperty policyEnforcement =
new ConfigurationProperty(ExtendedProtectionConfigurationStrings.PolicyEnforcement,
typeof(PolicyEnforcement), DefaultPolicyEnforcement,
ConfigurationPropertyOptions.None);
readonly ConfigurationProperty protectionScenario =
new ConfigurationProperty(ExtendedProtectionConfigurationStrings.ProtectionScenario,
typeof(ProtectionScenario), ProtectionScenario.TransportSelected,
ConfigurationPropertyOptions.None);
readonly ConfigurationProperty customServiceNames =
new ConfigurationProperty(ExtendedProtectionConfigurationStrings.CustomServiceNames,
typeof(ServiceNameElementCollection), null,
ConfigurationPropertyOptions.None);
}
}

View File

@@ -0,0 +1,45 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System.Configuration;
namespace System.Security.Authentication.ExtendedProtection.Configuration
{
public sealed class ServiceNameElement : ConfigurationElement
{
public ServiceNameElement()
{
this.properties.Add(this.name);
}
[ConfigurationProperty(ExtendedProtectionConfigurationStrings.Name)]
public string Name
{
get { return (string)this[this.name]; }
set { this[this.name] = value; }
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return this.properties;
}
}
internal string Key
{
get { return this.Name; }
}
ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();
readonly ConfigurationProperty name =
new ConfigurationProperty(ExtendedProtectionConfigurationStrings.Name,
typeof(string), null,
ConfigurationPropertyOptions.IsRequired);
}
}

View File

@@ -0,0 +1,94 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System.Configuration;
namespace System.Security.Authentication.ExtendedProtection.Configuration
{
[ConfigurationCollection(typeof(ServiceNameElement))]
public sealed class ServiceNameElementCollection : ConfigurationElementCollection
{
public ServiceNameElementCollection()
{
}
public ServiceNameElement this[int index]
{
get
{
return (ServiceNameElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public new ServiceNameElement this[string name]
{
get
{
return (ServiceNameElement)BaseGet(name);
}
set
{
if (BaseGet(name) != null)
{
BaseRemove(name);
}
BaseAdd(value);
}
}
public void Add(ServiceNameElement element)
{
BaseAdd(element);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new ServiceNameElement();
}
protected override Object GetElementKey(ConfigurationElement element)
{
if (element == null)
throw new ArgumentNullException("element");
return ((ServiceNameElement)element).Key;
}
public int IndexOf(ServiceNameElement element)
{
return BaseIndexOf(element);
}
public void Remove(ServiceNameElement element)
{
if (element == null)
throw new ArgumentNullException("element");
BaseRemove(element.Key);
}
public void Remove(string name)
{
BaseRemove(name);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
}
}

View File

@@ -0,0 +1,191 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;
namespace System.Security.Authentication.ExtendedProtection
{
/// <summary>
/// This class contains the necessary settings for specifying how Extended Protection
/// should behave. Use one of the Build* methods to create an instance of this type.
/// </summary>
[Serializable]
[TypeConverter(typeof(ExtendedProtectionPolicyTypeConverter))]
public class ExtendedProtectionPolicy : ISerializable
{
private const string policyEnforcementName = "policyEnforcement";
private const string protectionScenarioName = "protectionScenario";
private const string customServiceNamesName = "customServiceNames";
private const string customChannelBindingName = "customChannelBinding";
private ServiceNameCollection customServiceNames;
private PolicyEnforcement policyEnforcement;
private ProtectionScenario protectionScenario;
private ChannelBinding customChannelBinding;
public ExtendedProtectionPolicy(PolicyEnforcement policyEnforcement,
ProtectionScenario protectionScenario,
ServiceNameCollection customServiceNames)
{
if (policyEnforcement == PolicyEnforcement.Never)
{
throw new ArgumentException(SR.GetString(SR.security_ExtendedProtectionPolicy_UseDifferentConstructorForNever), "policyEnforcement");
}
if (customServiceNames != null && customServiceNames.Count == 0)
{
throw new ArgumentException(SR.GetString(SR.security_ExtendedProtectionPolicy_NoEmptyServiceNameCollection), "customServiceNames");
}
this.policyEnforcement = policyEnforcement;
this.protectionScenario = protectionScenario;
this.customServiceNames = customServiceNames;
}
public ExtendedProtectionPolicy(PolicyEnforcement policyEnforcement,
ProtectionScenario protectionScenario,
ICollection customServiceNames)
: this(policyEnforcement, protectionScenario,
customServiceNames == null ? (ServiceNameCollection)null : new ServiceNameCollection(customServiceNames))
{
}
public ExtendedProtectionPolicy(PolicyEnforcement policyEnforcement,
ChannelBinding customChannelBinding)
{
if (policyEnforcement == PolicyEnforcement.Never)
{
throw new ArgumentException(SR.GetString(SR.security_ExtendedProtectionPolicy_UseDifferentConstructorForNever), "policyEnforcement");
}
if (customChannelBinding == null)
{
throw new ArgumentNullException("customChannelBinding");
}
this.policyEnforcement = policyEnforcement;
this.protectionScenario = ProtectionScenario.TransportSelected;
this.customChannelBinding = customChannelBinding;
}
public ExtendedProtectionPolicy(PolicyEnforcement policyEnforcement)
{
// this is the only constructor which allows PolicyEnforcement.Never.
this.policyEnforcement = policyEnforcement;
this.protectionScenario = ProtectionScenario.TransportSelected;
}
protected ExtendedProtectionPolicy(SerializationInfo info, StreamingContext context)
{
policyEnforcement = (PolicyEnforcement)info.GetInt32(policyEnforcementName);
protectionScenario = (ProtectionScenario)info.GetInt32(protectionScenarioName);
customServiceNames = (ServiceNameCollection)info.GetValue(customServiceNamesName, typeof(ServiceNameCollection));
byte[] channelBindingData = (byte[])info.GetValue(customChannelBindingName, typeof(byte[]));
if (channelBindingData != null)
{
customChannelBinding = SafeLocalFreeChannelBinding.LocalAlloc(channelBindingData.Length);
Marshal.Copy(channelBindingData, 0, customChannelBinding.DangerousGetHandle(), channelBindingData.Length);
}
}
public ServiceNameCollection CustomServiceNames
{
get { return customServiceNames; }
}
public PolicyEnforcement PolicyEnforcement
{
get { return policyEnforcement; }
}
public ProtectionScenario ProtectionScenario
{
get { return protectionScenario; }
}
public ChannelBinding CustomChannelBinding
{
get { return customChannelBinding; }
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("ProtectionScenario=");
sb.Append(protectionScenario.ToString());
sb.Append("; PolicyEnforcement=");
sb.Append(policyEnforcement.ToString());
sb.Append("; CustomChannelBinding=");
if (customChannelBinding == null)
{
sb.Append("<null>");
}
else
{
sb.Append(customChannelBinding.ToString());
}
sb.Append("; ServiceNames=");
if (customServiceNames == null)
{
sb.Append("<null>");
}
else
{
bool first = true;
foreach (string serviceName in customServiceNames)
{
if (first)
{
first = false;
}
else
{
sb.Append(", ");
}
sb.Append(serviceName);
}
}
return sb.ToString();
}
public static bool OSSupportsExtendedProtection
{
get
{
return AuthenticationManager.OSSupportsExtendedProtection;
}
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, SerializationFormatter = true)]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(policyEnforcementName, (int)policyEnforcement);
info.AddValue(protectionScenarioName, (int)protectionScenario);
info.AddValue(customServiceNamesName, customServiceNames, typeof(ServiceNameCollection));
if (customChannelBinding == null)
{
info.AddValue(customChannelBindingName, null, typeof(byte[]));
}
else
{
byte[] channelBindingData = new byte[customChannelBinding.Size];
Marshal.Copy(customChannelBinding.DangerousGetHandle(), channelBindingData, 0, customChannelBinding.Size);
info.AddValue(customChannelBindingName, channelBindingData, typeof(byte[]));
}
}
}
}

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
namespace System.Security.Authentication.ExtendedProtection
{
public class ExtendedProtectionPolicyTypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor))
{
ExtendedProtectionPolicy policy = value as ExtendedProtectionPolicy;
if (policy != null)
{
Type[] parameterTypes;
object[] parameterValues;
if (policy.PolicyEnforcement == PolicyEnforcement.Never)
{
parameterTypes = new Type[] { typeof(PolicyEnforcement) };
parameterValues = new object[] { PolicyEnforcement.Never };
}
else
{
parameterTypes = new Type[] { typeof(PolicyEnforcement), typeof(ProtectionScenario), typeof(ICollection) };
object[] customServiceNames = null;
if (policy.CustomServiceNames != null && policy.CustomServiceNames.Count > 0)
{
customServiceNames = new object[policy.CustomServiceNames.Count];
((ICollection)policy.CustomServiceNames).CopyTo(customServiceNames, 0);
}
parameterValues = new object[] { policy.PolicyEnforcement, policy.ProtectionScenario, customServiceNames };
}
ConstructorInfo constructor = typeof(ExtendedProtectionPolicy).GetConstructor(parameterTypes);
return new InstanceDescriptor(constructor, parameterValues);
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}

View File

@@ -0,0 +1,15 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
namespace System.Security.Authentication.ExtendedProtection
{
public enum PolicyEnforcement
{
Never,
WhenSupported,
Always
}
}

View File

@@ -0,0 +1,14 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
namespace System.Security.Authentication.ExtendedProtection
{
public enum ProtectionScenario
{
TransportSelected,
TrustedProxy
}
}

View File

@@ -0,0 +1,199 @@
using System.Collections;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace System.Security.Authentication.ExtendedProtection
{
// derived from ReadOnlyCollectionBase because it needs to be back ported to .Net 1.x
[SuppressMessage("Microsoft.Design","CA1058:TypesShouldNotExtendCertainBaseTypes", Justification="changing this would be a breaking change; this code has already shipped")]
[Serializable]
public class ServiceNameCollection : ReadOnlyCollectionBase
{
public ServiceNameCollection(ICollection items)
{
if (items == null) {
throw new ArgumentNullException("items");
}
// Normalize and filter for duplicates
foreach (string serviceName in items)
{
AddIfNew(InnerList, serviceName);
}
}
public ServiceNameCollection Merge(string serviceName)
{
ArrayList newServiceNames = new ArrayList(); // be compatible with .Net 1.x; no generics
newServiceNames.AddRange(this.InnerList);
AddIfNew(newServiceNames, serviceName);
ServiceNameCollection newCollection = new ServiceNameCollection(newServiceNames);
return newCollection;
}
public ServiceNameCollection Merge(IEnumerable serviceNames)
{
ArrayList newServiceNames = new ArrayList(); // be compatible with .Net 1.x; no generics
newServiceNames.AddRange(this.InnerList);
// we have a pretty bad performance here: O(n^2), but since service name lists should
// be small (<<50) and Merge() should not be called frequently, this shouldn't be an issue
foreach (object item in serviceNames) {
AddIfNew(newServiceNames, item as string);
}
ServiceNameCollection newCollection = new ServiceNameCollection(newServiceNames);
return newCollection;
}
// Normalize, check for duplicates, and add if the value is unique
private static void AddIfNew(ArrayList newServiceNames, string serviceName)
{
if (String.IsNullOrEmpty(serviceName)) {
throw new ArgumentException(SR.GetString(SR.security_ServiceNameCollection_EmptyServiceName));
}
serviceName = NormalizeServiceName(serviceName);
if (!Contains(serviceName, newServiceNames)) {
newServiceNames.Add(serviceName);
}
}
// Assumes searchServiceName and serviceNames have already been normalized
internal static bool Contains(string searchServiceName, ICollection serviceNames)
{
Debug.Assert(serviceNames != null);
Debug.Assert(!String.IsNullOrEmpty(searchServiceName));
foreach (string serviceName in serviceNames) {
if (Match(serviceName, searchServiceName)) {
return true;
}
}
return false;
}
public bool Contains(string searchServiceName)
{
string searchName = NormalizeServiceName(searchServiceName);
return Contains(searchName, InnerList);
}
// Normalizes any punycode to unicode in an Service Name (SPN) host.
// If the algorithm fails at any point then the original input is returned.
// ServiceName is in one of the following forms:
// prefix/host
// prefix/host:port
// prefix/host/DistinguishedName
// prefix/host:port/DistinguishedName
internal static string NormalizeServiceName(string inputServiceName)
{
if (string.IsNullOrWhiteSpace(inputServiceName))
{
return inputServiceName;
}
// Separate out the prefix
int shashIndex = inputServiceName.IndexOf('/');
if (shashIndex < 0)
{
return inputServiceName;
}
string prefix = inputServiceName.Substring(0, shashIndex + 1); // Includes slash
string hostPortAndDistinguisher = inputServiceName.Substring(shashIndex + 1); // Excludes slash
if (string.IsNullOrWhiteSpace(hostPortAndDistinguisher))
{
return inputServiceName;
}
string host = hostPortAndDistinguisher;
string port = string.Empty;
string distinguisher = string.Empty;
// Check for the absence of a port or distinguisher.
UriHostNameType hostType = Uri.CheckHostName(hostPortAndDistinguisher);
if (hostType == UriHostNameType.Unknown)
{
string hostAndPort = hostPortAndDistinguisher;
// Check for distinguisher
int nextSlashIndex = hostPortAndDistinguisher.IndexOf('/');
if (nextSlashIndex >= 0)
{
// host:port/distinguisher or host/distinguisher
hostAndPort = hostPortAndDistinguisher.Substring(0, nextSlashIndex); // Excludes Slash
distinguisher = hostPortAndDistinguisher.Substring(nextSlashIndex); // Includes Slash
host = hostAndPort; // We don't know if there is a port yet.
// No need to validate the distinguisher
}
// Check for port
int colonIndex = hostAndPort.LastIndexOf(':'); // Allow IPv6 addresses
if (colonIndex >= 0)
{
// host:port
host = hostAndPort.Substring(0, colonIndex); // Excludes colon
port = hostAndPort.Substring(colonIndex + 1); // Excludes colon
// Loosely validate the port just to make sure it was a port and not something else
UInt16 portValue;
if (!UInt16.TryParse(port, NumberStyles.Integer, CultureInfo.InvariantCulture, out portValue))
{
return inputServiceName;
}
// Re-include the colon for the final output. Do not change the port format.
port = hostAndPort.Substring(colonIndex);
}
hostType = Uri.CheckHostName(host); // Revaidate the host
}
if (hostType != UriHostNameType.Dns)
{
// UriHostNameType.IPv4, UriHostNameType.IPv6: Do not normalize IPv4/6 hosts.
// UriHostNameType.Basic: This is never returned by CheckHostName today
// UriHostNameType.Unknown: Nothing recognizable to normalize
// default Some new UriHostNameType?
return inputServiceName;
}
// Now we have a valid DNS host, normalize it.
Uri constructedUri;
// This shouldn't fail, but we need to avoid any unexpected exceptions on this code path.
if (!Uri.TryCreate(Uri.UriSchemeHttp + Uri.SchemeDelimiter + host, UriKind.Absolute, out constructedUri))
{
return inputServiceName;
}
string normalizedHost = constructedUri.GetComponents(
UriComponents.NormalizedHost, UriFormat.SafeUnescaped);
string normalizedServiceName = string.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}{3}", prefix, normalizedHost, port, distinguisher);
// Don't return the new one unless we absolutely have to. It may have only changed casing.
if (Match(inputServiceName, normalizedServiceName))
{
return inputServiceName;
}
return normalizedServiceName;
}
// Assumes already normalized
internal static bool Match(string serviceName1, string serviceName2)
{
return (String.Compare(serviceName1, serviceName2, StringComparison.OrdinalIgnoreCase) == 0);
}
}
}

View File

@@ -0,0 +1,21 @@
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using System.Collections.Generic;
using System.ComponentModel;
namespace System.Security.Claims
{
public static class DynamicRoleClaimProvider
{
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use ClaimsAuthenticationManager to add claims to a ClaimsIdentity", true)]
public static void AddDynamicRoleClaims(ClaimsIdentity claimsIdentity, IEnumerable<Claim> claims)
{
claimsIdentity.ExternalClaims.Add(claims);
}
}
}

View File

@@ -0,0 +1,232 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// AsnEncodedData.cs
//
namespace System.Security.Cryptography {
using System.Collections;
using System.Globalization;
using System.Runtime.InteropServices;
public class AsnEncodedData {
internal Oid m_oid = null;
internal byte[] m_rawData = null;
internal AsnEncodedData (Oid oid) {
m_oid = oid;
}
internal AsnEncodedData (string oid, CAPI.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) {}
internal AsnEncodedData (Oid oid, CAPI.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) {}
protected AsnEncodedData () {}
public AsnEncodedData (byte[] rawData) {
Reset(null, rawData);
}
public AsnEncodedData (string oid, byte[] rawData) {
Reset(new Oid(oid), rawData);
}
public AsnEncodedData (Oid oid, byte[] rawData) {
Reset(oid, rawData);
}
public AsnEncodedData (AsnEncodedData asnEncodedData) {
if (asnEncodedData == null)
throw new ArgumentNullException("asnEncodedData");
Reset(asnEncodedData.m_oid, asnEncodedData.m_rawData);
}
public Oid Oid {
get {
return m_oid;
}
set {
if (value == null)
m_oid = null;
else
m_oid = new Oid(value);
}
}
public byte[] RawData {
get {
return m_rawData;
}
set {
if (value == null)
throw new ArgumentNullException("value");
m_rawData = (byte[]) value.Clone();
}
}
public virtual void CopyFrom (AsnEncodedData asnEncodedData) {
if (asnEncodedData == null)
throw new ArgumentNullException("asnEncodedData");
Reset(asnEncodedData.m_oid, asnEncodedData.m_rawData);
}
public virtual string Format (bool multiLine) {
// Return empty string if no data to format.
if (m_rawData == null || m_rawData.Length == 0)
return String.Empty;
// If OID is not present, then we can force CryptFormatObject
// to use hex formatting by providing an empty OID string.
string oidValue = String.Empty;
if (m_oid != null && m_oid.Value != null)
oidValue = m_oid.Value;
return CAPI.CryptFormatObject(CAPI.X509_ASN_ENCODING,
multiLine ? CAPI.CRYPT_FORMAT_STR_MULTI_LINE : 0,
oidValue,
m_rawData);
}
private void Reset (Oid oid, byte[] rawData) {
this.Oid = oid;
this.RawData = rawData;
}
}
public sealed class AsnEncodedDataCollection : ICollection {
private ArrayList m_list = null;
private Oid m_oid = null;
public AsnEncodedDataCollection () {
m_list = new ArrayList();
m_oid = null;
}
public AsnEncodedDataCollection(AsnEncodedData asnEncodedData) : this() {
m_list.Add(asnEncodedData);
}
public int Add (AsnEncodedData asnEncodedData) {
if (asnEncodedData == null)
throw new ArgumentNullException("asnEncodedData");
//
// If m_oid is not null, then OIDs must match.
//
if (m_oid != null) {
string szOid1 = m_oid.Value;
string szOid2 = asnEncodedData.Oid.Value;
if (szOid1 != null && szOid2 != null) {
// Both are not null, so make sure OIDs match.
if (String.Compare(szOid1, szOid2, StringComparison.OrdinalIgnoreCase) != 0)
throw new CryptographicException(SR.GetString(SR.Cryptography_Asn_MismatchedOidInCollection));
}
else if (szOid1 != null || szOid2 != null) {
// Can't be matching, since only one of them is null.
throw new CryptographicException(SR.GetString(SR.Cryptography_Asn_MismatchedOidInCollection));
}
}
return m_list.Add(asnEncodedData);
}
public void Remove (AsnEncodedData asnEncodedData) {
if (asnEncodedData == null)
throw new ArgumentNullException("asnEncodedData");
m_list.Remove(asnEncodedData);
}
public AsnEncodedData this[int index] {
get {
return (AsnEncodedData) m_list[index];
}
}
public int Count {
get {
return m_list.Count;
}
}
public AsnEncodedDataEnumerator GetEnumerator() {
return new AsnEncodedDataEnumerator(this);
}
/// <internalonly/>
IEnumerator IEnumerable.GetEnumerator() {
return new AsnEncodedDataEnumerator(this);
}
/// <internalonly/>
void ICollection.CopyTo(Array array, int index) {
if (array == null)
throw new ArgumentNullException("array");
if (array.Rank != 1)
throw new ArgumentException(SR.GetString(SR.Arg_RankMultiDimNotSupported));
if (index < 0 || index >= array.Length)
throw new ArgumentOutOfRangeException("index", SR.GetString(SR.ArgumentOutOfRange_Index));
if (index + this.Count > array.Length)
throw new ArgumentException(SR.GetString(SR.Argument_InvalidOffLen));
for (int i=0; i < this.Count; i++) {
array.SetValue(this[i], index);
index++;
}
}
public void CopyTo(AsnEncodedData[] array, int index) {
((ICollection)this).CopyTo(array, index);
}
public bool IsSynchronized {
get {
return false;
}
}
public Object SyncRoot {
get {
return this;
}
}
}
public sealed class AsnEncodedDataEnumerator : IEnumerator {
private AsnEncodedDataCollection m_asnEncodedDatas;
private int m_current;
private AsnEncodedDataEnumerator() {}
internal AsnEncodedDataEnumerator(AsnEncodedDataCollection asnEncodedDatas) {
m_asnEncodedDatas = asnEncodedDatas;
m_current = -1;
}
public AsnEncodedData Current {
get {
return m_asnEncodedDatas[m_current];
}
}
/// <internalonly/>
Object IEnumerator.Current {
get {
return (Object) m_asnEncodedDatas[m_current];
}
}
public bool MoveNext() {
if (m_current == ((int) m_asnEncodedDatas.Count - 1))
return false;
m_current++;
return true;
}
public void Reset() {
m_current = -1;
}
}
}

View File

@@ -0,0 +1,495 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// BigInt.cs
//
// 11/06/2002
//
namespace System.Security.Cryptography
{
using System.Security.Cryptography.X509Certificates;
using System.Text;
//
// This is a pretty "crude" implementation of BigInt arithmetic operations.
// This class is used in particular to convert certificate serial numbers from
// hexadecimal representation to decimal format and vice versa.
//
// We are not very concerned about the perf characterestics of this implementation
// for now. We perform all operations up to 128 bytes (which is enough for the current
// purposes although this constant can be increased). Any overflow bytes are going to be lost.
//
// A BigInt is represented as a little endian byte array of size 128 bytes. All
// arithmetic operations are performed in base 0x100 (256). The algorithms used
// are simply the common primary school techniques for doing operations in base 10.
//
internal sealed class BigInt {
private byte[] m_elements;
private const int m_maxbytes = 128; // 128 bytes is the maximum we can handle.
// This means any overflow bits beyond 128 bytes
// will be lost when doing arithmetic operations.
private const int m_base = 0x100;
private int m_size = 0;
internal BigInt () {
m_elements = new byte[m_maxbytes];
}
internal BigInt(byte b) {
m_elements = new byte[m_maxbytes];
SetDigit(0, b);
}
//
// Gets or sets the size of a BigInt.
//
internal int Size {
get {
return m_size;
}
set {
if (value > m_maxbytes)
m_size = m_maxbytes;
if (value < 0)
m_size = 0;
m_size = value;
}
}
//
// Gets the digit at the specified index.
//
internal byte GetDigit (int index) {
if (index < 0 || index >= m_size)
return 0;
return m_elements[index];
}
//
// Sets the digit at the specified index.
//
internal void SetDigit (int index, byte digit) {
if (index >= 0 && index < m_maxbytes) {
m_elements[index] = digit;
if (index >= m_size && digit != 0)
m_size = (index + 1);
if (index == m_size - 1 && digit == 0)
m_size--;
}
}
internal void SetDigit (int index, byte digit, ref int size) {
if (index >= 0 && index < m_maxbytes) {
m_elements[index] = digit;
if (index >= size && digit != 0)
size = (index + 1);
if (index == size - 1 && digit == 0)
size = (size - 1);
}
}
//
// overloaded operators.
//
public static bool operator < (BigInt value1, BigInt value2) {
if (value1 == null)
return true;
else if (value2 == null)
return false;
int Len1 = value1.Size;
int Len2 = value2.Size;
if (Len1 != Len2)
return (Len1 < Len2);
while (Len1-- > 0) {
if (value1.m_elements[Len1] != value2.m_elements[Len1])
return (value1.m_elements[Len1] < value2.m_elements[Len1]);
}
return false;
}
public static bool operator > (BigInt value1, BigInt value2) {
if (value1 == null)
return false;
else if (value2 == null)
return true;
int Len1 = value1.Size;
int Len2 = value2.Size;
if (Len1 != Len2)
return (Len1 > Len2);
while (Len1-- > 0) {
if (value1.m_elements[Len1] != value2.m_elements[Len1])
return (value1.m_elements[Len1] > value2.m_elements[Len1]);
}
return false;
}
public static bool operator == (BigInt value1, BigInt value2) {
if ((Object) value1 == null)
return ((Object) value2 == null);
else if ((Object) value2 == null)
return ((Object) value1 == null);
int Len1 = value1.Size;
int Len2 = value2.Size;
if (Len1 != Len2)
return false;
for (int index = 0; index < Len1; index++) {
if (value1.m_elements[index] != value2.m_elements[index])
return false;
}
return true;
}
public static bool operator != (BigInt value1, BigInt value2) {
return !(value1 == value2);
}
public override bool Equals (Object obj) {
if (obj is BigInt) {
return (this == (BigInt) obj);
}
return false;
}
public override int GetHashCode () {
int hash = 0;
for (int index = 0; index < m_size; index++) {
hash += GetDigit(index);
}
return hash;
}
//
// Adds a and b and outputs the result in c.
//
internal static void Add (BigInt a, byte b, ref BigInt c) {
byte carry = b;
int sum = 0;
int size = a.Size;
int newSize = 0;
for (int index = 0; index < size; index++) {
sum = a.GetDigit(index) + carry;
c.SetDigit(index, (byte) (sum & 0xFF), ref newSize);
carry = (byte) ((sum >> 8) & 0xFF);
}
if (carry != 0)
c.SetDigit(a.Size, carry, ref newSize);
c.Size = newSize;
}
//
// Negates a BigInt value. Each byte is complemented, then we add 1 to it.
//
internal static void Negate (ref BigInt a) {
int newSize = 0;
for (int index = 0; index < m_maxbytes; index++) {
a.SetDigit(index, (byte) (~a.GetDigit(index) & 0xFF), ref newSize);
}
for (int index = 0; index < m_maxbytes; index++) {
a.SetDigit(index, (byte) (a.GetDigit(index) + 1), ref newSize);
if ((a.GetDigit(index) & 0xFF) != 0) break;
a.SetDigit(index, (byte) (a.GetDigit(index) & 0xFF), ref newSize);
}
a.Size = newSize;
}
//
// Subtracts b from a and outputs the result in c.
//
internal static void Subtract (BigInt a, BigInt b, ref BigInt c) {
byte borrow = 0;
int diff = 0;
if (a < b) {
Subtract(b, a, ref c);
Negate(ref c);
return;
}
int index = 0;
int size = a.Size;
int newSize = 0;
for (index = 0; index < size; index++) {
diff = a.GetDigit(index) - b.GetDigit(index) - borrow;
borrow = 0;
if (diff < 0) {
diff += m_base;
borrow = 1;
}
c.SetDigit(index, (byte) (diff & 0xFF), ref newSize);
}
c.Size = newSize;
}
//
// multiplies a BigInt by an integer.
//
private void Multiply (int b) {
if (b == 0) {
Clear();
return;
}
int carry = 0, product = 0;
int size = this.Size;
int newSize = 0;
for (int index = 0; index < size; index++) {
product = b * GetDigit(index) + carry;
carry = product / m_base;
SetDigit(index, (byte) (product % m_base), ref newSize);
}
if (carry != 0) {
byte[] bytes = BitConverter.GetBytes(carry);
for (int index = 0; index < bytes.Length; index++) {
SetDigit(size + index, bytes[index], ref newSize);
}
}
this.Size = newSize;
}
private static void Multiply (BigInt a, int b, ref BigInt c) {
if (b == 0) {
c.Clear();
return;
}
int carry = 0, product = 0;
int size = a.Size;
int newSize = 0;
for (int index = 0; index < size; index++) {
product = b * a.GetDigit(index) + carry;
carry = product / m_base;
c.SetDigit(index, (byte) (product % m_base), ref newSize);
}
if (carry != 0) {
byte[] bytes = BitConverter.GetBytes(carry);
for (int index = 0; index < bytes.Length; index++) {
c.SetDigit(size + index, bytes[index], ref newSize);
}
}
c.Size = newSize;
}
//
// Divides a BigInt by a single byte.
//
private void Divide (int b) {
int carry = 0, quotient = 0;
int bLen = this.Size;
int newSize = 0;
while (bLen-- > 0) {
quotient = m_base * carry + GetDigit(bLen);
carry = quotient % b;
SetDigit(bLen, (byte) (quotient / b), ref newSize);
}
this.Size = newSize;
}
//
// Integer division of one BigInt by another.
//
internal static void Divide (BigInt numerator, BigInt denominator, ref BigInt quotient, ref BigInt remainder) {
// Avoid extra computations in special cases.
if (numerator < denominator) {
quotient.Clear();
remainder.CopyFrom(numerator);
return;
}
if (numerator == denominator) {
quotient.Clear(); quotient.SetDigit(0, 1);
remainder.Clear();
return;
}
BigInt dividend = new BigInt();
dividend.CopyFrom(numerator);
BigInt divisor = new BigInt();
divisor.CopyFrom(denominator);
uint zeroCount = 0;
// We pad the divisor with zeros until its size equals that of the dividend.
while (divisor.Size < dividend.Size) {
divisor.Multiply(m_base);
zeroCount++;
}
if (divisor > dividend) {
divisor.Divide(m_base);
zeroCount--;
}
// Use school division techniques, make a guess for how many times
// divisor goes into dividend, making adjustment if necessary.
int a = 0;
int b = 0;
int c = 0;
BigInt hold = new BigInt();
quotient.Clear();
for (int index = 0; index <= zeroCount; index++) {
a = dividend.Size == divisor.Size ? dividend.GetDigit(dividend.Size - 1) :
m_base * dividend.GetDigit(dividend.Size - 1) + dividend.GetDigit(dividend.Size - 2);
b = divisor.GetDigit(divisor.Size - 1);
c = a / b;
if (c >= m_base)
c = 0xFF;
Multiply(divisor, c, ref hold);
while (hold > dividend) {
c--;
Multiply(divisor, c, ref hold);
}
quotient.Multiply(m_base);
Add(quotient, (byte) c, ref quotient);
Subtract(dividend, hold, ref dividend);
divisor.Divide(m_base);
}
remainder.CopyFrom(dividend);
}
//
// copies a BigInt value.
//
internal void CopyFrom (BigInt a) {
Array.Copy(a.m_elements, m_elements, m_maxbytes);
m_size = a.m_size;
}
//
// This method returns true if the BigInt is equal to 0, false otherwise.
//
internal bool IsZero () {
for (int index = 0; index < m_size; index++) {
if (m_elements[index] != 0)
return false;
}
return true;
}
//
// returns the array in machine format, i.e. little endian format (as an integer).
//
internal byte[] ToByteArray() {
byte[] result = new byte[this.Size];
Array.Copy(m_elements, result, this.Size);
return result;
}
//
// zeroizes the content of the internal array.
//
internal void Clear () {
m_size = 0;
}
//
// Imports a hexadecimal string into a BigInt bit representation.
//
internal void FromHexadecimal (string hexNum) {
byte[] hex = X509Utils.DecodeHexString(hexNum);
Array.Reverse(hex);
int size = X509Utils.GetHexArraySize(hex);
Array.Copy(hex, m_elements, size);
this.Size = size;
}
//
// Imports a decimal string into a BigInt bit representation.
//
internal void FromDecimal (string decNum) {
BigInt c = new BigInt();
BigInt tmp = new BigInt();
int length = decNum.Length;
for (int index = 0; index < length; index++) {
// just ignore invalid characters. No need to raise an exception.
if (decNum[index] > '9' || decNum[index] < '0')
continue;
Multiply(c, 10, ref tmp);
Add(tmp, (byte) (decNum[index] - '0'), ref c);
}
CopyFrom(c);
}
//
// Exports the BigInt representation as a decimal string.
//
private static readonly char[] decValues = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
internal string ToDecimal ()
{
if (IsZero())
return "0";
BigInt ten = new BigInt(0xA);
BigInt numerator = new BigInt();
BigInt quotient = new BigInt();
BigInt remainder = new BigInt();
numerator.CopyFrom(this);
// Each hex digit can account for log(16) = 1.21 decimal digits. Times two hex digits in a byte
// and m_size bytes used in this BigInt, yields the maximum number of characters for the decimal
// representation of the BigInt.
char[] dec = new char[(int)Math.Ceiling(m_size * 2 * 1.21)];
int index = 0;
do
{
Divide(numerator, ten, ref quotient, ref remainder);
dec[index++] = decValues[remainder.IsZero() ? 0 : (int)remainder.m_elements[0]];
numerator.CopyFrom(quotient);
} while (quotient.IsZero() == false);
Array.Reverse(dec, 0, index);
return new String(dec, 0, index);
}
}
}

View File

@@ -0,0 +1 @@
81bfcadd0ba9a37b43ddcf92e44efaa90669ec39

View File

@@ -0,0 +1,249 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// Oid.cs
//
namespace System.Security.Cryptography {
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
// Values taken from wincrypt.h
public enum OidGroup {
All = 0,
HashAlgorithm = 1,
EncryptionAlgorithm = 2,
PublicKeyAlgorithm = 3,
SignatureAlgorithm = 4,
Attribute = 5,
ExtensionOrAttribute = 6,
EnhancedKeyUsage = 7,
Policy = 8,
Template = 9,
KeyDerivationFunction = 10
}
public sealed class Oid {
private string m_value = null;
private string m_friendlyName = null;
private OidGroup m_group = OidGroup.All;
public Oid() { }
public Oid(string oid) : this(oid, OidGroup.All, true)
{
}
internal Oid(string oid, OidGroup group, bool lookupFriendlyName)
{
if (lookupFriendlyName)
{
// If we were passed the friendly name, retrieve the value string.
string oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, oid, group);
if (oidValue == null)
oidValue = oid;
this.Value = oidValue;
}
else
{
this.Value = oid;
}
m_group = group;
}
public Oid(string value, string friendlyName) {
m_value = value;
m_friendlyName = friendlyName;
}
public Oid(Oid oid) {
if (oid == null)
throw new ArgumentNullException("oid");
m_value = oid.m_value;
m_friendlyName = oid.m_friendlyName;
m_group = oid.m_group;
}
private Oid(string value, string friendlyName, OidGroup group) {
Debug.Assert(value != null);
Debug.Assert(friendlyName != null);
m_value = value;
m_friendlyName = friendlyName;
m_group = group;
}
public static Oid FromFriendlyName(string friendlyName, OidGroup group) {
if (friendlyName == null) {
throw new ArgumentNullException("friendlyName");
}
string oidValue = X509Utils.FindOidInfo(CAPI.CRYPT_OID_INFO_NAME_KEY, friendlyName, group);
if (oidValue == null) {
throw new CryptographicException(SR.GetString(SR.Cryptography_Oid_InvalidValue));
}
return new Oid(oidValue, friendlyName, group);
}
public static Oid FromOidValue(string oidValue, OidGroup group) {
if (oidValue == null) {
throw new ArgumentNullException("oidValue");
}
string friendlyName = X509Utils.FindOidInfo(CAPI.CRYPT_OID_INFO_OID_KEY, oidValue, group);
if (friendlyName == null) {
throw new CryptographicException(SR.GetString(SR.Cryptography_Oid_InvalidValue));
}
return new Oid(oidValue, friendlyName, group);
}
public string Value {
get { return m_value; }
set { m_value = value; }
}
public string FriendlyName {
get {
if(m_friendlyName == null && m_value != null)
m_friendlyName = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_OID_KEY, m_value, m_group);
return m_friendlyName;
}
set {
m_friendlyName = value;
// If we can find the matching OID value, then update it as well
if (m_friendlyName != null) {
// If FindOidInfo fails, we return a null string
string oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, m_friendlyName, m_group);
if (oidValue != null)
m_value = oidValue;
}
}
}
}
public sealed class OidCollection : ICollection {
private ArrayList m_list;
public OidCollection() {
m_list = new ArrayList();
}
public int Add(Oid oid) {
return m_list.Add(oid);
}
public Oid this[int index] {
get {
return m_list[index] as Oid;
}
}
// Indexer using an OID friendly name or value.
public Oid this[string oid] {
get {
// If we were passed the friendly name, retrieve the value string.
string oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, oid, OidGroup.All);
if (oidValue == null)
oidValue = oid;
foreach (Oid entry in m_list) {
if (entry.Value == oidValue)
return entry;
}
return null;
}
}
public int Count {
get {
return m_list.Count;
}
}
public OidEnumerator GetEnumerator() {
return new OidEnumerator(this);
}
/// <internalonly/>
IEnumerator IEnumerable.GetEnumerator() {
return new OidEnumerator(this);
}
/// <internalonly/>
void ICollection.CopyTo(Array array, int index) {
if (array == null)
throw new ArgumentNullException("array");
if (array.Rank != 1)
throw new ArgumentException(SR.GetString(SR.Arg_RankMultiDimNotSupported));
if (index < 0 || index >= array.Length)
throw new ArgumentOutOfRangeException("index", SR.GetString(SR.ArgumentOutOfRange_Index));
if (index + this.Count > array.Length)
throw new ArgumentException(SR.GetString(SR.Argument_InvalidOffLen));
for (int i=0; i < this.Count; i++) {
array.SetValue(this[i], index);
index++;
}
}
public void CopyTo(Oid[] array, int index) {
((ICollection)this).CopyTo(array, index);
}
public bool IsSynchronized {
get {
return false;
}
}
public Object SyncRoot {
get {
return this;
}
}
}
public sealed class OidEnumerator : IEnumerator {
private OidCollection m_oids;
private int m_current;
private OidEnumerator() {}
internal OidEnumerator(OidCollection oids) {
m_oids = oids;
m_current = -1;
}
public Oid Current {
get {
return m_oids[m_current];
}
}
/// <internalonly/>
Object IEnumerator.Current {
get {
return (Object) m_oids[m_current];
}
}
public bool MoveNext() {
if (m_current == ((int) m_oids.Count - 1))
return false;
m_current++;
return true;
}
public void Reset() {
m_current = -1;
}
}
}

View File

@@ -0,0 +1,190 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// X500Name.cs
//
// 07/10/2003
//
namespace System.Security.Cryptography.X509Certificates {
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
[Flags]
public enum X500DistinguishedNameFlags {
None = 0x0000,
Reversed = 0x0001,
UseSemicolons = 0x0010,
DoNotUsePlusSign = 0x0020,
DoNotUseQuotes = 0x0040,
UseCommas = 0x0080,
UseNewLines = 0x0100,
UseUTF8Encoding = 0x1000,
UseT61Encoding = 0x2000,
ForceUTF8Encoding = 0x4000,
}
public sealed class X500DistinguishedName : AsnEncodedData {
private string m_distinguishedName = null;
//
// Constructors.
//
internal X500DistinguishedName (CAPI.CRYPTOAPI_BLOB encodedDistinguishedNameBlob) : base (new Oid(), encodedDistinguishedNameBlob) {}
public X500DistinguishedName (byte[] encodedDistinguishedName) : base(new Oid(), encodedDistinguishedName) {}
public X500DistinguishedName (AsnEncodedData encodedDistinguishedName) : base(encodedDistinguishedName) {}
public X500DistinguishedName (X500DistinguishedName distinguishedName) : base((AsnEncodedData) distinguishedName) {
m_distinguishedName = distinguishedName.Name;
}
public X500DistinguishedName (string distinguishedName) : this(distinguishedName, X500DistinguishedNameFlags.Reversed) {}
public X500DistinguishedName (string distinguishedName, X500DistinguishedNameFlags flag) : base(new Oid(), Encode(distinguishedName, flag)) {
m_distinguishedName = distinguishedName;
}
//
// Public properties.
//
public string Name {
get {
if (m_distinguishedName == null)
m_distinguishedName = Decode(X500DistinguishedNameFlags.Reversed);
return m_distinguishedName;
}
}
//
// Public methods.
//
public string Decode (X500DistinguishedNameFlags flag) {
uint dwStrType = CAPI.CERT_X500_NAME_STR | MapNameToStrFlag(flag);
unsafe {
byte[] encodedDistinguishedName = this.m_rawData;
fixed (byte * pbEncoded = encodedDistinguishedName) {
CAPI.CRYPTOAPI_BLOB nameBlob;
IntPtr pNameBlob = new IntPtr(&nameBlob);
nameBlob.cbData = (uint) encodedDistinguishedName.Length;
nameBlob.pbData = new IntPtr(pbEncoded);
uint cchDecoded = CAPI.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
pNameBlob,
dwStrType,
SafeLocalAllocHandle.InvalidHandle,
0);
if (cchDecoded == 0)
throw new CryptographicException(CAPI.CERT_E_INVALID_NAME);
using (SafeLocalAllocHandle pwszDecodeName = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(2 * cchDecoded))) {
if (CAPI.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
pNameBlob,
dwStrType,
pwszDecodeName,
cchDecoded) == 0)
throw new CryptographicException(CAPI.CERT_E_INVALID_NAME);
return Marshal.PtrToStringUni(pwszDecodeName.DangerousGetHandle());
}
}
}
}
public override string Format (bool multiLine) {
//
// We must override to use the "numeric" pointer version of
// CryptFormatObject, since X509 DN does not have an official OID.
//
// Return empty string if no data to format.
if (m_rawData == null || m_rawData.Length == 0)
return String.Empty;
return CAPI.CryptFormatObject(CAPI.X509_ASN_ENCODING,
multiLine ? CAPI.CRYPT_FORMAT_STR_MULTI_LINE : 0,
new IntPtr(CAPI.X509_NAME),
m_rawData);
}
//
// Private methods.
//
private unsafe static byte[] Encode (string distinguishedName, X500DistinguishedNameFlags flag) {
if (distinguishedName == null)
throw new ArgumentNullException("distinguishedName");
uint cbEncoded = 0;
uint dwStrType = CAPI.CERT_X500_NAME_STR | MapNameToStrFlag(flag);
if (!CAPI.CertStrToNameW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
distinguishedName,
dwStrType,
IntPtr.Zero,
IntPtr.Zero,
ref cbEncoded,
IntPtr.Zero))
throw new CryptographicException(Marshal.GetLastWin32Error());
byte[] encodedName = new byte[cbEncoded];
fixed (byte * pbEncoded = encodedName) {
if (!CAPI.CertStrToNameW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
distinguishedName,
dwStrType,
IntPtr.Zero,
new IntPtr(pbEncoded),
ref cbEncoded,
IntPtr.Zero))
throw new CryptographicException(Marshal.GetLastWin32Error());
}
return encodedName;
}
private static uint MapNameToStrFlag (X500DistinguishedNameFlags flag) {
// All values or'ed together. Change this if you add values to the enumeration.
uint allFlags = 0x71F1;
uint dwFlags = (uint) flag;
if ((dwFlags & ~allFlags) != 0)
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "flag"));
uint dwStrType = 0;
if (dwFlags != 0) {
if ((flag & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed)
dwStrType |= CAPI.CERT_NAME_STR_REVERSE_FLAG;
if ((flag & X500DistinguishedNameFlags.UseSemicolons) == X500DistinguishedNameFlags.UseSemicolons)
dwStrType |= CAPI.CERT_NAME_STR_SEMICOLON_FLAG;
else if ((flag & X500DistinguishedNameFlags.UseCommas) == X500DistinguishedNameFlags.UseCommas)
dwStrType |= CAPI.CERT_NAME_STR_COMMA_FLAG;
else if ((flag & X500DistinguishedNameFlags.UseNewLines) == X500DistinguishedNameFlags.UseNewLines)
dwStrType |= CAPI.CERT_NAME_STR_CRLF_FLAG;
if ((flag & X500DistinguishedNameFlags.DoNotUsePlusSign) == X500DistinguishedNameFlags.DoNotUsePlusSign)
dwStrType |= CAPI.CERT_NAME_STR_NO_PLUS_FLAG;
if ((flag & X500DistinguishedNameFlags.DoNotUseQuotes) == X500DistinguishedNameFlags.DoNotUseQuotes)
dwStrType |= CAPI.CERT_NAME_STR_NO_QUOTING_FLAG;
if ((flag & X500DistinguishedNameFlags.ForceUTF8Encoding) == X500DistinguishedNameFlags.ForceUTF8Encoding)
dwStrType |= CAPI.CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG;
if ((flag & X500DistinguishedNameFlags.UseUTF8Encoding) == X500DistinguishedNameFlags.UseUTF8Encoding)
dwStrType |= CAPI.CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG;
else if ((flag & X500DistinguishedNameFlags.UseT61Encoding) == X500DistinguishedNameFlags.UseT61Encoding)
dwStrType |= CAPI.CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
}
return dwStrType;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,477 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//
// X509Chain.cs
//
namespace System.Security.Cryptography.X509Certificates {
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using _FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
[Flags]
public enum X509ChainStatusFlags {
NoError = 0x00000000,
NotTimeValid = 0x00000001,
NotTimeNested = 0x00000002,
Revoked = 0x00000004,
NotSignatureValid = 0x00000008,
NotValidForUsage = 0x00000010,
UntrustedRoot = 0x00000020,
RevocationStatusUnknown = 0x00000040,
Cyclic = 0x00000080,
InvalidExtension = 0x00000100,
InvalidPolicyConstraints = 0x00000200,
InvalidBasicConstraints = 0x00000400,
InvalidNameConstraints = 0x00000800,
HasNotSupportedNameConstraint = 0x00001000,
HasNotDefinedNameConstraint = 0x00002000,
HasNotPermittedNameConstraint = 0x00004000,
HasExcludedNameConstraint = 0x00008000,
PartialChain = 0x00010000,
CtlNotTimeValid = 0x00020000,
CtlNotSignatureValid = 0x00040000,
CtlNotValidForUsage = 0x00080000,
OfflineRevocation = 0x01000000,
NoIssuanceChainPolicy = 0x02000000
}
public struct X509ChainStatus {
private X509ChainStatusFlags m_status;
private string m_statusInformation;
public X509ChainStatusFlags Status {
get {
return m_status;
}
set {
m_status = value;
}
}
public string StatusInformation {
get {
if (m_statusInformation == null)
return String.Empty;
return m_statusInformation;
}
set {
m_statusInformation = value;
}
}
}
public class X509Chain {
private uint m_status;
private X509ChainPolicy m_chainPolicy;
private X509ChainStatus[] m_chainStatus;
private X509ChainElementCollection m_chainElementCollection;
private SafeCertChainHandle m_safeCertChainHandle;
private bool m_useMachineContext;
private readonly object m_syncRoot = new object();
public static X509Chain Create() {
return (X509Chain) CryptoConfig.CreateFromName("X509Chain");
}
public X509Chain () : this (false) {}
public X509Chain (bool useMachineContext) {
m_status = 0;
m_chainPolicy = null;
m_chainStatus = null;
m_chainElementCollection = new X509ChainElementCollection();
m_safeCertChainHandle = SafeCertChainHandle.InvalidHandle;
m_useMachineContext = useMachineContext;
}
// Package protected constructor for creating a chain from a PCCERT_CHAIN_CONTEXT
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
[SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public X509Chain (IntPtr chainContext) {
if (chainContext == IntPtr.Zero)
throw new ArgumentNullException("chainContext");
m_safeCertChainHandle = CAPI.CertDuplicateCertificateChain(chainContext);
if (m_safeCertChainHandle == null || m_safeCertChainHandle == SafeCertChainHandle.InvalidHandle)
throw new CryptographicException(SR.GetString(SR.Cryptography_InvalidContextHandle), "chainContext");
Init();
}
public IntPtr ChainContext {
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
[SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
get {
return m_safeCertChainHandle.DangerousGetHandle();
}
}
public X509ChainPolicy ChainPolicy {
get {
if (m_chainPolicy == null)
m_chainPolicy = new X509ChainPolicy();
return m_chainPolicy;
}
set {
if (value == null)
throw new ArgumentNullException("value");
m_chainPolicy = value;
}
}
public X509ChainStatus[] ChainStatus {
get {
// We give the user a reference to the array since we'll never access it.
if (m_chainStatus == null) {
if (m_status == 0) {
m_chainStatus = new X509ChainStatus[0]; // empty array
} else {
m_chainStatus = GetChainStatusInformation(m_status);
}
}
return m_chainStatus;
}
}
public X509ChainElementCollection ChainElements {
get {
return m_chainElementCollection;
}
}
[PermissionSetAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted=true)]
public bool Build (X509Certificate2 certificate) {
lock (m_syncRoot) {
if (certificate == null || certificate.CertContext.IsInvalid)
throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidContextHandle), "certificate");
// Chain building opens and enumerates the root store to see if the root of the chain is trusted.
StorePermission sp = new StorePermission(StorePermissionFlags.OpenStore | StorePermissionFlags.EnumerateCertificates);
sp.Demand();
X509ChainPolicy chainPolicy = this.ChainPolicy;
if (chainPolicy.RevocationMode == X509RevocationMode.Online) {
if (certificate.Extensions[CAPI.szOID_CRL_DIST_POINTS] != null ||
certificate.Extensions[CAPI.szOID_AUTHORITY_INFO_ACCESS] != null) {
// If there is a CDP or AIA extension, we demand unrestricted network access and store add permission
// since CAPI can download certificates into the CA store from the network.
PermissionSet ps = new PermissionSet(PermissionState.None);
ps.AddPermission(new WebPermission(PermissionState.Unrestricted));
ps.AddPermission(new StorePermission(StorePermissionFlags.AddToStore));
ps.Demand();
}
}
Reset();
int hr = BuildChain(m_useMachineContext ? new IntPtr(CAPI.HCCE_LOCAL_MACHINE) : new IntPtr(CAPI.HCCE_CURRENT_USER),
certificate.CertContext,
chainPolicy.ExtraStore,
chainPolicy.ApplicationPolicy,
chainPolicy.CertificatePolicy,
chainPolicy.RevocationMode,
chainPolicy.RevocationFlag,
chainPolicy.VerificationTime,
chainPolicy.UrlRetrievalTimeout,
ref m_safeCertChainHandle);
if (hr != CAPI.S_OK)
return false;
// Init.
Init();
// Verify the chain using the specified policy.
CAPI.CERT_CHAIN_POLICY_PARA PolicyPara = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA)));
CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS)));
PolicyPara.dwFlags = (uint) chainPolicy.VerificationFlags;
if (!CAPI.CertVerifyCertificateChainPolicy(new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE),
m_safeCertChainHandle,
ref PolicyPara,
ref PolicyStatus))
// The API failed.
throw new CryptographicException(Marshal.GetLastWin32Error());
CAPI.SetLastError(PolicyStatus.dwError);
return (PolicyStatus.dwError == 0);
}
}
[PermissionSetAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted=true)]
public void Reset () {
m_status = 0;
m_chainStatus = null;
m_chainElementCollection = new X509ChainElementCollection();
if (!m_safeCertChainHandle.IsInvalid) {
m_safeCertChainHandle.Dispose();
m_safeCertChainHandle = SafeCertChainHandle.InvalidHandle;
}
}
private unsafe void Init () {
using (SafeCertChainHandle safeCertChainHandle = CAPI.CertDuplicateCertificateChain(m_safeCertChainHandle)) {
CAPI.CERT_CHAIN_CONTEXT pChain = new CAPI.CERT_CHAIN_CONTEXT(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_CONTEXT)));
uint cbSize = (uint) Marshal.ReadInt32(safeCertChainHandle.DangerousGetHandle());
if (cbSize > Marshal.SizeOf(pChain))
cbSize = (uint) Marshal.SizeOf(pChain);
X509Utils.memcpy(m_safeCertChainHandle.DangerousGetHandle(), new IntPtr(&pChain), cbSize);
m_status = pChain.dwErrorStatus;
Debug.Assert(pChain.cChain > 0);
m_chainElementCollection = new X509ChainElementCollection(Marshal.ReadIntPtr(pChain.rgpChain));
}
}
internal static X509ChainStatus[] GetChainStatusInformation (uint dwStatus) {
if (dwStatus == 0)
return new X509ChainStatus[0];
int count = 0;
for (uint bits = dwStatus; bits != 0; bits = bits >> 1) {
if ((bits & 0x1) != 0)
count++;
}
X509ChainStatus[] chainStatus = new X509ChainStatus[count];
int index = 0;
if ((dwStatus & CAPI.CERT_TRUST_IS_NOT_SIGNATURE_VALID) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.TRUST_E_CERT_SIGNATURE);
chainStatus[index].Status = X509ChainStatusFlags.NotSignatureValid;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_NOT_SIGNATURE_VALID;
}
if ((dwStatus & CAPI.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.TRUST_E_CERT_SIGNATURE);
chainStatus[index].Status = X509ChainStatusFlags.CtlNotSignatureValid;
index++;
dwStatus &= ~CAPI.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_UNTRUSTED_ROOT) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_UNTRUSTEDROOT);
chainStatus[index].Status = X509ChainStatusFlags.UntrustedRoot;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_UNTRUSTED_ROOT;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_PARTIAL_CHAIN) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_CHAINING);
chainStatus[index].Status = X509ChainStatusFlags.PartialChain;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_PARTIAL_CHAIN;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_REVOKED) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CRYPT_E_REVOKED);
chainStatus[index].Status = X509ChainStatusFlags.Revoked;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_REVOKED;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_NOT_VALID_FOR_USAGE) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_WRONG_USAGE);
chainStatus[index].Status = X509ChainStatusFlags.NotValidForUsage;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
}
if ((dwStatus & CAPI.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_WRONG_USAGE);
chainStatus[index].Status = X509ChainStatusFlags.CtlNotValidForUsage;
index++;
dwStatus &= ~CAPI.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_NOT_TIME_VALID) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_EXPIRED);
chainStatus[index].Status = X509ChainStatusFlags.NotTimeValid;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_NOT_TIME_VALID;
}
if ((dwStatus & CAPI.CERT_TRUST_CTL_IS_NOT_TIME_VALID) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_EXPIRED);
chainStatus[index].Status = X509ChainStatusFlags.CtlNotTimeValid;
index++;
dwStatus &= ~CAPI.CERT_TRUST_CTL_IS_NOT_TIME_VALID;
}
if ((dwStatus & CAPI.CERT_TRUST_INVALID_NAME_CONSTRAINTS) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_NAME);
chainStatus[index].Status = X509ChainStatusFlags.InvalidNameConstraints;
index++;
dwStatus &= ~CAPI.CERT_TRUST_INVALID_NAME_CONSTRAINTS;
}
if ((dwStatus & CAPI.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_NAME);
chainStatus[index].Status = X509ChainStatusFlags.HasNotSupportedNameConstraint;
index++;
dwStatus &= ~CAPI.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT;
}
if ((dwStatus & CAPI.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_NAME);
chainStatus[index].Status = X509ChainStatusFlags.HasNotDefinedNameConstraint;
index++;
dwStatus &= ~CAPI.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT;
}
if ((dwStatus & CAPI.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_NAME);
chainStatus[index].Status = X509ChainStatusFlags.HasNotPermittedNameConstraint;
index++;
dwStatus &= ~CAPI.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT;
}
if ((dwStatus & CAPI.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_NAME);
chainStatus[index].Status = X509ChainStatusFlags.HasExcludedNameConstraint;
index++;
dwStatus &= ~CAPI.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT;
}
if ((dwStatus & CAPI.CERT_TRUST_INVALID_POLICY_CONSTRAINTS) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_POLICY);
chainStatus[index].Status = X509ChainStatusFlags.InvalidPolicyConstraints;
index++;
dwStatus &= ~CAPI.CERT_TRUST_INVALID_POLICY_CONSTRAINTS;
}
if ((dwStatus & CAPI.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_INVALID_POLICY);
chainStatus[index].Status = X509ChainStatusFlags.NoIssuanceChainPolicy;
index++;
dwStatus &= ~CAPI.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY;
}
if ((dwStatus & CAPI.CERT_TRUST_INVALID_BASIC_CONSTRAINTS) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.TRUST_E_BASIC_CONSTRAINTS);
chainStatus[index].Status = X509ChainStatusFlags.InvalidBasicConstraints;
index++;
dwStatus &= ~CAPI.CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_NOT_TIME_NESTED) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CERT_E_VALIDITYPERIODNESTING);
chainStatus[index].Status = X509ChainStatusFlags.NotTimeNested;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_NOT_TIME_NESTED;
}
if ((dwStatus & CAPI.CERT_TRUST_REVOCATION_STATUS_UNKNOWN) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CRYPT_E_NO_REVOCATION_CHECK);
chainStatus[index].Status = X509ChainStatusFlags.RevocationStatusUnknown;
index++;
dwStatus &= ~CAPI.CERT_TRUST_REVOCATION_STATUS_UNKNOWN;
}
if ((dwStatus & CAPI.CERT_TRUST_IS_OFFLINE_REVOCATION) != 0) {
chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(CAPI.CRYPT_E_REVOCATION_OFFLINE);
chainStatus[index].Status = X509ChainStatusFlags.OfflineRevocation;
index++;
dwStatus &= ~CAPI.CERT_TRUST_IS_OFFLINE_REVOCATION;
}
int shiftCount = 0;
for (uint bits = dwStatus; bits != 0; bits = bits >> 1) {
if ((bits & 0x1) != 0) {
chainStatus[index].Status = (X509ChainStatusFlags) (1 << shiftCount);
chainStatus[index].StatusInformation = SR.GetString(SR.Unknown_Error);
index++;
}
shiftCount++;
}
return chainStatus;
}
//
// Builds a certificate chain.
//
internal static unsafe int BuildChain (IntPtr hChainEngine,
SafeCertContextHandle pCertContext,
X509Certificate2Collection extraStore,
OidCollection applicationPolicy,
OidCollection certificatePolicy,
X509RevocationMode revocationMode,
X509RevocationFlag revocationFlag,
DateTime verificationTime,
TimeSpan timeout,
ref SafeCertChainHandle ppChainContext) {
if (pCertContext == null || pCertContext.IsInvalid)
throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidContextHandle), "pCertContext");
SafeCertStoreHandle hCertStore = SafeCertStoreHandle.InvalidHandle;
if (extraStore != null && extraStore.Count > 0)
hCertStore = X509Utils.ExportToMemoryStore(extraStore);
CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.CERT_CHAIN_PARA();
// Initialize the structure size.
ChainPara.cbSize = (uint) Marshal.SizeOf(ChainPara);
SafeLocalAllocHandle applicationPolicyHandle = SafeLocalAllocHandle.InvalidHandle;
SafeLocalAllocHandle certificatePolicyHandle = SafeLocalAllocHandle.InvalidHandle;
try {
// Application policy
if (applicationPolicy != null && applicationPolicy.Count > 0) {
ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND;
ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint) applicationPolicy.Count;
applicationPolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(applicationPolicy);
ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle();
}
// Certificate policy
if (certificatePolicy != null && certificatePolicy.Count > 0) {
ChainPara.RequestedIssuancePolicy.dwType = CAPI.USAGE_MATCH_TYPE_AND;
ChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint) certificatePolicy.Count;
certificatePolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(certificatePolicy);
ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle();
}
ChainPara.dwUrlRetrievalTimeout = (uint) Math.Floor(timeout.TotalMilliseconds);
_FILETIME ft = new _FILETIME();
*((long*) &ft) = verificationTime.ToFileTime();
uint flags = X509Utils.MapRevocationFlags(revocationMode, revocationFlag);
// Build the chain.
if (!CAPI.CertGetCertificateChain(hChainEngine,
pCertContext,
ref ft,
hCertStore,
ref ChainPara,
flags,
IntPtr.Zero,
ref ppChainContext))
return Marshal.GetHRForLastWin32Error();
}
finally {
applicationPolicyHandle.Dispose();
certificatePolicyHandle.Dispose();
}
return CAPI.S_OK;
}
}
}

Some files were not shown because too many files have changed in this diff Show More