mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-03 20:17:36 +03:00
crypto/tls: add server-side ECH
Adds support for server-side ECH. We make a couple of implementation decisions that are not completely in-line with the spec. In particular, we don't enforce that the SNI matches the ECHConfig public_name, and we implement a hybrid shared/backend mode (rather than shared or split mode, as described in Section 7). Both of these match the behavior of BoringSSL. The hybrid server mode will either act as a shared mode server, where-in the server accepts "outer" client hellos and unwraps them before processing the "inner" hello, or accepts bare "inner" hellos initially. This lets the server operate either transparently as a shared mode server, or a backend server, in Section 7 terminology. This seems like the best implementation choice for a TLS library. Fixes #68500 Change-Id: Ife69db7c1886610742e95e76b0ca92587e6d7ed4 Reviewed-on: https://go-review.googlesource.com/c/go/+/623576 Reviewed-by: Filippo Valsorda <filippo@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> Auto-Submit: Roland Shoemaker <roland@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
83cefcdeed
commit
212bbb2c77
12 changed files with 770 additions and 95 deletions
47
common.go
47
common.go
|
@ -791,8 +791,10 @@ type Config struct {
|
|||
|
||||
// EncryptedClientHelloConfigList is a serialized ECHConfigList. If
|
||||
// provided, clients will attempt to connect to servers using Encrypted
|
||||
// Client Hello (ECH) using one of the provided ECHConfigs. Servers
|
||||
// currently ignore this field.
|
||||
// Client Hello (ECH) using one of the provided ECHConfigs.
|
||||
//
|
||||
// Servers do not use this field. In order to configure ECH for servers, see
|
||||
// the EncryptedClientHelloKeys field.
|
||||
//
|
||||
// If the list contains no valid ECH configs, the handshake will fail
|
||||
// and return an error.
|
||||
|
@ -810,9 +812,11 @@ type Config struct {
|
|||
EncryptedClientHelloConfigList []byte
|
||||
|
||||
// EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is
|
||||
// rejected, in order to verify the ECH provider certificate in the outer
|
||||
// Client Hello. If it returns a non-nil error, the handshake is aborted and
|
||||
// that error results.
|
||||
// rejected by the remote server, in order to verify the ECH provider
|
||||
// certificate in the outer Client Hello. If it returns a non-nil error, the
|
||||
// handshake is aborted and that error results.
|
||||
//
|
||||
// On the server side this field is not used.
|
||||
//
|
||||
// Unlike VerifyPeerCertificate and VerifyConnection, normal certificate
|
||||
// verification will not be performed before calling
|
||||
|
@ -824,6 +828,20 @@ type Config struct {
|
|||
// when ECH is rejected, even if set, and InsecureSkipVerify is ignored.
|
||||
EncryptedClientHelloRejectionVerify func(ConnectionState) error
|
||||
|
||||
// EncryptedClientHelloKeys are the ECH keys to use when a client
|
||||
// attempts ECH.
|
||||
//
|
||||
// If EncryptedClientHelloKeys is set, MinVersion, if set, must be
|
||||
// VersionTLS13.
|
||||
//
|
||||
// If a client attempts ECH, but it is rejected by the server, the server
|
||||
// will send a list of configs to retry based on the set of
|
||||
// EncryptedClientHelloKeys which have the SendAsRetry field set.
|
||||
//
|
||||
// On the client side, this field is ignored. In order to configure ECH for
|
||||
// clients, see the EncryptedClientHelloConfigList field.
|
||||
EncryptedClientHelloKeys []EncryptedClientHelloKey
|
||||
|
||||
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
|
||||
mutex sync.RWMutex
|
||||
// sessionTicketKeys contains zero or more ticket keys. If set, it means
|
||||
|
@ -837,6 +855,24 @@ type Config struct {
|
|||
autoSessionTicketKeys []ticketKey
|
||||
}
|
||||
|
||||
// EncryptedClientHelloKey holds a private key that is associated
|
||||
// with a specific ECH config known to a client.
|
||||
type EncryptedClientHelloKey struct {
|
||||
// Config should be a marshalled ECHConfig associated with PrivateKey. This
|
||||
// must match the config provided to clients byte-for-byte. The config
|
||||
// should only specify the DHKEM(X25519, HKDF-SHA256) KEM ID (0x0020), the
|
||||
// HKDF-SHA256 KDF ID (0x0001), and a subset of the following AEAD IDs:
|
||||
// AES-128-GCM (0x0000), AES-256-GCM (0x0001), ChaCha20Poly1305 (0x0002).
|
||||
Config []byte
|
||||
// PrivateKey should be a marshalled private key. Currently, we expect
|
||||
// this to be the output of [ecdh.PrivateKey.Bytes].
|
||||
PrivateKey []byte
|
||||
// SendAsRetry indicates if Config should be sent as part of the list of
|
||||
// retry configs when ECH is requested by the client but rejected by the
|
||||
// server.
|
||||
SendAsRetry bool
|
||||
}
|
||||
|
||||
const (
|
||||
// ticketKeyLifetime is how long a ticket key remains valid and can be used to
|
||||
// resume a client connection.
|
||||
|
@ -913,6 +949,7 @@ func (c *Config) Clone() *Config {
|
|||
KeyLogWriter: c.KeyLogWriter,
|
||||
EncryptedClientHelloConfigList: c.EncryptedClientHelloConfigList,
|
||||
EncryptedClientHelloRejectionVerify: c.EncryptedClientHelloRejectionVerify,
|
||||
EncryptedClientHelloKeys: c.EncryptedClientHelloKeys,
|
||||
sessionTicketKeys: c.sessionTicketKeys,
|
||||
autoSessionTicketKeys: c.autoSessionTicketKeys,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue