diff options
| author | Michael Stapelberg <stapelberg@golang.org> | 2025-07-10 10:58:35 +0200 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2025-09-11 08:14:50 -0700 |
| commit | 96dc232fbd7928e9c23da42e770c8b79a2348d86 (patch) | |
| tree | eaeda4be0b841c6e7e04eb09b34ad7816c4b39dd /x509roots/fallback | |
| parent | 8c9ba318361080ea198c7461b6db621022d0a88e (diff) | |
| download | go-x-crypto-96dc232fbd7928e9c23da42e770c8b79a2348d86.tar.xz | |
x509roots/fallback/bundle: add bundle package to export root certs
Fixes golang/go#69898
Change-Id: Idbb1bbe48016a622414c84a56fe26f48bfe712c8
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/687155
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Roland Shoemaker <roland@golang.org>
Reviewed-by: Mateusz Poliwczak <mpoliwczak34@gmail.com>
Diffstat (limited to 'x509roots/fallback')
| -rw-r--r-- | x509roots/fallback/bundle/bundle.der (renamed from x509roots/fallback/bundle.der) | bin | 154797 -> 154797 bytes | |||
| -rw-r--r-- | x509roots/fallback/bundle/bundle.go (renamed from x509roots/fallback/bundle.go) | 2 | ||||
| -rw-r--r-- | x509roots/fallback/bundle/bundle_test.go (renamed from x509roots/fallback/bundle_test.go) | 2 | ||||
| -rw-r--r-- | x509roots/fallback/bundle/roots.go | 73 | ||||
| -rw-r--r-- | x509roots/fallback/bundle/roots_test.go | 18 | ||||
| -rw-r--r-- | x509roots/fallback/fallback.go | 68 |
6 files changed, 102 insertions, 61 deletions
diff --git a/x509roots/fallback/bundle.der b/x509roots/fallback/bundle/bundle.der Binary files differindex 1abf12f..1abf12f 100644 --- a/x509roots/fallback/bundle.der +++ b/x509roots/fallback/bundle/bundle.der diff --git a/x509roots/fallback/bundle.go b/x509roots/fallback/bundle/bundle.go index ee99a40..be9e857 100644 --- a/x509roots/fallback/bundle.go +++ b/x509roots/fallback/bundle/bundle.go @@ -1,6 +1,6 @@ // Code generated by gen_fallback_bundle.go; DO NOT EDIT. -package fallback +package bundle var unparsedCertificates = []unparsedCertificate{ { diff --git a/x509roots/fallback/bundle_test.go b/x509roots/fallback/bundle/bundle_test.go index a8922cc..3eafe15 100644 --- a/x509roots/fallback/bundle_test.go +++ b/x509roots/fallback/bundle/bundle_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package fallback +package bundle import ( "crypto/sha256" diff --git a/x509roots/fallback/bundle/roots.go b/x509roots/fallback/bundle/roots.go new file mode 100644 index 0000000..38a1b3d --- /dev/null +++ b/x509roots/fallback/bundle/roots.go @@ -0,0 +1,73 @@ +// 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 +} diff --git a/x509roots/fallback/bundle/roots_test.go b/x509roots/fallback/bundle/roots_test.go new file mode 100644 index 0000000..04ba9db --- /dev/null +++ b/x509roots/fallback/bundle/roots_test.go @@ -0,0 +1,18 @@ +// 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 + +import ( + "crypto/x509" + "testing" +) + +func TestRootsCanBeParsed(t *testing.T) { + for root := range Roots() { + if _, err := x509.ParseCertificate(root.Certificate); err != nil { + t.Fatalf("Could not parse root certificate: %v", err) + } + } +} diff --git a/x509roots/fallback/fallback.go b/x509roots/fallback/fallback.go index a0dad33..79e1870 100644 --- a/x509roots/fallback/fallback.go +++ b/x509roots/fallback/fallback.go @@ -20,13 +20,9 @@ package fallback import ( "crypto/x509" - _ "embed" - "fmt" - "time" -) -//go:embed bundle.der -var rawCerts []byte + "golang.org/x/crypto/x509roots/fallback/bundle" +) func init() { x509.SetFallbackRoots(newFallbackCertPool()) @@ -34,62 +30,16 @@ func init() { func newFallbackCertPool() *x509.CertPool { p := x509.NewCertPool() - for _, c := range mustParse(unparsedCertificates) { - if len(c.constraints) == 0 { - p.AddCert(c.cert) - } else { - p.AddCertWithConstraint(c.cert, func(chain []*x509.Certificate) error { - for _, constraint := range c.constraints { - if err := constraint(chain); err != nil { - return err - } - } - return nil - }) - } - } - return p -} - -type unparsedCertificate struct { - cn string - sha256Hash string - certStartOff int - certLength int - - // possible constraints - distrustAfter string -} - -type parsedCertificate struct { - cert *x509.Certificate - constraints []func([]*x509.Certificate) error -} - -func mustParse(unparsedCerts []unparsedCertificate) []parsedCertificate { - b := make([]parsedCertificate, 0, len(unparsedCerts)) - for _, unparsed := range unparsedCerts { - cert, err := x509.ParseCertificate(rawCerts[unparsed.certStartOff : unparsed.certStartOff+unparsed.certLength]) + for c := range bundle.Roots() { + cert, err := x509.ParseCertificate(c.Certificate) if err != nil { panic(err) } - parsed := parsedCertificate{cert: cert} - // 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)) - } - parsed.constraints = append(parsed.constraints, 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 c.Constraint == nil { + p.AddCert(cert) + } else { + p.AddCertWithConstraint(cert, c.Constraint) } - b = append(b, parsed) } - return b + return p } |
