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>
This commit is contained in:
Michael Stapelberg
2025-09-11 08:14:50 -07:00
committed by Gopher Robot
parent 8c9ba31836
commit 96dc232fbd
7 changed files with 106 additions and 65 deletions
+10 -60
View File
@@ -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)
for c := range bundle.Roots() {
cert, err := x509.ParseCertificate(c.Certificate)
if err != nil {
panic(err)
}
if c.Constraint == nil {
p.AddCert(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
})
p.AddCertWithConstraint(cert, c.Constraint)
}
}
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])
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
})
}
b = append(b, parsed)
}
return b
}