3

I'm having hard time with pyOpenssl server to negotiate TLS 1.3. I used openssl s_client(1.3 supported) to connect to the server with no luck. However the server works with version TLS 1.2 and below. Could you please help what am I missing? Thanks in advance!

tls_server.py
-------------

import socket
from OpenSSL import SSL
sslctx = SSL.Context(SSL.TLSv1_2_METHOD)
sslctx.set_options(SSL.OP_NO_TLSv1_2 | SSL.OP_NO_TLSv1_1 | SSL.OP_NO_TLSv1)
sslctx.set_cipher_list(b"TLS_AES_128_GCM_SHA256:AES128-GCM-SHA256")
sslctx.use_privatekey_file("key.pem")
sslctx.use_certificate_file("cert.pem")

bindsocket = socket.socket()
bindsocket.bind(('', 4433))
bindsocket.listen(5)

while True:
    newsocket, fromaddr = bindsocket.accept()
    sslconn = SSL.Connection(sslctx, newsocket)
    sslconn.set_accept_state()
    sslconn.do_handshake()
    print(f"List of ciphers: {sslconn.get_cipher_list()}")
    req = sslconn.read(4096)
    print(req)
    sslconn.write(b"HTTP/1.1 200 OK\r\nServer: my-special\r\nContent-length: 10\r\n\r\nHello!\r\n\r\n")
    sslconn.set_shutdown(SSL.SENT_SHUTDOWN)

All I'm getting is the below error when I force my client to connect tls1.3 only

$ openssl version
OpenSSL 1.1.1d  10 Sep 2019
$ openssl s_client -connect localhost:4433 -tls1_3
4641068480:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl/record/rec_layer_s3.c:1544:SSL alert number 40

and the server returns the trace:


$ python3.8 tls_server.py
Traceback (most recent call last):
  File "tls_server.py", line 18, in <module>
    sobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/OpenSSL/SSL.py", line 1934, in do_handshake
    self._raise_ssl_error(self._ssl, result)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/OpenSSL/SSL.py", line 1671, in _raise_ssl_error
    _raise_current_error()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'tls_post_process_client_hello', 'no shared cipher')]
$

with successful TLS 1.2 connection, I see the server returns the following ciphers confirming TLS 1.3 support.

$ python3.8 tls_server.py
List of ciphers: ['TLS_AES_256_GCM_SHA384', 'TLS_CHACHA20_POLY1305_SHA256', 'TLS_AES_128_GCM_SHA256', 'AES128-GCM-SHA256']
b'GET /\n'

version of the tools I'm using

$ python3.8 -m OpenSSL.debug
pyOpenSSL: 19.1.0
cryptography: 2.9.2
cffi: 1.13.2
cryptography's compiled against OpenSSL: OpenSSL 1.1.1g  21 Apr 2020
cryptography's linked OpenSSL: OpenSSL 1.1.1g  21 Apr 2020
Pythons's OpenSSL: OpenSSL 1.1.1d  10 Sep 2019
Python executable: /Library/Frameworks/Python.framework/Versions/3.8/bin/python3.8
Python version: 3.8.1 (v3.8.1:1b293b6006, Dec 18 2019, 14:08:53)
[Clang 6.0 (clang-600.0.57)]
Platform: darwin
Pr1614
  • 61
  • 1
  • 6

1 Answers1

3

I'm not sure about this config:

sslctx = SSL.Context(SSL.TLSv1_2_METHOD)
sslctx.set_options(SSL.OP_NO_TLSv1_2 | SSL.OP_NO_TLSv1_1 | SSL.OP_NO_TLSv1)

Aren't you saying to only use TLSv1.2 and then also not to use TLSv1 - TLSv1.2?

Now there is no SSL.TLSv1_3_METHOD option and you’re supposed to use SSL.TLS_METHOD but looks like that is not exposed to pyopenssl yet.

It seems there is a (currently) open issue about how to configure this better but that still doesn’t add SSL.TLS_METHOD.

Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • Thank you for your response. Since there is no `SSL.TLSv1_3_METHOD` available, I'm left to use the next higher protocol version ie: `SSL.TLSv1_2_METHOD`. `sslctx = SSL.Context(SSL.TLSv1_2_METHOD)`. On the next line in config, I tried many options to see if I can force to listen TLS 1.3 only but no luck. Also tried without this option as well and same result. `sslctx.set_options(SSL.OP_NO_TLSv1_2 | SSL.OP_NO_TLSv1_1 | SSL.OP_NO_TLSv1)`. Thanks for pointing me to the open issue. Is there a way to make TLS 1.3 negotiate with pyopenssl? – Pr1614 Jun 07 '20 at 21:10
  • Hmmm... it would appear not. You’re supposed to set this with `sslctx = SSL.Context(SSL.TLS_METHOD)` but looks like that is not exposed to pyopenssl. – Barry Pollard Jun 07 '20 at 22:30
  • It seems `SSL.Context(SSL.SSLv23_METHOD)` is able to negotiate a TLS 1.3 version handshake, at least when used as a client (Python 2.7, Debian Python OpenSSL package 19.0.0-1, Debian openssl 1.1.1d) – Patrick Mevzek Jul 19 '20 at 21:49
  • Do you have a code example @PatrickMevzek ? I tried that without success – Santiago Rodriguez Sep 28 '21 at 15:36
  • @SantiagoRodriguez If you have a specific question please open a new one with your code, explaining what you want to do and what doesn't work. – Patrick Mevzek Sep 28 '21 at 16:06
  • I was just looking at this and currently `SSL.TLS_METHOD` [does seem to be exposed](https://github.com/pyca/pyopenssl/blob/main/src/OpenSSL/SSL.py#L140). And `SSL.Context(method=SSL.TLS_METHOD)` works fine for non-TLS1.3 connections. However on TLS1.3 I get `OpenSSL.SSL.Error: [('SSL routines', '', 'wrong version number')]` – Nexus Jun 07 '22 at 02:35