crypto/x509: add support for CertPool to load certs lazily

(from patchset 1, 7cdc3c3e7427c9ef69e19224d6036c09c5ea1723, of
https://go-review.googlesource.com/c/go/+/229917/1)

This will allow building CertPools that consume less memory. (Most
certs are never accessed. Different users/programs access different
ones, but not many.)

This CL only adds the new internal mechanism (and uses it for the
old AddCert) but does not modify any existing root pool behavior.
(That is, the default Unix roots are still all slurped into memory as
of this CL)

Change-Id: Ib3a42e4050627b5e34413c595d8ced839c7bfa14
This commit is contained in:
Brad Fitzpatrick
2020-04-24 21:13:43 -07:00
parent 6b232b5a79
commit f5993f2440
6 changed files with 136 additions and 43 deletions
+20 -8
View File
@@ -737,11 +737,13 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
if len(c.Raw) == 0 {
return nil, errNotParsed
}
if opts.Intermediates != nil {
for _, intermediate := range opts.Intermediates.certs {
if len(intermediate.Raw) == 0 {
return nil, errNotParsed
}
for i := 0; i < opts.Intermediates.len(); i++ {
c, err := opts.Intermediates.cert(i)
if err != nil {
return nil, fmt.Errorf("crypto/x509: error fetching cert: %w", err)
}
if len(c.Raw) == 0 {
return nil, errNotParsed
}
}
@@ -770,8 +772,10 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
}
var candidateChains [][]*Certificate
if opts.Roots.contains(c) {
if inRoots, err := opts.Roots.contains(c); inRoots {
candidateChains = append(candidateChains, []*Certificate{c})
} else if err != nil {
return nil, err
} else {
if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil {
return nil, err
@@ -868,10 +872,18 @@ func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, curre
}
for _, rootNum := range opts.Roots.findPotentialParents(c) {
considerCandidate(rootCertificate, opts.Roots.certs[rootNum])
c, err := opts.Roots.cert(rootNum)
if err != nil {
return nil, fmt.Errorf("crypto/x509: error fetching cert: %w", err)
}
considerCandidate(rootCertificate, c)
}
for _, intermediateNum := range opts.Intermediates.findPotentialParents(c) {
considerCandidate(intermediateCertificate, opts.Intermediates.certs[intermediateNum])
c, err := opts.Intermediates.cert(intermediateNum)
if err != nil {
return nil, fmt.Errorf("crypto/x509: error fetching cert: %w", err)
}
considerCandidate(intermediateCertificate, c)
}
if len(chains) > 0 {