private static string ReadString(DerSequenceReader tavReader)
        {
            var tag = (DerSequenceReader.DerTag)tavReader.PeekTag();

            switch (tag)
            {
            case DerSequenceReader.DerTag.BMPString:
                return(tavReader.ReadBMPString());

            case DerSequenceReader.DerTag.IA5String:
                return(tavReader.ReadIA5String());

            case DerSequenceReader.DerTag.PrintableString:
                return(tavReader.ReadPrintableString());

            case DerSequenceReader.DerTag.UTF8String:
                return(tavReader.ReadUtf8String());

            case DerSequenceReader.DerTag.T61String:
                return(tavReader.ReadT61String());

            default:
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }
        }
示例#2
0
        private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy)
        {
            DerSequenceReader reader = new DerSequenceReader(extension.RawData);

            while (reader.HasData)
            {
                // Policy Constraints context specific tag values are defined in RFC 3280 4.2.1.12,
                // and restated (unchanged) in RFC 5280 4.2.1.11.
                switch (reader.PeekTag())
                {
                case DerSequenceReader.ContextSpecificTagFlag | 0:
                    policy.RequireExplicitPolicyDepth = reader.ReadInteger();
                    break;

                case DerSequenceReader.ContextSpecificTagFlag | 1:
                    policy.InhibitMappingDepth = reader.ReadInteger();
                    break;

                default:
                    if (extension.Critical)
                    {
                        // If an unknown value is read, but we're marked as critical,
                        // then we don't know what we're doing and MUST fail validation
                        // (RFC 3280).
                        // If it isn't critical then it means we're allowed to be ignorant
                        // of data defined more recently than we understand.
                        throw new CryptographicException();
                    }

                    break;
                }
            }
        }
示例#3
0
            protected override string DerStringToManagedString(byte[] anyString)
            {
                DerSequenceReader reader = DerSequenceReader.CreateForPayload(anyString);

                var    tag   = (DerSequenceReader.DerTag)reader.PeekTag();
                string value = null;

                switch (tag)
                {
                case DerSequenceReader.DerTag.BMPString:
                    value = reader.ReadBMPString();
                    break;

                case DerSequenceReader.DerTag.IA5String:
                    value = reader.ReadIA5String();
                    break;

                case DerSequenceReader.DerTag.PrintableString:
                    value = reader.ReadPrintableString();
                    break;

                case DerSequenceReader.DerTag.UTF8String:
                    value = reader.ReadUtf8String();
                    break;

                    // Ignore anything we don't know how to read.
                }

                return(value);
            }
示例#4
0
        private static IEnumerable <KeyValuePair <string, string> > ReadReverseRdns(X500DistinguishedName name)
        {
            DerSequenceReader x500NameReader = new DerSequenceReader(name.RawData);
            var rdnReaders = new Stack <DerSequenceReader>();

            while (x500NameReader.HasData)
            {
                rdnReaders.Push(x500NameReader.ReadSet());
            }


            while (rdnReaders.Count > 0)
            {
                DerSequenceReader rdnReader = rdnReaders.Pop();

                while (rdnReader.HasData)
                {
                    DerSequenceReader tavReader = rdnReader.ReadSequence();
                    string            oid       = tavReader.ReadOidAsString();

                    var    tag   = (DerSequenceReader.DerTag)tavReader.PeekTag();
                    string value = null;

                    switch (tag)
                    {
                    case DerSequenceReader.DerTag.BMPString:
                        value = tavReader.ReadBMPString();
                        break;

                    case DerSequenceReader.DerTag.IA5String:
                        value = tavReader.ReadIA5String();
                        break;

                    case DerSequenceReader.DerTag.PrintableString:
                        value = tavReader.ReadPrintableString();
                        break;

                    case DerSequenceReader.DerTag.UTF8String:
                        value = tavReader.ReadUtf8String();
                        break;

                    case DerSequenceReader.DerTag.T61String:
                        value = tavReader.ReadT61String();
                        break;

                        // Ignore anything we don't know how to read.
                    }

                    if (value != null)
                    {
                        yield return(new KeyValuePair <string, string>(oid, value));
                    }
                }
            }
        }
        private static X509Certificate2 DownloadCertificate(
            byte[] authorityInformationAccess,
            ref TimeSpan remainingDownloadTime)
        {
            // Don't do any work if we're over limit.
            if (remainingDownloadTime <= TimeSpan.Zero)
            {
                return(null);
            }

            DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess);

            while (reader.HasData)
            {
                DerSequenceReader innerReader = reader.ReadSequence();

                // If the sequence's first element is a sequence, unwrap it.
                if (innerReader.PeekTag() == ConstructedSequenceTagId)
                {
                    innerReader = innerReader.ReadSequence();
                }

                Oid oid = innerReader.ReadOid();

                if (StringComparer.Ordinal.Equals(oid.Value, Oids.CertificateAuthorityIssuers))
                {
                    string uri = innerReader.ReadIA5String();

                    Uri parsedUri;
                    if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri))
                    {
                        continue;
                    }

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return(CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime));
                }
            }

            return(null);
        }
        public void FindByTemplateName(string templateName)
        {
            FindCore(
                cert =>
            {
                X509Extension ext = FindExtension(cert, Oids.EnrollCertTypeExtension);

                if (ext != null)
                {
                    // Try a V1 template structure, just a string:
                    string decodedName = Interop.Crypto.DerStringToManagedString(ext.RawData);

                    // If this doesn't match, maybe a V2 template will
                    if (StringComparer.OrdinalIgnoreCase.Equals(templateName, decodedName))
                    {
                        return(true);
                    }
                }

                ext = FindExtension(cert, Oids.CertificateTemplate);

                if (ext != null)
                {
                    DerSequenceReader reader = new DerSequenceReader(ext.RawData);
                    // SEQUENCE (
                    //     OID oid,
                    //     INTEGER major,
                    //     INTEGER minor OPTIONAL
                    //  )

                    if (reader.PeekTag() == (byte)DerSequenceReader.DerTag.ObjectIdentifier)
                    {
                        Oid oid = reader.ReadOid();

                        if (StringComparer.Ordinal.Equals(templateName, oid.Value))
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            });
        }
示例#7
0
        public virtual void DecodeX509BasicConstraints2Extension(
            byte[] encoded,
            out bool certificateAuthority,
            out bool hasPathLengthConstraint,
            out int pathLengthConstraint)
        {
            // BasicConstraints ::= SEQUENCE {
            //   cA BOOLEAN DEFAULT FALSE,
            //   pathLenConstraint INTEGER(0..MAX) OPTIONAL }

            DerSequenceReader constraints = new DerSequenceReader(encoded);

            if (!constraints.HasData)
            {
                certificateAuthority    = false;
                hasPathLengthConstraint = false;
                pathLengthConstraint    = 0;
                return;
            }

            if (constraints.PeekTag() == (byte)DerSequenceReader.DerTag.Boolean)
            {
                certificateAuthority = constraints.ReadBoolean();
            }
            else
            {
                certificateAuthority = false;
            }

            if (constraints.HasData)
            {
                pathLengthConstraint    = constraints.ReadInteger();
                hasPathLengthConstraint = true;
            }
            else
            {
                pathLengthConstraint    = 0;
                hasPathLengthConstraint = false;
            }
        }
示例#8
0
        internal static string FindHttpAiaRecord(byte[] authorityInformationAccess, string recordTypeOid)
        {
            DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess);

            while (reader.HasData)
            {
                DerSequenceReader innerReader = reader.ReadSequence();

                // If the sequence's first element is a sequence, unwrap it.
                if (innerReader.PeekTag() == ConstructedSequenceTagId)
                {
                    innerReader = innerReader.ReadSequence();
                }

                Oid oid = innerReader.ReadOid();

                if (StringComparer.Ordinal.Equals(oid.Value, recordTypeOid))
                {
                    string uri = innerReader.ReadIA5String();

                    Uri parsedUri;
                    if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri))
                    {
                        continue;
                    }

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return(uri);
                }
            }

            return(null);
        }
示例#9
0
        internal CertificateData(byte[] rawData)
        {
#if DEBUG
            try
            {
#endif
            DerSequenceReader reader = new DerSequenceReader(rawData);

            DerSequenceReader tbsCertificate = reader.ReadSequence();

            if (tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag0)
            {
                DerSequenceReader version = tbsCertificate.ReadSequence();
                Version = version.ReadInteger();
            }
            else if (tbsCertificate.PeekTag() != (byte)DerSequenceReader.DerTag.Integer)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }
            else
            {
                Version = 0;
            }

            if (Version < 0 || Version > 2)
            {
                throw new CryptographicException();
            }

            SerialNumber = tbsCertificate.ReadIntegerBytes();

            DerSequenceReader tbsSignature = tbsCertificate.ReadSequence();
            TbsSignature.AlgorithmId = tbsSignature.ReadOidAsString();
            TbsSignature.Parameters  = tbsSignature.HasData ? tbsSignature.ReadNextEncodedValue() : Array.Empty <byte>();

            if (tbsSignature.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            Issuer = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue());

            DerSequenceReader validity = tbsCertificate.ReadSequence();
            NotBefore = validity.ReadX509Date();
            NotAfter  = validity.ReadX509Date();

            if (validity.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            Subject = new X500DistinguishedName(tbsCertificate.ReadNextEncodedValue());

            SubjectPublicKeyInfo = tbsCertificate.ReadNextEncodedValue();
            DerSequenceReader subjectPublicKeyInfo = new DerSequenceReader(SubjectPublicKeyInfo);
            DerSequenceReader subjectKeyAlgorithm  = subjectPublicKeyInfo.ReadSequence();
            PublicKeyAlgorithm.AlgorithmId = subjectKeyAlgorithm.ReadOidAsString();
            PublicKeyAlgorithm.Parameters  = subjectKeyAlgorithm.HasData ? subjectKeyAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>();

            if (subjectKeyAlgorithm.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            PublicKey = subjectPublicKeyInfo.ReadBitString();

            if (subjectPublicKeyInfo.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            if (Version > 0 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag1)
            {
                IssuerUniqueId = tbsCertificate.ReadBitString();
            }
            else
            {
                IssuerUniqueId = null;
            }

            if (Version > 0 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag2)
            {
                SubjectUniqueId = tbsCertificate.ReadBitString();
            }
            else
            {
                SubjectUniqueId = null;
            }

            Extensions = new List <X509Extension>();

            if (Version > 1 &&
                tbsCertificate.HasData &&
                tbsCertificate.PeekTag() == DerSequenceReader.ContextSpecificConstructedTag3)
            {
                DerSequenceReader extensions = tbsCertificate.ReadSequence();
                extensions = extensions.ReadSequence();

                while (extensions.HasData)
                {
                    DerSequenceReader extensionReader = extensions.ReadSequence();
                    string            oid             = extensionReader.ReadOidAsString();
                    bool critical = false;

                    if (extensionReader.PeekTag() == (byte)DerSequenceReader.DerTag.Boolean)
                    {
                        critical = extensionReader.ReadBoolean();
                    }

                    byte[] extensionData = extensionReader.ReadOctetString();

                    Extensions.Add(new X509Extension(oid, extensionData, critical));

                    if (extensionReader.HasData)
                    {
                        throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    }
                }
            }

            if (tbsCertificate.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            DerSequenceReader signatureAlgorithm = reader.ReadSequence();
            SignatureAlgorithm.AlgorithmId = signatureAlgorithm.ReadOidAsString();
            SignatureAlgorithm.Parameters  = signatureAlgorithm.HasData ? signatureAlgorithm.ReadNextEncodedValue() : Array.Empty <byte>();

            if (signatureAlgorithm.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            SignatureValue = reader.ReadBitString();

            if (reader.HasData)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            RawData = rawData;
#if DEBUG
        }

        catch (Exception e)
        {
            throw new CryptographicException(
                      $"Error in reading certificate:{Environment.NewLine}{PemPrintCert(rawData)}",
                      e);
        }
#endif
        }
示例#10
0
        private static string FindAltNameMatch(byte[] extensionBytes, GeneralNameType matchType, string otherOid)
        {
            // If Other, have OID, else, no OID.
            Debug.Assert(
                (otherOid == null) == (matchType != GeneralNameType.OtherName),
                $"otherOid has incorrect nullarity for matchType {matchType}");

            Debug.Assert(
                matchType == GeneralNameType.UniformResourceIdentifier ||
                matchType == GeneralNameType.DnsName ||
                matchType == GeneralNameType.Email ||
                matchType == GeneralNameType.OtherName,
                $"matchType ({matchType}) is not currently supported");

            Debug.Assert(
                otherOid == null || otherOid == Oids.UserPrincipalName,
                $"otherOid ({otherOid}) is not supported");

            // SubjectAltName ::= GeneralNames
            //
            // IssuerAltName ::= GeneralNames
            //
            // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
            //
            // GeneralName ::= CHOICE {
            //   otherName                       [0]     OtherName,
            //   rfc822Name                      [1]     IA5String,
            //   dNSName                         [2]     IA5String,
            //   x400Address                     [3]     ORAddress,
            //   directoryName                   [4]     Name,
            //   ediPartyName                    [5]     EDIPartyName,
            //   uniformResourceIdentifier       [6]     IA5String,
            //   iPAddress                       [7]     OCTET STRING,
            //   registeredID                    [8]     OBJECT IDENTIFIER }
            //
            // OtherName::= SEQUENCE {
            //   type - id    OBJECT IDENTIFIER,
            //   value[0] EXPLICIT ANY DEFINED BY type - id }

            byte expectedTag = (byte)(DerSequenceReader.ContextSpecificTagFlag | (byte)matchType);

            if (matchType == GeneralNameType.OtherName)
            {
                expectedTag |= DerSequenceReader.ConstructedFlag;
            }

            DerSequenceReader altNameReader = new DerSequenceReader(extensionBytes);

            while (altNameReader.HasData)
            {
                if (altNameReader.PeekTag() != expectedTag)
                {
                    altNameReader.SkipValue();
                    continue;
                }

                switch (matchType)
                {
                case GeneralNameType.OtherName:
                {
                    DerSequenceReader otherNameReader = altNameReader.ReadSequence();
                    string            oid             = otherNameReader.ReadOidAsString();

                    if (oid == otherOid)
                    {
                        // Payload is value[0] EXPLICIT, meaning
                        // a) it'll be tagged as ContextSpecific0
                        // b) that's interpretable as a Sequence (EXPLICIT)
                        // c) the payload will then be retagged as the correct type (EXPLICIT)
                        if (otherNameReader.PeekTag() != DerSequenceReader.ContextSpecificConstructedTag0)
                        {
                            throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                        }

                        otherNameReader = otherNameReader.ReadSequence();

                        // Currently only UPN is supported, which is a UTF8 string per
                        // https://msdn.microsoft.com/en-us/library/ff842518.aspx
                        return(otherNameReader.ReadUtf8String());
                    }

                    // If the OtherName OID didn't match, move to the next entry.
                    continue;
                }

                case GeneralNameType.Rfc822Name:
                case GeneralNameType.DnsName:
                case GeneralNameType.UniformResourceIdentifier:
                    return(altNameReader.ReadIA5String());

                default:
                    altNameReader.SkipValue();
                    continue;
                }
            }

            return(null);
        }
示例#11
0
        private static string GetCdpUrl(X509Certificate2 cert)
        {
            byte[] crlDistributionPoints = null;

            foreach (X509Extension extension in cert.Extensions)
            {
                if (StringComparer.Ordinal.Equals(extension.Oid.Value, Oids.CrlDistributionPoints))
                {
                    // If there's an Authority Information Access extension, it might be used for
                    // looking up additional certificates for the chain.
                    crlDistributionPoints = extension.RawData;
                    break;
                }
            }

            if (crlDistributionPoints == null)
            {
                return(null);
            }

            // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
            //
            // DistributionPoint ::= SEQUENCE {
            //    distributionPoint       [0]     DistributionPointName OPTIONAL,
            //    reasons                 [1]     ReasonFlags OPTIONAL,
            //    cRLIssuer               [2]     GeneralNames OPTIONAL }
            //
            // DistributionPointName ::= CHOICE {
            //    fullName                [0]     GeneralNames,
            //    nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
            //
            // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
            //
            // GeneralName ::= CHOICE {
            //    otherName                       [0]     OtherName,
            //    rfc822Name                      [1]     IA5String,
            //    dNSName                         [2]     IA5String,
            //    x400Address                     [3]     ORAddress,
            //    directoryName                   [4]     Name,
            //    ediPartyName                    [5]     EDIPartyName,
            //    uniformResourceIdentifier       [6]     IA5String,
            //    iPAddress                       [7]     OCTET STRING,
            //    registeredID                    [8]     OBJECT IDENTIFIER }

            DerSequenceReader cdpSequence = new DerSequenceReader(crlDistributionPoints);

            while (cdpSequence.HasData)
            {
                const byte ContextSpecificFlag         = 0x80;
                const byte ContextSpecific0            = ContextSpecificFlag;
                const byte ConstructedFlag             = 0x20;
                const byte ContextSpecificConstructed0 = ContextSpecific0 | ConstructedFlag;
                const byte GeneralNameUri = ContextSpecificFlag | 0x06;

                DerSequenceReader distributionPointReader = cdpSequence.ReadSequence();
                byte tag = distributionPointReader.PeekTag();

                // Only distributionPoint is supported
                if (tag != ContextSpecificConstructed0)
                {
                    continue;
                }

                // The DistributionPointName is a CHOICE, not a SEQUENCE, but the reader is the same.
                DerSequenceReader dpNameReader = distributionPointReader.ReadSequence();
                tag = dpNameReader.PeekTag();

                // Only fullName is supported,
                // nameRelativeToCRLIssuer is for LDAP-based lookup.
                if (tag != ContextSpecificConstructed0)
                {
                    continue;
                }

                DerSequenceReader fullNameReader = dpNameReader.ReadSequence();

                while (fullNameReader.HasData)
                {
                    tag = fullNameReader.PeekTag();

                    if (tag != GeneralNameUri)
                    {
                        fullNameReader.SkipValue();
                        continue;
                    }

                    string uri = fullNameReader.ReadIA5String();

                    Uri parsedUri = new Uri(uri);

                    if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http"))
                    {
                        continue;
                    }

                    return(uri);
                }
            }

            return(null);
        }