@@ -102,6 +102,8 @@ const (
102102 extensionSignatureAlgorithmsCert uint16 = 50
103103 extensionKeyShare uint16 = 51
104104 extensionRenegotiationInfo uint16 = 0xff01
105+ extensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-13
106+ extensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-13
105107)
106108
107109// TLS signaling cipher suite values
@@ -224,6 +226,45 @@ const (
224226// include downgrade canaries even if it's using its highers supported version.
225227var testingOnlyForceDowngradeCanary bool
226228
229+ // testingTriggerHRR causes the server to intentionally trigger a
230+ // HelloRetryRequest (HRR). This is useful for testing new TLS features that
231+ // change the HRR codepath.
232+ var testingTriggerHRR bool
233+
234+ // testingECHTriggerBypassAfterHRR causes the client to bypass ECH after HRR.
235+ // If available, the client will offer ECH in the first CH only.
236+ var testingECHTriggerBypassAfterHRR bool
237+
238+ // testingECHTriggerBypassBeforeHRR causes the client to bypass ECH before HRR.
239+ // The client will offer ECH in the second CH only.
240+ var testingECHTriggerBypassBeforeHRR bool
241+
242+ // testingECHIllegalHandleAfterHRR causes the client to illegally change the ECH
243+ // extension after HRR.
244+ var testingECHIllegalHandleAfterHRR bool
245+
246+ // testingECHTriggerPayloadDecryptError causes the client to to send an
247+ // inauthentic payload.
248+ var testingECHTriggerPayloadDecryptError bool
249+
250+ // testingECHOuterExtMany causes a client to incorporate a sequence of
251+ // outer extensions into the ClientHelloInner when it offers the ECH extension.
252+ // The "key_share" extension is the only incorporated extension by default.
253+ var testingECHOuterExtMany bool
254+
255+ // testingECHOuterExtNone causes a client to not use the "outer_extension"
256+ // mechanism for ECH. The "key_shares" extension is incorporated by default.
257+ var testingECHOuterExtNone bool
258+
259+ // testingECHOuterExtIncorrectOrder causes the client to send the
260+ // "outer_extension" extension in the wrong order when offering the ECH
261+ // extension.
262+ var testingECHOuterExtIncorrectOrder bool
263+
264+ // testingECHOuterExtIllegal causes the client to send in its
265+ // "outer_extension" extension the codepoint for the ECH extension.
266+ var testingECHOuterExtIllegal bool
267+
227268// ConnectionState records basic TLS details about the connection.
228269type ConnectionState struct {
229270 // Version is the TLS version used by the connection (e.g. VersionTLS12).
@@ -292,6 +333,14 @@ type ConnectionState struct {
292333 // RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
293334 TLSUnique []byte
294335
336+ // ECHAccepted is set if the ECH extension was offered by the client and
337+ // accepted by the server.
338+ ECHAccepted bool
339+
340+ // ECHOffered is set if the ECH extension is present in the ClientHello.
341+ // This means the client has offered ECH or sent GREASE ECH.
342+ ECHOffered bool
343+
295344 // CFControl is used to pass additional TLS configuration information to
296345 // HTTP requests.
297346 //
@@ -711,7 +760,8 @@ type Config struct {
711760
712761 // SessionTicketsDisabled may be set to true to disable session ticket and
713762 // PSK (resumption) support. Note that on clients, session ticket support is
714- // also disabled if ClientSessionCache is nil.
763+ // also disabled if ClientSessionCache is nil. On clients or servers,
764+ // support is disabled if the ECH extension is enabled.
715765 SessionTicketsDisabled bool
716766
717767 // SessionTicketKey is used by TLS servers to provide session resumption.
@@ -775,6 +825,23 @@ type Config struct {
775825 // used for debugging.
776826 KeyLogWriter io.Writer
777827
828+ // ECHEnabled determines whether the ECH extension is enabled for this
829+ // connection.
830+ ECHEnabled bool
831+
832+ // ClientECHConfigs are the parameters used by the client when it offers the
833+ // ECH extension. If ECH is enabled, a suitable configuration is found, and
834+ // the client supports TLS 1.3, then it will offer ECH in this handshake.
835+ // Otherwise, if ECH is enabled, it will send a dummy ECH extension.
836+ ClientECHConfigs []ECHConfig
837+
838+ // ServerECHProvider is the ECH provider used by the client-facing server
839+ // for the ECH extension. If the client offers ECH and TLS 1.3 is
840+ // negotiated, then the provider is used to compute the HPKE context
841+ // (draft-irtf-cfrg-hpke-07), which in turn is used to decrypt the extension
842+ // payload.
843+ ServerECHProvider ECHProvider
844+
778845 // CFEventHandler, if set, is called by the client and server at various
779846 // points during the handshake to handle specific events. This is used
780847 // primarily for collecting metrics.
@@ -888,6 +955,9 @@ func (c *Config) Clone() *Config {
888955 Renegotiation : c .Renegotiation ,
889956 KeyLogWriter : c .KeyLogWriter ,
890957 SupportDelegatedCredential : c .SupportDelegatedCredential ,
958+ ECHEnabled : c .ECHEnabled ,
959+ ClientECHConfigs : c .ClientECHConfigs ,
960+ ServerECHProvider : c .ServerECHProvider ,
891961 CFEventHandler : c .CFEventHandler ,
892962 CFControl : c .CFControl ,
893963 sessionTicketKeys : c .sessionTicketKeys ,
@@ -1077,6 +1147,27 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
10771147 return versions
10781148}
10791149
1150+ func (c * Config ) supportedVersionsFromMin (isClient bool , minVersion uint16 ) []uint16 {
1151+ versions := make ([]uint16 , 0 , len (supportedVersions ))
1152+ for _ , v := range supportedVersions {
1153+ if (c == nil || c .MinVersion == 0 ) && ! debugEnableTLS10 &&
1154+ isClient && v < VersionTLS12 {
1155+ continue
1156+ }
1157+ if c != nil && c .MinVersion != 0 && v < c .MinVersion {
1158+ continue
1159+ }
1160+ if c != nil && c .MaxVersion != 0 && v > c .MaxVersion {
1161+ continue
1162+ }
1163+ if v < minVersion {
1164+ continue
1165+ }
1166+ versions = append (versions , v )
1167+ }
1168+ return versions
1169+ }
1170+
10801171func (c * Config ) maxSupportedVersion (isClient bool ) uint16 {
10811172 supportedVersions := c .supportedVersions (isClient )
10821173 if len (supportedVersions ) == 0 {
0 commit comments