@@ -214,7 +214,6 @@ purposes.
214
214
The context now uses :data: `VERIFY_X509_PARTIAL_CHAIN ` and
215
215
:data: `VERIFY_X509_STRICT ` in its default verify flags.
216
216
217
-
218
217
Exceptions
219
218
^^^^^^^^^^
220
219
@@ -1003,6 +1002,13 @@ Constants
1003
1002
1004
1003
.. versionadded :: 3.6
1005
1004
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
+
1006
1012
.. data :: Purpose.SERVER_AUTH
1007
1013
1008
1014
Option for :func: `create_default_context ` and
@@ -1307,6 +1313,22 @@ SSL sockets also have the following additional methods and attributes:
1307
1313
1308
1314
.. versionadded :: 3.3
1309
1315
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
+
1310
1332
.. method :: SSLSocket.selected_alpn_protocol()
1311
1333
1312
1334
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:
1379
1401
1380
1402
.. versionadded :: 3.2
1381
1403
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
+
1382
1413
.. attribute :: SSLSocket.server_side
1383
1414
1384
1415
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.
1680
1711
1681
1712
.. versionadded :: 3.5
1682
1713
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
+
1683
1732
.. method :: SSLContext.set_npn_protocols(protocols)
1684
1733
1685
1734
Specify which protocols the socket should advertise during the SSL/TLS
@@ -1699,6 +1748,28 @@ to speed up repeated connections from the same clients.
1699
1748
1700
1749
NPN has been superseded by ALPN
1701
1750
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
+
1702
1773
.. attribute :: SSLContext.sni_callback
1703
1774
1704
1775
Register a callback function that will be called after the TLS Client Hello
@@ -2594,6 +2665,8 @@ provided.
2594
2665
- :meth: `~SSLSocket.verify_client_post_handshake `
2595
2666
- :meth: `~SSLSocket.unwrap `
2596
2667
- :meth: `~SSLSocket.get_channel_binding `
2668
+ - :meth: `~SSLSocket.get_ech_retry_config `
2669
+ - :meth: `~SSLSocket.get_ech_status `
2597
2670
- :meth: `~SSLSocket.version `
2598
2671
2599
2672
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.
2813
2886
- TLS 1.3 features like early data, deferred TLS client cert request,
2814
2887
signature algorithm configuration, and rekeying are not supported yet.
2815
2888
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 `
2816
2935
2817
2936
.. seealso ::
2818
2937
0 commit comments