Skip to content

Commit 9eeb627

Browse files
crypto/tls: add ech client support
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 <iant@google.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Roland Shoemaker <roland@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent 83ff4fd commit 9eeb627

16 files changed

+1223
-251
lines changed

api/next/63369.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pkg crypto/tls, type Config struct, EncryptedClientHelloConfigList []uint8 #63369
2+
pkg crypto/tls, type Config struct, EncryptedClientHelloRejectionVerify func(ConnectionState) error #63369
3+
pkg crypto/tls, type ConnectionState struct, ECHAccepted bool #63369
4+
pkg crypto/tls, type ECHRejectionError struct #63369
5+
pkg crypto/tls, type ECHRejectionError struct, RetryConfigList []uint8 #63369
6+
pkg crypto/tls, method (*ECHRejectionError) Error() string #63369
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The TLS client now supports the Encrypted Client Hello [draft specification](https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html).
2+
This feature can be enabled by setting the [Config.EncryptedClientHelloConfigList]
3+
field to an encoded ECHConfigList for the host that is being connected to.

src/crypto/tls/alert.go

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const (
5858
alertUnknownPSKIdentity alert = 115
5959
alertCertificateRequired alert = 116
6060
alertNoApplicationProtocol alert = 120
61+
alertECHRequired alert = 121
6162
)
6263

6364
var alertText = map[alert]string{
@@ -94,6 +95,7 @@ var alertText = map[alert]string{
9495
alertUnknownPSKIdentity: "unknown PSK identity",
9596
alertCertificateRequired: "certificate required",
9697
alertNoApplicationProtocol: "no application protocol",
98+
alertECHRequired: "encrypted client hello required",
9799
}
98100

99101
func (e alert) String() string {

src/crypto/tls/bogo_config.json

+58-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
{
22
"DisabledTests": {
3+
"*-Async": "We don't support boringssl concept of async",
4+
5+
"TLS-ECH-Client-Reject-NoClientCertificate-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
6+
"TLS-ECH-Client-Reject-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
7+
"TLS-ECH-Client-TLS12-RejectRetryConfigs": "We won't attempt to negotiate 1.2 if ECH is enabled",
8+
"TLS-ECH-Client-Rejected-OverrideName-TLS12": "We won't attempt to negotiate 1.2 if ECH is enabled",
9+
"TLS-ECH-Client-Reject-TLS12-NoFalseStart": "We won't attempt to negotiate 1.2 if ECH is enabled",
10+
"TLS-ECH-Client-TLS12SessionTicket": "We won't attempt to negotiate 1.2 if ECH is enabled",
11+
"TLS-ECH-Client-TLS12SessionID": "We won't attempt to negotiate 1.2 if ECH is enabled",
12+
13+
"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?)",
14+
15+
"TLS-ECH-Client-Reject-EarlyDataRejected": "We don't support switiching out ECH configs with this level of granularity",
16+
17+
"TLS-ECH-Client-NoNPN": "We don't support NPN",
18+
19+
"TLS-ECH-Client-ChannelID": "We don't support sending channel ID",
20+
"TLS-ECH-Client-Reject-NoChannelID-TLS13": "We don't support sending channel ID",
21+
"TLS-ECH-Client-Reject-NoChannelID-TLS12": "We don't support sending channel ID",
22+
23+
"TLS-ECH-Client-GREASE-IgnoreHRRExtension": "We don't support ECH GREASE because we don't fallback to plaintext",
24+
"TLS-ECH-Client-NoSupportedConfigs-GREASE": "We don't support ECH GREASE because we don't fallback to plaintext",
25+
"TLS-ECH-Client-GREASEExtensions": "We don't support ECH GREASE because we don't fallback to plaintext",
26+
"TLS-ECH-Client-GREASE-NoOverrideName": "We don't support ECH GREASE because we don't fallback to plaintext",
27+
28+
"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'",
29+
30+
"TLS-ECH-Client-NoSupportedConfigs": "We don't support fallback to cleartext when there are no valid ECH configs",
31+
"TLS-ECH-Client-SkipInvalidPublicName": "We don't support fallback to cleartext when there are no valid ECH configs",
32+
33+
"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",
34+
"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",
35+
"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",
36+
"TLS-ECH-Client-Reject": "TODO: bogo test cases have mismatching public certificates and public names in ECH configs. Can be removed once bogo fixed",
37+
"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",
38+
"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",
39+
"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",
40+
41+
"*ECH-Server*": "no ECH server support",
42+
"SendV2ClientHello*": "We don't support SSLv2",
343
"*QUIC*": "No QUIC support",
444
"Compliance-fips*": "No FIPS",
545
"*DTLS*": "No DTLS",
@@ -16,8 +56,6 @@
1656
"GarbageCertificate*": "TODO ask davidben, alertDecode vs alertBadCertificate",
1757
"SendBogusAlertType": "sending wrong alert type",
1858
"EchoTLS13CompatibilitySessionID": "TODO reject compat session ID",
19-
"*ECH-Server*": "no ECH server support",
20-
"TLS-ECH-Client-UnsolictedHRRExtension": "TODO",
2159
"*Client-P-224*": "no P-224 support",
2260
"*Server-P-224*": "no P-224 support",
2361
"CurveID-Resume*": "unexposed curveID is not stored in the ticket yet",
@@ -180,6 +218,23 @@
180218
"DuplicateCertCompressionExt-TLS13": "TODO: first pass, this should be fixed",
181219
"Client-RejectJDK11DowngradeRandom": "TODO: first pass, this should be fixed",
182220
"CheckClientCertificateTypes": "TODO: first pass, this should be fixed",
183-
"CheckECDSACurve-TLS12": "TODO: first pass, this should be fixed"
221+
"CheckECDSACurve-TLS12": "TODO: first pass, this should be fixed",
222+
"ALPNClient-RejectUnknown-TLS-TLS1": "TODO: first pass, this should be fixed",
223+
"ALPNClient-RejectUnknown-TLS-TLS11": "TODO: first pass, this should be fixed",
224+
"ALPNClient-RejectUnknown-TLS-TLS12": "TODO: first pass, this should be fixed",
225+
"ALPNClient-RejectUnknown-TLS-TLS13": "TODO: first pass, this should be fixed",
226+
"ClientHelloPadding": "TODO: first pass, this should be fixed",
227+
"TLS13-ExpectTicketEarlyDataSupport": "TODO: first pass, this should be fixed",
228+
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync": "TODO: first pass, this should be fixed",
229+
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync-SplitHandshakeRecords": "TODO: first pass, this should be fixed",
230+
"TLS13-EarlyData-TooMuchData-Client-TLS-Sync-PackHandshake": "TODO: first pass, this should be fixed",
231+
"WrongMessageType-TLS13-EndOfEarlyData-TLS": "TODO: first pass, this should be fixed",
232+
"TrailingMessageData-TLS13-EndOfEarlyData-TLS": "TODO: first pass, this should be fixed",
233+
"SendHelloRetryRequest-2-TLS13": "TODO: first pass, this should be fixed",
234+
"EarlyData-SkipEndOfEarlyData-TLS13": "TODO: first pass, this should be fixed",
235+
"EarlyData-Server-BadFinished-TLS13": "TODO: first pass, this should be fixed",
236+
"EarlyData-UnexpectedHandshake-Server-TLS13": "TODO: first pass, this should be fixed",
237+
"EarlyData-CipherMismatch-Client-TLS13": "TODO: first pass, this should be fixed",
238+
"Resume-Server-UnofferedCipher-TLS13": "TODO: first pass, this should be fixed"
184239
}
185240
}

0 commit comments

Comments
 (0)