Synss / python-mbedtls

Cryptographic library with an mbed TLS back end
MIT License
79 stars 28 forks source link

(D)TLS PSK Examples not working on Windows build #41

Closed victorlawn closed 2 years ago

victorlawn commented 3 years ago

I am submitting a …

Description

Setup:

The module was successfully setup, hashing functions proved to be working. It appears that all the functionality is working except TLS. A (D)TLS PSK client and server were setup.

The ClientHello message gets sent but the server fails on do_handshake function. Exception thrown: mbedtls.exceptions.TLSError: TLSError([0x0047] 'NET - Polling the net context failed')

Included .pcap trace: python-mbedtls_rst.zip

Current behavior

Client error traceback:

Traceback (most recent call last): File "...\mbedtls\mbedtls-test.py", line 36, in block(tls_cli.do_handshake) File "...\mbedtls\mbedtls-test.py", line 26, in block return callback(*args, **kwargs) File "src\mbedtls\tls.pyx", line 1691, in mbedtls.tls.TLSWrappedSocket.do_handshake File "src\mbedtls\tls.pyx", line 1458, in mbedtls.tls.TLSWrappedBuffer.do_handshake File "src\mbedtls\tls.pyx", line 1276, in mbedtls.tls._BaseContext._do_handshake File "src\mbedtls\tls.pyx", line 1281, in mbedtls.tls._BaseContext._do_handshake_step File "src\mbedtls\tls.pyx", line 1300, in mbedtls.tls._BaseContext._handle_handshake_response File "src\mbedtls\exceptions.pyx", line 54, in mbedtls.exceptions.check_error File "src\mbedtls\exceptions.pyx", line 57, in mbedtls.exceptions.check_error mbedtls.exceptions.TLSError: TLSError([0x0047] 'NET - Polling the net context failed')

Server error traceback:

Traceback (most recent call last): File "...\mbedtls\mbedtls-test-server.py", line 60, in server_main_loop(tls_srv) File "...\mbedtls\mbedtls-test-server.py", line 33, in server_main_loop block(conn.do_handshake) File "...\mbedtls\mbedtls-test-server.py", line 27, in block return callback(*args, **kwargs) File "src\mbedtls\tls.pyx", line 1691, in mbedtls.tls.TLSWrappedSocket.do_handshake File "src\mbedtls\tls.pyx", line 1458, in mbedtls.tls.TLSWrappedBuffer.do_handshake File "src\mbedtls\tls.pyx", line 1276, in mbedtls.tls._BaseContext._do_handshake File "src\mbedtls\tls.pyx", line 1281, in mbedtls.tls._BaseContext._do_handshake_step File "src\mbedtls\tls.pyx", line 1300, in mbedtls.tls._BaseContext._handle_handshake_response File "src\mbedtls\exceptions.pyx", line 54, in mbedtls.exceptions.check_error File "src\mbedtls\exceptions.pyx", line 57, in mbedtls.exceptions.check_error mbedtls.exceptions.TLSError: TLSError([0x0047] 'NET - Polling the net context failed')

Expected behavior

The handshake should be successful.

Steps to reproduce

  1. Run server
  2. Run client

Minimal demo of the problem

Server code:

import socket

from mbedtls import tls
import contextlib

get_request = "\r\n".join((
    "GET / HTTP/1.0",
    "",
    "")).encode("ascii")
http_response = "\r\n".join((
    "HTTP/1.0 200 OK",
    "Content-Type: text/html",
    "",
    "<h2>Test Server</h2>",
    "<p>Successful connection.</p>",
    "")).encode("ascii")
http_error = "\r\n".join((
    "HTTP/1.0 400 Bad Request",
    "",
    ""))

def block(callback, *args, **kwargs):
    while True:
        with contextlib.suppress(tls.WantReadError, tls.WantWriteError):
            return callback(*args, **kwargs)

def server_main_loop(sock):
    conn, addr = sock.accept()
    print(conn, addr)
    block(conn.do_handshake)
    data = conn.recv(1024)
    if data == get_request:
        conn.sendall(http_response)
    else:
        conn.sendall(http_error)

srv_conf = tls.TLSConfiguration(
    ciphers=(
        # PSK Requires the selection PSK ciphers.
        "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
    ),
    pre_shared_key_store={
        "test2": b"secret"
    }
)

tls_srv_ctx = tls.ServerContext(srv_conf)

tls_srv = tls_srv_ctx.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))

port = 4433
tls_srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tls_srv.bind(("127.0.0.1", port))
tls_srv.listen(1)

server_main_loop(tls_srv)

Client code:

import socket

from mbedtls import tls
import contextlib

get_request = "\r\n".join((
    "GET / HTTP/1.0",
    "",
    "")).encode("ascii")
http_response = "\r\n".join((
    "HTTP/1.0 200 OK",
    "Content-Type: text/html",
    "",
    "<h2>Test Server</h2>",
    "<p>Successful connection.</p>",
    "")).encode("ascii")
http_error = "\r\n".join((
    "HTTP/1.0 400 Bad Request",
    "",
    ""))

def block(callback, *args, **kwargs):
    while True:
        with contextlib.suppress(tls.WantReadError, tls.WantWriteError):
            return callback(*args, **kwargs)

cli_conf = tls.TLSConfiguration(pre_shared_key=("test2", b"secret"))

tls_cli_ctx = tls.ClientContext(cli_conf)

tls_cli = tls_cli_ctx.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname=None)

tls_cli.connect(("127.0.0.1", 4433))
block(tls_cli.do_handshake)
tls_cli.send(get_request)

Other information

Synss commented 3 years ago

Hi Victor! Thank you for your feedback. You are correct and I am currently working on that.

Synss commented 3 years ago

By the way, I already have client/server tests in the test suite (TestCommunication in tests/test_tls.py) and I just pushed a couple of PowerShell scripts to make building on Windows easier. You can find them on master under /scripts. Adding a simple HTML conversation such as the one you posted would be a good idea as well.

victorlawn commented 2 years ago

Hi Synss, I am wondering if you had any progress this topic, if a fix for this could be available in near time? Or a different question, in your knowledge, is there a prior python-mbedtls release in which both TLS/DTLS are working?

Thanks!

Synss commented 2 years ago

Hi!

‘master’ fixes some problems but the tests still fail in my VM with some Windows error I do not really understand.

I do accept patches, however.

I have not tried that but the WSL would most likely work. Maybe that could be a solution for the time being.

Cheers