@@ -101,6 +101,8 @@ const (
101101 extensionSignatureAlgorithmsCert uint16 = 50
102102 extensionKeyShare uint16 = 51
103103 extensionRenegotiationInfo uint16 = 0xff01
104+ extensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-13
105+ extensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-13
104106)
105107
106108// TLS signaling cipher suite values
@@ -223,6 +225,45 @@ const (
223225// include downgrade canaries even if it's using its highers supported version.
224226var testingOnlyForceDowngradeCanary bool
225227
228+ // testingTriggerHRR causes the server to intentionally trigger a
229+ // HelloRetryRequest (HRR). This is useful for testing new TLS features that
230+ // change the HRR codepath.
231+ var testingTriggerHRR bool
232+
233+ // testingECHTriggerBypassAfterHRR causes the client to bypass ECH after HRR.
234+ // If available, the client will offer ECH in the first CH only.
235+ var testingECHTriggerBypassAfterHRR bool
236+
237+ // testingECHTriggerBypassBeforeHRR causes the client to bypass ECH before HRR.
238+ // The client will offer ECH in the second CH only.
239+ var testingECHTriggerBypassBeforeHRR bool
240+
241+ // testingECHIllegalHandleAfterHRR causes the client to illegally change the ECH
242+ // extension after HRR.
243+ var testingECHIllegalHandleAfterHRR bool
244+
245+ // testingECHTriggerPayloadDecryptError causes the client to to send an
246+ // inauthentic payload.
247+ var testingECHTriggerPayloadDecryptError bool
248+
249+ // testingECHOuterExtMany causes a client to incorporate a sequence of
250+ // outer extensions into the ClientHelloInner when it offers the ECH extension.
251+ // The "key_share" extension is the only incorporated extension by default.
252+ var testingECHOuterExtMany bool
253+
254+ // testingECHOuterExtNone causes a client to not use the "outer_extension"
255+ // mechanism for ECH. The "key_shares" extension is incorporated by default.
256+ var testingECHOuterExtNone bool
257+
258+ // testingECHOuterExtIncorrectOrder causes the client to send the
259+ // "outer_extension" extension in the wrong order when offering the ECH
260+ // extension.
261+ var testingECHOuterExtIncorrectOrder bool
262+
263+ // testingECHOuterExtIllegal causes the client to send in its
264+ // "outer_extension" extension the codepoint for the ECH extension.
265+ var testingECHOuterExtIllegal bool
266+
226267// ConnectionState records basic TLS details about the connection.
227268type ConnectionState struct {
228269 // Version is the TLS version used by the connection (e.g. VersionTLS12).
@@ -291,6 +332,14 @@ type ConnectionState struct {
291332 // RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
292333 TLSUnique []byte
293334
335+ // ECHAccepted is set if the ECH extension was offered by the client and
336+ // accepted by the server.
337+ ECHAccepted bool
338+
339+ // ECHOffered is set if the ECH extension is present in the ClientHello.
340+ // This means the client has offered ECH or sent GREASE ECH.
341+ ECHOffered bool
342+
294343 // CFControl is used to pass additional TLS configuration information to
295344 // HTTP requests.
296345 //
@@ -710,7 +759,8 @@ type Config struct {
710759
711760 // SessionTicketsDisabled may be set to true to disable session ticket and
712761 // PSK (resumption) support. Note that on clients, session ticket support is
713- // also disabled if ClientSessionCache is nil.
762+ // also disabled if ClientSessionCache is nil. On clients or servers,
763+ // support is disabled if the ECH extension is enabled.
714764 SessionTicketsDisabled bool
715765
716766 // SessionTicketKey is used by TLS servers to provide session resumption.
@@ -765,6 +815,23 @@ type Config struct {
765815 // used for debugging.
766816 KeyLogWriter io.Writer
767817
818+ // ECHEnabled determines whether the ECH extension is enabled for this
819+ // connection.
820+ ECHEnabled bool
821+
822+ // ClientECHConfigs are the parameters used by the client when it offers the
823+ // ECH extension. If ECH is enabled, a suitable configuration is found, and
824+ // the client supports TLS 1.3, then it will offer ECH in this handshake.
825+ // Otherwise, if ECH is enabled, it will send a dummy ECH extension.
826+ ClientECHConfigs []ECHConfig
827+
828+ // ServerECHProvider is the ECH provider used by the client-facing server
829+ // for the ECH extension. If the client offers ECH and TLS 1.3 is
830+ // negotiated, then the provider is used to compute the HPKE context
831+ // (draft-irtf-cfrg-hpke-07), which in turn is used to decrypt the extension
832+ // payload.
833+ ServerECHProvider ECHProvider
834+
768835 // CFEventHandler, if set, is called by the client and server at various
769836 // points during the handshake to handle specific events. This is used
770837 // primarily for collecting metrics.
@@ -878,6 +945,9 @@ func (c *Config) Clone() *Config {
878945 Renegotiation : c .Renegotiation ,
879946 KeyLogWriter : c .KeyLogWriter ,
880947 SupportDelegatedCredential : c .SupportDelegatedCredential ,
948+ ECHEnabled : c .ECHEnabled ,
949+ ClientECHConfigs : c .ClientECHConfigs ,
950+ ServerECHProvider : c .ServerECHProvider ,
881951 CFEventHandler : c .CFEventHandler ,
882952 CFControl : c .CFControl ,
883953 sessionTicketKeys : c .sessionTicketKeys ,
@@ -1055,6 +1125,23 @@ func (c *Config) supportedVersions() []uint16 {
10551125 return versions
10561126}
10571127
1128+ func (c * Config ) supportedVersionsFromMin (minVersion uint16 ) []uint16 {
1129+ versions := make ([]uint16 , 0 , len (supportedVersions ))
1130+ for _ , v := range supportedVersions {
1131+ if c != nil && c .MinVersion != 0 && v < c .MinVersion {
1132+ continue
1133+ }
1134+ if c != nil && c .MaxVersion != 0 && v > c .MaxVersion {
1135+ continue
1136+ }
1137+ if v < minVersion {
1138+ continue
1139+ }
1140+ versions = append (versions , v )
1141+ }
1142+ return versions
1143+ }
1144+
10581145func (c * Config ) maxSupportedVersion () uint16 {
10591146 supportedVersions := c .supportedVersions ()
10601147 if len (supportedVersions ) == 0 {
0 commit comments