]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/x509/verify.go
crypto/x509: rework path building
[gostls13.git] / src / crypto / x509 / verify.go
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.
4
5 package x509
6
7 import (
8         "bytes"
9         "crypto"
10         "errors"
11         "fmt"
12         "net"
13         "net/url"
14         "reflect"
15         "runtime"
16         "strings"
17         "time"
18         "unicode/utf8"
19 )
20
21 type InvalidReason int
22
23 const (
24         // NotAuthorizedToSign results when a certificate is signed by another
25         // which isn't marked as a CA certificate.
26         NotAuthorizedToSign InvalidReason = iota
27         // Expired results when a certificate has expired, based on the time
28         // given in the VerifyOptions.
29         Expired
30         // CANotAuthorizedForThisName results when an intermediate or root
31         // certificate has a name constraint which doesn't permit a DNS or
32         // other name (including IP address) in the leaf certificate.
33         CANotAuthorizedForThisName
34         // TooManyIntermediates results when a path length constraint is
35         // violated.
36         TooManyIntermediates
37         // IncompatibleUsage results when the certificate's key usage indicates
38         // that it may only be used for a different purpose.
39         IncompatibleUsage
40         // NameMismatch results when the subject name of a parent certificate
41         // does not match the issuer name in the child.
42         NameMismatch
43         // NameConstraintsWithoutSANs is a legacy error and is no longer returned.
44         NameConstraintsWithoutSANs
45         // UnconstrainedName results when a CA certificate contains permitted
46         // name constraints, but leaf certificate contains a name of an
47         // unsupported or unconstrained type.
48         UnconstrainedName
49         // TooManyConstraints results when the number of comparison operations
50         // needed to check a certificate exceeds the limit set by
51         // VerifyOptions.MaxConstraintComparisions. This limit exists to
52         // prevent pathological certificates can consuming excessive amounts of
53         // CPU time to verify.
54         TooManyConstraints
55         // CANotAuthorizedForExtKeyUsage results when an intermediate or root
56         // certificate does not permit a requested extended key usage.
57         CANotAuthorizedForExtKeyUsage
58 )
59
60 // CertificateInvalidError results when an odd error occurs. Users of this
61 // library probably want to handle all these errors uniformly.
62 type CertificateInvalidError struct {
63         Cert   *Certificate
64         Reason InvalidReason
65         Detail string
66 }
67
68 func (e CertificateInvalidError) Error() string {
69         switch e.Reason {
70         case NotAuthorizedToSign:
71                 return "x509: certificate is not authorized to sign other certificates"
72         case Expired:
73                 return "x509: certificate has expired or is not yet valid: " + e.Detail
74         case CANotAuthorizedForThisName:
75                 return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail
76         case CANotAuthorizedForExtKeyUsage:
77                 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail
78         case TooManyIntermediates:
79                 return "x509: too many intermediates for path length constraint"
80         case IncompatibleUsage:
81                 return "x509: certificate specifies an incompatible key usage"
82         case NameMismatch:
83                 return "x509: issuer name does not match subject from issuing certificate"
84         case NameConstraintsWithoutSANs:
85                 return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
86         case UnconstrainedName:
87                 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail
88         }
89         return "x509: unknown error"
90 }
91
92 // HostnameError results when the set of authorized names doesn't match the
93 // requested name.
94 type HostnameError struct {
95         Certificate *Certificate
96         Host        string
97 }
98
99 func (h HostnameError) Error() string {
100         c := h.Certificate
101
102         if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
103                 return "x509: certificate relies on legacy Common Name field, use SANs instead"
104         }
105
106         var valid string
107         if ip := net.ParseIP(h.Host); ip != nil {
108                 // Trying to validate an IP
109                 if len(c.IPAddresses) == 0 {
110                         return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
111                 }
112                 for _, san := range c.IPAddresses {
113                         if len(valid) > 0 {
114                                 valid += ", "
115                         }
116                         valid += san.String()
117                 }
118         } else {
119                 valid = strings.Join(c.DNSNames, ", ")
120         }
121
122         if len(valid) == 0 {
123                 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
124         }
125         return "x509: certificate is valid for " + valid + ", not " + h.Host
126 }
127
128 // UnknownAuthorityError results when the certificate issuer is unknown
129 type UnknownAuthorityError struct {
130         Cert *Certificate
131         // hintErr contains an error that may be helpful in determining why an
132         // authority wasn't found.
133         hintErr error
134         // hintCert contains a possible authority certificate that was rejected
135         // because of the error in hintErr.
136         hintCert *Certificate
137 }
138
139 func (e UnknownAuthorityError) Error() string {
140         s := "x509: certificate signed by unknown authority"
141         if e.hintErr != nil {
142                 certName := e.hintCert.Subject.CommonName
143                 if len(certName) == 0 {
144                         if len(e.hintCert.Subject.Organization) > 0 {
145                                 certName = e.hintCert.Subject.Organization[0]
146                         } else {
147                                 certName = "serial:" + e.hintCert.SerialNumber.String()
148                         }
149                 }
150                 s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
151         }
152         return s
153 }
154
155 // SystemRootsError results when we fail to load the system root certificates.
156 type SystemRootsError struct {
157         Err error
158 }
159
160 func (se SystemRootsError) Error() string {
161         msg := "x509: failed to load system roots and no roots provided"
162         if se.Err != nil {
163                 return msg + "; " + se.Err.Error()
164         }
165         return msg
166 }
167
168 func (se SystemRootsError) Unwrap() error { return se.Err }
169
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")
173
174 // VerifyOptions contains parameters for Certificate.Verify.
175 type VerifyOptions struct {
176         // DNSName, if set, is checked against the leaf certificate with
177         // Certificate.VerifyHostname or the platform verifier.
178         DNSName string
179
180         // Intermediates is an optional pool of certificates that are not trust
181         // anchors, but can be used to form a chain from the leaf certificate to a
182         // root certificate.
183         Intermediates *CertPool
184         // Roots is the set of trusted root certificates the leaf certificate needs
185         // to chain up to. If nil, the system roots or the platform verifier are used.
186         Roots *CertPool
187
188         // CurrentTime is used to check the validity of all certificates in the
189         // chain. If zero, the current time is used.
190         CurrentTime time.Time
191
192         // KeyUsages specifies which Extended Key Usage values are acceptable. A
193         // chain is accepted if it allows any of the listed values. An empty list
194         // means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
195         KeyUsages []ExtKeyUsage
196
197         // MaxConstraintComparisions is the maximum number of comparisons to
198         // perform when checking a given certificate's name constraints. If
199         // zero, a sensible default is used. This limit prevents pathological
200         // certificates from consuming excessive amounts of CPU time when
201         // validating. It does not apply to the platform verifier.
202         MaxConstraintComparisions int
203 }
204
205 const (
206         leafCertificate = iota
207         intermediateCertificate
208         rootCertificate
209 )
210
211 // rfc2821Mailbox represents a “mailbox” (which is an email address to most
212 // people) by breaking it into the “local” (i.e. before the '@') and “domain”
213 // parts.
214 type rfc2821Mailbox struct {
215         local, domain string
216 }
217
218 // parseRFC2821Mailbox parses an email address into local and domain parts,
219 // based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280,
220 // Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The
221 // format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”.
222 func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
223         if len(in) == 0 {
224                 return mailbox, false
225         }
226
227         localPartBytes := make([]byte, 0, len(in)/2)
228
229         if in[0] == '"' {
230                 // Quoted-string = DQUOTE *qcontent DQUOTE
231                 // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127
232                 // qcontent = qtext / quoted-pair
233                 // qtext = non-whitespace-control /
234                 //         %d33 / %d35-91 / %d93-126
235                 // quoted-pair = ("\" text) / obs-qp
236                 // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text
237                 //
238                 // (Names beginning with “obs-” are the obsolete syntax from RFC 2822,
239                 // Section 4. Since it has been 16 years, we no longer accept that.)
240                 in = in[1:]
241         QuotedString:
242                 for {
243                         if len(in) == 0 {
244                                 return mailbox, false
245                         }
246                         c := in[0]
247                         in = in[1:]
248
249                         switch {
250                         case c == '"':
251                                 break QuotedString
252
253                         case c == '\\':
254                                 // quoted-pair
255                                 if len(in) == 0 {
256                                         return mailbox, false
257                                 }
258                                 if in[0] == 11 ||
259                                         in[0] == 12 ||
260                                         (1 <= in[0] && in[0] <= 9) ||
261                                         (14 <= in[0] && in[0] <= 127) {
262                                         localPartBytes = append(localPartBytes, in[0])
263                                         in = in[1:]
264                                 } else {
265                                         return mailbox, false
266                                 }
267
268                         case c == 11 ||
269                                 c == 12 ||
270                                 // Space (char 32) is not allowed based on the
271                                 // BNF, but RFC 3696 gives an example that
272                                 // assumes that it is. Several “verified”
273                                 // errata continue to argue about this point.
274                                 // We choose to accept it.
275                                 c == 32 ||
276                                 c == 33 ||
277                                 c == 127 ||
278                                 (1 <= c && c <= 8) ||
279                                 (14 <= c && c <= 31) ||
280                                 (35 <= c && c <= 91) ||
281                                 (93 <= c && c <= 126):
282                                 // qtext
283                                 localPartBytes = append(localPartBytes, c)
284
285                         default:
286                                 return mailbox, false
287                         }
288                 }
289         } else {
290                 // Atom ("." Atom)*
291         NextChar:
292                 for len(in) > 0 {
293                         // atext from RFC 2822, Section 3.2.4
294                         c := in[0]
295
296                         switch {
297                         case c == '\\':
298                                 // Examples given in RFC 3696 suggest that
299                                 // escaped characters can appear outside of a
300                                 // quoted string. Several “verified” errata
301                                 // continue to argue the point. We choose to
302                                 // accept it.
303                                 in = in[1:]
304                                 if len(in) == 0 {
305                                         return mailbox, false
306                                 }
307                                 fallthrough
308
309                         case ('0' <= c && c <= '9') ||
310                                 ('a' <= c && c <= 'z') ||
311                                 ('A' <= c && c <= 'Z') ||
312                                 c == '!' || c == '#' || c == '$' || c == '%' ||
313                                 c == '&' || c == '\'' || c == '*' || c == '+' ||
314                                 c == '-' || c == '/' || c == '=' || c == '?' ||
315                                 c == '^' || c == '_' || c == '`' || c == '{' ||
316                                 c == '|' || c == '}' || c == '~' || c == '.':
317                                 localPartBytes = append(localPartBytes, in[0])
318                                 in = in[1:]
319
320                         default:
321                                 break NextChar
322                         }
323                 }
324
325                 if len(localPartBytes) == 0 {
326                         return mailbox, false
327                 }
328
329                 // From RFC 3696, Section 3:
330                 // “period (".") may also appear, but may not be used to start
331                 // or end the local part, nor may two or more consecutive
332                 // periods appear.”
333                 twoDots := []byte{'.', '.'}
334                 if localPartBytes[0] == '.' ||
335                         localPartBytes[len(localPartBytes)-1] == '.' ||
336                         bytes.Contains(localPartBytes, twoDots) {
337                         return mailbox, false
338                 }
339         }
340
341         if len(in) == 0 || in[0] != '@' {
342                 return mailbox, false
343         }
344         in = in[1:]
345
346         // The RFC species a format for domains, but that's known to be
347         // violated in practice so we accept that anything after an '@' is the
348         // domain part.
349         if _, ok := domainToReverseLabels(in); !ok {
350                 return mailbox, false
351         }
352
353         mailbox.local = string(localPartBytes)
354         mailbox.domain = in
355         return mailbox, true
356 }
357
358 // domainToReverseLabels converts a textual domain name like foo.example.com to
359 // the list of labels in reverse order, e.g. ["com", "example", "foo"].
360 func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
361         for len(domain) > 0 {
362                 if i := strings.LastIndexByte(domain, '.'); i == -1 {
363                         reverseLabels = append(reverseLabels, domain)
364                         domain = ""
365                 } else {
366                         reverseLabels = append(reverseLabels, domain[i+1:])
367                         domain = domain[:i]
368                 }
369         }
370
371         if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 {
372                 // An empty label at the end indicates an absolute value.
373                 return nil, false
374         }
375
376         for _, label := range reverseLabels {
377                 if len(label) == 0 {
378                         // Empty labels are otherwise invalid.
379                         return nil, false
380                 }
381
382                 for _, c := range label {
383                         if c < 33 || c > 126 {
384                                 // Invalid character.
385                                 return nil, false
386                         }
387                 }
388         }
389
390         return reverseLabels, true
391 }
392
393 func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) {
394         // If the constraint contains an @, then it specifies an exact mailbox
395         // name.
396         if strings.Contains(constraint, "@") {
397                 constraintMailbox, ok := parseRFC2821Mailbox(constraint)
398                 if !ok {
399                         return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint)
400                 }
401                 return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil
402         }
403
404         // Otherwise the constraint is like a DNS constraint of the domain part
405         // of the mailbox.
406         return matchDomainConstraint(mailbox.domain, constraint)
407 }
408
409 func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
410         // From RFC 5280, Section 4.2.1.10:
411         // “a uniformResourceIdentifier that does not include an authority
412         // component with a host name specified as a fully qualified domain
413         // name (e.g., if the URI either does not include an authority
414         // component or includes an authority component in which the host name
415         // is specified as an IP address), then the application MUST reject the
416         // certificate.”
417
418         host := uri.Host
419         if len(host) == 0 {
420                 return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String())
421         }
422
423         if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") {
424                 var err error
425                 host, _, err = net.SplitHostPort(uri.Host)
426                 if err != nil {
427                         return false, err
428                 }
429         }
430
431         if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") ||
432                 net.ParseIP(host) != nil {
433                 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
434         }
435
436         return matchDomainConstraint(host, constraint)
437 }
438
439 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
440         if len(ip) != len(constraint.IP) {
441                 return false, nil
442         }
443
444         for i := range ip {
445                 if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask {
446                         return false, nil
447                 }
448         }
449
450         return true, nil
451 }
452
453 func matchDomainConstraint(domain, constraint string) (bool, error) {
454         // The meaning of zero length constraints is not specified, but this
455         // code follows NSS and accepts them as matching everything.
456         if len(constraint) == 0 {
457                 return true, nil
458         }
459
460         domainLabels, ok := domainToReverseLabels(domain)
461         if !ok {
462                 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
463         }
464
465         // RFC 5280 says that a leading period in a domain name means that at
466         // least one label must be prepended, but only for URI and email
467         // constraints, not DNS constraints. The code also supports that
468         // behaviour for DNS constraints.
469
470         mustHaveSubdomains := false
471         if constraint[0] == '.' {
472                 mustHaveSubdomains = true
473                 constraint = constraint[1:]
474         }
475
476         constraintLabels, ok := domainToReverseLabels(constraint)
477         if !ok {
478                 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
479         }
480
481         if len(domainLabels) < len(constraintLabels) ||
482                 (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) {
483                 return false, nil
484         }
485
486         for i, constraintLabel := range constraintLabels {
487                 if !strings.EqualFold(constraintLabel, domainLabels[i]) {
488                         return false, nil
489                 }
490         }
491
492         return true, nil
493 }
494
495 // checkNameConstraints checks that c permits a child certificate to claim the
496 // given name, of type nameType. The argument parsedName contains the parsed
497 // form of name, suitable for passing to the match function. The total number
498 // of comparisons is tracked in the given count and should not exceed the given
499 // limit.
500 func (c *Certificate) checkNameConstraints(count *int,
501         maxConstraintComparisons int,
502         nameType string,
503         name string,
504         parsedName any,
505         match func(parsedName, constraint any) (match bool, err error),
506         permitted, excluded any) error {
507
508         excludedValue := reflect.ValueOf(excluded)
509
510         *count += excludedValue.Len()
511         if *count > maxConstraintComparisons {
512                 return CertificateInvalidError{c, TooManyConstraints, ""}
513         }
514
515         for i := 0; i < excludedValue.Len(); i++ {
516                 constraint := excludedValue.Index(i).Interface()
517                 match, err := match(parsedName, constraint)
518                 if err != nil {
519                         return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
520                 }
521
522                 if match {
523                         return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)}
524                 }
525         }
526
527         permittedValue := reflect.ValueOf(permitted)
528
529         *count += permittedValue.Len()
530         if *count > maxConstraintComparisons {
531                 return CertificateInvalidError{c, TooManyConstraints, ""}
532         }
533
534         ok := true
535         for i := 0; i < permittedValue.Len(); i++ {
536                 constraint := permittedValue.Index(i).Interface()
537
538                 var err error
539                 if ok, err = match(parsedName, constraint); err != nil {
540                         return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
541                 }
542
543                 if ok {
544                         break
545                 }
546         }
547
548         if !ok {
549                 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)}
550         }
551
552         return nil
553 }
554
555 // isValid performs validity checks on c given that it is a candidate to append
556 // to the chain in currentChain.
557 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
558         if len(c.UnhandledCriticalExtensions) > 0 {
559                 return UnhandledCriticalExtension{}
560         }
561
562         if len(currentChain) > 0 {
563                 child := currentChain[len(currentChain)-1]
564                 if !bytes.Equal(child.RawIssuer, c.RawSubject) {
565                         return CertificateInvalidError{c, NameMismatch, ""}
566                 }
567         }
568
569         now := opts.CurrentTime
570         if now.IsZero() {
571                 now = time.Now()
572         }
573         if now.Before(c.NotBefore) {
574                 return CertificateInvalidError{
575                         Cert:   c,
576                         Reason: Expired,
577                         Detail: fmt.Sprintf("current time %s is before %s", now.Format(time.RFC3339), c.NotBefore.Format(time.RFC3339)),
578                 }
579         } else if now.After(c.NotAfter) {
580                 return CertificateInvalidError{
581                         Cert:   c,
582                         Reason: Expired,
583                         Detail: fmt.Sprintf("current time %s is after %s", now.Format(time.RFC3339), c.NotAfter.Format(time.RFC3339)),
584                 }
585         }
586
587         maxConstraintComparisons := opts.MaxConstraintComparisions
588         if maxConstraintComparisons == 0 {
589                 maxConstraintComparisons = 250000
590         }
591         comparisonCount := 0
592
593         var leaf *Certificate
594         if certType == intermediateCertificate || certType == rootCertificate {
595                 if len(currentChain) == 0 {
596                         return errors.New("x509: internal error: empty chain when appending CA cert")
597                 }
598                 leaf = currentChain[0]
599         }
600
601         if (len(c.ExtKeyUsage) > 0 || len(c.UnknownExtKeyUsage) > 0) && len(opts.KeyUsages) > 0 {
602                 acceptableUsage := false
603                 um := make(map[ExtKeyUsage]bool, len(opts.KeyUsages))
604                 for _, u := range opts.KeyUsages {
605                         um[u] = true
606                 }
607                 if !um[ExtKeyUsageAny] {
608                         for _, u := range c.ExtKeyUsage {
609                                 if u == ExtKeyUsageAny || um[u] {
610                                         acceptableUsage = true
611                                         break
612                                 }
613                         }
614                         if !acceptableUsage {
615                                 return CertificateInvalidError{c, IncompatibleUsage, ""}
616                         }
617                 }
618         }
619
620         if (certType == intermediateCertificate || certType == rootCertificate) &&
621                 c.hasNameConstraints() {
622                 toCheck := []*Certificate{}
623                 if leaf.hasSANExtension() {
624                         toCheck = append(toCheck, leaf)
625                 }
626                 if c.hasSANExtension() {
627                         toCheck = append(toCheck, c)
628                 }
629                 for _, sanCert := range toCheck {
630                         err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error {
631                                 switch tag {
632                                 case nameTypeEmail:
633                                         name := string(data)
634                                         mailbox, ok := parseRFC2821Mailbox(name)
635                                         if !ok {
636                                                 return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
637                                         }
638
639                                         if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
640                                                 func(parsedName, constraint any) (bool, error) {
641                                                         return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
642                                                 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
643                                                 return err
644                                         }
645
646                                 case nameTypeDNS:
647                                         name := string(data)
648                                         if _, ok := domainToReverseLabels(name); !ok {
649                                                 return fmt.Errorf("x509: cannot parse dnsName %q", name)
650                                         }
651
652                                         if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
653                                                 func(parsedName, constraint any) (bool, error) {
654                                                         return matchDomainConstraint(parsedName.(string), constraint.(string))
655                                                 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
656                                                 return err
657                                         }
658
659                                 case nameTypeURI:
660                                         name := string(data)
661                                         uri, err := url.Parse(name)
662                                         if err != nil {
663                                                 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name)
664                                         }
665
666                                         if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
667                                                 func(parsedName, constraint any) (bool, error) {
668                                                         return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
669                                                 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
670                                                 return err
671                                         }
672
673                                 case nameTypeIP:
674                                         ip := net.IP(data)
675                                         if l := len(ip); l != net.IPv4len && l != net.IPv6len {
676                                                 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data)
677                                         }
678
679                                         if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
680                                                 func(parsedName, constraint any) (bool, error) {
681                                                         return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
682                                                 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
683                                                 return err
684                                         }
685
686                                 default:
687                                         // Unknown SAN types are ignored.
688                                 }
689
690                                 return nil
691                         })
692
693                         if err != nil {
694                                 return err
695                         }
696                 }
697         }
698
699         // KeyUsage status flags are ignored. From Engineering Security, Peter
700         // Gutmann: A European government CA marked its signing certificates as
701         // being valid for encryption only, but no-one noticed. Another
702         // European CA marked its signature keys as not being valid for
703         // signatures. A different CA marked its own trusted root certificate
704         // as being invalid for certificate signing. Another national CA
705         // distributed a certificate to be used to encrypt data for the
706         // country’s tax authority that was marked as only being usable for
707         // digital signatures but not for encryption. Yet another CA reversed
708         // the order of the bit flags in the keyUsage due to confusion over
709         // encoding endianness, essentially setting a random keyUsage in
710         // certificates that it issued. Another CA created a self-invalidating
711         // certificate by adding a certificate policy statement stipulating
712         // that the certificate had to be used strictly as specified in the
713         // keyUsage, and a keyUsage containing a flag indicating that the RSA
714         // encryption key could only be used for Diffie-Hellman key agreement.
715
716         if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
717                 return CertificateInvalidError{c, NotAuthorizedToSign, ""}
718         }
719
720         if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
721                 numIntermediates := len(currentChain) - 1
722                 if numIntermediates > c.MaxPathLen {
723                         return CertificateInvalidError{c, TooManyIntermediates, ""}
724                 }
725         }
726
727         return nil
728 }
729
730 // Verify attempts to verify c by building one or more chains from c to a
731 // certificate in opts.Roots, using certificates in opts.Intermediates if
732 // needed. If successful, it returns one or more chains where the first
733 // element of the chain is c and the last element is from opts.Roots.
734 //
735 // If opts.Roots is nil, the platform verifier might be used, and
736 // verification details might differ from what is described below. If system
737 // roots are unavailable the returned error will be of type SystemRootsError.
738 //
739 // Name constraints in the intermediates will be applied to all names claimed
740 // in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
741 // example.com if an intermediate doesn't permit it, even if example.com is not
742 // the name being validated. Note that DirectoryName constraints are not
743 // supported.
744 //
745 // Name constraint validation follows the rules from RFC 5280, with the
746 // addition that DNS name constraints may use the leading period format
747 // defined for emails and URIs. When a constraint has a leading period
748 // it indicates that at least one additional label must be prepended to
749 // the constrained name to be considered valid.
750 //
751 // Extended Key Usage values are enforced nested down a chain, so an intermediate
752 // or root that enumerates EKUs prevents a leaf from asserting an EKU not in that
753 // list. (While this is not specified, it is common practice in order to limit
754 // the types of certificates a CA can issue.)
755 //
756 // Certificates that use SHA1WithRSA and ECDSAWithSHA1 signatures are not supported,
757 // and will not be used to build chains.
758 //
759 // WARNING: this function doesn't do any revocation checking.
760 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
761         // Platform-specific verification needs the ASN.1 contents so
762         // this makes the behavior consistent across platforms.
763         if len(c.Raw) == 0 {
764                 return nil, errNotParsed
765         }
766         for i := 0; i < opts.Intermediates.len(); i++ {
767                 c, err := opts.Intermediates.cert(i)
768                 if err != nil {
769                         return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err)
770                 }
771                 if len(c.Raw) == 0 {
772                         return nil, errNotParsed
773                 }
774         }
775
776         // Use platform verifiers, where available, if Roots is from SystemCertPool.
777         if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
778                 if opts.Roots == nil {
779                         return c.systemVerify(&opts)
780                 }
781                 if opts.Roots != nil && opts.Roots.systemPool {
782                         platformChains, err := c.systemVerify(&opts)
783                         // If the platform verifier succeeded, or there are no additional
784                         // roots, return the platform verifier result. Otherwise, continue
785                         // with the Go verifier.
786                         if err == nil || opts.Roots.len() == 0 {
787                                 return platformChains, err
788                         }
789                 }
790         }
791
792         if opts.Roots == nil {
793                 opts.Roots = systemRootsPool()
794                 if opts.Roots == nil {
795                         return nil, SystemRootsError{systemRootsErr}
796                 }
797         }
798
799         if len(opts.KeyUsages) == 0 {
800                 opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
801         }
802
803         err = c.isValid(leafCertificate, nil, &opts)
804         if err != nil {
805                 return
806         }
807
808         if len(opts.DNSName) > 0 {
809                 err = c.VerifyHostname(opts.DNSName)
810                 if err != nil {
811                         return
812                 }
813         }
814
815         if opts.Roots.contains(c) {
816                 return [][]*Certificate{{c}}, nil
817         }
818         return c.buildChains([]*Certificate{c}, nil, &opts)
819 }
820
821 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
822         n := make([]*Certificate, len(chain)+1)
823         copy(n, chain)
824         n[len(chain)] = cert
825         return n
826 }
827
828 // maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
829 // that an invocation of buildChains will (transitively) make. Most chains are
830 // less than 15 certificates long, so this leaves space for multiple chains and
831 // for failed checks due to different intermediates having the same Subject.
832 const maxChainSignatureChecks = 100
833
834 func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
835         var (
836                 hintErr  error
837                 hintCert *Certificate
838         )
839
840         type pubKeyEqual interface {
841                 Equal(crypto.PublicKey) bool
842         }
843
844         considerCandidate := func(certType int, candidate *Certificate) {
845                 for _, cert := range currentChain {
846                         // If a certificate already appeared in the chain we've built, don't
847                         // reconsider it. This prevents loops, for isntance those created by
848                         // mutual cross-signatures, or other cross-signature bridges oddities.
849                         if bytes.Equal(cert.RawSubject, candidate.RawSubject) && cert.PublicKey.(pubKeyEqual).Equal(candidate.PublicKey) {
850                                 return
851                         }
852                 }
853
854                 if sigChecks == nil {
855                         sigChecks = new(int)
856                 }
857                 *sigChecks++
858                 if *sigChecks > maxChainSignatureChecks {
859                         err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
860                         return
861                 }
862
863                 if err := c.CheckSignatureFrom(candidate); err != nil {
864                         if hintErr == nil {
865                                 hintErr = err
866                                 hintCert = candidate
867                         }
868                         return
869                 }
870
871                 err = candidate.isValid(certType, currentChain, opts)
872                 if err != nil {
873                         return
874                 }
875
876                 switch certType {
877                 case rootCertificate:
878                         chains = append(chains, appendToFreshChain(currentChain, candidate))
879                 case intermediateCertificate:
880                         var childChains [][]*Certificate
881                         childChains, err = candidate.buildChains(appendToFreshChain(currentChain, candidate), sigChecks, opts)
882                         chains = append(chains, childChains...)
883                 }
884         }
885
886         for _, root := range opts.Roots.findPotentialParents(c) {
887                 considerCandidate(rootCertificate, root)
888         }
889         for _, intermediate := range opts.Intermediates.findPotentialParents(c) {
890                 considerCandidate(intermediateCertificate, intermediate)
891         }
892
893         if len(chains) > 0 {
894                 err = nil
895         }
896         if len(chains) == 0 && err == nil {
897                 err = UnknownAuthorityError{c, hintErr, hintCert}
898         }
899
900         return
901 }
902
903 func validHostnamePattern(host string) bool { return validHostname(host, true) }
904 func validHostnameInput(host string) bool   { return validHostname(host, false) }
905
906 // validHostname reports whether host is a valid hostname that can be matched or
907 // matched against according to RFC 6125 2.2, with some leniency to accommodate
908 // legacy values.
909 func validHostname(host string, isPattern bool) bool {
910         if !isPattern {
911                 host = strings.TrimSuffix(host, ".")
912         }
913         if len(host) == 0 {
914                 return false
915         }
916
917         for i, part := range strings.Split(host, ".") {
918                 if part == "" {
919                         // Empty label.
920                         return false
921                 }
922                 if isPattern && i == 0 && part == "*" {
923                         // Only allow full left-most wildcards, as those are the only ones
924                         // we match, and matching literal '*' characters is probably never
925                         // the expected behavior.
926                         continue
927                 }
928                 for j, c := range part {
929                         if 'a' <= c && c <= 'z' {
930                                 continue
931                         }
932                         if '0' <= c && c <= '9' {
933                                 continue
934                         }
935                         if 'A' <= c && c <= 'Z' {
936                                 continue
937                         }
938                         if c == '-' && j != 0 {
939                                 continue
940                         }
941                         if c == '_' {
942                                 // Not a valid character in hostnames, but commonly
943                                 // found in deployments outside the WebPKI.
944                                 continue
945                         }
946                         return false
947                 }
948         }
949
950         return true
951 }
952
953 func matchExactly(hostA, hostB string) bool {
954         if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
955                 return false
956         }
957         return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
958 }
959
960 func matchHostnames(pattern, host string) bool {
961         pattern = toLowerCaseASCII(pattern)
962         host = toLowerCaseASCII(strings.TrimSuffix(host, "."))
963
964         if len(pattern) == 0 || len(host) == 0 {
965                 return false
966         }
967
968         patternParts := strings.Split(pattern, ".")
969         hostParts := strings.Split(host, ".")
970
971         if len(patternParts) != len(hostParts) {
972                 return false
973         }
974
975         for i, patternPart := range patternParts {
976                 if i == 0 && patternPart == "*" {
977                         continue
978                 }
979                 if patternPart != hostParts[i] {
980                         return false
981                 }
982         }
983
984         return true
985 }
986
987 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
988 // an explicitly ASCII function to avoid any sharp corners resulting from
989 // performing Unicode operations on DNS labels.
990 func toLowerCaseASCII(in string) string {
991         // If the string is already lower-case then there's nothing to do.
992         isAlreadyLowerCase := true
993         for _, c := range in {
994                 if c == utf8.RuneError {
995                         // If we get a UTF-8 error then there might be
996                         // upper-case ASCII bytes in the invalid sequence.
997                         isAlreadyLowerCase = false
998                         break
999                 }
1000                 if 'A' <= c && c <= 'Z' {
1001                         isAlreadyLowerCase = false
1002                         break
1003                 }
1004         }
1005
1006         if isAlreadyLowerCase {
1007                 return in
1008         }
1009
1010         out := []byte(in)
1011         for i, c := range out {
1012                 if 'A' <= c && c <= 'Z' {
1013                         out[i] += 'a' - 'A'
1014                 }
1015         }
1016         return string(out)
1017 }
1018
1019 // VerifyHostname returns nil if c is a valid certificate for the named host.
1020 // Otherwise it returns an error describing the mismatch.
1021 //
1022 // IP addresses can be optionally enclosed in square brackets and are checked
1023 // against the IPAddresses field. Other names are checked case insensitively
1024 // against the DNSNames field. If the names are valid hostnames, the certificate
1025 // fields can have a wildcard as the left-most label.
1026 //
1027 // Note that the legacy Common Name field is ignored.
1028 func (c *Certificate) VerifyHostname(h string) error {
1029         // IP addresses may be written in [ ].
1030         candidateIP := h
1031         if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
1032                 candidateIP = h[1 : len(h)-1]
1033         }
1034         if ip := net.ParseIP(candidateIP); ip != nil {
1035                 // We only match IP addresses against IP SANs.
1036                 // See RFC 6125, Appendix B.2.
1037                 for _, candidate := range c.IPAddresses {
1038                         if ip.Equal(candidate) {
1039                                 return nil
1040                         }
1041                 }
1042                 return HostnameError{c, candidateIP}
1043         }
1044
1045         candidateName := toLowerCaseASCII(h) // Save allocations inside the loop.
1046         validCandidateName := validHostnameInput(candidateName)
1047
1048         for _, match := range c.DNSNames {
1049                 // Ideally, we'd only match valid hostnames according to RFC 6125 like
1050                 // browsers (more or less) do, but in practice Go is used in a wider
1051                 // array of contexts and can't even assume DNS resolution. Instead,
1052                 // always allow perfect matches, and only apply wildcard and trailing
1053                 // dot processing to valid hostnames.
1054                 if validCandidateName && validHostnamePattern(match) {
1055                         if matchHostnames(match, candidateName) {
1056                                 return nil
1057                         }
1058                 } else {
1059                         if matchExactly(match, candidateName) {
1060                                 return nil
1061                         }
1062                 }
1063         }
1064
1065         return HostnameError{c, h}
1066 }
1067
1068 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
1069         usages := make([]ExtKeyUsage, len(keyUsages))
1070         copy(usages, keyUsages)
1071
1072         if len(chain) == 0 {
1073                 return false
1074         }
1075
1076         usagesRemaining := len(usages)
1077
1078         // We walk down the list and cross out any usages that aren't supported
1079         // by each certificate. If we cross out all the usages, then the chain
1080         // is unacceptable.
1081
1082 NextCert:
1083         for i := len(chain) - 1; i >= 0; i-- {
1084                 cert := chain[i]
1085                 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
1086                         // The certificate doesn't have any extended key usage specified.
1087                         continue
1088                 }
1089
1090                 for _, usage := range cert.ExtKeyUsage {
1091                         if usage == ExtKeyUsageAny {
1092                                 // The certificate is explicitly good for any usage.
1093                                 continue NextCert
1094                         }
1095                 }
1096
1097                 const invalidUsage ExtKeyUsage = -1
1098
1099         NextRequestedUsage:
1100                 for i, requestedUsage := range usages {
1101                         if requestedUsage == invalidUsage {
1102                                 continue
1103                         }
1104
1105                         for _, usage := range cert.ExtKeyUsage {
1106                                 if requestedUsage == usage {
1107                                         continue NextRequestedUsage
1108                                 }
1109                         }
1110
1111                         usages[i] = invalidUsage
1112                         usagesRemaining--
1113                         if usagesRemaining == 0 {
1114                                 return false
1115                         }
1116                 }
1117         }
1118
1119         return true
1120 }