mirror of
https://github.com/XTLS/REALITY.git
synced 2025-08-22 14:38:35 +00:00
crypto/tls: add GetEncryptedClientHelloKeys
This allows servers to rotate their ECH keys without needing to restart the server. Fixes #71920 Change-Id: I55591ab3303d5fde639038541c50edcf1fafc9aa Reviewed-on: https://go-review.googlesource.com/c/go/+/670655 TryBot-Bypass: Roland Shoemaker <roland@golang.org> Reviewed-by: David Chase <drchase@google.com> Auto-Submit: Roland Shoemaker <roland@golang.org> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
This commit is contained in:
parent
3682e614bc
commit
1b86b6ea09
18
common.go
18
common.go
@ -851,6 +851,20 @@ type Config struct {
|
|||||||
// when ECH is rejected, even if set, and InsecureSkipVerify is ignored.
|
// when ECH is rejected, even if set, and InsecureSkipVerify is ignored.
|
||||||
EncryptedClientHelloRejectionVerify func(ConnectionState) error
|
EncryptedClientHelloRejectionVerify func(ConnectionState) error
|
||||||
|
|
||||||
|
// GetEncryptedClientHelloKeys, if not nil, is called when by a server when
|
||||||
|
// a client attempts ECH.
|
||||||
|
//
|
||||||
|
// If GetEncryptedClientHelloKeys is not nil, [EncryptedClientHelloKeys] is
|
||||||
|
// ignored.
|
||||||
|
//
|
||||||
|
// If GetEncryptedClientHelloKeys returns an error, the handshake will be
|
||||||
|
// aborted and the error will be returned. Otherwise,
|
||||||
|
// GetEncryptedClientHelloKeys must return a non-nil slice of
|
||||||
|
// [EncryptedClientHelloKey] that represents the acceptable ECH keys.
|
||||||
|
//
|
||||||
|
// For further details, see [EncryptedClientHelloKeys].
|
||||||
|
GetEncryptedClientHelloKeys func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error)
|
||||||
|
|
||||||
// EncryptedClientHelloKeys are the ECH keys to use when a client
|
// EncryptedClientHelloKeys are the ECH keys to use when a client
|
||||||
// attempts ECH.
|
// attempts ECH.
|
||||||
//
|
//
|
||||||
@ -861,6 +875,9 @@ type Config struct {
|
|||||||
// will send a list of configs to retry based on the set of
|
// will send a list of configs to retry based on the set of
|
||||||
// EncryptedClientHelloKeys which have the SendAsRetry field set.
|
// EncryptedClientHelloKeys which have the SendAsRetry field set.
|
||||||
//
|
//
|
||||||
|
// If GetEncryptedClientHelloKeys is non-nil, EncryptedClientHelloKeys is
|
||||||
|
// ignored.
|
||||||
|
//
|
||||||
// On the client side, this field is ignored. In order to configure ECH for
|
// On the client side, this field is ignored. In order to configure ECH for
|
||||||
// clients, see the EncryptedClientHelloConfigList field.
|
// clients, see the EncryptedClientHelloConfigList field.
|
||||||
EncryptedClientHelloKeys []EncryptedClientHelloKey
|
EncryptedClientHelloKeys []EncryptedClientHelloKey
|
||||||
@ -961,6 +978,7 @@ func (c *Config) Clone() *Config {
|
|||||||
GetCertificate: c.GetCertificate,
|
GetCertificate: c.GetCertificate,
|
||||||
GetClientCertificate: c.GetClientCertificate,
|
GetClientCertificate: c.GetClientCertificate,
|
||||||
GetConfigForClient: c.GetConfigForClient,
|
GetConfigForClient: c.GetConfigForClient,
|
||||||
|
GetEncryptedClientHelloKeys: c.GetEncryptedClientHelloKeys,
|
||||||
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
||||||
VerifyConnection: c.VerifyConnection,
|
VerifyConnection: c.VerifyConnection,
|
||||||
RootCAs: c.RootCAs,
|
RootCAs: c.RootCAs,
|
||||||
|
6
ech.go
6
ech.go
@ -579,7 +579,7 @@ func marshalEncryptedClientHelloConfigList(configs []EncryptedClientHelloKey) ([
|
|||||||
return builder.Bytes()
|
return builder.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *echServerContext, error) {
|
func (c *Conn) processECHClientHello(outer *clientHelloMsg, echKeys []EncryptedClientHelloKey) (*clientHelloMsg, *echServerContext, error) {
|
||||||
echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello)
|
echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errInvalidECHExt) {
|
if errors.Is(err, errInvalidECHExt) {
|
||||||
@ -595,11 +595,11 @@ func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *e
|
|||||||
return outer, &echServerContext{inner: true}, nil
|
return outer, &echServerContext{inner: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.config.EncryptedClientHelloKeys) == 0 {
|
if len(echKeys) == 0 {
|
||||||
return outer, nil, nil
|
return outer, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, echKey := range c.config.EncryptedClientHelloKeys {
|
for _, echKey := range echKeys {
|
||||||
skip, config, err := parseECHConfig(echKey.Config)
|
skip, config, err := parseECHConfig(echKey.Config)
|
||||||
if err != nil || skip {
|
if err != nil || skip {
|
||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
|
@ -150,7 +150,15 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, *echServer
|
|||||||
// the contents of the client hello, since we may swap it out completely.
|
// the contents of the client hello, since we may swap it out completely.
|
||||||
var ech *echServerContext
|
var ech *echServerContext
|
||||||
if len(clientHello.encryptedClientHello) != 0 {
|
if len(clientHello.encryptedClientHello) != 0 {
|
||||||
clientHello, ech, err = c.processECHClientHello(clientHello)
|
echKeys := c.config.EncryptedClientHelloKeys
|
||||||
|
if c.config.GetEncryptedClientHelloKeys != nil {
|
||||||
|
echKeys, err = c.config.GetEncryptedClientHelloKeys(clientHelloInfo(ctx, c, clientHello))
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clientHello, ech, err = c.processECHClientHello(clientHello, echKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -877,8 +877,16 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
|
|||||||
|
|
||||||
// If client sent ECH extension, but we didn't accept it,
|
// If client sent ECH extension, but we didn't accept it,
|
||||||
// send retry configs, if available.
|
// send retry configs, if available.
|
||||||
if len(hs.c.config.EncryptedClientHelloKeys) > 0 && len(hs.clientHello.encryptedClientHello) > 0 && hs.echContext == nil {
|
echKeys := hs.c.config.EncryptedClientHelloKeys
|
||||||
encryptedExtensions.echRetryConfigs, err = buildRetryConfigList(hs.c.config.EncryptedClientHelloKeys)
|
if hs.c.config.GetEncryptedClientHelloKeys != nil {
|
||||||
|
echKeys, err = hs.c.config.GetEncryptedClientHelloKeys(clientHelloInfo(hs.ctx, c, hs.clientHello))
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(echKeys) > 0 && len(hs.clientHello.encryptedClientHello) > 0 && hs.echContext == nil {
|
||||||
|
encryptedExtensions.echRetryConfigs, err = buildRetryConfigList(echKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user