File: System\Security\Cryptography\X509Certificates\X509EnhancedKeyUsageExtension.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Formats.Asn1;
 
namespace System.Security.Cryptography.X509Certificates
{
    public sealed class X509EnhancedKeyUsageExtension : X509Extension
    {
        public X509EnhancedKeyUsageExtension()
            : base(Oids.EnhancedKeyUsageOid)
        {
            _enhancedKeyUsages = new OidCollection();
            _decoded = true;
        }
 
        public X509EnhancedKeyUsageExtension(AsnEncodedData encodedEnhancedKeyUsages, bool critical)
            : base(Oids.EnhancedKeyUsageOid, encodedEnhancedKeyUsages.RawData, critical)
        {
        }
 
        public X509EnhancedKeyUsageExtension(OidCollection enhancedKeyUsages, bool critical)
            : base(Oids.EnhancedKeyUsageOid, EncodeExtension(enhancedKeyUsages), critical, skipCopy: true)
        {
        }
 
        public OidCollection EnhancedKeyUsages
        {
            get
            {
                if (!_decoded)
                {
                    DecodeX509EnhancedKeyUsageExtension(RawData, out _enhancedKeyUsages);
                    _decoded = true;
                }
 
                OidCollection oids = new OidCollection(_enhancedKeyUsages!.Count);
 
                foreach (Oid oid in _enhancedKeyUsages)
                {
                    oids.Add(oid);
                }
 
                return oids;
            }
        }
 
        public override void CopyFrom(AsnEncodedData asnEncodedData)
        {
            base.CopyFrom(asnEncodedData);
            _decoded = false;
        }
 
        private static byte[] EncodeExtension(OidCollection enhancedKeyUsages)
        {
            ArgumentNullException.ThrowIfNull(enhancedKeyUsages);
 
            // https://tools.ietf.org/html/rfc5280#section-4.2.1.12
            //
            // extKeyUsage EXTENSION ::= {
            //     SYNTAX SEQUENCE SIZE(1..MAX) OF KeyPurposeId
            //     IDENTIFIED BY id-ce-extKeyUsage
            // }
            //
            // KeyPurposeId ::= OBJECT IDENTIFIER
 
            AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
 
            using (writer.PushSequence())
            {
                foreach (Oid usage in enhancedKeyUsages)
                {
                    writer.WriteObjectIdentifierForCrypto(usage.Value!);
                }
            }
 
            return writer.Encode();
        }
 
        private static void DecodeX509EnhancedKeyUsageExtension(byte[] encoded, out OidCollection usages)
        {
            // https://tools.ietf.org/html/rfc5924#section-4.1
            //
            // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
            //
            // KeyPurposeId ::= OBJECT IDENTIFIER
 
            try
            {
                AsnReader reader = new AsnReader(encoded, AsnEncodingRules.BER);
                AsnReader sequenceReader = reader.ReadSequence();
                reader.ThrowIfNotEmpty();
                usages = new OidCollection();
 
                while (sequenceReader.HasData)
                {
                    usages.Add(new Oid(sequenceReader.ReadObjectIdentifier(), null));
                }
            }
            catch (AsnContentException e)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
            }
        }
 
        private OidCollection? _enhancedKeyUsages;
        private bool _decoded;
    }
}