]> code.ossystems Code Review - openembedded-core.git/blob
d48cad7586b7cee8369fa020300c13c49c007b76
[openembedded-core.git] /
1 From e950ea68dab006944af194c9910b8f2341d1437d Mon Sep 17 00:00:00 2001
2 From: Christian Heimes <christian@python.org>
3 Date: Thu, 7 Sep 2017 20:23:52 -0700
4 Subject: [PATCH] bpo-29136: Add TLS 1.3 cipher suites and OP_NO_TLSv1_3
5  (GH-1363) (#3444)
6
7 * bpo-29136: Add TLS 1.3 support
8
9 TLS 1.3 introduces a new, distinct set of cipher suites. The TLS 1.3
10 cipher suites don't overlap with cipher suites from TLS 1.2 and earlier.
11 Since Python sets its own set of permitted ciphers, TLS 1.3 handshake
12 will fail as soon as OpenSSL 1.1.1 is released. Let's enable the common
13 AES-GCM and ChaCha20 suites.
14
15 Additionally the flag OP_NO_TLSv1_3 is added. It defaults to 0 (no op) with
16 OpenSSL prior to 1.1.1. This allows applications to opt-out from TLS 1.3
17 now.
18
19 Signed-off-by: Christian Heimes <christian@python.org>.
20 (cherry picked from commit cb5b68abdeb1b1d56c581d5b4d647018703d61e3)
21
22 Upstream-Status: Backport
23 [https://github.com/python/cpython/commit/cb5b68abdeb1b1d56c581d5b4d647018703d61e3]
24
25 Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
26 ---
27  Doc/library/ssl.rst                           | 21 ++++++++++++++
28  Lib/ssl.py                                    |  7 +++++
29  Lib/test/test_ssl.py                          | 29 ++++++++++++++++++-
30  .../2017-09-04-16-39-49.bpo-29136.vSn1oR.rst  |  1 +
31  Modules/_ssl.c                                | 13 +++++++++
32  5 files changed, 70 insertions(+), 1 deletion(-)
33  create mode 100644 Misc/NEWS.d/next/Library/2017-09-04-16-39-49.bpo-29136.vSn1oR.rst
34
35 diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
36 index 14f2d68217..29c5e94cf6 100644
37 --- a/Doc/library/ssl.rst
38 +++ b/Doc/library/ssl.rst
39 @@ -285,6 +285,11 @@ purposes.
40  
41       3DES was dropped from the default cipher string.
42  
43 +   .. versionchanged:: 3.7
44 +
45 +     TLS 1.3 cipher suites TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384,
46 +     and TLS_CHACHA20_POLY1305_SHA256 were added to the default cipher string.
47 +
48  
49  Random generation
50  ^^^^^^^^^^^^^^^^^
51 @@ -719,6 +724,16 @@ Constants
52  
53     .. versionadded:: 3.4
54  
55 +.. data:: OP_NO_TLSv1_3
56 +
57 +   Prevents a TLSv1.3 connection. This option is only applicable in conjunction
58 +   with :const:`PROTOCOL_TLS`. It prevents the peers from choosing TLSv1.3 as
59 +   the protocol version. TLS 1.3 is available with OpenSSL 1.1.1 or later.
60 +   When Python has been compiled against an older version of OpenSSL, the
61 +   flag defaults to *0*.
62 +
63 +   .. versionadded:: 3.7
64 +
65  .. data:: OP_CIPHER_SERVER_PREFERENCE
66  
67     Use the server's cipher ordering preference, rather than the client's.
68 @@ -783,6 +798,12 @@ Constants
69  
70     .. versionadded:: 3.3
71  
72 +.. data:: HAS_TLSv1_3
73 +
74 +   Whether the OpenSSL library has built-in support for the TLS 1.3 protocol.
75 +
76 +   .. versionadded:: 3.7
77 +
78  .. data:: CHANNEL_BINDING_TYPES
79  
80     List of supported TLS channel binding types.  Strings in this list
81 diff --git a/Lib/ssl.py b/Lib/ssl.py
82 index 4d302a78fa..f233e72e1f 100644
83 --- a/Lib/ssl.py
84 +++ b/Lib/ssl.py
85 @@ -122,6 +122,7 @@ _import_symbols('OP_')
86  _import_symbols('ALERT_DESCRIPTION_')
87  _import_symbols('SSL_ERROR_')
88  _import_symbols('VERIFY_')
89 +from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3
90  
91  from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN
92  
93 @@ -162,6 +163,7 @@ else:
94  # (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL')
95  # Enable a better set of ciphers by default
96  # This list has been explicitly chosen to:
97 +#   * TLS 1.3 ChaCha20 and AES-GCM cipher suites
98  #   * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE)
99  #   * Prefer ECDHE over DHE for better performance
100  #   * Prefer AEAD over CBC for better performance and security
101 @@ -173,6 +175,8 @@ else:
102  #   * Disable NULL authentication, NULL encryption, 3DES and MD5 MACs
103  #     for security reasons
104  _DEFAULT_CIPHERS = (
105 +    'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:'
106 +    'TLS13-AES-128-GCM-SHA256:'
107      'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:'
108      'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:'
109      '!aNULL:!eNULL:!MD5:!3DES'
110 @@ -180,6 +184,7 @@ _DEFAULT_CIPHERS = (
111  
112  # Restricted and more secure ciphers for the server side
113  # This list has been explicitly chosen to:
114 +#   * TLS 1.3 ChaCha20 and AES-GCM cipher suites
115  #   * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE)
116  #   * Prefer ECDHE over DHE for better performance
117  #   * Prefer AEAD over CBC for better performance and security
118 @@ -190,6 +195,8 @@ _DEFAULT_CIPHERS = (
119  #   * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, RC4, and
120  #     3DES for security reasons
121  _RESTRICTED_SERVER_CIPHERS = (
122 +    'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:'
123 +    'TLS13-AES-128-GCM-SHA256:'
124      'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:'
125      'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:'
126      '!aNULL:!eNULL:!MD5:!DSS:!RC4:!3DES'
127 diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
128 index f91af7bd05..1acc12ec2d 100644
129 --- a/Lib/test/test_ssl.py
130 +++ b/Lib/test/test_ssl.py
131 @@ -150,6 +150,13 @@ class BasicSocketTests(unittest.TestCase):
132              ssl.OP_NO_COMPRESSION
133          self.assertIn(ssl.HAS_SNI, {True, False})
134          self.assertIn(ssl.HAS_ECDH, {True, False})
135 +        ssl.OP_NO_SSLv2
136 +        ssl.OP_NO_SSLv3
137 +        ssl.OP_NO_TLSv1
138 +        ssl.OP_NO_TLSv1_3
139 +    if ssl.OPENSSL_VERSION_INFO >= (1, 0, 1):
140 +            ssl.OP_NO_TLSv1_1
141 +            ssl.OP_NO_TLSv1_2
142  
143      def test_str_for_enums(self):
144          # Make sure that the PROTOCOL_* constants have enum-like string
145 @@ -3028,12 +3035,33 @@ else:
146                      self.assertEqual(s.version(), 'TLSv1')
147                  self.assertIs(s.version(), None)
148  
149 +        @unittest.skipUnless(ssl.HAS_TLSv1_3,
150 +                             "test requires TLSv1.3 enabled OpenSSL")
151 +        def test_tls1_3(self):
152 +            context = ssl.SSLContext(ssl.PROTOCOL_TLS)
153 +            context.load_cert_chain(CERTFILE)
154 +            # disable all but TLS 1.3
155 +            context.options |= (
156 +                ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2
157 +            )
158 +            with ThreadedEchoServer(context=context) as server:
159 +                with context.wrap_socket(socket.socket()) as s:
160 +                    s.connect((HOST, server.port))
161 +                    self.assertIn(s.cipher()[0], [
162 +                        'TLS13-AES-256-GCM-SHA384',
163 +                        'TLS13-CHACHA20-POLY1305-SHA256',
164 +                        'TLS13-AES-128-GCM-SHA256',
165 +                    ])
166 +
167          @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL")
168          def test_default_ecdh_curve(self):
169              # Issue #21015: elliptic curve-based Diffie Hellman key exchange
170              # should be enabled by default on SSL contexts.
171              context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
172              context.load_cert_chain(CERTFILE)
173 +            # TLSv1.3 defaults to PFS key agreement and no longer has KEA in
174 +            # cipher name.
175 +            context.options |= ssl.OP_NO_TLSv1_3
176              # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled
177              # explicitly using the 'ECCdraft' cipher alias.  Otherwise,
178              # our default cipher list should prefer ECDH-based ciphers
179 @@ -3394,7 +3422,6 @@ else:
180                          s.sendfile(file)
181                          self.assertEqual(s.recv(1024), TEST_DATA)
182  
183 -
184  def test_main(verbose=False):
185      if support.verbose:
186          import warnings
187 diff --git a/Misc/NEWS.d/next/Library/2017-09-04-16-39-49.bpo-29136.vSn1oR.rst b/Misc/NEWS.d/next/Library/2017-09-04-16-39-49.bpo-29136.vSn1oR.rst
188 new file mode 100644
189 index 0000000000..e76997ef83
190 --- /dev/null
191 +++ b/Misc/NEWS.d/next/Library/2017-09-04-16-39-49.bpo-29136.vSn1oR.rst
192 @@ -0,0 +1 @@
193 +Add TLS 1.3 cipher suites and OP_NO_TLSv1_3.
194 diff --git a/Modules/_ssl.c b/Modules/_ssl.c
195 index 0d5c121d2c..c71d89607c 100644
196 --- a/Modules/_ssl.c
197 +++ b/Modules/_ssl.c
198 @@ -4842,6 +4842,11 @@ PyInit__ssl(void)
199  #if HAVE_TLSv1_2
200      PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1);
201      PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2);
202 +#endif
203 +#ifdef SSL_OP_NO_TLSv1_3
204 +    PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", SSL_OP_NO_TLSv1_3);
205 +#else
206 +    PyModule_AddIntConstant(m, "OP_NO_TLSv1_3", 0);
207  #endif
208      PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE",
209                              SSL_OP_CIPHER_SERVER_PREFERENCE);
210 @@ -4890,6 +4895,14 @@ PyInit__ssl(void)
211      Py_INCREF(r);
212      PyModule_AddObject(m, "HAS_ALPN", r);
213  
214 +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3)
215 +    r = Py_True;
216 +#else
217 +    r = Py_False;
218 +#endif
219 +    Py_INCREF(r);
220 +    PyModule_AddObject(m, "HAS_TLSv1_3", r);
221 +
222      /* Mappings for error codes */
223      err_codes_to_names = PyDict_New();
224      err_names_to_codes = PyDict_New();
225 -- 
226 2.17.1
227