Example #1
0
        internal static GeneralName Read(DerSequenceReader reader)
        {
            var tag = reader.PeekTag();

            // Per RFC 2634 section 5.4.1 (https://tools.ietf.org/html/rfc2634#section-5.4.1)
            // only the directory name choice (#4) is allowed.
            if (tag == DerSequenceReader.ContextSpecificConstructedTag4)
            {
                var value = reader.ReadValue((DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificConstructedTag4);

                if (reader.HasData)
                {
                    throw new SignatureException(Strings.InvalidAsn1);
                }

                var directoryName = new X500DistinguishedName(value);

                return(new GeneralName(directoryName));
            }

            while (reader.HasData)
            {
                reader.ValidateAndSkipDerValue();
            }

            throw new SignatureException(Strings.UnsupportedAsn1);
        }
        /// <summary>
        /// Determines if a certificate is self-issued.
        /// </summary>
        /// <remarks>Warning:  this method does not evaluate certificate trust, revocation status, or validity!
        /// This method attempts to build a chain for the provided certificate, and although revocation status
        /// checking is explicitly skipped, the underlying chain building engine may go online to fetch
        /// additional information (e.g.:  the issuer's certificate).  This method is not a guaranteed offline
        /// check.</remarks>
        /// <param name="certificate">The certificate to check.</param>
        /// <returns><c>true</c> if the certificate is self-issued; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception>
        public static bool IsSelfIssued(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            using (var chainHolder = new X509ChainHolder())
            {
                var chain = chainHolder.Chain;

                chain.ChainPolicy.RevocationMode    = X509RevocationMode.NoCheck;
                chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority |
                                                      X509VerificationFlags.IgnoreRootRevocationUnknown |
                                                      X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown |
                                                      X509VerificationFlags.IgnoreEndRevocationUnknown;

                chain.Build(certificate);

                if (chain.ChainElements.Count != 1)
                {
                    return(false);
                }

                if (chain.ChainStatus.Any(
                        chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) ||
                        chainStatus.Status.HasFlag(X509ChainStatusFlags.PartialChain) ||
                        chainStatus.Status.HasFlag(X509ChainStatusFlags.NotSignatureValid)))
                {
                    return(false);
                }

                if (!certificate.IssuerName.RawData.SequenceEqual(certificate.SubjectName.RawData))
                {
                    return(false);
                }

                var akiExtension = certificate.Extensions[Oids.AuthorityKeyIdentifier];
                var skiExtension = certificate.Extensions[Oids.SubjectKeyIdentifier] as X509SubjectKeyIdentifierExtension;

                if (akiExtension != null && skiExtension != null)
                {
                    var reader           = new DerSequenceReader(akiExtension.RawData);
                    var keyIdentifierTag = (DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificTagFlag;

                    if (reader.HasTag(keyIdentifierTag))
                    {
                        var keyIdentifier    = reader.ReadValue(keyIdentifierTag);
                        var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", "");

                        return(string.Equals(skiExtension.SubjectKeyIdentifier, akiKeyIdentifier, StringComparison.OrdinalIgnoreCase));
                    }
                }

                return(true);
            }
        }