@@ -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).
@@ -295,6 +336,14 @@ type ConnectionState struct {
295336 // RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
296337 TLSUnique []byte
297338
339+ // ECHAccepted is set if the ECH extension was offered by the client and
340+ // accepted by the server.
341+ ECHAccepted bool
342+
343+ // ECHOffered is set if the ECH extension is present in the ClientHello.
344+ // This means the client has offered ECH or sent GREASE ECH.
345+ ECHOffered bool
346+
298347 // ekm is a closure exposed via ExportKeyingMaterial.
299348 ekm func (label string , context []byte , length int ) ([]byte , error )
300349}
@@ -713,7 +762,8 @@ type Config struct {
713762
714763 // SessionTicketsDisabled may be set to true to disable session ticket and
715764 // PSK (resumption) support. Note that on clients, session ticket support is
716- // also disabled if ClientSessionCache is nil.
765+ // also disabled if ClientSessionCache is nil. On clients or servers,
766+ // support is disabled if the ECH extension is enabled.
717767 SessionTicketsDisabled bool
718768
719769 // SessionTicketKey is used by TLS servers to provide session resumption.
@@ -777,6 +827,23 @@ type Config struct {
777827 // used for debugging.
778828 KeyLogWriter io.Writer
779829
830+ // ECHEnabled determines whether the ECH extension is enabled for this
831+ // connection.
832+ ECHEnabled bool
833+
834+ // ClientECHConfigs are the parameters used by the client when it offers the
835+ // ECH extension. If ECH is enabled, a suitable configuration is found, and
836+ // the client supports TLS 1.3, then it will offer ECH in this handshake.
837+ // Otherwise, if ECH is enabled, it will send a dummy ECH extension.
838+ ClientECHConfigs []ECHConfig
839+
840+ // ServerECHProvider is the ECH provider used by the client-facing server
841+ // for the ECH extension. If the client offers ECH and TLS 1.3 is
842+ // negotiated, then the provider is used to compute the HPKE context
843+ // (draft-irtf-cfrg-hpke-07), which in turn is used to decrypt the extension
844+ // payload.
845+ ServerECHProvider ECHProvider
846+
780847 // SupportDelegatedCredential is true if the client or server is willing
781848 // to negotiate the delegated credential extension.
782849 // This can only be used with TLS 1.3.
@@ -875,6 +942,9 @@ func (c *Config) Clone() *Config {
875942 Renegotiation : c .Renegotiation ,
876943 KeyLogWriter : c .KeyLogWriter ,
877944 SupportDelegatedCredential : c .SupportDelegatedCredential ,
945+ ECHEnabled : c .ECHEnabled ,
946+ ClientECHConfigs : c .ClientECHConfigs ,
947+ ServerECHProvider : c .ServerECHProvider ,
878948 sessionTicketKeys : c .sessionTicketKeys ,
879949 autoSessionTicketKeys : c .autoSessionTicketKeys ,
880950 }
@@ -1065,6 +1135,17 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
10651135 return versions
10661136}
10671137
1138+ func (c * Config ) supportedVersionsFromMin (isClient bool , minVersion uint16 ) []uint16 {
1139+ versions := c .supportedVersions (isClient )
1140+ filteredVersions := versions [:0 ]
1141+ for _ , v := range versions {
1142+ if v >= minVersion {
1143+ filteredVersions = append (filteredVersions , v )
1144+ }
1145+ }
1146+ return filteredVersions
1147+ }
1148+
10681149func (c * Config ) maxSupportedVersion (isClient bool ) uint16 {
10691150 supportedVersions := c .supportedVersions (isClient )
10701151 if len (supportedVersions ) == 0 {
0 commit comments