Skip to content

proposal: crypto/tls: Config adds an option to get RootCAs #70946

Closed as not planned
@shaj13

Description

@shaj13

Proposal Details

The tls.config provides several callback functions such as GetCertificate, GetClientCertificate, and GetConfigForClient, which enable dynamic behavior during the TLS handshake. These callbacks are particularly useful for scenarios involving certificate rotation, both on the client and server sides.

However, tls.Config currently lacks an option for dynamically managing the Root CAs used to verify server certificates on the client side. Since x509.CertPool methods cannot be invoked concurrently by multiple goroutines, it becomes challenging to update or reload the Root CA pool at runtime without risking data races or inconsistent state.

Motivation:

  • Root CA Certificate rotation
  • Dynamic trust policies

This proposal seeks to introduce a new callback in tls.Config that allows for dynamically retrieving the latest CertPool, similar to the existing callback functions.

// GetRootCAs returns  the set of root certificate authorities
// that clients use when verifying server certificates.
// 
// If GetRootCAs is nil, then the RootCAs is used. 
GetRootCAs func() (*x509.CertPool)

The client handshake will work with the proposed changes as follows:

func (c *Config) rootCAs() *x509.CertPool{
	if c.GetRootCAs == nil {
		return c.RootCAs
	}
        
        return c.GetRootCAs()
}
func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
	} else if !c.config.InsecureSkipVerify {
		opts := x509.VerifyOptions{
			Roots:         c.config.rootCAs(),
			CurrentTime:   c.config.time(),
			DNSName:       c.config.ServerName,
			Intermediates: x509.NewCertPool(),
		}

		for _, cert := range certs[1:] {
			opts.Intermediates.AddCert(cert)
		}
		chains, err := certs[0].Verify(opts)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
		}

		c.verifiedChains, err = fipsAllowedChains(chains)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
		}
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions