1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
20 type InvalidReason
int
23 // NotAuthorizedToSign results when a certificate is signed by another
24 // which isn't marked as a CA certificate.
25 NotAuthorizedToSign InvalidReason
= iota
26 // Expired results when a certificate has expired, based on the time
27 // given in the VerifyOptions.
29 // CANotAuthorizedForThisName results when an intermediate or root
30 // certificate has a name constraint which doesn't permit a DNS or
31 // other name (including IP address) in the leaf certificate.
32 CANotAuthorizedForThisName
33 // TooManyIntermediates results when a path length constraint is
36 // IncompatibleUsage results when the certificate's key usage indicates
37 // that it may only be used for a different purpose.
39 // NameMismatch results when the subject name of a parent certificate
40 // does not match the issuer name in the child.
42 // NameConstraintsWithoutSANs results when a leaf certificate doesn't
43 // contain a Subject Alternative Name extension, but a CA certificate
44 // contains name constraints.
45 NameConstraintsWithoutSANs
46 // UnconstrainedName results when a CA certificate contains permitted
47 // name constraints, but leaf certificate contains a name of an
48 // unsupported or unconstrained type.
50 // TooManyConstraints results when the number of comparision operations
51 // needed to check a certificate exceeds the limit set by
52 // VerifyOptions.MaxConstraintComparisions. This limit exists to
53 // prevent pathological certificates can consuming excessive amounts of
54 // CPU time to verify.
56 // CANotAuthorizedForExtKeyUsage results when an intermediate or root
57 // certificate does not permit an extended key usage that is claimed by
58 // the leaf certificate.
59 CANotAuthorizedForExtKeyUsage
62 // CertificateInvalidError results when an odd error occurs. Users of this
63 // library probably want to handle all these errors uniformly.
64 type CertificateInvalidError
struct {
70 func (e CertificateInvalidError
) Error() string {
72 case NotAuthorizedToSign
:
73 return "x509: certificate is not authorized to sign other certificates"
75 return "x509: certificate has expired or is not yet valid"
76 case CANotAuthorizedForThisName
:
77 return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e
.Detail
78 case CANotAuthorizedForExtKeyUsage
:
79 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e
.Detail
80 case TooManyIntermediates
:
81 return "x509: too many intermediates for path length constraint"
82 case IncompatibleUsage
:
83 return "x509: certificate specifies an incompatible key usage: " + e
.Detail
85 return "x509: issuer name does not match subject from issuing certificate"
86 case NameConstraintsWithoutSANs
:
87 return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
88 case UnconstrainedName
:
89 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e
.Detail
91 return "x509: unknown error"
94 // HostnameError results when the set of authorized names doesn't match the
96 type HostnameError
struct {
97 Certificate
*Certificate
101 func (h HostnameError
) Error() string {
105 if ip
:= net
.ParseIP(h
.Host
); ip
!= nil {
106 // Trying to validate an IP
107 if len(c
.IPAddresses
) == 0 {
108 return "x509: cannot validate certificate for " + h
.Host
+ " because it doesn't contain any IP SANs"
110 for _
, san
:= range c
.IPAddresses
{
114 valid
+= san
.String()
117 if c
.hasSANExtension() {
118 valid
= strings
.Join(c
.DNSNames
, ", ")
120 valid
= c
.Subject
.CommonName
125 return "x509: certificate is not valid for any names, but wanted to match " + h
.Host
127 return "x509: certificate is valid for " + valid
+ ", not " + h
.Host
130 // UnknownAuthorityError results when the certificate issuer is unknown
131 type UnknownAuthorityError
struct {
133 // hintErr contains an error that may be helpful in determining why an
134 // authority wasn't found.
136 // hintCert contains a possible authority certificate that was rejected
137 // because of the error in hintErr.
138 hintCert
*Certificate
141 func (e UnknownAuthorityError
) Error() string {
142 s
:= "x509: certificate signed by unknown authority"
143 if e
.hintErr
!= nil {
144 certName
:= e
.hintCert
.Subject
.CommonName
145 if len(certName
) == 0 {
146 if len(e
.hintCert
.Subject
.Organization
) > 0 {
147 certName
= e
.hintCert
.Subject
.Organization
[0]
149 certName
= "serial:" + e
.hintCert
.SerialNumber
.String()
152 s
+= fmt
.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e
.hintErr
, certName
)
157 // SystemRootsError results when we fail to load the system root certificates.
158 type SystemRootsError
struct {
162 func (se SystemRootsError
) Error() string {
163 msg
:= "x509: failed to load system roots and no roots provided"
165 return msg
+ "; " + se
.Err
.Error()
170 // errNotParsed is returned when a certificate without ASN.1 contents is
171 // verified. Platform-specific verification needs the ASN.1 contents.
172 var errNotParsed
= errors
.New("x509: missing ASN.1 contents; use ParseCertificate")
174 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
175 // because other PKIX verification APIs have ended up needing many options.
176 type VerifyOptions
struct {
178 Intermediates
*CertPool
179 Roots
*CertPool
// if nil, the system roots are used
180 CurrentTime time
.Time
// if zero, the current time is used
181 // KeyUsage specifies which Extended Key Usage values are acceptable.
182 // An empty list means ExtKeyUsageServerAuth. Key usage is considered a
183 // constraint down the chain which mirrors Windows CryptoAPI behavior,
184 // but not the spec. To accept any key usage, include ExtKeyUsageAny.
185 KeyUsages
[]ExtKeyUsage
186 // MaxConstraintComparisions is the maximum number of comparisons to
187 // perform when checking a given certificate's name constraints. If
188 // zero, a sensible default is used. This limit prevents pathalogical
189 // certificates from consuming excessive amounts of CPU time when
191 MaxConstraintComparisions
int
195 leafCertificate
= iota
196 intermediateCertificate
200 // rfc2821Mailbox represents a “mailbox” (which is an email address to most
201 // people) by breaking it into the “local” (i.e. before the '@') and “domain”
203 type rfc2821Mailbox
struct {
207 // parseRFC2821Mailbox parses an email address into local and domain parts,
208 // based on the ABNF for a “Mailbox” from RFC 2821. According to
209 // https://tools.ietf.org/html/rfc5280#section-4.2.1.6 that's correct for an
210 // rfc822Name from a certificate: “The format of an rfc822Name is a "Mailbox"
211 // as defined in https://tools.ietf.org/html/rfc2821#section-4.1.2”.
212 func parseRFC2821Mailbox(in
string) (mailbox rfc2821Mailbox
, ok
bool) {
214 return mailbox
, false
217 localPartBytes
:= make([]byte, 0, len(in
)/2)
220 // Quoted-string = DQUOTE *qcontent DQUOTE
221 // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127
222 // qcontent = qtext / quoted-pair
223 // qtext = non-whitespace-control /
224 // %d33 / %d35-91 / %d93-126
225 // quoted-pair = ("\" text) / obs-qp
226 // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text
228 // (Names beginning with “obs-” are the obsolete syntax from
229 // https://tools.ietf.org/html/rfc2822#section-4. Since it has
230 // been 16 years, we no longer accept that.)
235 return mailbox
, false
247 return mailbox
, false
251 (1 <= in
[0] && in
[0] <= 9) ||
252 (14 <= in
[0] && in
[0] <= 127) {
253 localPartBytes
= append(localPartBytes
, in
[0])
256 return mailbox
, false
261 // Space (char 32) is not allowed based on the
262 // BNF, but RFC 3696 gives an example that
263 // assumes that it is. Several “verified”
264 // errata continue to argue about this point.
265 // We choose to accept it.
269 (1 <= c
&& c
<= 8) ||
270 (14 <= c
&& c
<= 31) ||
271 (35 <= c
&& c
<= 91) ||
272 (93 <= c
&& c
<= 126):
274 localPartBytes
= append(localPartBytes
, c
)
277 return mailbox
, false
284 // atext from https://tools.ietf.org/html/rfc2822#section-3.2.4
289 // Examples given in RFC 3696 suggest that
290 // escaped characters can appear outside of a
291 // quoted string. Several “verified” errata
292 // continue to argue the point. We choose to
296 return mailbox
, false
300 case ('0' <= c
&& c
<= '9') ||
301 ('a' <= c
&& c
<= 'z') ||
302 ('A' <= c
&& c
<= 'Z') ||
303 c
== '!' || c
== '#' || c
== '$' || c
== '%' ||
304 c
== '&' || c
== '\'' || c
== '*' || c
== '+' ||
305 c
== '-' || c
== '/' || c
== '=' || c
== '?' ||
306 c
== '^' || c
== '_' || c
== '`' || c
== '{' ||
307 c
== '|' || c
== '}' || c
== '~' || c
== '.':
308 localPartBytes
= append(localPartBytes
, in
[0])
316 if len(localPartBytes
) == 0 {
317 return mailbox
, false
320 // https://tools.ietf.org/html/rfc3696#section-3
321 // “period (".") may also appear, but may not be used to start
322 // or end the local part, nor may two or more consecutive
324 twoDots
:= []byte{'.', '.'}
325 if localPartBytes
[0] == '.' ||
326 localPartBytes
[len(localPartBytes
)-1] == '.' ||
327 bytes
.Contains(localPartBytes
, twoDots
) {
328 return mailbox
, false
332 if len(in
) == 0 || in
[0] != '@' {
333 return mailbox
, false
337 // The RFC species a format for domains, but that's known to be
338 // violated in practice so we accept that anything after an '@' is the
340 if _
, ok
:= domainToReverseLabels(in
); !ok
{
341 return mailbox
, false
344 mailbox
.local
= string(localPartBytes
)
349 // domainToReverseLabels converts a textual domain name like foo.example.com to
350 // the list of labels in reverse order, e.g. ["com", "example", "foo"].
351 func domainToReverseLabels(domain
string) (reverseLabels
[]string, ok
bool) {
352 for len(domain
) > 0 {
353 if i
:= strings
.LastIndexByte(domain
, '.'); i
== -1 {
354 reverseLabels
= append(reverseLabels
, domain
)
357 reverseLabels
= append(reverseLabels
, domain
[i
+1:len(domain
)])
362 if len(reverseLabels
) > 0 && len(reverseLabels
[0]) == 0 {
363 // An empty label at the end indicates an absolute value.
367 for _
, label
:= range reverseLabels
{
369 // Empty labels are otherwise invalid.
373 for _
, c
:= range label
{
374 if c
< 33 || c
> 126 {
375 // Invalid character.
381 return reverseLabels
, true
384 func matchEmailConstraint(mailbox rfc2821Mailbox
, constraint
string) (bool, error
) {
385 // If the constraint contains an @, then it specifies an exact mailbox
387 if strings
.Contains(constraint
, "@") {
388 constraintMailbox
, ok
:= parseRFC2821Mailbox(constraint
)
390 return false, fmt
.Errorf("x509: internal error: cannot parse constraint %q", constraint
)
392 return mailbox
.local
== constraintMailbox
.local
&& strings
.EqualFold(mailbox
.domain
, constraintMailbox
.domain
), nil
395 // Otherwise the constraint is like a DNS constraint of the domain part
397 return matchDomainConstraint(mailbox
.domain
, constraint
)
400 func matchURIConstraint(uri
*url
.URL
, constraint
string) (bool, error
) {
401 // https://tools.ietf.org/html/rfc5280#section-4.2.1.10
402 // “a uniformResourceIdentifier that does not include an authority
403 // component with a host name specified as a fully qualified domain
404 // name (e.g., if the URI either does not include an authority
405 // component or includes an authority component in which the host name
406 // is specified as an IP address), then the application MUST reject the
411 return false, fmt
.Errorf("URI with empty host (%q) cannot be matched against constraints", uri
.String())
414 if strings
.Contains(host
, ":") && !strings
.HasSuffix(host
, "]") {
416 host
, _
, err
= net
.SplitHostPort(uri
.Host
)
422 if strings
.HasPrefix(host
, "[") && strings
.HasSuffix(host
, "]") ||
423 net
.ParseIP(host
) != nil {
424 return false, fmt
.Errorf("URI with IP (%q) cannot be matched against constraints", uri
.String())
427 return matchDomainConstraint(host
, constraint
)
430 func matchIPConstraint(ip net
.IP
, constraint
*net
.IPNet
) (bool, error
) {
431 if len(ip
) != len(constraint
.IP
) {
436 if mask
:= constraint
.Mask
[i
]; ip
[i
]&mask
!= constraint
.IP
[i
]&mask
{
444 func matchDomainConstraint(domain
, constraint
string) (bool, error
) {
445 // The meaning of zero length constraints is not specified, but this
446 // code follows NSS and accepts them as matching everything.
447 if len(constraint
) == 0 {
451 domainLabels
, ok
:= domainToReverseLabels(domain
)
453 return false, fmt
.Errorf("x509: internal error: cannot parse domain %q", domain
)
456 // RFC 5280 says that a leading period in a domain name means that at
457 // least one label must be prepended, but only for URI and email
458 // constraints, not DNS constraints. The code also supports that
459 // behaviour for DNS constraints.
461 mustHaveSubdomains
:= false
462 if constraint
[0] == '.' {
463 mustHaveSubdomains
= true
464 constraint
= constraint
[1:]
467 constraintLabels
, ok
:= domainToReverseLabels(constraint
)
469 return false, fmt
.Errorf("x509: internal error: cannot parse domain %q", constraint
)
472 if len(domainLabels
) < len(constraintLabels
) ||
473 (mustHaveSubdomains
&& len(domainLabels
) == len(constraintLabels
)) {
477 for i
, constraintLabel
:= range constraintLabels
{
478 if !strings
.EqualFold(constraintLabel
, domainLabels
[i
]) {
486 // checkNameConstraints checks that c permits a child certificate to claim the
487 // given name, of type nameType. The argument parsedName contains the parsed
488 // form of name, suitable for passing to the match function. The total number
489 // of comparisons is tracked in the given count and should not exceed the given
491 func (c
*Certificate
) checkNameConstraints(count
*int,
492 maxConstraintComparisons
int,
495 parsedName
interface{},
496 match
func(parsedName
, constraint
interface{}) (match
bool, err error
),
497 permitted
, excluded
interface{}) error
{
499 excludedValue
:= reflect
.ValueOf(excluded
)
501 *count
+= excludedValue
.Len()
502 if *count
> maxConstraintComparisons
{
503 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
506 for i
:= 0; i
< excludedValue
.Len(); i
++ {
507 constraint
:= excludedValue
.Index(i
).Interface()
508 match
, err
:= match(parsedName
, constraint
)
510 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, err
.Error()}
514 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, fmt
.Sprintf("%s %q is excluded by constraint %q", nameType
, name
, constraint
)}
518 permittedValue
:= reflect
.ValueOf(permitted
)
520 *count
+= permittedValue
.Len()
521 if *count
> maxConstraintComparisons
{
522 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
526 for i
:= 0; i
< permittedValue
.Len(); i
++ {
527 constraint
:= permittedValue
.Index(i
).Interface()
530 if ok
, err
= match(parsedName
, constraint
); err
!= nil {
531 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, err
.Error()}
540 return CertificateInvalidError
{c
, CANotAuthorizedForThisName
, fmt
.Sprintf("%s %q is not permitted by any constraint", nameType
, name
)}
546 // ekuPermittedBy returns true iff the given extended key usage is permitted by
547 // the given EKU from a certificate. Normally, this would be a simple
548 // comparison plus a special case for the “any” EKU. But, in order to support
549 // existing certificates, some exceptions are made.
550 func ekuPermittedBy(eku
, certEKU ExtKeyUsage
) bool {
551 if certEKU
== ExtKeyUsageAny || eku
== certEKU
{
555 // Some exceptions are made to support existing certificates. Firstly,
556 // the ServerAuth and SGC EKUs are treated as a group.
557 mapServerAuthEKUs
:= func(eku ExtKeyUsage
) ExtKeyUsage
{
558 if eku
== ExtKeyUsageNetscapeServerGatedCrypto || eku
== ExtKeyUsageMicrosoftServerGatedCrypto
{
559 return ExtKeyUsageServerAuth
564 eku
= mapServerAuthEKUs(eku
)
565 certEKU
= mapServerAuthEKUs(certEKU
)
568 // ServerAuth in a CA permits ClientAuth in the leaf.
569 (eku
== ExtKeyUsageClientAuth
&& certEKU
== ExtKeyUsageServerAuth
) ||
570 // Any CA may issue an OCSP responder certificate.
571 eku
== ExtKeyUsageOCSPSigning ||
572 // Code-signing CAs can use Microsoft's commercial and
574 ((eku
== ExtKeyUsageMicrosoftCommercialCodeSigning || eku
== ExtKeyUsageMicrosoftKernelCodeSigning
) && certEKU
== ExtKeyUsageCodeSigning
) {
581 // isValid performs validity checks on c given that it is a candidate to append
582 // to the chain in currentChain.
583 func (c
*Certificate
) isValid(certType
int, currentChain
[]*Certificate
, opts
*VerifyOptions
) error
{
584 if len(c
.UnhandledCriticalExtensions
) > 0 {
585 return UnhandledCriticalExtension
{}
588 if len(currentChain
) > 0 {
589 child
:= currentChain
[len(currentChain
)-1]
590 if !bytes
.Equal(child
.RawIssuer
, c
.RawSubject
) {
591 return CertificateInvalidError
{c
, NameMismatch
, ""}
595 now
:= opts
.CurrentTime
599 if now
.Before(c
.NotBefore
) || now
.After(c
.NotAfter
) {
600 return CertificateInvalidError
{c
, Expired
, ""}
603 maxConstraintComparisons
:= opts
.MaxConstraintComparisions
604 if maxConstraintComparisons
== 0 {
605 maxConstraintComparisons
= 250000
609 var leaf
*Certificate
610 if certType
== intermediateCertificate || certType
== rootCertificate
{
611 if len(currentChain
) == 0 {
612 return errors
.New("x509: internal error: empty chain when appending CA cert")
614 leaf
= currentChain
[0]
617 if (certType
== intermediateCertificate || certType
== rootCertificate
) && c
.hasNameConstraints() {
618 sanExtension
, ok
:= leaf
.getSANExtension()
620 // This is the deprecated, legacy case of depending on
621 // the CN as a hostname. Chains modern enough to be
622 // using name constraints should not be depending on
624 return CertificateInvalidError
{c
, NameConstraintsWithoutSANs
, ""}
627 err
:= forEachSAN(sanExtension
, func(tag
int, data
[]byte) error
{
631 mailbox
, ok
:= parseRFC2821Mailbox(name
)
633 // This certificate should not have parsed.
634 return errors
.New("x509: internal error: rfc822Name SAN failed to parse")
637 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "email address", name
, mailbox
,
638 func(parsedName
, constraint
interface{}) (bool, error
) {
639 return matchEmailConstraint(parsedName
.(rfc2821Mailbox
), constraint
.(string))
640 }, c
.PermittedEmailAddresses
, c
.ExcludedEmailAddresses
); err
!= nil {
646 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "DNS name", name
, name
,
647 func(parsedName
, constraint
interface{}) (bool, error
) {
648 return matchDomainConstraint(parsedName
.(string), constraint
.(string))
649 }, c
.PermittedDNSDomains
, c
.ExcludedDNSDomains
); err
!= nil {
655 uri
, err
:= url
.Parse(name
)
657 return fmt
.Errorf("x509: internal error: URI SAN %q failed to parse", name
)
660 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "URI", name
, uri
,
661 func(parsedName
, constraint
interface{}) (bool, error
) {
662 return matchURIConstraint(parsedName
.(*url
.URL
), constraint
.(string))
663 }, c
.PermittedURIDomains
, c
.ExcludedURIDomains
); err
!= nil {
669 if l
:= len(ip
); l
!= net
.IPv4len
&& l
!= net
.IPv6len
{
670 return fmt
.Errorf("x509: internal error: IP SAN %x failed to parse", data
)
673 if err
:= c
.checkNameConstraints(&comparisonCount
, maxConstraintComparisons
, "IP address", ip
.String(), ip
,
674 func(parsedName
, constraint
interface{}) (bool, error
) {
675 return matchIPConstraint(parsedName
.(net
.IP
), constraint
.(*net
.IPNet
))
676 }, c
.PermittedIPRanges
, c
.ExcludedIPRanges
); err
!= nil {
681 // Unknown SAN types are ignored.
692 checkEKUs
:= certType
== intermediateCertificate
694 // If no extended key usages are specified, then all are acceptable.
695 if checkEKUs
&& (len(c
.ExtKeyUsage
) == 0 && len(c
.UnknownExtKeyUsage
) == 0) {
699 // If the “any” key usage is permitted, then no more checks are needed.
701 for _
, caEKU
:= range c
.ExtKeyUsage
{
703 if caEKU
== ExtKeyUsageAny
{
712 for _
, eku
:= range leaf
.ExtKeyUsage
{
713 if comparisonCount
> maxConstraintComparisons
{
714 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
717 for _
, caEKU
:= range c
.ExtKeyUsage
{
719 if ekuPermittedBy(eku
, caEKU
) {
724 oid
, _
:= oidFromExtKeyUsage(eku
)
725 return CertificateInvalidError
{c
, CANotAuthorizedForExtKeyUsage
, fmt
.Sprintf("EKU not permitted: %#v", oid
)}
729 for _
, eku
:= range leaf
.UnknownExtKeyUsage
{
730 if comparisonCount
> maxConstraintComparisons
{
731 return CertificateInvalidError
{c
, TooManyConstraints
, ""}
734 for _
, caEKU
:= range c
.UnknownExtKeyUsage
{
736 if caEKU
.Equal(eku
) {
737 continue NextUnknownEKU
741 return CertificateInvalidError
{c
, CANotAuthorizedForExtKeyUsage
, fmt
.Sprintf("EKU not permitted: %#v", eku
)}
745 // KeyUsage status flags are ignored. From Engineering Security, Peter
746 // Gutmann: A European government CA marked its signing certificates as
747 // being valid for encryption only, but no-one noticed. Another
748 // European CA marked its signature keys as not being valid for
749 // signatures. A different CA marked its own trusted root certificate
750 // as being invalid for certificate signing. Another national CA
751 // distributed a certificate to be used to encrypt data for the
752 // country’s tax authority that was marked as only being usable for
753 // digital signatures but not for encryption. Yet another CA reversed
754 // the order of the bit flags in the keyUsage due to confusion over
755 // encoding endianness, essentially setting a random keyUsage in
756 // certificates that it issued. Another CA created a self-invalidating
757 // certificate by adding a certificate policy statement stipulating
758 // that the certificate had to be used strictly as specified in the
759 // keyUsage, and a keyUsage containing a flag indicating that the RSA
760 // encryption key could only be used for Diffie-Hellman key agreement.
762 if certType
== intermediateCertificate
&& (!c
.BasicConstraintsValid ||
!c
.IsCA
) {
763 return CertificateInvalidError
{c
, NotAuthorizedToSign
, ""}
766 if c
.BasicConstraintsValid
&& c
.MaxPathLen
>= 0 {
767 numIntermediates
:= len(currentChain
) - 1
768 if numIntermediates
> c
.MaxPathLen
{
769 return CertificateInvalidError
{c
, TooManyIntermediates
, ""}
776 // Verify attempts to verify c by building one or more chains from c to a
777 // certificate in opts.Roots, using certificates in opts.Intermediates if
778 // needed. If successful, it returns one or more chains where the first
779 // element of the chain is c and the last element is from opts.Roots.
781 // If opts.Roots is nil and system roots are unavailable the returned error
782 // will be of type SystemRootsError.
784 // Name constraints in the intermediates will be applied to all names claimed
785 // in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
786 // example.com if an intermediate doesn't permit it, even if example.com is not
787 // the name being validated. Note that DirectoryName constraints are not
790 // Extended Key Usage values are enforced down a chain, so an intermediate or
791 // root that enumerates EKUs prevents a leaf from asserting an EKU not in that
794 // WARNING: this function doesn't do any revocation checking.
795 func (c
*Certificate
) Verify(opts VerifyOptions
) (chains
[][]*Certificate
, err error
) {
796 // Platform-specific verification needs the ASN.1 contents so
797 // this makes the behavior consistent across platforms.
799 return nil, errNotParsed
801 if opts
.Intermediates
!= nil {
802 for _
, intermediate
:= range opts
.Intermediates
.certs
{
803 if len(intermediate
.Raw
) == 0 {
804 return nil, errNotParsed
809 // Use Windows's own verification and chain building.
810 if opts
.Roots
== nil && runtime
.GOOS
== "windows" {
811 return c
.systemVerify(&opts
)
814 if opts
.Roots
== nil {
815 opts
.Roots
= systemRootsPool()
816 if opts
.Roots
== nil {
817 return nil, SystemRootsError
{systemRootsErr
}
821 err
= c
.isValid(leafCertificate
, nil, &opts
)
826 if len(opts
.DNSName
) > 0 {
827 err
= c
.VerifyHostname(opts
.DNSName
)
833 requestedKeyUsages
:= make([]ExtKeyUsage
, len(opts
.KeyUsages
))
834 copy(requestedKeyUsages
, opts
.KeyUsages
)
835 if len(requestedKeyUsages
) == 0 {
836 requestedKeyUsages
= append(requestedKeyUsages
, ExtKeyUsageServerAuth
)
839 // If no key usages are specified, then any are acceptable.
840 checkEKU
:= len(c
.ExtKeyUsage
) > 0
842 for _
, eku
:= range requestedKeyUsages
{
843 if eku
== ExtKeyUsageAny
{
851 for _
, eku
:= range requestedKeyUsages
{
852 for _
, leafEKU
:= range c
.ExtKeyUsage
{
853 if ekuPermittedBy(eku
, leafEKU
) {
858 oid
, _
:= oidFromExtKeyUsage(eku
)
859 return nil, CertificateInvalidError
{c
, IncompatibleUsage
, fmt
.Sprintf("%#v", oid
)}
863 var candidateChains
[][]*Certificate
864 if opts
.Roots
.contains(c
) {
865 candidateChains
= append(candidateChains
, []*Certificate
{c
})
867 if candidateChains
, err
= c
.buildChains(make(map[int][][]*Certificate
), []*Certificate
{c
}, &opts
); err
!= nil {
872 return candidateChains
, nil
875 func appendToFreshChain(chain
[]*Certificate
, cert
*Certificate
) []*Certificate
{
876 n
:= make([]*Certificate
, len(chain
)+1)
882 func (c
*Certificate
) buildChains(cache
map[int][][]*Certificate
, currentChain
[]*Certificate
, opts
*VerifyOptions
) (chains
[][]*Certificate
, err error
) {
883 possibleRoots
, failedRoot
, rootErr
:= opts
.Roots
.findVerifiedParents(c
)
885 for _
, rootNum
:= range possibleRoots
{
886 root
:= opts
.Roots
.certs
[rootNum
]
888 for _
, cert
:= range currentChain
{
889 if cert
.Equal(root
) {
894 err
= root
.isValid(rootCertificate
, currentChain
, opts
)
898 chains
= append(chains
, appendToFreshChain(currentChain
, root
))
901 possibleIntermediates
, failedIntermediate
, intermediateErr
:= opts
.Intermediates
.findVerifiedParents(c
)
903 for _
, intermediateNum
:= range possibleIntermediates
{
904 intermediate
:= opts
.Intermediates
.certs
[intermediateNum
]
905 for _
, cert
:= range currentChain
{
906 if cert
.Equal(intermediate
) {
907 continue nextIntermediate
910 err
= intermediate
.isValid(intermediateCertificate
, currentChain
, opts
)
914 var childChains
[][]*Certificate
915 childChains
, ok
:= cache
[intermediateNum
]
917 childChains
, err
= intermediate
.buildChains(cache
, appendToFreshChain(currentChain
, intermediate
), opts
)
918 cache
[intermediateNum
] = childChains
920 chains
= append(chains
, childChains
...)
927 if len(chains
) == 0 && err
== nil {
929 hintCert
:= failedRoot
931 hintErr
= intermediateErr
932 hintCert
= failedIntermediate
934 err
= UnknownAuthorityError
{c
, hintErr
, hintCert
}
940 func matchHostnames(pattern
, host
string) bool {
941 host
= strings
.TrimSuffix(host
, ".")
942 pattern
= strings
.TrimSuffix(pattern
, ".")
944 if len(pattern
) == 0 ||
len(host
) == 0 {
948 patternParts
:= strings
.Split(pattern
, ".")
949 hostParts
:= strings
.Split(host
, ".")
951 if len(patternParts
) != len(hostParts
) {
955 for i
, patternPart
:= range patternParts
{
956 if i
== 0 && patternPart
== "*" {
959 if patternPart
!= hostParts
[i
] {
967 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
968 // an explicitly ASCII function to avoid any sharp corners resulting from
969 // performing Unicode operations on DNS labels.
970 func toLowerCaseASCII(in
string) string {
971 // If the string is already lower-case then there's nothing to do.
972 isAlreadyLowerCase
:= true
973 for _
, c
:= range in
{
974 if c
== utf8
.RuneError
{
975 // If we get a UTF-8 error then there might be
976 // upper-case ASCII bytes in the invalid sequence.
977 isAlreadyLowerCase
= false
980 if 'A' <= c
&& c
<= 'Z' {
981 isAlreadyLowerCase
= false
986 if isAlreadyLowerCase
{
991 for i
, c
:= range out
{
992 if 'A' <= c
&& c
<= 'Z' {
999 // VerifyHostname returns nil if c is a valid certificate for the named host.
1000 // Otherwise it returns an error describing the mismatch.
1001 func (c
*Certificate
) VerifyHostname(h
string) error
{
1002 // IP addresses may be written in [ ].
1004 if len(h
) >= 3 && h
[0] == '[' && h
[len(h
)-1] == ']' {
1005 candidateIP
= h
[1 : len(h
)-1]
1007 if ip
:= net
.ParseIP(candidateIP
); ip
!= nil {
1008 // We only match IP addresses against IP SANs.
1009 // https://tools.ietf.org/html/rfc6125#appendix-B.2
1010 for _
, candidate
:= range c
.IPAddresses
{
1011 if ip
.Equal(candidate
) {
1015 return HostnameError
{c
, candidateIP
}
1018 lowered
:= toLowerCaseASCII(h
)
1020 if c
.hasSANExtension() {
1021 for _
, match
:= range c
.DNSNames
{
1022 if matchHostnames(toLowerCaseASCII(match
), lowered
) {
1026 // If Subject Alt Name is given, we ignore the common name.
1027 } else if matchHostnames(toLowerCaseASCII(c
.Subject
.CommonName
), lowered
) {
1031 return HostnameError
{c
, h
}