Skip to content

Commit

Permalink
crypto/tls: add ech client support
Browse files Browse the repository at this point in the history
This CL adds a (very opinionated) client-side ECH implementation.

In particular, if a user configures a ECHConfigList, by setting the
Config.EncryptedClientHelloConfigList, but we determine that none of
the configs are appropriate, we will not fallback to plaintext SNI, and
will instead return an error. It is then up to the user to decide if
they wish to fallback to plaintext themselves (by removing the config
list).

Additionally if Config.EncryptedClientHelloConfigList is provided, we
will not offer TLS support lower than 1.3, since negotiating any other
version, while offering ECH, is a hard error anyway. Similarly, if a
user wishes to fallback to plaintext SNI by using 1.2, they may do so
by removing the config list.

With regard to PSK GREASE, we match the boringssl  behavior, which does
not include PSK identities/binders in the outer hello when doing ECH.

If the server rejects ECH, we will return a ECHRejectionError error,
which, if provided by the server, will contain a ECHConfigList in the
RetryConfigList field containing configs that should be used if the user
wishes to retry. It is up to the user to replace their existing
Config.EncryptedClientHelloConfigList with the retry config list.

Fixes #63369

Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest
Change-Id: I9bc373c044064221a647a388ac61624efd6bbdbf
Reviewed-on: https://go-review.googlesource.com/c/go/+/578575
Reviewed-by: Ian Lance Taylor <[email protected]>
Reviewed-by: Filippo Valsorda <[email protected]>
Reviewed-by: Than McIntosh <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Auto-Submit: Roland Shoemaker <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
rolandshoemaker committed May 23, 2024
1 parent 83ff4fd commit 9eeb627
Show file tree
Hide file tree
Showing 16 changed files with 1,223 additions and 251 deletions.
6 changes: 6 additions & 0 deletions api/next/63369.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pkg crypto/tls, type Config struct, EncryptedClientHelloConfigList []uint8 #63369
pkg crypto/tls, type Config struct, EncryptedClientHelloRejectionVerify func(ConnectionState) error #63369
pkg crypto/tls, type ConnectionState struct, ECHAccepted bool #63369
pkg crypto/tls, type ECHRejectionError struct #63369
pkg crypto/tls, type ECHRejectionError struct, RetryConfigList []uint8 #63369
pkg crypto/tls, method (*ECHRejectionError) Error() string #63369
3 changes: 3 additions & 0 deletions doc/next/6-stdlib/99-minor/crypto/tls/63369.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The TLS client now supports the Encrypted Client Hello [draft specification](https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html).
This feature can be enabled by setting the [Config.EncryptedClientHelloConfigList]
field to an encoded ECHConfigList for the host that is being connected to.
2 changes: 2 additions & 0 deletions src/crypto/tls/alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const (
alertUnknownPSKIdentity alert = 115
alertCertificateRequired alert = 116
alertNoApplicationProtocol alert = 120
alertECHRequired alert = 121
)

var alertText = map[alert]string{
Expand Down Expand Up @@ -94,6 +95,7 @@ var alertText = map[alert]string{
alertUnknownPSKIdentity: "unknown PSK identity",
alertCertificateRequired: "certificate required",
alertNoApplicationProtocol: "no application protocol",
alertECHRequired: "encrypted client hello required",
}

func (e alert) String() string {
Expand Down
61 changes: 58 additions & 3 deletions src/crypto/tls/bogo_config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
{
"DisabledTests": {
"*-Async": "We don't support boringssl concept of async",

"TLS-ECH-Client-Reject-NoClientCertificate-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-Reject-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-TLS12-RejectRetryConfigs": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-Rejected-OverrideName-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-Reject-TLS12-NoFalseStart": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-TLS12SessionTicket": "We won't attempt to negotiate 1.2 if ECH is enabled",
"TLS-ECH-Client-TLS12SessionID": "We won't attempt to negotiate 1.2 if ECH is enabled",

"TLS-ECH-Client-Reject-ResumeInnerSession-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled (we could possibly test this if we had the ability to indicate not to send ECH on resumption?)",

"TLS-ECH-Client-Reject-EarlyDataRejected": "We don't support switiching out ECH configs with this level of granularity",

"TLS-ECH-Client-NoNPN": "We don't support NPN",

"TLS-ECH-Client-ChannelID": "We don't support sending channel ID",
"TLS-ECH-Client-Reject-NoChannelID-TLS13": "We don't support sending channel ID",
"TLS-ECH-Client-Reject-NoChannelID-TLS12": "We don't support sending channel ID",

"TLS-ECH-Client-GREASE-IgnoreHRRExtension": "We don't support ECH GREASE because we don't fallback to plaintext",
"TLS-ECH-Client-NoSupportedConfigs-GREASE": "We don't support ECH GREASE because we don't fallback to plaintext",
"TLS-ECH-Client-GREASEExtensions": "We don't support ECH GREASE because we don't fallback to plaintext",
"TLS-ECH-Client-GREASE-NoOverrideName": "We don't support ECH GREASE because we don't fallback to plaintext",

"TLS-ECH-Client-UnsolicitedInnerServerNameAck": "We don't allow sending empty SNI without skipping certificate verification, TODO: could add special flag to bogo to indicate 'empty sni'",

"TLS-ECH-Client-NoSupportedConfigs": "We don't support fallback to cleartext when there are no valid ECH configs",
"TLS-ECH-Client-SkipInvalidPublicName": "We don't support fallback to cleartext when there are no valid ECH configs",

"TLS-ECH-Client-Reject-RandomHRRExtension": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject-UnsupportedRetryConfigs": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject-NoRetryConfigs": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject-HelloRetryRequest": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject-NoClientCertificate-TLS13": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
"TLS-ECH-Client-Reject-OverrideName-TLS13": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",

"*ECH-Server*": "no ECH server support",
"SendV2ClientHello*": "We don't support SSLv2",
"*QUIC*": "No QUIC support",
"Compliance-fips*": "No FIPS",
"*DTLS*": "No DTLS",
Expand All @@ -16,8 +56,6 @@
"GarbageCertificate*": "TODO ask davidben, alertDecode vs alertBadCertificate",
"SendBogusAlertType": "sending wrong alert type",
"EchoTLS13CompatibilitySessionID": "TODO reject compat session ID",
"*ECH-Server*": "no ECH server support",
"TLS-ECH-Client-UnsolictedHRRExtension": "TODO",
"*Client-P-224*": "no P-224 support",
"*Server-P-224*": "no P-224 support",
"CurveID-Resume*": "unexposed curveID is not stored in the ticket yet",
Expand Down Expand Up @@ -180,6 +218,23 @@
"DuplicateCertCompressionExt-TLS13": "TODO: first pass, this should be fixed",
"Client-RejectJDK11DowngradeRandom": "TODO: first pass, this should be fixed",
"CheckClientCertificateTypes": "TODO: first pass, this should be fixed",
"CheckECDSACurve-TLS12": "TODO: first pass, this should be fixed"
"CheckECDSACurve-TLS12": "TODO: first pass, this should be fixed",
"ALPNClient-RejectUnknown-TLS-TLS1": "TODO: first pass, this should be fixed",
"ALPNClient-RejectUnknown-TLS-TLS11": "TODO: first pass, this should be fixed",
"ALPNClient-RejectUnknown-TLS-TLS12": "TODO: first pass, this should be fixed",
"ALPNClient-RejectUnknown-TLS-TLS13": "TODO: first pass, this should be fixed",
"ClientHelloPadding": "TODO: first pass, this should be fixed",
"TLS13-ExpectTicketEarlyDataSupport": "TODO: first pass, this should be fixed",
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync": "TODO: first pass, this should be fixed",
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync-SplitHandshakeRecords": "TODO: first pass, this should be fixed",
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync-PackHandshake": "TODO: first pass, this should be fixed",
"WrongMessageType-TLS13-EndOfEarlyData-TLS": "TODO: first pass, this should be fixed",
"TrailingMessageData-TLS13-EndOfEarlyData-TLS": "TODO: first pass, this should be fixed",
"SendHelloRetryRequest-2-TLS13": "TODO: first pass, this should be fixed",
"EarlyData-SkipEndOfEarlyData-TLS13": "TODO: first pass, this should be fixed",
"EarlyData-Server-BadFinished-TLS13": "TODO: first pass, this should be fixed",
"EarlyData-UnexpectedHandshake-Server-TLS13": "TODO: first pass, this should be fixed",
"EarlyData-CipherMismatch-Client-TLS13": "TODO: first pass, this should be fixed",
"Resume-Server-UnofferedCipher-TLS13": "TODO: first pass, this should be fixed"
}
}
Loading

0 comments on commit 9eeb627

Please sign in to comment.