Add ECH TLS client
This commit is contained in:
@@ -834,6 +834,8 @@ type Config struct {
|
||||
// Otherwise, if ECH is enabled, it will send a dummy ECH extension.
|
||||
ClientECHConfigs []ECHConfig
|
||||
|
||||
GetClientECHConfigs func(ctx context.Context, serverName string) ([]ECHConfig, error)
|
||||
|
||||
// ServerECHProvider is the ECH provider used by the client-facing server
|
||||
// for the ECH extension. If the client offers ECH and TLS 1.3 is
|
||||
// negotiated, then the provider is used to compute the HPKE context
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -37,7 +38,7 @@ var zeros = [8]byte{}
|
||||
//
|
||||
// TODO(cjpatton): "[When offering ECH, the client] MUST NOT offer to resume any
|
||||
// session for TLS 1.2 and below [in ClientHelloInner]."
|
||||
func (c *Conn) echOfferOrGrease(helloBase *clientHelloMsg) (hello, helloInner *clientHelloMsg, err error) {
|
||||
func (c *Conn) echOfferOrGrease(ctx context.Context, helloBase *clientHelloMsg) (hello, helloInner *clientHelloMsg, err error) {
|
||||
config := c.config
|
||||
|
||||
if !config.ECHEnabled || testingECHTriggerBypassBeforeHRR {
|
||||
@@ -47,7 +48,10 @@ func (c *Conn) echOfferOrGrease(helloBase *clientHelloMsg) (hello, helloInner *c
|
||||
|
||||
// Choose the ECHConfig to use for this connection. If none is available, or
|
||||
// if we're not offering TLS 1.3 or above, then GREASE.
|
||||
echConfig := config.echSelectConfig()
|
||||
echConfig, err := config.echSelectConfig(ctx, helloBase.serverName)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("tls: ech: fetch ech config: %s", err)
|
||||
}
|
||||
if echConfig == nil || config.maxSupportedVersion(roleClient) < VersionTLS13 {
|
||||
var err error
|
||||
|
||||
@@ -1008,14 +1012,26 @@ func splitClientHelloExtensions(data []byte) ([]byte, []byte) {
|
||||
//
|
||||
// TODO(cjpatton): Implement ECH config extensions as described in
|
||||
// draft-ietf-tls-esni-13, Section 4.1.
|
||||
func (c *Config) echSelectConfig() *ECHConfig {
|
||||
func (c *Config) echSelectConfig(ctx context.Context, serverName string) (*ECHConfig, error) {
|
||||
for _, echConfig := range c.ClientECHConfigs {
|
||||
if _, err := echConfig.selectSuite(); err == nil &&
|
||||
echConfig.version == extensionECH {
|
||||
return &echConfig
|
||||
return &echConfig, nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
if c.GetClientECHConfigs != nil {
|
||||
echConfigs, err := c.GetClientECHConfigs(ctx, serverName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, echConfig := range echConfigs {
|
||||
if _, err = echConfig.selectSuite(); err == nil &&
|
||||
echConfig.version == extensionECH {
|
||||
return &echConfig, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *Config) echCanOffer() bool {
|
||||
@@ -1023,7 +1039,6 @@ func (c *Config) echCanOffer() bool {
|
||||
return false
|
||||
}
|
||||
return c.ECHEnabled &&
|
||||
c.echSelectConfig() != nil &&
|
||||
c.maxSupportedVersion(roleClient) >= VersionTLS13
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
hello, helloInner, err := c.echOfferOrGrease(helloBase)
|
||||
hello, helloInner, err := c.echOfferOrGrease(ctx, helloBase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user