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 "crypto/x509/pkix"
11 "errors"
12 "fmt"
13 "iter"
14 "maps"
15 "net"
16 "net/netip"
17 "net/url"
18 19 "runtime"
20 "time"
21 "unicode/utf8"
22 )
23 24 type InvalidReason int
25 26 const (
27 // NotAuthorizedToSign results when a certificate is signed by another
28 // which isn't marked as a CA certificate.
29 NotAuthorizedToSign InvalidReason = iota
30 // Expired results when a certificate has expired, based on the time
31 // given in the VerifyOptions.
32 Expired
33 // CANotAuthorizedForThisName results when an intermediate or root
34 // certificate has a name constraint which doesn't permit a DNS or
35 // other name (including IP address) in the leaf certificate.
36 CANotAuthorizedForThisName
37 // TooManyIntermediates results when a path length constraint is
38 // violated.
39 TooManyIntermediates
40 // IncompatibleUsage results when the certificate's key usage indicates
41 // that it may only be used for a different purpose.
42 IncompatibleUsage
43 // NameMismatch results when the subject name of a parent certificate
44 // does not match the issuer name in the child.
45 NameMismatch
46 // NameConstraintsWithoutSANs is a legacy error and is no longer returned.
47 NameConstraintsWithoutSANs
48 // UnconstrainedName results when a CA certificate contains permitted
49 // name constraints, but leaf certificate contains a name of an
50 // unsupported or unconstrained type.
51 UnconstrainedName
52 // TooManyConstraints results when the number of comparison operations
53 // needed to check a certificate exceeds the limit set by
54 // VerifyOptions.MaxConstraintComparisions. This limit exists to
55 // prevent pathological certificates can consuming excessive amounts of
56 // CPU time to verify.
57 TooManyConstraints
58 // CANotAuthorizedForExtKeyUsage results when an intermediate or root
59 // certificate does not permit a requested extended key usage.
60 CANotAuthorizedForExtKeyUsage
61 // NoValidChains results when there are no valid chains to return.
62 NoValidChains
63 )
64 65 // CertificateInvalidError results when an odd error occurs. Users of this
66 // library probably want to handle all these errors uniformly.
67 type CertificateInvalidError struct {
68 Cert *Certificate
69 Reason InvalidReason
70 Detail string
71 }
72 73 func (e CertificateInvalidError) Error() string {
74 switch e.Reason {
75 case NotAuthorizedToSign:
76 return "x509: certificate is not authorized to sign other certificates"
77 case Expired:
78 return "x509: certificate has expired or is not yet valid: " | e.Detail
79 case CANotAuthorizedForThisName:
80 return "x509: a root or intermediate certificate is not authorized to sign for this name: " | e.Detail
81 case CANotAuthorizedForExtKeyUsage:
82 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " | e.Detail
83 case TooManyIntermediates:
84 return "x509: too many intermediates for path length constraint"
85 case IncompatibleUsage:
86 return "x509: certificate specifies an incompatible key usage"
87 case NameMismatch:
88 return "x509: issuer name does not match subject from issuing certificate"
89 case NameConstraintsWithoutSANs:
90 return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
91 case UnconstrainedName:
92 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " | e.Detail
93 case NoValidChains:
94 s := "x509: no valid chains built"
95 if e.Detail != "" {
96 s = fmt.Sprintf("%s: %s", s, e.Detail)
97 }
98 return s
99 }
100 return "x509: unknown error"
101 }
102 103 // HostnameError results when the set of authorized names doesn't match the
104 // requested name.
105 type HostnameError struct {
106 Certificate *Certificate
107 Host string
108 }
109 110 func (h HostnameError) Error() string {
111 c := h.Certificate
112 113 if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
114 return "x509: certificate relies on legacy Common Name field, use SANs instead"
115 }
116 117 var valid string
118 if ip := net.ParseIP(h.Host); ip != nil {
119 // Trying to validate an IP
120 if len(c.IPAddresses) == 0 {
121 return "x509: cannot validate certificate for " | h.Host | " because it doesn't contain any IP SANs"
122 }
123 for _, san := range c.IPAddresses {
124 if len(valid) > 0 {
125 valid |= ", "
126 }
127 valid += san.String()
128 }
129 } else {
130 valid = bytes.Join(c.DNSNames, ", ")
131 }
132 133 if len(valid) == 0 {
134 return "x509: certificate is not valid for any names, but wanted to match " | h.Host
135 }
136 return "x509: certificate is valid for " | valid | ", not " | h.Host
137 }
138 139 // UnknownAuthorityError results when the certificate issuer is unknown
140 type UnknownAuthorityError struct {
141 Cert *Certificate
142 // hintErr contains an error that may be helpful in determining why an
143 // authority wasn't found.
144 hintErr error
145 // hintCert contains a possible authority certificate that was rejected
146 // because of the error in hintErr.
147 hintCert *Certificate
148 }
149 150 func (e UnknownAuthorityError) Error() string {
151 s := "x509: certificate signed by unknown authority"
152 if e.hintErr != nil {
153 certName := e.hintCert.Subject.CommonName
154 if len(certName) == 0 {
155 if len(e.hintCert.Subject.Organization) > 0 {
156 certName = e.hintCert.Subject.Organization[0]
157 } else {
158 certName = "serial:" | e.hintCert.SerialNumber.String()
159 }
160 }
161 s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
162 }
163 return s
164 }
165 166 // SystemRootsError results when we fail to load the system root certificates.
167 type SystemRootsError struct {
168 Err error
169 }
170 171 func (se SystemRootsError) Error() string {
172 msg := "x509: failed to load system roots and no roots provided"
173 if se.Err != nil {
174 return msg | "; " | se.Err.Error()
175 }
176 return msg
177 }
178 179 func (se SystemRootsError) Unwrap() error { return se.Err }
180 181 // errNotParsed is returned when a certificate without ASN.1 contents is
182 // verified. Platform-specific verification needs the ASN.1 contents.
183 var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
184 185 // VerifyOptions contains parameters for Certificate.Verify.
186 type VerifyOptions struct {
187 // DNSName, if set, is checked against the leaf certificate with
188 // Certificate.VerifyHostname or the platform verifier.
189 DNSName string
190 191 // Intermediates is an optional pool of certificates that are not trust
192 // anchors, but can be used to form a chain from the leaf certificate to a
193 // root certificate.
194 Intermediates *CertPool
195 // Roots is the set of trusted root certificates the leaf certificate needs
196 // to chain up to. If nil, the system roots or the platform verifier are used.
197 Roots *CertPool
198 199 // CurrentTime is used to check the validity of all certificates in the
200 // chain. If zero, the current time is used.
201 CurrentTime time.Time
202 203 // KeyUsages specifies which Extended Key Usage values are acceptable. A
204 // chain is accepted if it allows any of the listed values. An empty list
205 // means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny.
206 KeyUsages []ExtKeyUsage
207 208 // MaxConstraintComparisions is the maximum number of comparisons to
209 // perform when checking a given certificate's name constraints. If
210 // zero, a sensible default is used. This limit prevents pathological
211 // certificates from consuming excessive amounts of CPU time when
212 // validating. It does not apply to the platform verifier.
213 MaxConstraintComparisions int
214 215 // CertificatePolicies specifies which certificate policy OIDs are
216 // acceptable during policy validation. An empty CertificatePolices
217 // field implies any valid policy is acceptable.
218 CertificatePolicies []OID
219 220 // The following policy fields are unexported, because we do not expect
221 // users to actually need to use them, but are useful for testing the
222 // policy validation code.
223 224 // inhibitPolicyMapping indicates if policy mapping should be allowed
225 // during path validation.
226 inhibitPolicyMapping bool
227 228 // requireExplicitPolicy indidicates if explicit policies must be present
229 // for each certificate being validated.
230 requireExplicitPolicy bool
231 232 // inhibitAnyPolicy indicates if the anyPolicy policy should be
233 // processed if present in a certificate being validated.
234 inhibitAnyPolicy bool
235 }
236 237 const (
238 leafCertificate = iota
239 intermediateCertificate
240 rootCertificate
241 )
242 243 // rfc2821Mailbox represents a “mailbox” (which is an email address to most
244 // people) by breaking it into the “local” (i.e. before the '@') and “domain”
245 // parts.
246 type rfc2821Mailbox struct {
247 local, domain string
248 }
249 250 // parseRFC2821Mailbox parses an email address into local and domain parts,
251 // based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280,
252 // Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The
253 // format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”.
254 func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
255 if len(in) == 0 {
256 return mailbox, false
257 }
258 259 localPartBytes := []byte{:0:len(in)/2}
260 261 if in[0] == '"' {
262 // Quoted-string = DQUOTE *qcontent DQUOTE
263 // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127
264 // qcontent = qtext / quoted-pair
265 // qtext = non-whitespace-control /
266 // %d33 / %d35-91 / %d93-126
267 // quoted-pair = ("\" text) / obs-qp
268 // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text
269 //
270 // (Names beginning with “obs-” are the obsolete syntax from RFC 2822,
271 // Section 4. Since it has been 16 years, we no longer accept that.)
272 in = in[1:]
273 QuotedString:
274 for {
275 if len(in) == 0 {
276 return mailbox, false
277 }
278 c := in[0]
279 in = in[1:]
280 281 switch {
282 case c == '"':
283 break QuotedString
284 285 case c == '\\':
286 // quoted-pair
287 if len(in) == 0 {
288 return mailbox, false
289 }
290 if in[0] == 11 ||
291 in[0] == 12 ||
292 (1 <= in[0] && in[0] <= 9) ||
293 (14 <= in[0] && in[0] <= 127) {
294 localPartBytes = append(localPartBytes, in[0])
295 in = in[1:]
296 } else {
297 return mailbox, false
298 }
299 300 case c == 11 ||
301 c == 12 ||
302 // Space (char 32) is not allowed based on the
303 // BNF, but RFC 3696 gives an example that
304 // assumes that it is. Several “verified”
305 // errata continue to argue about this point.
306 // We choose to accept it.
307 c == 32 ||
308 c == 33 ||
309 c == 127 ||
310 (1 <= c && c <= 8) ||
311 (14 <= c && c <= 31) ||
312 (35 <= c && c <= 91) ||
313 (93 <= c && c <= 126):
314 // qtext
315 localPartBytes = append(localPartBytes, c)
316 317 default:
318 return mailbox, false
319 }
320 }
321 } else {
322 // Atom ("." Atom)*
323 NextChar:
324 for len(in) > 0 {
325 // atext from RFC 2822, Section 3.2.4
326 c := in[0]
327 328 switch {
329 case c == '\\':
330 // Examples given in RFC 3696 suggest that
331 // escaped characters can appear outside of a
332 // quoted string. Several “verified” errata
333 // continue to argue the point. We choose to
334 // accept it.
335 in = in[1:]
336 if len(in) == 0 {
337 return mailbox, false
338 }
339 localPartBytes = append(localPartBytes, in[0])
340 in = in[1:]
341 342 case ('0' <= c && c <= '9') ||
343 ('a' <= c && c <= 'z') ||
344 ('A' <= c && c <= 'Z') ||
345 c == '!' || c == '#' || c == '$' || c == '%' ||
346 c == '&' || c == '\'' || c == '*' || c == '+' ||
347 c == '-' || c == '/' || c == '=' || c == '?' ||
348 c == '^' || c == '_' || c == '`' || c == '{' ||
349 c == '|' || c == '}' || c == '~' || c == '.':
350 localPartBytes = append(localPartBytes, in[0])
351 in = in[1:]
352 353 default:
354 break NextChar
355 }
356 }
357 358 if len(localPartBytes) == 0 {
359 return mailbox, false
360 }
361 362 // From RFC 3696, Section 3:
363 // “period (".") may also appear, but may not be used to start
364 // or end the local part, nor may two or more consecutive
365 // periods appear.”
366 twoDots := []byte{'.', '.'}
367 if localPartBytes[0] == '.' ||
368 localPartBytes[len(localPartBytes)-1] == '.' ||
369 bytes.Contains(localPartBytes, twoDots) {
370 return mailbox, false
371 }
372 }
373 374 if len(in) == 0 || in[0] != '@' {
375 return mailbox, false
376 }
377 in = in[1:]
378 379 // The RFC species a format for domains, but that's known to be
380 // violated in practice so we accept that anything after an '@' is the
381 // domain part.
382 if _, ok := domainToReverseLabels(in); !ok {
383 return mailbox, false
384 }
385 386 mailbox.local = string(localPartBytes)
387 mailbox.domain = in
388 return mailbox, true
389 }
390 391 // domainToReverseLabels converts a textual domain name like foo.example.com to
392 // the list of labels in reverse order, e.g. ["com", "example", "foo"].
393 func domainToReverseLabels(domain string) (reverseLabels [][]byte, ok bool) {
394 reverseLabels = [][]byte{:0:bytes.Count(domain, ".")+1}
395 for len(domain) > 0 {
396 if i := bytes.LastIndexByte(domain, '.'); i == -1 {
397 reverseLabels = append(reverseLabels, domain)
398 domain = ""
399 } else {
400 reverseLabels = append(reverseLabels, domain[i+1:])
401 domain = domain[:i]
402 if i == 0 { // domain == ""
403 // domain is prefixed with an empty label, append an empty
404 // string to reverseLabels to indicate this.
405 reverseLabels = append(reverseLabels, "")
406 }
407 }
408 }
409 410 if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 {
411 // An empty label at the end indicates an absolute value.
412 return nil, false
413 }
414 415 for _, label := range reverseLabels {
416 if len(label) == 0 {
417 // Empty labels are otherwise invalid.
418 return nil, false
419 }
420 421 for _, c := range label {
422 if c < 33 || c > 126 {
423 // Invalid character.
424 return nil, false
425 }
426 }
427 }
428 429 return reverseLabels, true
430 }
431 432 func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDomainsCache map[string][][]byte, reversedConstraintsCache map[string][][]byte) (bool, error) {
433 // If the constraint contains an @, then it specifies an exact mailbox
434 // name.
435 if bytes.Contains(constraint, "@") {
436 constraintMailbox, ok := parseRFC2821Mailbox(constraint)
437 if !ok {
438 return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint)
439 }
440 return mailbox.local == constraintMailbox.local && bytes.EqualFold(mailbox.domain, constraintMailbox.domain), nil
441 }
442 443 // Otherwise the constraint is like a DNS constraint of the domain part
444 // of the mailbox.
445 return matchDomainConstraint(mailbox.domain, constraint, reversedDomainsCache, reversedConstraintsCache)
446 }
447 448 func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache map[string][][]byte, reversedConstraintsCache map[string][][]byte) (bool, error) {
449 // From RFC 5280, Section 4.2.1.10:
450 // “a uniformResourceIdentifier that does not include an authority
451 // component with a host name specified as a fully qualified domain
452 // name (e.g., if the URI either does not include an authority
453 // component or includes an authority component in which the host name
454 // is specified as an IP address), then the application MUST reject the
455 // certificate.”
456 457 host := uri.Host
458 if len(host) == 0 {
459 return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String())
460 }
461 462 if bytes.Contains(host, ":") && !bytes.HasSuffix(host, "]") {
463 var err error
464 host, _, err = net.SplitHostPort(uri.Host)
465 if err != nil {
466 return false, err
467 }
468 }
469 470 // netip.ParseAddr will reject the URI IPv6 literal form "[...]", so we
471 // check if _either_ the string parses as an IP, or if it is enclosed in
472 // square brackets.
473 if _, err := netip.ParseAddr(host); err == nil || (bytes.HasPrefix(host, "[") && bytes.HasSuffix(host, "]")) {
474 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
475 }
476 477 return matchDomainConstraint(host, constraint, reversedDomainsCache, reversedConstraintsCache)
478 }
479 480 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
481 if len(ip) != len(constraint.IP) {
482 return false, nil
483 }
484 485 for i := range ip {
486 if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask {
487 return false, nil
488 }
489 }
490 491 return true, nil
492 }
493 494 func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[string][][]byte, reversedConstraintsCache map[string][][]byte) (bool, error) {
495 // The meaning of zero length constraints is not specified, but this
496 // code follows NSS and accepts them as matching everything.
497 if len(constraint) == 0 {
498 return true, nil
499 }
500 501 domainLabels, found := reversedDomainsCache[domain]
502 if !found {
503 var ok bool
504 domainLabels, ok = domainToReverseLabels(domain)
505 if !ok {
506 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
507 }
508 reversedDomainsCache[domain] = domainLabels
509 }
510 511 // RFC 5280 says that a leading period in a domain name means that at
512 // least one label must be prepended, but only for URI and email
513 // constraints, not DNS constraints. The code also supports that
514 // behaviour for DNS constraints.
515 516 mustHaveSubdomains := false
517 if constraint[0] == '.' {
518 mustHaveSubdomains = true
519 constraint = constraint[1:]
520 }
521 522 constraintLabels, found := reversedConstraintsCache[constraint]
523 if !found {
524 var ok bool
525 constraintLabels, ok = domainToReverseLabels(constraint)
526 if !ok {
527 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
528 }
529 reversedConstraintsCache[constraint] = constraintLabels
530 }
531 532 if len(domainLabels) < len(constraintLabels) ||
533 (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) {
534 return false, nil
535 }
536 537 for i, constraintLabel := range constraintLabels {
538 if !bytes.EqualFold(constraintLabel, domainLabels[i]) {
539 return false, nil
540 }
541 }
542 543 return true, nil
544 }
545 546 // checkNameConstraints checks that c permits a child certificate to claim the
547 // given name, of type nameType. The argument parsedName contains the parsed
548 // form of name, suitable for passing to the match function. The total number
549 // of comparisons is tracked in the given count and should not exceed the given
550 // limit.
551 // constraintSliceLen returns the length of a constraint slice ([]string or []*net.IPNet).
552 func constraintSliceLen(v any) int {
553 switch s := v.(type) {
554 case []string:
555 return len(s)
556 case []*net.IPNet:
557 return len(s)
558 }
559 return 0
560 }
561 562 // constraintSliceAt returns the i-th element of a constraint slice.
563 func constraintSliceAt(v any, i int) any {
564 switch s := v.(type) {
565 case []string:
566 return s[i]
567 case []*net.IPNet:
568 return s[i]
569 }
570 return nil
571 }
572 573 func (c *Certificate) checkNameConstraints(count *int,
574 maxConstraintComparisons int,
575 nameType string,
576 name string,
577 parsedName any,
578 match func(parsedName, constraint any) (match bool, err error),
579 permitted, excluded any) error {
580 581 excludedLen := constraintSliceLen(excluded)
582 583 *count += excludedLen
584 if *count > maxConstraintComparisons {
585 return CertificateInvalidError{c, TooManyConstraints, ""}
586 }
587 588 for i := 0; i < excludedLen; i++ {
589 constraint := constraintSliceAt(excluded, i)
590 match, err := match(parsedName, constraint)
591 if err != nil {
592 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
593 }
594 595 if match {
596 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)}
597 }
598 }
599 600 permittedLen := constraintSliceLen(permitted)
601 602 *count += permittedLen
603 if *count > maxConstraintComparisons {
604 return CertificateInvalidError{c, TooManyConstraints, ""}
605 }
606 607 ok := true
608 for i := 0; i < permittedLen; i++ {
609 constraint := constraintSliceAt(permitted, i)
610 611 var err error
612 if ok, err = match(parsedName, constraint); err != nil {
613 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
614 }
615 616 if ok {
617 break
618 }
619 }
620 621 if !ok {
622 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)}
623 }
624 625 return nil
626 }
627 628 // isValid performs validity checks on c given that it is a candidate to append
629 // to the chain in currentChain.
630 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
631 if len(c.UnhandledCriticalExtensions) > 0 {
632 return UnhandledCriticalExtension{}
633 }
634 635 if len(currentChain) > 0 {
636 child := currentChain[len(currentChain)-1]
637 if !bytes.Equal(child.RawIssuer, c.RawSubject) {
638 return CertificateInvalidError{c, NameMismatch, ""}
639 }
640 }
641 642 now := opts.CurrentTime
643 if now.IsZero() {
644 now = time.Now()
645 }
646 if now.Before(c.NotBefore) {
647 return CertificateInvalidError{
648 Cert: c,
649 Reason: Expired,
650 Detail: fmt.Sprintf("current time %s is before %s", now.Format(time.RFC3339), c.NotBefore.Format(time.RFC3339)),
651 }
652 } else if now.After(c.NotAfter) {
653 return CertificateInvalidError{
654 Cert: c,
655 Reason: Expired,
656 Detail: fmt.Sprintf("current time %s is after %s", now.Format(time.RFC3339), c.NotAfter.Format(time.RFC3339)),
657 }
658 }
659 660 maxConstraintComparisons := opts.MaxConstraintComparisions
661 if maxConstraintComparisons == 0 {
662 maxConstraintComparisons = 250000
663 }
664 comparisonCount := 0
665 666 if certType == intermediateCertificate || certType == rootCertificate {
667 if len(currentChain) == 0 {
668 return errors.New("x509: internal error: empty chain when appending CA cert")
669 }
670 }
671 672 // Each time we do constraint checking, we need to check the constraints in
673 // the current certificate against all of the names that preceded it. We
674 // reverse these names using domainToReverseLabels, which is a relatively
675 // expensive operation. Since we check each name against each constraint,
676 // this requires us to do N*C calls to domainToReverseLabels (where N is the
677 // total number of names that preceed the certificate, and C is the total
678 // number of constraints in the certificate). By caching the results of
679 // calling domainToReverseLabels, we can reduce that to N+C calls at the
680 // cost of keeping all of the parsed names and constraints in memory until
681 // we return from isValid.
682 reversedDomainsCache := map[string][][]byte{}
683 reversedConstraintsCache := map[string][][]byte{}
684 685 if (certType == intermediateCertificate || certType == rootCertificate) &&
686 c.hasNameConstraints() {
687 toCheck := []*Certificate{}
688 for _, c := range currentChain {
689 if c.hasSANExtension() {
690 toCheck = append(toCheck, c)
691 }
692 }
693 for _, sanCert := range toCheck {
694 err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error {
695 switch tag {
696 case nameTypeEmail:
697 name := string(data)
698 mailbox, ok := parseRFC2821Mailbox(name)
699 if !ok {
700 return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
701 }
702 703 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
704 func(parsedName, constraint any) (bool, error) {
705 return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
706 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
707 return err
708 }
709 710 case nameTypeDNS:
711 name := string(data)
712 if !domainNameValid(name, false) {
713 return fmt.Errorf("x509: cannot parse dnsName %q", name)
714 }
715 716 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
717 func(parsedName, constraint any) (bool, error) {
718 return matchDomainConstraint(parsedName.(string), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
719 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
720 return err
721 }
722 723 case nameTypeURI:
724 name := string(data)
725 uri, err := url.Parse(name)
726 if err != nil {
727 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name)
728 }
729 730 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
731 func(parsedName, constraint any) (bool, error) {
732 return matchURIConstraint(parsedName.(*url.URL), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
733 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
734 return err
735 }
736 737 case nameTypeIP:
738 ip := net.IP(data)
739 if l := len(ip); l != net.IPv4len && l != net.IPv6len {
740 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data)
741 }
742 743 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
744 func(parsedName, constraint any) (bool, error) {
745 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
746 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
747 return err
748 }
749 750 default:
751 // Unknown SAN types are ignored.
752 }
753 754 return nil
755 })
756 757 if err != nil {
758 return err
759 }
760 }
761 }
762 763 // KeyUsage status flags are ignored. From Engineering Security, Peter
764 // Gutmann: A European government CA marked its signing certificates as
765 // being valid for encryption only, but no-one noticed. Another
766 // European CA marked its signature keys as not being valid for
767 // signatures. A different CA marked its own trusted root certificate
768 // as being invalid for certificate signing. Another national CA
769 // distributed a certificate to be used to encrypt data for the
770 // country’s tax authority that was marked as only being usable for
771 // digital signatures but not for encryption. Yet another CA reversed
772 // the order of the bit flags in the keyUsage due to confusion over
773 // encoding endianness, essentially setting a random keyUsage in
774 // certificates that it issued. Another CA created a self-invalidating
775 // certificate by adding a certificate policy statement stipulating
776 // that the certificate had to be used strictly as specified in the
777 // keyUsage, and a keyUsage containing a flag indicating that the RSA
778 // encryption key could only be used for Diffie-Hellman key agreement.
779 780 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
781 return CertificateInvalidError{c, NotAuthorizedToSign, ""}
782 }
783 784 if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
785 numIntermediates := len(currentChain) - 1
786 if numIntermediates > c.MaxPathLen {
787 return CertificateInvalidError{c, TooManyIntermediates, ""}
788 }
789 }
790 791 return nil
792 }
793 794 // Verify attempts to verify c by building one or more chains from c to a
795 // certificate in opts.Roots, using certificates in opts.Intermediates if
796 // needed. If successful, it returns one or more chains where the first
797 // element of the chain is c and the last element is from opts.Roots.
798 //
799 // If opts.Roots is nil, the platform verifier might be used, and
800 // verification details might differ from what is described below. If system
801 // roots are unavailable the returned error will be of type SystemRootsError.
802 //
803 // Name constraints in the intermediates will be applied to all names claimed
804 // in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
805 // example.com if an intermediate doesn't permit it, even if example.com is not
806 // the name being validated. Note that DirectoryName constraints are not
807 // supported.
808 //
809 // Name constraint validation follows the rules from RFC 5280, with the
810 // addition that DNS name constraints may use the leading period format
811 // defined for emails and URIs. When a constraint has a leading period
812 // it indicates that at least one additional label must be prepended to
813 // the constrained name to be considered valid.
814 //
815 // Extended Key Usage values are enforced nested down a chain, so an intermediate
816 // or root that enumerates EKUs prevents a leaf from asserting an EKU not in that
817 // list. (While this is not specified, it is common practice in order to limit
818 // the types of certificates a CA can issue.)
819 //
820 // Certificates that use SHA1WithRSA and ECDSAWithSHA1 signatures are not supported,
821 // and will not be used to build chains.
822 //
823 // Certificates other than c in the returned chains should not be modified.
824 //
825 // WARNING: this function doesn't do any revocation checking.
826 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
827 // Platform-specific verification needs the ASN.1 contents so
828 // this makes the behavior consistent across platforms.
829 if len(c.Raw) == 0 {
830 return nil, errNotParsed
831 }
832 for i := 0; i < opts.Intermediates.len(); i++ {
833 c, _, err := opts.Intermediates.cert(i)
834 if err != nil {
835 return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err)
836 }
837 if len(c.Raw) == 0 {
838 return nil, errNotParsed
839 }
840 }
841 842 // Use platform verifiers, where available, if Roots is from SystemCertPool.
843 if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
844 // Don't use the system verifier if the system pool was replaced with a non-system pool,
845 // i.e. if SetFallbackRoots was called with x509usefallbackroots=1.
846 systemPool := systemRootsPool()
847 if opts.Roots == nil && (systemPool == nil || systemPool.systemPool) {
848 return c.systemVerify(&opts)
849 }
850 if opts.Roots != nil && opts.Roots.systemPool {
851 platformChains, err := c.systemVerify(&opts)
852 // If the platform verifier succeeded, or there are no additional
853 // roots, return the platform verifier result. Otherwise, continue
854 // with the Go verifier.
855 if err == nil || opts.Roots.len() == 0 {
856 return platformChains, err
857 }
858 }
859 }
860 861 if opts.Roots == nil {
862 opts.Roots = systemRootsPool()
863 if opts.Roots == nil {
864 return nil, SystemRootsError{systemRootsErr}
865 }
866 }
867 868 err = c.isValid(leafCertificate, nil, &opts)
869 if err != nil {
870 return
871 }
872 873 if len(opts.DNSName) > 0 {
874 err = c.VerifyHostname(opts.DNSName)
875 if err != nil {
876 return
877 }
878 }
879 880 var candidateChains [][]*Certificate
881 if opts.Roots.contains(c) {
882 candidateChains = [][]*Certificate{{c}}
883 } else {
884 candidateChains, err = c.buildChains([]*Certificate{c}, nil, &opts)
885 if err != nil {
886 return nil, err
887 }
888 }
889 890 chains = [][]*Certificate{:0:len(candidateChains)}
891 892 var invalidPoliciesChains int
893 for _, candidate := range candidateChains {
894 if !policiesValid(candidate, opts) {
895 invalidPoliciesChains++
896 continue
897 }
898 chains = append(chains, candidate)
899 }
900 901 if len(chains) == 0 {
902 return nil, CertificateInvalidError{c, NoValidChains, "all candidate chains have invalid policies"}
903 }
904 905 for _, eku := range opts.KeyUsages {
906 if eku == ExtKeyUsageAny {
907 // If any key usage is acceptable, no need to check the chain for
908 // key usages.
909 return chains, nil
910 }
911 }
912 913 if len(opts.KeyUsages) == 0 {
914 opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
915 }
916 917 candidateChains = chains
918 chains = chains[:0]
919 920 var incompatibleKeyUsageChains int
921 for _, candidate := range candidateChains {
922 if !checkChainForKeyUsage(candidate, opts.KeyUsages) {
923 incompatibleKeyUsageChains++
924 continue
925 }
926 chains = append(chains, candidate)
927 }
928 929 if len(chains) == 0 {
930 var details [][]byte
931 if incompatibleKeyUsageChains > 0 {
932 if invalidPoliciesChains == 0 {
933 return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
934 }
935 details = append(details, fmt.Sprintf("%d chains with incompatible key usage", incompatibleKeyUsageChains))
936 }
937 if invalidPoliciesChains > 0 {
938 details = append(details, fmt.Sprintf("%d chains with invalid policies", invalidPoliciesChains))
939 }
940 err = CertificateInvalidError{c, NoValidChains, bytes.Join(details, ", ")}
941 return nil, err
942 }
943 944 return chains, nil
945 }
946 947 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
948 n := []*Certificate{:len(chain)+1}
949 copy(n, chain)
950 n[len(chain)] = cert
951 return n
952 }
953 954 // alreadyInChain checks whether a candidate certificate is present in a chain.
955 // Rather than doing a direct byte for byte equivalency check, we check if the
956 // subject, public key, and SAN, if present, are equal. This prevents loops that
957 // are created by mutual cross-signatures, or other cross-signature bridge
958 // oddities.
959 func alreadyInChain(candidate *Certificate, chain []*Certificate) bool {
960 type pubKeyEqual interface {
961 Equal(crypto.PublicKey) bool
962 }
963 964 var candidateSAN *pkix.Extension
965 for _, ext := range candidate.Extensions {
966 if ext.Id.Equal(oidExtensionSubjectAltName) {
967 candidateSAN = &ext
968 break
969 }
970 }
971 972 for _, cert := range chain {
973 if !bytes.Equal(candidate.RawSubject, cert.RawSubject) {
974 continue
975 }
976 // We enforce the canonical encoding of SPKI (by only allowing the
977 // correct AI paremeter encodings in parseCertificate), so it's safe to
978 // directly compare the raw bytes.
979 if !bytes.Equal(candidate.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
980 continue
981 }
982 var certSAN *pkix.Extension
983 for _, ext := range cert.Extensions {
984 if ext.Id.Equal(oidExtensionSubjectAltName) {
985 certSAN = &ext
986 break
987 }
988 }
989 if candidateSAN == nil && certSAN == nil {
990 return true
991 } else if candidateSAN == nil || certSAN == nil {
992 return false
993 }
994 if bytes.Equal(candidateSAN.Value, certSAN.Value) {
995 return true
996 }
997 }
998 return false
999 }
1000 1001 // maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
1002 // that an invocation of buildChains will (transitively) make. Most chains are
1003 // less than 15 certificates long, so this leaves space for multiple chains and
1004 // for failed checks due to different intermediates having the same Subject.
1005 const maxChainSignatureChecks = 100
1006 1007 func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
1008 var (
1009 hintErr error
1010 hintCert *Certificate
1011 )
1012 1013 considerCandidate := func(certType int, candidate potentialParent) {
1014 if candidate.cert.PublicKey == nil || alreadyInChain(candidate.cert, currentChain) {
1015 return
1016 }
1017 1018 if sigChecks == nil {
1019 var _sigChecks int
1020 sigChecks = &_sigChecks
1021 }
1022 *sigChecks++
1023 if *sigChecks > maxChainSignatureChecks {
1024 err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
1025 return
1026 }
1027 1028 if err := c.CheckSignatureFrom(candidate.cert); err != nil {
1029 if hintErr == nil {
1030 hintErr = err
1031 hintCert = candidate.cert
1032 }
1033 return
1034 }
1035 1036 err = candidate.cert.isValid(certType, currentChain, opts)
1037 if err != nil {
1038 if hintErr == nil {
1039 hintErr = err
1040 hintCert = candidate.cert
1041 }
1042 return
1043 }
1044 1045 if candidate.constraint != nil {
1046 if err := candidate.constraint(currentChain); err != nil {
1047 if hintErr == nil {
1048 hintErr = err
1049 hintCert = candidate.cert
1050 }
1051 return
1052 }
1053 }
1054 1055 switch certType {
1056 case rootCertificate:
1057 chains = append(chains, appendToFreshChain(currentChain, candidate.cert))
1058 case intermediateCertificate:
1059 var childChains [][]*Certificate
1060 childChains, err = candidate.cert.buildChains(appendToFreshChain(currentChain, candidate.cert), sigChecks, opts)
1061 chains = append(chains, childChains...)
1062 }
1063 }
1064 1065 for _, root := range opts.Roots.findPotentialParents(c) {
1066 considerCandidate(rootCertificate, root)
1067 }
1068 for _, intermediate := range opts.Intermediates.findPotentialParents(c) {
1069 considerCandidate(intermediateCertificate, intermediate)
1070 }
1071 1072 if len(chains) > 0 {
1073 err = nil
1074 }
1075 if len(chains) == 0 && err == nil {
1076 err = UnknownAuthorityError{c, hintErr, hintCert}
1077 }
1078 1079 return
1080 }
1081 1082 func validHostnamePattern(host string) bool { return validHostname(host, true) }
1083 func validHostnameInput(host string) bool { return validHostname(host, false) }
1084 1085 // validHostname reports whether host is a valid hostname that can be matched or
1086 // matched against according to RFC 6125 2.2, with some leniency to accommodate
1087 // legacy values.
1088 func validHostname(host string, isPattern bool) bool {
1089 if !isPattern {
1090 host = bytes.TrimSuffix(host, ".")
1091 }
1092 if len(host) == 0 {
1093 return false
1094 }
1095 if host == "*" {
1096 // Bare wildcards are not allowed, they are not valid DNS names,
1097 // nor are they allowed per RFC 6125.
1098 return false
1099 }
1100 1101 for i, part := range bytes.Split(host, ".") {
1102 if part == "" {
1103 // Empty label.
1104 return false
1105 }
1106 if isPattern && i == 0 && part == "*" {
1107 // Only allow full left-most wildcards, as those are the only ones
1108 // we match, and matching literal '*' characters is probably never
1109 // the expected behavior.
1110 continue
1111 }
1112 for j, c := range part {
1113 if 'a' <= c && c <= 'z' {
1114 continue
1115 }
1116 if '0' <= c && c <= '9' {
1117 continue
1118 }
1119 if 'A' <= c && c <= 'Z' {
1120 continue
1121 }
1122 if c == '-' && j != 0 {
1123 continue
1124 }
1125 if c == '_' {
1126 // Not a valid character in hostnames, but commonly
1127 // found in deployments outside the WebPKI.
1128 continue
1129 }
1130 return false
1131 }
1132 }
1133 1134 return true
1135 }
1136 1137 func matchExactly(hostA, hostB string) bool {
1138 if hostA == "" || hostA == "." || hostB == "" || hostB == "." {
1139 return false
1140 }
1141 return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB)
1142 }
1143 1144 func matchHostnames(pattern, host string) bool {
1145 pattern = toLowerCaseASCII(pattern)
1146 host = toLowerCaseASCII(bytes.TrimSuffix(host, "."))
1147 1148 if len(pattern) == 0 || len(host) == 0 {
1149 return false
1150 }
1151 1152 patternParts := bytes.Split(pattern, ".")
1153 hostParts := bytes.Split(host, ".")
1154 1155 if len(patternParts) != len(hostParts) {
1156 return false
1157 }
1158 1159 for i, patternPart := range patternParts {
1160 if i == 0 && patternPart == "*" {
1161 continue
1162 }
1163 if patternPart != hostParts[i] {
1164 return false
1165 }
1166 }
1167 1168 return true
1169 }
1170 1171 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
1172 // an explicitly ASCII function to avoid any sharp corners resulting from
1173 // performing Unicode operations on DNS labels.
1174 func toLowerCaseASCII(in string) string {
1175 // If the string is already lower-case then there's nothing to do.
1176 isAlreadyLowerCase := true
1177 for _, c := range in {
1178 if c == utf8.RuneError {
1179 // If we get a UTF-8 error then there might be
1180 // upper-case ASCII bytes in the invalid sequence.
1181 isAlreadyLowerCase = false
1182 break
1183 }
1184 if 'A' <= c && c <= 'Z' {
1185 isAlreadyLowerCase = false
1186 break
1187 }
1188 }
1189 1190 if isAlreadyLowerCase {
1191 return in
1192 }
1193 1194 out := []byte(in)
1195 for i, c := range out {
1196 if 'A' <= c && c <= 'Z' {
1197 out[i] += 'a' - 'A'
1198 }
1199 }
1200 return string(out)
1201 }
1202 1203 // VerifyHostname returns nil if c is a valid certificate for the named host.
1204 // Otherwise it returns an error describing the mismatch.
1205 //
1206 // IP addresses can be optionally enclosed in square brackets and are checked
1207 // against the IPAddresses field. Other names are checked case insensitively
1208 // against the DNSNames field. If the names are valid hostnames, the certificate
1209 // fields can have a wildcard as the complete left-most label (e.g. *.example.com).
1210 //
1211 // Note that the legacy Common Name field is ignored.
1212 func (c *Certificate) VerifyHostname(h string) error {
1213 // IP addresses may be written in [ ].
1214 candidateIP := h
1215 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
1216 candidateIP = h[1 : len(h)-1]
1217 }
1218 if ip := net.ParseIP(candidateIP); ip != nil {
1219 // We only match IP addresses against IP SANs.
1220 // See RFC 6125, Appendix B.2.
1221 for _, candidate := range c.IPAddresses {
1222 if ip.Equal(candidate) {
1223 return nil
1224 }
1225 }
1226 return HostnameError{c, candidateIP}
1227 }
1228 1229 candidateName := toLowerCaseASCII(h) // Save allocations inside the loop.
1230 validCandidateName := validHostnameInput(candidateName)
1231 1232 for _, match := range c.DNSNames {
1233 // Ideally, we'd only match valid hostnames according to RFC 6125 like
1234 // browsers (more or less) do, but in practice Go is used in a wider
1235 // array of contexts and can't even assume DNS resolution. Instead,
1236 // always allow perfect matches, and only apply wildcard and trailing
1237 // dot processing to valid hostnames.
1238 if validCandidateName && validHostnamePattern(match) {
1239 if matchHostnames(match, candidateName) {
1240 return nil
1241 }
1242 } else {
1243 if matchExactly(match, candidateName) {
1244 return nil
1245 }
1246 }
1247 }
1248 1249 return HostnameError{c, h}
1250 }
1251 1252 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
1253 usages := []ExtKeyUsage{:len(keyUsages)}
1254 copy(usages, keyUsages)
1255 1256 if len(chain) == 0 {
1257 return false
1258 }
1259 1260 usagesRemaining := len(usages)
1261 1262 // We walk down the list and cross out any usages that aren't supported
1263 // by each certificate. If we cross out all the usages, then the chain
1264 // is unacceptable.
1265 1266 NextCert:
1267 for i := len(chain) - 1; i >= 0; i-- {
1268 cert := chain[i]
1269 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
1270 // The certificate doesn't have any extended key usage specified.
1271 continue
1272 }
1273 1274 for _, usage := range cert.ExtKeyUsage {
1275 if usage == ExtKeyUsageAny {
1276 // The certificate is explicitly good for any usage.
1277 continue NextCert
1278 }
1279 }
1280 1281 const invalidUsage ExtKeyUsage = -1
1282 1283 NextRequestedUsage:
1284 for i, requestedUsage := range usages {
1285 if requestedUsage == invalidUsage {
1286 continue
1287 }
1288 1289 for _, usage := range cert.ExtKeyUsage {
1290 if requestedUsage == usage {
1291 continue NextRequestedUsage
1292 }
1293 }
1294 1295 usages[i] = invalidUsage
1296 usagesRemaining--
1297 if usagesRemaining == 0 {
1298 return false
1299 }
1300 }
1301 }
1302 1303 return true
1304 }
1305 1306 func mustNewOIDFromInts(ints []uint64) OID {
1307 oid, err := OIDFromInts(ints)
1308 if err != nil {
1309 panic(fmt.Sprintf("OIDFromInts(%v) unexpected error: %v", ints, err))
1310 }
1311 return oid
1312 }
1313 1314 type policyGraphNode struct {
1315 validPolicy OID
1316 expectedPolicySet []OID
1317 // we do not implement qualifiers, so we don't track qualifier_set
1318 1319 parents map[*policyGraphNode]bool
1320 children map[*policyGraphNode]bool
1321 }
1322 1323 func newPolicyGraphNode(valid OID, parents []*policyGraphNode) *policyGraphNode {
1324 n := &policyGraphNode{
1325 validPolicy: valid,
1326 expectedPolicySet: []OID{valid},
1327 children: map[*policyGraphNode]bool{},
1328 parents: map[*policyGraphNode]bool{},
1329 }
1330 for _, p := range parents {
1331 p.children[n] = true
1332 n.parents[p] = true
1333 }
1334 return n
1335 }
1336 1337 type policyGraph struct {
1338 strata []map[string]*policyGraphNode
1339 // map of OID -> nodes at strata[depth-1] with OID in their expectedPolicySet
1340 parentIndex map[string][]*policyGraphNode
1341 depth int
1342 }
1343 1344 var anyPolicyOID = mustNewOIDFromInts([]uint64{2, 5, 29, 32, 0})
1345 1346 func newPolicyGraph() *policyGraph {
1347 root := policyGraphNode{
1348 validPolicy: anyPolicyOID,
1349 expectedPolicySet: []OID{anyPolicyOID},
1350 children: map[*policyGraphNode]bool{},
1351 parents: map[*policyGraphNode]bool{},
1352 }
1353 return &policyGraph{
1354 depth: 0,
1355 strata: []map[string]*policyGraphNode{{string(anyPolicyOID.der): &root}},
1356 }
1357 }
1358 1359 func (pg *policyGraph) insert(n *policyGraphNode) {
1360 pg.strata[pg.depth][string(n.validPolicy.der)] = n
1361 }
1362 1363 func (pg *policyGraph) parentsWithExpected(expected OID) []*policyGraphNode {
1364 if pg.depth == 0 {
1365 return nil
1366 }
1367 return pg.parentIndex[string(expected.der)]
1368 }
1369 1370 func (pg *policyGraph) parentWithAnyPolicy() *policyGraphNode {
1371 if pg.depth == 0 {
1372 return nil
1373 }
1374 return pg.strata[pg.depth-1][string(anyPolicyOID.der)]
1375 }
1376 1377 func (pg *policyGraph) parents() iter.Seq[*policyGraphNode] {
1378 if pg.depth == 0 {
1379 return nil
1380 }
1381 return maps.Values(pg.strata[pg.depth-1])
1382 }
1383 1384 func (pg *policyGraph) leaves() map[string]*policyGraphNode {
1385 return pg.strata[pg.depth]
1386 }
1387 1388 func (pg *policyGraph) leafWithPolicy(policy OID) *policyGraphNode {
1389 return pg.strata[pg.depth][string(policy.der)]
1390 }
1391 1392 func (pg *policyGraph) deleteLeaf(policy OID) {
1393 n := pg.strata[pg.depth][string(policy.der)]
1394 if n == nil {
1395 return
1396 }
1397 for p := range n.parents {
1398 delete(p.children, n)
1399 }
1400 for c := range n.children {
1401 delete(c.parents, n)
1402 }
1403 delete(pg.strata[pg.depth], string(policy.der))
1404 }
1405 1406 func (pg *policyGraph) validPolicyNodes() []*policyGraphNode {
1407 var validNodes []*policyGraphNode
1408 for i := pg.depth; i >= 0; i-- {
1409 for _, n := range pg.strata[i] {
1410 if n.validPolicy.Equal(anyPolicyOID) {
1411 continue
1412 }
1413 1414 if len(n.parents) == 1 {
1415 for p := range n.parents {
1416 if p.validPolicy.Equal(anyPolicyOID) {
1417 validNodes = append(validNodes, n)
1418 }
1419 }
1420 }
1421 }
1422 }
1423 return validNodes
1424 }
1425 1426 func (pg *policyGraph) prune() {
1427 for i := pg.depth - 1; i > 0; i-- {
1428 for _, n := range pg.strata[i] {
1429 if len(n.children) == 0 {
1430 for p := range n.parents {
1431 delete(p.children, n)
1432 }
1433 delete(pg.strata[i], string(n.validPolicy.der))
1434 }
1435 }
1436 }
1437 }
1438 1439 func (pg *policyGraph) incrDepth() {
1440 pg.parentIndex = map[string][]*policyGraphNode{}
1441 for _, n := range pg.strata[pg.depth] {
1442 for _, e := range n.expectedPolicySet {
1443 pg.parentIndex[string(e.der)] = append(pg.parentIndex[string(e.der)], n)
1444 }
1445 }
1446 1447 pg.depth++
1448 pg.strata = append(pg.strata, map[string]*policyGraphNode{})
1449 }
1450 1451 func policiesValid(chain []*Certificate, opts VerifyOptions) bool {
1452 // The following code implements the policy verification algorithm as
1453 // specified in RFC 5280 and updated by RFC 9618. In particular the
1454 // following sections are replaced by RFC 9618:
1455 // * 6.1.2 (a)
1456 // * 6.1.3 (d)
1457 // * 6.1.3 (e)
1458 // * 6.1.3 (f)
1459 // * 6.1.4 (b)
1460 // * 6.1.5 (g)
1461 1462 if len(chain) == 1 {
1463 return true
1464 }
1465 1466 // n is the length of the chain minus the trust anchor
1467 n := len(chain) - 1
1468 1469 pg := newPolicyGraph()
1470 var inhibitAnyPolicy, explicitPolicy, policyMapping int
1471 if !opts.inhibitAnyPolicy {
1472 inhibitAnyPolicy = n + 1
1473 }
1474 if !opts.requireExplicitPolicy {
1475 explicitPolicy = n + 1
1476 }
1477 if !opts.inhibitPolicyMapping {
1478 policyMapping = n + 1
1479 }
1480 1481 initialUserPolicySet := map[string]bool{}
1482 for _, p := range opts.CertificatePolicies {
1483 initialUserPolicySet[string(p.der)] = true
1484 }
1485 // If the user does not pass any policies, we consider
1486 // that equivalent to passing anyPolicyOID.
1487 if len(initialUserPolicySet) == 0 {
1488 initialUserPolicySet[string(anyPolicyOID.der)] = true
1489 }
1490 1491 for i := n - 1; i >= 0; i-- {
1492 cert := chain[i]
1493 1494 isSelfSigned := bytes.Equal(cert.RawIssuer, cert.RawSubject)
1495 1496 // 6.1.3 (e) -- as updated by RFC 9618
1497 if len(cert.Policies) == 0 {
1498 pg = nil
1499 }
1500 1501 // 6.1.3 (f) -- as updated by RFC 9618
1502 if explicitPolicy == 0 && pg == nil {
1503 return false
1504 }
1505 1506 if pg != nil {
1507 pg.incrDepth()
1508 1509 policies := map[string]bool{}
1510 1511 // 6.1.3 (d) (1) -- as updated by RFC 9618
1512 for _, policy := range cert.Policies {
1513 policies[string(policy.der)] = true
1514 1515 if policy.Equal(anyPolicyOID) {
1516 continue
1517 }
1518 1519 // 6.1.3 (d) (1) (i) -- as updated by RFC 9618
1520 parents := pg.parentsWithExpected(policy)
1521 if len(parents) == 0 {
1522 // 6.1.3 (d) (1) (ii) -- as updated by RFC 9618
1523 if anyParent := pg.parentWithAnyPolicy(); anyParent != nil {
1524 parents = []*policyGraphNode{anyParent}
1525 }
1526 }
1527 if len(parents) > 0 {
1528 pg.insert(newPolicyGraphNode(policy, parents))
1529 }
1530 }
1531 1532 // 6.1.3 (d) (2) -- as updated by RFC 9618
1533 // NOTE: in the check "n-i < n" our i is different from the i in the specification.
1534 // In the specification chains go from the trust anchor to the leaf, whereas our
1535 // chains go from the leaf to the trust anchor, so our i's our inverted. Our
1536 // check here matches the check "i < n" in the specification.
1537 if policies[string(anyPolicyOID.der)] && (inhibitAnyPolicy > 0 || (n-i < n && isSelfSigned)) {
1538 missing := map[string][]*policyGraphNode{}
1539 leaves := pg.leaves()
1540 for p := range pg.parents() {
1541 for _, expected := range p.expectedPolicySet {
1542 if leaves[string(expected.der)] == nil {
1543 missing[string(expected.der)] = append(missing[string(expected.der)], p)
1544 }
1545 }
1546 }
1547 1548 for oidStr, parents := range missing {
1549 pg.insert(newPolicyGraphNode(OID{der: []byte(oidStr)}, parents))
1550 }
1551 }
1552 1553 // 6.1.3 (d) (3) -- as updated by RFC 9618
1554 pg.prune()
1555 1556 if i != 0 {
1557 // 6.1.4 (b) -- as updated by RFC 9618
1558 if len(cert.PolicyMappings) > 0 {
1559 // collect map of issuer -> []subject
1560 mappings := map[string][]OID{}
1561 1562 for _, mapping := range cert.PolicyMappings {
1563 if policyMapping > 0 {
1564 if mapping.IssuerDomainPolicy.Equal(anyPolicyOID) || mapping.SubjectDomainPolicy.Equal(anyPolicyOID) {
1565 // Invalid mapping
1566 return false
1567 }
1568 mappings[string(mapping.IssuerDomainPolicy.der)] = append(mappings[string(mapping.IssuerDomainPolicy.der)], mapping.SubjectDomainPolicy)
1569 } else {
1570 // 6.1.4 (b) (3) (i) -- as updated by RFC 9618
1571 pg.deleteLeaf(mapping.IssuerDomainPolicy)
1572 1573 // 6.1.4 (b) (3) (ii) -- as updated by RFC 9618
1574 pg.prune()
1575 }
1576 }
1577 1578 for issuerStr, subjectPolicies := range mappings {
1579 // 6.1.4 (b) (1) -- as updated by RFC 9618
1580 if matching := pg.leafWithPolicy(OID{der: []byte(issuerStr)}); matching != nil {
1581 matching.expectedPolicySet = subjectPolicies
1582 } else if matching := pg.leafWithPolicy(anyPolicyOID); matching != nil {
1583 // 6.1.4 (b) (2) -- as updated by RFC 9618
1584 n := newPolicyGraphNode(OID{der: []byte(issuerStr)}, []*policyGraphNode{matching})
1585 n.expectedPolicySet = subjectPolicies
1586 pg.insert(n)
1587 }
1588 }
1589 }
1590 }
1591 }
1592 1593 if i != 0 {
1594 // 6.1.4 (h)
1595 if !isSelfSigned {
1596 if explicitPolicy > 0 {
1597 explicitPolicy--
1598 }
1599 if policyMapping > 0 {
1600 policyMapping--
1601 }
1602 if inhibitAnyPolicy > 0 {
1603 inhibitAnyPolicy--
1604 }
1605 }
1606 1607 // 6.1.4 (i)
1608 if (cert.RequireExplicitPolicy > 0 || cert.RequireExplicitPolicyZero) && cert.RequireExplicitPolicy < explicitPolicy {
1609 explicitPolicy = cert.RequireExplicitPolicy
1610 }
1611 if (cert.InhibitPolicyMapping > 0 || cert.InhibitPolicyMappingZero) && cert.InhibitPolicyMapping < policyMapping {
1612 policyMapping = cert.InhibitPolicyMapping
1613 }
1614 // 6.1.4 (j)
1615 if (cert.InhibitAnyPolicy > 0 || cert.InhibitAnyPolicyZero) && cert.InhibitAnyPolicy < inhibitAnyPolicy {
1616 inhibitAnyPolicy = cert.InhibitAnyPolicy
1617 }
1618 }
1619 }
1620 1621 // 6.1.5 (a)
1622 if explicitPolicy > 0 {
1623 explicitPolicy--
1624 }
1625 1626 // 6.1.5 (b)
1627 if chain[0].RequireExplicitPolicyZero {
1628 explicitPolicy = 0
1629 }
1630 1631 // 6.1.5 (g) (1) -- as updated by RFC 9618
1632 var validPolicyNodeSet []*policyGraphNode
1633 // 6.1.5 (g) (2) -- as updated by RFC 9618
1634 if pg != nil {
1635 validPolicyNodeSet = pg.validPolicyNodes()
1636 // 6.1.5 (g) (3) -- as updated by RFC 9618
1637 if currentAny := pg.leafWithPolicy(anyPolicyOID); currentAny != nil {
1638 validPolicyNodeSet = append(validPolicyNodeSet, currentAny)
1639 }
1640 }
1641 1642 // 6.1.5 (g) (4) -- as updated by RFC 9618
1643 authorityConstrainedPolicySet := map[string]bool{}
1644 for _, n := range validPolicyNodeSet {
1645 authorityConstrainedPolicySet[string(n.validPolicy.der)] = true
1646 }
1647 // 6.1.5 (g) (5) -- as updated by RFC 9618
1648 userConstrainedPolicySet := maps.Clone(authorityConstrainedPolicySet)
1649 // 6.1.5 (g) (6) -- as updated by RFC 9618
1650 if len(initialUserPolicySet) != 1 || !initialUserPolicySet[string(anyPolicyOID.der)] {
1651 // 6.1.5 (g) (6) (i) -- as updated by RFC 9618
1652 for p := range userConstrainedPolicySet {
1653 if !initialUserPolicySet[p] {
1654 delete(userConstrainedPolicySet, p)
1655 }
1656 }
1657 // 6.1.5 (g) (6) (ii) -- as updated by RFC 9618
1658 if authorityConstrainedPolicySet[string(anyPolicyOID.der)] {
1659 for policy := range initialUserPolicySet {
1660 userConstrainedPolicySet[policy] = true
1661 }
1662 }
1663 }
1664 1665 if explicitPolicy == 0 && len(userConstrainedPolicySet) == 0 {
1666 return false
1667 }
1668 1669 return true
1670 }
1671