﻿// Decompiled with JetBrains decompiler
// Type: System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 5ABD58FD-DF31-44FD-A492-63F2B47CC9AF
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll

using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

namespace System.Security.Cryptography.X509Certificates
{
  /// <summary>
  /// Defines the collection of object identifiers (OIDs) that indicates the applications that use the key. This class cannot be inherited.
  /// </summary>
  public sealed class X509EnhancedKeyUsageExtension : X509Extension
  {
    private OidCollection m_enhancedKeyUsages;
    private bool m_decoded;

    /// <summary>
    /// Gets the collection of object identifiers (OIDs) that indicate the applications that use the key.
    /// </summary>
    /// 
    /// <returns>
    /// An <see cref="T:System.Security.Cryptography.OidCollection"/> object indicating the applications that use the key.
    /// </returns>
    /// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/></PermissionSet>
    public OidCollection EnhancedKeyUsages
    {
      get
      {
        if (!this.m_decoded)
          this.DecodeExtension();
        OidCollection oidCollection = new OidCollection();
        foreach (Oid oid in this.m_enhancedKeyUsages)
          oidCollection.Add(oid);
        return oidCollection;
      }
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension"/> class.
    /// </summary>
    public X509EnhancedKeyUsageExtension()
      : base("2.5.29.37")
    {
      this.m_enhancedKeyUsages = new OidCollection();
      this.m_decoded = true;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension"/> class using an <see cref="T:System.Security.Cryptography.OidCollection"/> and a value that identifies whether the extension is critical.
    /// </summary>
    /// <param name="enhancedKeyUsages">An <see cref="T:System.Security.Cryptography.OidCollection"/> collection. </param><param name="critical">true if the extension is critical; otherwise, false.</param><exception cref="T:System.Security.Cryptography.CryptographicException">The specified <see cref="T:System.Security.Cryptography.OidCollection"/>  contains one or more corrupt values.</exception>
    public X509EnhancedKeyUsageExtension(OidCollection enhancedKeyUsages, bool critical)
      : base("2.5.29.37", X509EnhancedKeyUsageExtension.EncodeExtension(enhancedKeyUsages), critical)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension"/> class using an <see cref="T:System.Security.Cryptography.AsnEncodedData"/> object and a value that identifies whether the extension is critical.
    /// </summary>
    /// <param name="encodedEnhancedKeyUsages">The encoded data to use to create the extension.</param><param name="critical">true if the extension is critical; otherwise, false.</param>
    public X509EnhancedKeyUsageExtension(AsnEncodedData encodedEnhancedKeyUsages, bool critical)
      : base("2.5.29.37", encodedEnhancedKeyUsages.RawData, critical)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension"/> class using an <see cref="T:System.Security.Cryptography.AsnEncodedData"/> object.
    /// </summary>
    /// <param name="asnEncodedData">The encoded data to use to create the extension.</param>
    public override void CopyFrom(AsnEncodedData asnEncodedData)
    {
      base.CopyFrom(asnEncodedData);
      this.m_decoded = false;
    }

    private void DecodeExtension()
    {
      uint cbDecodedValue = 0U;
      SafeLocalAllocHandle decodedValue = (SafeLocalAllocHandle) null;
      if (!CAPI.DecodeObject(new IntPtr(36L), this.m_rawData, out decodedValue, out cbDecodedValue))
        throw new CryptographicException(Marshal.GetLastWin32Error());
      CAPIBase.CERT_ENHKEY_USAGE certEnhkeyUsage = (CAPIBase.CERT_ENHKEY_USAGE) Marshal.PtrToStructure(decodedValue.DangerousGetHandle(), typeof (CAPIBase.CERT_ENHKEY_USAGE));
      this.m_enhancedKeyUsages = new OidCollection();
      for (int index = 0; (long) index < (long) certEnhkeyUsage.cUsageIdentifier; ++index)
        this.m_enhancedKeyUsages.Add(new Oid(Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(new IntPtr((long) certEnhkeyUsage.rgpszUsageIdentifier + (long) (index * Marshal.SizeOf(typeof (IntPtr)))))), System.Security.Cryptography.OidGroup.ExtensionOrAttribute, false));
      this.m_decoded = true;
      decodedValue.Dispose();
    }

    private static unsafe byte[] EncodeExtension(OidCollection enhancedKeyUsages)
    {
      if (enhancedKeyUsages == null)
        throw new ArgumentNullException("enhancedKeyUsages");
      SafeLocalAllocHandle localAllocHandle = X509Utils.CopyOidsToUnmanagedMemory(enhancedKeyUsages);
      byte[] encodedData = (byte[]) null;
      using (localAllocHandle)
      {
        if (!CAPI.EncodeObject("2.5.29.37", new IntPtr((void*) &new CAPIBase.CERT_ENHKEY_USAGE()
        {
          cUsageIdentifier = (uint) enhancedKeyUsages.Count,
          rgpszUsageIdentifier = localAllocHandle.DangerousGetHandle()
        }), out encodedData))
          throw new CryptographicException(Marshal.GetLastWin32Error());
      }
      return encodedData;
    }
  }
}
