Copyright 2011 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package x509

import (
	
	
	
	
	
	
	
	
	
	
	
)
ignoreCN disables interpreting Common Name as a hostname. See issue 24151.
var ignoreCN = !strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=0")

type InvalidReason int

NotAuthorizedToSign results when a certificate is signed by another which isn't marked as a CA certificate.
Expired results when a certificate has expired, based on the time given in the VerifyOptions.
CANotAuthorizedForThisName results when an intermediate or root certificate has a name constraint which doesn't permit a DNS or other name (including IP address) in the leaf certificate.
TooManyIntermediates results when a path length constraint is violated.
IncompatibleUsage results when the certificate's key usage indicates that it may only be used for a different purpose.
NameMismatch results when the subject name of a parent certificate does not match the issuer name in the child.
NameConstraintsWithoutSANs results when a leaf certificate doesn't contain a Subject Alternative Name extension, but a CA certificate contains name constraints, and the Common Name can be interpreted as a hostname. This error is only returned when legacy Common Name matching is enabled by setting the GODEBUG environment variable to "x509ignoreCN=1". This setting might be removed in the future.
UnconstrainedName results when a CA certificate contains permitted name constraints, but leaf certificate contains a name of an unsupported or unconstrained type.
TooManyConstraints results when the number of comparison operations needed to check a certificate exceeds the limit set by VerifyOptions.MaxConstraintComparisions. This limit exists to prevent pathological certificates can consuming excessive amounts of CPU time to verify.
CANotAuthorizedForExtKeyUsage results when an intermediate or root certificate does not permit a requested extended key usage.
CertificateInvalidError results when an odd error occurs. Users of this library probably want to handle all these errors uniformly.
type CertificateInvalidError struct {
	Cert   *Certificate
	Reason InvalidReason
	Detail string
}

func ( CertificateInvalidError) () string {
	switch .Reason {
	case NotAuthorizedToSign:
		return "x509: certificate is not authorized to sign other certificates"
	case Expired:
		return "x509: certificate has expired or is not yet valid: " + .Detail
	case CANotAuthorizedForThisName:
		return "x509: a root or intermediate certificate is not authorized to sign for this name: " + .Detail
	case CANotAuthorizedForExtKeyUsage:
		return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + .Detail
	case TooManyIntermediates:
		return "x509: too many intermediates for path length constraint"
	case IncompatibleUsage:
		return "x509: certificate specifies an incompatible key usage"
	case NameMismatch:
		return "x509: issuer name does not match subject from issuing certificate"
	case NameConstraintsWithoutSANs:
		return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
	case UnconstrainedName:
		return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + .Detail
	}
	return "x509: unknown error"
}
HostnameError results when the set of authorized names doesn't match the requested name.
This would have validated, if it weren't for the validHostname check on Common Name.
			return "x509: Common Name is not a valid hostname: " + .Subject.CommonName
		}
This would have validated if x509ignoreCN=0 were set.
			return "x509: certificate relies on legacy Common Name field, " +
				"use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0"
		}
	}

	var  string
Trying to validate an IP
		if len(.IPAddresses) == 0 {
			return "x509: cannot validate certificate for " + .Host + " because it doesn't contain any IP SANs"
		}
		for ,  := range .IPAddresses {
			if len() > 0 {
				 += ", "
			}
			 += .String()
		}
	} else {
		if .commonNameAsHostname() {
			 = .Subject.CommonName
		} else {
			 = strings.Join(.DNSNames, ", ")
		}
	}

	if len() == 0 {
		return "x509: certificate is not valid for any names, but wanted to match " + .Host
	}
	return "x509: certificate is valid for " +  + ", not " + .Host
}
UnknownAuthorityError results when the certificate issuer is unknown
type UnknownAuthorityError struct {
hintErr contains an error that may be helpful in determining why an authority wasn't found.
hintCert contains a possible authority certificate that was rejected because of the error in hintErr.
	hintCert *Certificate
}

func ( UnknownAuthorityError) () string {
	 := "x509: certificate signed by unknown authority"
	if .hintErr != nil {
		 := .hintCert.Subject.CommonName
		if len() == 0 {
			if len(.hintCert.Subject.Organization) > 0 {
				 = .hintCert.Subject.Organization[0]
			} else {
				 = "serial:" + .hintCert.SerialNumber.String()
			}
		}
		 += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", .hintErr, )
	}
	return 
}
SystemRootsError results when we fail to load the system root certificates.
type SystemRootsError struct {
	Err error
}

func ( SystemRootsError) () string {
	 := "x509: failed to load system roots and no roots provided"
	if .Err != nil {
		return  + "; " + .Err.Error()
	}
	return 
}

func ( SystemRootsError) () error { return .Err }
errNotParsed is returned when a certificate without ASN.1 contents is verified. Platform-specific verification needs the ASN.1 contents.
var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
VerifyOptions contains parameters for Certificate.Verify.
DNSName, if set, is checked against the leaf certificate with Certificate.VerifyHostname or the platform verifier.
Intermediates is an optional pool of certificates that are not trust anchors, but can be used to form a chain from the leaf certificate to a root certificate.
Roots is the set of trusted root certificates the leaf certificate needs to chain up to. If nil, the system roots or the platform verifier are used.
CurrentTime is used to check the validity of all certificates in the chain. If zero, the current time is used.
KeyUsages specifies which Extended Key Usage values are acceptable. A chain is accepted if it allows any of the listed values. An empty list means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
MaxConstraintComparisions is the maximum number of comparisons to perform when checking a given certificate's name constraints. If zero, a sensible default is used. This limit prevents pathological certificates from consuming excessive amounts of CPU time when validating. It does not apply to the platform verifier.
rfc2821Mailbox represents a “mailbox” (which is an email address to most people) by breaking it into the “local” (i.e. before the '@') and “domain” parts.
type rfc2821Mailbox struct {
	local, domain string
}
parseRFC2821Mailbox parses an email address into local and domain parts, based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280, Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”.
func ( string) ( rfc2821Mailbox,  bool) {
	if len() == 0 {
		return , false
	}

	 := make([]byte, 0, len()/2)

Quoted-string = DQUOTE *qcontent DQUOTE non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127 qcontent = qtext / quoted-pair qtext = non-whitespace-control / %d33 / %d35-91 / %d93-126 quoted-pair = ("\" text) / obs-qp text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text (Names beginning with “obs-” are the obsolete syntax from RFC 2822, Section 4. Since it has been 16 years, we no longer accept that.)
		 = [1:]
	:
		for {
			if len() == 0 {
				return , false
			}
			 := [0]
			 = [1:]

			switch {
			case  == '"':
				break 

quoted-pair
				if len() == 0 {
					return , false
				}
				if [0] == 11 ||
					[0] == 12 ||
					(1 <= [0] && [0] <= 9) ||
					(14 <= [0] && [0] <= 127) {
					 = append(, [0])
					 = [1:]
				} else {
					return , false
				}

			case  == 11 ||
Space (char 32) is not allowed based on the BNF, but RFC 3696 gives an example that assumes that it is. Several “verified” errata continue to argue about this point. We choose to accept it.
				 == 32 ||
				 == 33 ||
				 == 127 ||
				(1 <=  &&  <= 8) ||
				(14 <=  &&  <= 31) ||
				(35 <=  &&  <= 91) ||
qtext
				 = append(, )

			default:
				return , false
			}
		}
Atom ("." Atom)*
	:
atext from RFC 2822, Section 3.2.4
			 := [0]

			switch {
Examples given in RFC 3696 suggest that escaped characters can appear outside of a quoted string. Several “verified” errata continue to argue the point. We choose to accept it.
				 = [1:]
				if len() == 0 {
					return , false
				}
				fallthrough

			case ('0' <=  &&  <= '9') ||
				('a' <=  &&  <= 'z') ||
				('A' <=  &&  <= 'Z') ||
				 == '!' ||  == '#' ||  == '$' ||  == '%' ||
				 == '&' ||  == '\'' ||  == '*' ||  == '+' ||
				 == '-' ||  == '/' ||  == '=' ||  == '?' ||
				 == '^' ||  == '_' ||  == '`' ||  == '{' ||
				 == '|' ||  == '}' ||  == '~' ||  == '.':
				 = append(, [0])
				 = [1:]

			default:
				break 
			}
		}

		if len() == 0 {
			return , false
		}
From RFC 3696, Section 3: “period (".") may also appear, but may not be used to start or end the local part, nor may two or more consecutive periods appear.”
		 := []byte{'.', '.'}
		if [0] == '.' ||
			[len()-1] == '.' ||
			bytes.Contains(, ) {
			return , false
		}
	}

	if len() == 0 || [0] != '@' {
		return , false
	}
	 = [1:]
The RFC species a format for domains, but that's known to be violated in practice so we accept that anything after an '@' is the domain part.
	if ,  := domainToReverseLabels(); ! {
		return , false
	}

	.local = string()
	.domain = 
	return , true
}
domainToReverseLabels converts a textual domain name like foo.example.com to the list of labels in reverse order, e.g. ["com", "example", "foo"].
func ( string) ( []string,  bool) {
	for len() > 0 {
		if  := strings.LastIndexByte(, '.');  == -1 {
			 = append(, )
			 = ""
		} else {
			 = append(, [+1:])
			 = [:]
		}
	}

An empty label at the end indicates an absolute value.
		return nil, false
	}

	for ,  := range  {
Empty labels are otherwise invalid.
			return nil, false
		}

		for ,  := range  {
Invalid character.
				return nil, false
			}
		}
	}

	return , true
}

If the constraint contains an @, then it specifies an exact mailbox name.
	if strings.Contains(, "@") {
		,  := parseRFC2821Mailbox()
		if ! {
			return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", )
		}
		return .local == .local && strings.EqualFold(.domain, .domain), nil
	}
Otherwise the constraint is like a DNS constraint of the domain part of the mailbox.
	return matchDomainConstraint(.domain, )
}

From RFC 5280, Section 4.2.1.10: “a uniformResourceIdentifier that does not include an authority component with a host name specified as a fully qualified domain name (e.g., if the URI either does not include an authority component or includes an authority component in which the host name is specified as an IP address), then the application MUST reject the certificate.”

	 := .Host
	if len() == 0 {
		return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", .String())
	}

	if strings.Contains(, ":") && !strings.HasSuffix(, "]") {
		var  error
		, _,  = net.SplitHostPort(.Host)
		if  != nil {
			return false, 
		}
	}

	if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") ||
		net.ParseIP() != nil {
		return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", .String())
	}

	return matchDomainConstraint(, )
}

func ( net.IP,  *net.IPNet) (bool, error) {
	if len() != len(.IP) {
		return false, nil
	}

	for  := range  {
		if  := .Mask[]; []& != .IP[]& {
			return false, nil
		}
	}

	return true, nil
}

The meaning of zero length constraints is not specified, but this code follows NSS and accepts them as matching everything.
	if len() == 0 {
		return true, nil
	}

	,  := domainToReverseLabels()
	if ! {
		return false, fmt.Errorf("x509: internal error: cannot parse domain %q", )
	}
RFC 5280 says that a leading period in a domain name means that at least one label must be prepended, but only for URI and email constraints, not DNS constraints. The code also supports that behaviour for DNS constraints.

	 := false
	if [0] == '.' {
		 = true
		 = [1:]
	}

	,  := domainToReverseLabels()
	if ! {
		return false, fmt.Errorf("x509: internal error: cannot parse domain %q", )
	}

	if len() < len() ||
		( && len() == len()) {
		return false, nil
	}

	for ,  := range  {
		if !strings.EqualFold(, []) {
			return false, nil
		}
	}

	return true, nil
}
checkNameConstraints checks that c permits a child certificate to claim the given name, of type nameType. The argument parsedName contains the parsed form of name, suitable for passing to the match function. The total number of comparisons is tracked in the given count and should not exceed the given limit.
func ( *Certificate) ( *int,
	 int,
	 string,
	 string,
	 interface{},
	 func(,  interface{}) ( bool,  error),
	,  interface{}) error {

	 := reflect.ValueOf()

	* += .Len()
	if * >  {
		return CertificateInvalidError{, TooManyConstraints, ""}
	}

	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()
		,  := (, )
		if  != nil {
			return CertificateInvalidError{, CANotAuthorizedForThisName, .Error()}
		}

		if  {
			return CertificateInvalidError{, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", , , )}
		}
	}

	 := reflect.ValueOf()

	* += .Len()
	if * >  {
		return CertificateInvalidError{, TooManyConstraints, ""}
	}

	 := true
	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()

		var  error
		if ,  = (, );  != nil {
			return CertificateInvalidError{, CANotAuthorizedForThisName, .Error()}
		}

		if  {
			break
		}
	}

	if ! {
		return CertificateInvalidError{, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", , )}
	}

	return nil
}
isValid performs validity checks on c given that it is a candidate to append to the chain in currentChain.
func ( *Certificate) ( int,  []*Certificate,  *VerifyOptions) error {
	if len(.UnhandledCriticalExtensions) > 0 {
		return UnhandledCriticalExtension{}
	}

	if len() > 0 {
		 := [len()-1]
		if !bytes.Equal(.RawIssuer, .RawSubject) {
			return CertificateInvalidError{, NameMismatch, ""}
		}
	}

	 := .CurrentTime
	if .IsZero() {
		 = time.Now()
	}
	if .Before(.NotBefore) {
		return CertificateInvalidError{
			Cert:   ,
			Reason: Expired,
			Detail: fmt.Sprintf("current time %s is before %s", .Format(time.RFC3339), .NotBefore.Format(time.RFC3339)),
		}
	} else if .After(.NotAfter) {
		return CertificateInvalidError{
			Cert:   ,
			Reason: Expired,
			Detail: fmt.Sprintf("current time %s is after %s", .Format(time.RFC3339), .NotAfter.Format(time.RFC3339)),
		}
	}

	 := .MaxConstraintComparisions
	if  == 0 {
		 = 250000
	}
	 := 0

	var  *Certificate
	if  == intermediateCertificate ||  == rootCertificate {
		if len() == 0 {
			return errors.New("x509: internal error: empty chain when appending CA cert")
		}
		 = [0]
	}

	 := ( == intermediateCertificate ||  == rootCertificate) && .hasNameConstraints()
This is the deprecated, legacy case of depending on the commonName as a hostname. We don't enforce name constraints against the CN, but VerifyHostname will look for hostnames in there if there are no SANs. In order to ensure VerifyHostname will not accept an unchecked name, return an error here.
		return CertificateInvalidError{, NameConstraintsWithoutSANs, ""}
	} else if  && .hasSANExtension() {
		 := forEachSAN(.getSANExtension(), func( int,  []byte) error {
			switch  {
			case nameTypeEmail:
				 := string()
				,  := parseRFC2821Mailbox()
				if ! {
					return fmt.Errorf("x509: cannot parse rfc822Name %q", )
				}

				if  := .checkNameConstraints(&, , "email address", , ,
					func(,  interface{}) (bool, error) {
						return matchEmailConstraint(.(rfc2821Mailbox), .(string))
					}, .PermittedEmailAddresses, .ExcludedEmailAddresses);  != nil {
					return 
				}

			case nameTypeDNS:
				 := string()
				if ,  := domainToReverseLabels(); ! {
					return fmt.Errorf("x509: cannot parse dnsName %q", )
				}

				if  := .checkNameConstraints(&, , "DNS name", , ,
					func(,  interface{}) (bool, error) {
						return matchDomainConstraint(.(string), .(string))
					}, .PermittedDNSDomains, .ExcludedDNSDomains);  != nil {
					return 
				}

			case nameTypeURI:
				 := string()
				,  := url.Parse()
				if  != nil {
					return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", )
				}

				if  := .checkNameConstraints(&, , "URI", , ,
					func(,  interface{}) (bool, error) {
						return matchURIConstraint(.(*url.URL), .(string))
					}, .PermittedURIDomains, .ExcludedURIDomains);  != nil {
					return 
				}

			case nameTypeIP:
				 := net.IP()
				if  := len();  != net.IPv4len &&  != net.IPv6len {
					return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", )
				}

				if  := .checkNameConstraints(&, , "IP address", .String(), ,
					func(,  interface{}) (bool, error) {
						return matchIPConstraint(.(net.IP), .(*net.IPNet))
					}, .PermittedIPRanges, .ExcludedIPRanges);  != nil {
					return 
				}

Unknown SAN types are ignored.
			}

			return nil
		})

		if  != nil {
			return 
		}
	}
KeyUsage status flags are ignored. From Engineering Security, Peter Gutmann: A European government CA marked its signing certificates as being valid for encryption only, but no-one noticed. Another European CA marked its signature keys as not being valid for signatures. A different CA marked its own trusted root certificate as being invalid for certificate signing. Another national CA distributed a certificate to be used to encrypt data for the country’s tax authority that was marked as only being usable for digital signatures but not for encryption. Yet another CA reversed the order of the bit flags in the keyUsage due to confusion over encoding endianness, essentially setting a random keyUsage in certificates that it issued. Another CA created a self-invalidating certificate by adding a certificate policy statement stipulating that the certificate had to be used strictly as specified in the keyUsage, and a keyUsage containing a flag indicating that the RSA encryption key could only be used for Diffie-Hellman key agreement.

	if  == intermediateCertificate && (!.BasicConstraintsValid || !.IsCA) {
		return CertificateInvalidError{, NotAuthorizedToSign, ""}
	}

	if .BasicConstraintsValid && .MaxPathLen >= 0 {
		 := len() - 1
		if  > .MaxPathLen {
			return CertificateInvalidError{, TooManyIntermediates, ""}
		}
	}

	return nil
}
Verify attempts to verify c by building one or more chains from c to a certificate in opts.Roots, using certificates in opts.Intermediates if needed. If successful, it returns one or more chains where the first element of the chain is c and the last element is from opts.Roots. If opts.Roots is nil, the platform verifier might be used, and verification details might differ from what is described below. If system roots are unavailable the returned error will be of type SystemRootsError. Name constraints in the intermediates will be applied to all names claimed in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim example.com if an intermediate doesn't permit it, even if example.com is not the name being validated. Note that DirectoryName constraints are not supported. Name constraint validation follows the rules from RFC 5280, with the addition that DNS name constraints may use the leading period format defined for emails and URIs. When a constraint has a leading period it indicates that at least one additional label must be prepended to the constrained name to be considered valid. Extended Key Usage values are enforced nested down a chain, so an intermediate or root that enumerates EKUs prevents a leaf from asserting an EKU not in that list. (While this is not specified, it is common practice in order to limit the types of certificates a CA can issue.) WARNING: this function doesn't do any revocation checking.
Platform-specific verification needs the ASN.1 contents so this makes the behavior consistent across platforms.
	if len(.Raw) == 0 {
		return nil, errNotParsed
	}
	for  := 0;  < .Intermediates.len(); ++ {
		,  := .Intermediates.cert()
		if  != nil {
			return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", )
		}
		if len(.Raw) == 0 {
			return nil, errNotParsed
		}
	}
Use Windows's own verification and chain building.
	if .Roots == nil && runtime.GOOS == "windows" {
		return .systemVerify(&)
	}

	if .Roots == nil {
		.Roots = systemRootsPool()
		if .Roots == nil {
			return nil, SystemRootsError{systemRootsErr}
		}
	}

	 = .isValid(leafCertificate, nil, &)
	if  != nil {
		return
	}

	if len(.DNSName) > 0 {
		 = .VerifyHostname(.DNSName)
		if  != nil {
			return
		}
	}

	var  [][]*Certificate
	if .Roots.contains() {
		 = append(, []*Certificate{})
	} else {
		if ,  = .buildChains(nil, []*Certificate{}, nil, &);  != nil {
			return nil, 
		}
	}

	 := .KeyUsages
	if len() == 0 {
		 = []ExtKeyUsage{ExtKeyUsageServerAuth}
	}
If any key usage is acceptable then we're done.
	for ,  := range  {
		if  == ExtKeyUsageAny {
			return , nil
		}
	}

	for ,  := range  {
		if checkChainForKeyUsage(, ) {
			 = append(, )
		}
	}

	if len() == 0 {
		return nil, CertificateInvalidError{, IncompatibleUsage, ""}
	}

	return , nil
}

func ( []*Certificate,  *Certificate) []*Certificate {
	 := make([]*Certificate, len()+1)
	copy(, )
	[len()] = 
	return 
}
maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls that an invocation of buildChains will (tranistively) make. Most chains are less than 15 certificates long, so this leaves space for multiple chains and for failed checks due to different intermediates having the same Subject.
const maxChainSignatureChecks = 100

func ( *Certificate) ( map[*Certificate][][]*Certificate,  []*Certificate,  *int,  *VerifyOptions) ( [][]*Certificate,  error) {
	var (
		  error
		 *Certificate
	)

	 := func( int,  *Certificate) {
		for ,  := range  {
			if .Equal() {
				return
			}
		}

		if  == nil {
			 = new(int)
		}
		*++
		if * > maxChainSignatureChecks {
			 = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
			return
		}

		if  := .CheckSignatureFrom();  != nil {
			if  == nil {
				 = 
				 = 
			}
			return
		}

		 = .isValid(, , )
		if  != nil {
			return
		}

		switch  {
		case rootCertificate:
			 = append(, appendToFreshChain(, ))
		case intermediateCertificate:
			if  == nil {
				 = make(map[*Certificate][][]*Certificate)
			}
			,  := []
			if ! {
				,  = .(, appendToFreshChain(, ), , )
				[] = 
			}
			 = append(, ...)
		}
	}

	for ,  := range .Roots.findPotentialParents() {
		(rootCertificate, )
	}
	for ,  := range .Intermediates.findPotentialParents() {
		(intermediateCertificate, )
	}

	if len() > 0 {
		 = nil
	}
	if len() == 0 &&  == nil {
		 = UnknownAuthorityError{, , }
	}

	return
}

func ( string) bool { return validHostname(, true) }
func ( string) bool   { return validHostname(, false) }
validHostname reports whether host is a valid hostname that can be matched or matched against according to RFC 6125 2.2, with some leniency to accommodate legacy values.
func ( string,  bool) bool {
	if ! {
		 = strings.TrimSuffix(, ".")
	}
	if len() == 0 {
		return false
	}

	for ,  := range strings.Split(, ".") {
Empty label.
			return false
		}
Only allow full left-most wildcards, as those are the only ones we match, and matching literal '*' characters is probably never the expected behavior.
			continue
		}
		for ,  := range  {
			if 'a' <=  &&  <= 'z' {
				continue
			}
			if '0' <=  &&  <= '9' {
				continue
			}
			if 'A' <=  &&  <= 'Z' {
				continue
			}
			if  == '-' &&  != 0 {
				continue
			}
Not a valid character in hostnames, but commonly found in deployments outside the WebPKI.
				continue
			}
			return false
		}
	}

	return true
}
commonNameAsHostname reports whether the Common Name field should be considered the hostname that the certificate is valid for. This is a legacy behavior, disabled by default or if the Subject Alt Name extension is present. It applies the strict validHostname check to the Common Name field, so that certificates without SANs can still be validated against CAs with name constraints if there is no risk the CN would be matched as a hostname. See NameConstraintsWithoutSANs and issue 24151.
func ( *Certificate) () bool {
	return !ignoreCN && !.hasSANExtension() && validHostnamePattern(.Subject.CommonName)
}

func (,  string) bool {
	if  == "" ||  == "." ||  == "" ||  == "." {
		return false
	}
	return toLowerCaseASCII() == toLowerCaseASCII()
}

func (,  string) bool {
	 = toLowerCaseASCII()
	 = toLowerCaseASCII(strings.TrimSuffix(, "."))

	if len() == 0 || len() == 0 {
		return false
	}

	 := strings.Split(, ".")
	 := strings.Split(, ".")

	if len() != len() {
		return false
	}

	for ,  := range  {
		if  == 0 &&  == "*" {
			continue
		}
		if  != [] {
			return false
		}
	}

	return true
}
toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use an explicitly ASCII function to avoid any sharp corners resulting from performing Unicode operations on DNS labels.
If the string is already lower-case then there's nothing to do.
	 := true
	for ,  := range  {
If we get a UTF-8 error then there might be upper-case ASCII bytes in the invalid sequence.
			 = false
			break
		}
		if 'A' <=  &&  <= 'Z' {
			 = false
			break
		}
	}

	if  {
		return 
	}

	 := []byte()
	for ,  := range  {
		if 'A' <=  &&  <= 'Z' {
			[] += 'a' - 'A'
		}
	}
	return string()
}
VerifyHostname returns nil if c is a valid certificate for the named host. Otherwise it returns an error describing the mismatch. IP addresses can be optionally enclosed in square brackets and are checked against the IPAddresses field. Other names are checked case insensitively against the DNSNames field. If the names are valid hostnames, the certificate fields can have a wildcard as the left-most label. The legacy Common Name field is ignored unless it's a valid hostname, the certificate doesn't have any Subject Alternative Names, and the GODEBUG environment variable is set to "x509ignoreCN=0". Support for Common Name is deprecated will be entirely removed in the future.
IP addresses may be written in [ ].
	 := 
	if len() >= 3 && [0] == '[' && [len()-1] == ']' {
		 = [1 : len()-1]
	}
We only match IP addresses against IP SANs. See RFC 6125, Appendix B.2.
		for ,  := range .IPAddresses {
			if .Equal() {
				return nil
			}
		}
		return HostnameError{, }
	}

	 := .DNSNames
	if .commonNameAsHostname() {
		 = []string{.Subject.CommonName}
	}

	 := toLowerCaseASCII() // Save allocations inside the loop.
	 := validHostnameInput()

Ideally, we'd only match valid hostnames according to RFC 6125 like browsers (more or less) do, but in practice Go is used in a wider array of contexts and can't even assume DNS resolution. Instead, always allow perfect matches, and only apply wildcard and trailing dot processing to valid hostnames.
		if  && validHostnamePattern() {
			if matchHostnames(, ) {
				return nil
			}
		} else {
			if matchExactly(, ) {
				return nil
			}
		}
	}

	return HostnameError{, }
}

func ( []*Certificate,  []ExtKeyUsage) bool {
	 := make([]ExtKeyUsage, len())
	copy(, )

	if len() == 0 {
		return false
	}

	 := len()
We walk down the list and cross out any usages that aren't supported by each certificate. If we cross out all the usages, then the chain is unacceptable.

:
	for  := len() - 1;  >= 0; -- {
		 := []
The certificate doesn't have any extended key usage specified.
			continue
		}

		for ,  := range .ExtKeyUsage {
The certificate is explicitly good for any usage.
				continue 
			}
		}

		const  ExtKeyUsage = -1

	:
		for ,  := range  {
			if  ==  {
				continue
			}

			for ,  := range .ExtKeyUsage {
				if  ==  {
					continue 
				} else if  == ExtKeyUsageServerAuth &&
					( == ExtKeyUsageNetscapeServerGatedCrypto ||
In order to support COMODO certificate chains, we have to accept Netscape or Microsoft SGC usages as equal to ServerAuth.
					continue 
				}
			}

			[] = 
			--
			if  == 0 {
				return false
			}
		}
	}

	return true