@@ -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.
@@ -774,6 +824,23 @@ type Config struct {
774824 // used for debugging.
775825 KeyLogWriter io.Writer
776826
827+ // ECHEnabled determines whether the ECH extension is enabled for this
828+ // connection.
829+ ECHEnabled bool
830+
831+ // ClientECHConfigs are the parameters used by the client when it offers the
832+ // ECH extension. If ECH is enabled, a suitable configuration is found, and
833+ // the client supports TLS 1.3, then it will offer ECH in this handshake.
834+ // Otherwise, if ECH is enabled, it will send a dummy ECH extension.
835+ ClientECHConfigs []ECHConfig
836+
837+ // ServerECHProvider is the ECH provider used by the client-facing server
838+ // for the ECH extension. If the client offers ECH and TLS 1.3 is
839+ // negotiated, then the provider is used to compute the HPKE context
840+ // (draft-irtf-cfrg-hpke-07), which in turn is used to decrypt the extension
841+ // payload.
842+ ServerECHProvider ECHProvider
843+
777844 // CFEventHandler, if set, is called by the client and server at various
778845 // points during the handshake to handle specific events. This is used
779846 // primarily for collecting metrics.
@@ -887,6 +954,9 @@ func (c *Config) Clone() *Config {
887954 Renegotiation : c .Renegotiation ,
888955 KeyLogWriter : c .KeyLogWriter ,
889956 SupportDelegatedCredential : c .SupportDelegatedCredential ,
957+ ECHEnabled : c .ECHEnabled ,
958+ ClientECHConfigs : c .ClientECHConfigs ,
959+ ServerECHProvider : c .ServerECHProvider ,
890960 CFEventHandler : c .CFEventHandler ,
891961 CFControl : c .CFControl ,
892962 sessionTicketKeys : c .sessionTicketKeys ,
@@ -1079,6 +1149,17 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
10791149 return versions
10801150}
10811151
1152+ func (c * Config ) supportedVersionsFromMin (isClient bool , minVersion uint16 ) []uint16 {
1153+ versions := c .supportedVersions (isClient )
1154+ filteredVersions := versions [:0 ]
1155+ for _ , v := range versions {
1156+ if v >= minVersion {
1157+ filteredVersions = append (filteredVersions , v )
1158+ }
1159+ }
1160+ return filteredVersions
1161+ }
1162+
10821163func (c * Config ) maxSupportedVersion (isClient bool ) uint16 {
10831164 supportedVersions := c .supportedVersions (isClient )
10841165 if len (supportedVersions ) == 0 {
0 commit comments