Laszlo
Laszlo

Reputation: 21

ESP32 MicroPython SSL WebSocket server fail

I'm trying to set up a secure socket server on esp32 with micropython. I used/tried the latest bulid (esp32-idf3-20200117-v1.12-68-g3032ae115.bin) with a self-signed certificate.

I saw a lot of memory leak related problem with ssl.wrap_socket() on esp32/esp8266 but what I got is different:

mbedtls_ssl_handshake error: -4310
Traceback (most recent call last):
  File "boot.py", line 100, in <module>
OSError: [Errno 5] EIO

and the connection fails of course. I try to connect from my laptop. The exact same code of client side works if I start a secure socket server on the laptop itself (127.0.0.1) so I suppose that the client side is OK and the problem is on the server side.

I could not find any solution for this problem yet. I tried certificate and key both in 'der' and 'pem' format the result is the same.

The toy server code I tried:

import esp
esp.osdebug(None)

import gc
gc.collect()

import usocket as socket
import ssl
import machine
import network

KEY_PATH = 'server_key.der'
CERT_PATH = 'server_cert.der'

ssid= "AP_local"
pw="passwd"
ap = network.WLAN(network.AP_IF)  # create access-point interface
ap.config(essid=ssid, password=pw, authmode=4)  # set the ESSID of the access point
ap.ifconfig(('192.168.3.1', '255.25.255.0', '192.168.3.1', '8.8.8.8'))
ap.active(True)


with open(KEY_PATH, 'rb') as f:
    key = f.read()
print(key)
print(" ")
with open(CERT_PATH, 'rb') as f:
    cert = f.read()


#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET,  socket.SO_REUSEADDR, 1)
ad = ap.ifconfig()
addr = socket.getaddrinfo(ad[0], 8443)[0][-1]
s.bind(addr)
s.listen(5)

import gc
gc.collect()


while True:
    print("ssl connection started")
    cl, addr = s.accept()
    scl = ssl.wrap_socket(cl, server_side=True, cert=cert, key=key)

    print(gc.mem_free())
    l = 0
    while True:
        req = scl.read(1024)
        print(req)
        if not req or b'\r\n' in req:
            break

    response = '\r\n'.join(['HTTP/1.1 200 OK',
                            'Content-Type: text/plain',
                            'OK',
                           'Connection: close', '\r\n'])
    scl.write(response.encode("utf-8"))
    scl.close()

I hope someone could help me with this, thanks!

Upvotes: 1

Views: 2015

Answers (1)

Laszlo
Laszlo

Reputation: 21

OK, after spending a few days on searching and reading and testing I got a solution and a possible reason for this issue. I hope it will help others a little. I want to put forward that I didn't dig into the source code of mbedtls so the reasoning is somewhat phenomenological.

First, I tried to connect from a python program with default settings which failed as shown above. Then I tried with the openssl cli, which also failed. I tried with the example given at https://github.com/micropython/micropython/blob/master/examples/network/http_server_ssl.py and failed again but with different error codes. Finally I found a very useful page: https://tls.mbed.org/api/ssl_8h.html#a55ed67b6e414f9b381ff536d9ea6b9c0 which helped to understand where the problem occures. Now depending on requirements different errors occured from -7900,-7780, -7380, -7d00.

It turned out that although in the documentation the cipher suit being used is automatically agreed during handshake but there is some bug in it or the implementation of some of them in micropython is different.

I didn't tested all the available ciphers on my laptop but e.g.: AES_256_GCM_SHA384 cipher works. For me it is enough now.

Upvotes: 1

Related Questions