// Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package bundle contains the bundle of root certificates parsed from the NSS // trust store, using x509roots/nss. package bundle import ( "crypto/x509" _ "embed" "fmt" "iter" "time" ) //go:embed bundle.der var rawCerts []byte // Root represents a root certificate parsed from the NSS trust store. type Root struct { // Certificate is the DER-encoded certificate (read-only; do not modify!). Certificate []byte // Constraint is nil if the root is unconstrained. If Constraint is non-nil, // the certificate has additional constraints that cannot be encoded in // X.509, and when building a certificate chain anchored with this root the // chain should be passed to this function to check its validity. If using a // [crypto/x509.CertPool] the root should be added using // [crypto/x509.CertPool.AddCertWithConstraint]. Constraint func([]*x509.Certificate) error } // Roots returns the bundle of root certificates from the NSS trust store. The // [Root.Certificate] slice must be treated as read-only and should not be // modified. func Roots() iter.Seq[Root] { return func(yield func(Root) bool) { for _, unparsed := range unparsedCertificates { root := Root{ Certificate: rawCerts[unparsed.certStartOff : unparsed.certStartOff+unparsed.certLength], } // parse possible constraints, this should check all fields of unparsedCertificate. if unparsed.distrustAfter != "" { distrustAfter, err := time.Parse(time.RFC3339, unparsed.distrustAfter) if err != nil { panic(fmt.Sprintf("failed to parse distrustAfter %q: %s", unparsed.distrustAfter, err)) } root.Constraint = func(chain []*x509.Certificate) error { for _, c := range chain { if c.NotBefore.After(distrustAfter) { return fmt.Errorf("certificate issued after distrust-after date %q", distrustAfter) } } return nil } } if !yield(root) { return } } } } type unparsedCertificate struct { cn string sha256Hash string certStartOff int certLength int // possible constraints distrustAfter string }