Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private static int ReadInhibitAnyPolicyExtension(X509Extension extension)
        {
            DerSequenceReader reader = DerSequenceReader.CreateForPayload(extension.RawData);

            return(reader.ReadInteger());
        }
Ejemplo n.º 3
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
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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;
        }
Ejemplo n.º 6
0
        internal static byte[] DecodeX509SubjectKeyIdentifierExtension(byte[] encoded)
        {
            DerSequenceReader reader = DerSequenceReader.CreateForPayload(encoded);

            return(reader.ReadOctetString());
        }
        private static string X500DistinguishedNameDecode(
            byte[] encodedName,
            bool printOid,
            bool reverse,
            bool quoteIfNeeded,
            string dnSeparator,
            string multiValueSeparator,
            bool addTrailingDelimiter)
        {
            DerSequenceReader x500NameReader = new DerSequenceReader(encodedName);
            var rdnReaders = new List <DerSequenceReader>();

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

            // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual
            // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting
            // too much space in the average case.
            //
            // So, let's look at an example of what our output might be.
            //
            // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs):
            //   businessCategory=Private Organization
            //   1.3.6.1.4.1.311.60.2.1.3=US
            //   1.3.6.1.4.1.311.60.2.1.2=Delaware
            //   serialNumber=5157550
            //   street=548 4th Street
            //   postalCode=94107
            //   C=US
            //   ST=California
            //   L=San Francisco
            //   O=GitHub, Inc.
            //   CN=github.com
            //
            // Which comes out to 228 characters using OpenSSL's default pretty-print
            // (openssl x509 -in github.cer -text -noout)
            // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values
            // and round that up to the next programmer number, and you get that 512 should avoid reallocations
            // in all but the most dire of cases.
            StringBuilder decodedName  = new StringBuilder(512);
            int           entryCount   = rdnReaders.Count;
            bool          printSpacing = false;

            for (int i = 0; i < entryCount; i++)
            {
                int loc = reverse ? entryCount - i - 1 : i;

                // RelativeDistinguishedName ::=
                //   SET SIZE (1..MAX) OF AttributeTypeAndValue
                //
                // AttributeTypeAndValue::= SEQUENCE {
                //   type AttributeType,
                //   value    AttributeValue }
                //
                // AttributeType::= OBJECT IDENTIFIER
                //
                // AttributeValue ::= ANY-- DEFINED BY AttributeType

                if (printSpacing)
                {
                    decodedName.Append(dnSeparator);
                }
                else
                {
                    printSpacing = true;
                }

                DerSequenceReader rdnReader = rdnReaders[loc];
                bool hadValue = false;

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

                    if (hadValue)
                    {
                        decodedName.Append(multiValueSeparator);
                    }
                    else
                    {
                        hadValue = true;
                    }

                    if (printOid)
                    {
                        AppendOid(decodedName, tavReader.ReadOidAsString());
                    }
                    else
                    {
                        tavReader.SkipValue();
                    }

                    string attributeValue = ReadString(tavReader);

                    bool quote = quoteIfNeeded && NeedsQuoting(attributeValue);

                    if (quote)
                    {
                        decodedName.Append('"');

                        // If the RDN itself had a quote within it, that quote needs to be escaped
                        // with another quote.
                        attributeValue = attributeValue.Replace("\"", "\"\"");
                    }

                    decodedName.Append(attributeValue);

                    if (quote)
                    {
                        decodedName.Append('"');
                    }
                }
            }

            if (addTrailingDelimiter && decodedName.Length > 0)
            {
                decodedName.Append(dnSeparator);
            }

            return(decodedName.ToString());
        }
Ejemplo n.º 8
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);
        }