@@ -214,7 +214,6 @@ purposes.
214214 The context now uses :data: `VERIFY_X509_PARTIAL_CHAIN ` and
215215 :data: `VERIFY_X509_STRICT ` in its default verify flags.
216216
217-
218217Exceptions
219218^^^^^^^^^^
220219
@@ -1003,6 +1002,13 @@ Constants
10031002
10041003 .. versionadded :: 3.6
10051004
1005+ .. class :: ECHStatus
1006+
1007+ :class: `enum.IntEnum ` collection of Encrypted Client Hello (ECH) statuses
1008+ returned by :meth: `SSLSocket.get_ech_status `.
1009+
1010+ .. versionadded :: TODO XXX
1011+
10061012.. data :: Purpose.SERVER_AUTH
10071013
10081014 Option for :func: `create_default_context ` and
@@ -1307,6 +1313,22 @@ SSL sockets also have the following additional methods and attributes:
13071313
13081314 .. versionadded :: 3.3
13091315
1316+ .. method :: SSLSocket.get_ech_retry_config()
1317+
1318+ When the status returned by :meth: `SSLSocket.get_ech_status ` after completion of the
1319+ handshake is :data: `ECHStatus.ECH_STATUS_GREASE_ECH `, this method returns the
1320+ configuration value provided by the server to be used for a new connection using
1321+ ECH.
1322+
1323+ .. versionadded :: TODO XXX
1324+
1325+ .. method :: SSLSocket.get_ech_status()
1326+
1327+ Gets the status of Encrypted Client Hello (ECH) processing. Returns an
1328+ :class: `ECHStatus ` instance.
1329+
1330+ .. versionadded :: TODO XXX
1331+
13101332.. method :: SSLSocket.selected_alpn_protocol()
13111333
13121334 Return the protocol that was selected during the TLS handshake. If
@@ -1379,6 +1401,15 @@ SSL sockets also have the following additional methods and attributes:
13791401
13801402 .. versionadded :: 3.2
13811403
1404+ .. attribute :: SSLSocket.outer_server_hostname
1405+
1406+ Hostname of the server name used in the outer ClientHello when Encrypted Client
1407+ Hello (ECH) is used: :class: `str ` type, or ``None `` for server-side socket or
1408+ if the outer server name was not specified in the constructor or the ECH
1409+ configuration.
1410+
1411+ .. versionadded :: TODO XXX
1412+
13821413.. attribute :: SSLSocket.server_side
13831414
13841415 A boolean which is ``True `` for server-side sockets and ``False `` for
@@ -1680,6 +1711,24 @@ to speed up repeated connections from the same clients.
16801711
16811712 .. versionadded :: 3.5
16821713
1714+ .. method :: SSLContext.set_ech_config(ech_config)
1715+
1716+ Sets an Encrypted Client Hello (ECH) configuration, which may be discovered from
1717+ an HTTPS resource record in DNS or from :meth: `SSLSocket.get_ech_retry_config `.
1718+ Multiple calls to this functions will accumulate the set of values available for
1719+ a connection.
1720+
1721+ If the input value provided contains no suitable value (e.g. if it only contains
1722+ ECH configuration versions that are not supported), an :class: `SSLError ` will be
1723+ raised.
1724+
1725+ The ech_config parameter should be a bytes-like object containing the raw ECH
1726+ configuration.
1727+
1728+ This method will raise :exc: `NotImplementedError ` if :data: `HAS_ECH ` is ``False ``.
1729+
1730+ .. versionadded :: TODO XXX
1731+
16831732.. method :: SSLContext.set_npn_protocols(protocols)
16841733
16851734 Specify which protocols the socket should advertise during the SSL/TLS
@@ -1699,6 +1748,28 @@ to speed up repeated connections from the same clients.
16991748
17001749 NPN has been superseded by ALPN
17011750
1751+ .. method :: SSLContext.set_outer_alpn_protocols(protocols)
1752+
1753+ Specify which protocols the socket should advertise during the TLS
1754+ handshake in the outer ClientHello when ECH is used. The *protocols *
1755+ argument accepts the same values as for
1756+ :meth: `~SSLContext.set_alpn_protocols `.
1757+
1758+ This method will raise :exc: `NotImplementedError ` if :data: `HAS_ECH ` is
1759+ ``False ``.
1760+
1761+ .. versionadded :: TODO XXX
1762+
1763+ .. method :: SSLContext.set_outer_server_hostname(server_hostname)
1764+
1765+ Specify which hostname the socket should advertise during the TLS
1766+ handshake in the outer ClientHello when ECH is used.
1767+
1768+ This method will raise :exc: `NotImplementedError ` if :data: `HAS_ECH ` is
1769+ ``False ``.
1770+
1771+ .. versionadded :: TODO XXX
1772+
17021773.. attribute :: SSLContext.sni_callback
17031774
17041775 Register a callback function that will be called after the TLS Client Hello
@@ -2594,6 +2665,8 @@ provided.
25942665 - :meth: `~SSLSocket.verify_client_post_handshake `
25952666 - :meth: `~SSLSocket.unwrap `
25962667 - :meth: `~SSLSocket.get_channel_binding `
2668+ - :meth: `~SSLSocket.get_ech_retry_config `
2669+ - :meth: `~SSLSocket.get_ech_status `
25972670 - :meth: `~SSLSocket.version `
25982671
25992672 When compared to :class: `SSLSocket `, this object lacks the following
@@ -2813,6 +2886,52 @@ of TLS/SSL. Some new TLS 1.3 features are not yet available.
28132886- TLS 1.3 features like early data, deferred TLS client cert request,
28142887 signature algorithm configuration, and rekeying are not supported yet.
28152888
2889+ Encrypted Client Hello
2890+ ^^^^^^^^^^^^^^^^^^^^^^
2891+
2892+ .. versionadded :: TODO XXX
2893+
2894+ Encrypted Client Hello (ECH) allows for encrypting values that have previously only been
2895+ included unencrypted in the ClientHello records when establishing a TLS connection. To use
2896+ ECH it is necessary to provide configuration values that contain a version, algorithm
2897+ parameters, the public key to use for HPKE encryption and the "public_name" that is by
2898+ default used for the unencrypted (outer) SNI when ECH is attempted. These configuration
2899+ values may be discovered through DNS or through the "retry config" mechanism.
2900+
2901+ The following example assumes that you have discovered a set of ECH configuration values
2902+ from DNS, or *ech_configs * may be an empty list to rely on the "retry config" mechanism::
2903+
2904+ import socket
2905+ import ssl
2906+
2907+
2908+ def connect_with_tls_ech(hostname: str, ech_configs: List[str],
2909+ use_retry_config: bool=True) -> ssl.SSLSocket:
2910+ context = ssl.create_default_context()
2911+ for ech_config in ech_configs:
2912+ context.set_ech_config(ech_config)
2913+ with socket.create_connection((hostname, 443)) as sock:
2914+ with context.wrap_socket(sock, server_hostname=hostname) as ssock:
2915+ if (ssock.get_ech_status == ECHStatus.ECH_STATUS_GREASE_ECH
2916+ and use_retry_config):
2917+ return connect_with_ech(hostname, [ssock.get_ech_retry_config()],
2918+ False)
2919+ return ssock
2920+
2921+ hostname = "www.python.org"
2922+ ech_configs = [] # Replace with a call to a function to lookup
2923+ # ECH configurations in DNS
2924+
2925+ ssock = connect_with_tls_ech(hostname, ech_configs)
2926+
2927+ The following classes, methods, and attributes will be useful for using ECH:
2928+
2929+ - :class: `ECHStatus `
2930+ - :meth: `SSLContext.set_ech_config `
2931+ - :meth: `SSLContext.set_outer_alpn_protocols `
2932+ - :meth: `SSLContext.set_outer_server_hostname `
2933+ - :meth: `SSLSocket.get_ech_status `
2934+ - :meth: `SSLSocket.get_ech_retry_config `
28162935
28172936.. seealso ::
28182937
0 commit comments