Skip to content

ussl.wrapsocket and mbedtls #3646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tsc87 opened this issue Feb 28, 2018 · 13 comments
Open

ussl.wrapsocket and mbedtls #3646

tsc87 opened this issue Feb 28, 2018 · 13 comments
Labels
extmod Relates to extmod/ directory in source

Comments

@tsc87
Copy link

tsc87 commented Feb 28, 2018

The function arguments for ussl.wrapsocket for ESP32 do not match with the documentation. ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
It seems that the modussl_mbedtls file has a modified function that has parameters listed as "key" and "cert" and missing argument for ca_cert.
Also, in socket_new, the call to mbedtls_ctr_drbg_seed takes null_entropy_func instead of mbedtls_entropy_func.
How to make the ussl.wrapsocket working for ESP32 for use with AWS IoT?

@dpgeorge
Copy link
Member

dpgeorge commented Mar 5, 2018

It seems that the modussl_mbedtls file has a modified function that has parameters listed as "key" and "cert" and missing argument for ca_cert.

Yes there is a discrepancy with the docs and the implementation. Actually, both the axtls and mbedtls implementations of ussl accept the same set of keyword args: key, cert, server_side, server_hostname.

The key and cert args are equivalent to keyfile and certfile respectively, except the former take a bytes object with the data rather than a filename to read the data from. So you can use it like this:

with open('mykeyfile', 'rb') as f:
    keydata = f.read()
with open('mycertfile', 'rb') as f:
    certdata = f.read()
sock2 = ussl.wrap_socket(sock, key=keydata, cert=certdata)

Also, in socket_new, the call to mbedtls_ctr_drbg_seed takes null_entropy_func instead of mbedtls_entropy_func.

Yes that needs to be fixed. But it should still work as-is.

@Sunrise17
Copy link

Dear @dpgeorge , yes this is the same issue which i have opened in Link
When approx. will it be available for the Esp-WRoom-32 Boards? As far as i see, @danicampora applied for cc3200, allows passing through ca_certs in ssl_params. ~/ports/cc3200/mods/modussl.c.

@dpgeorge
Copy link
Member

Also, in socket_new, the call to mbedtls_ctr_drbg_seed takes null_entropy_func instead of mbedtls_entropy_func.

This was fixed by ea22406

@m0ot
Copy link

m0ot commented Apr 2, 2019

As I newly understood, esp32 port supports the open source mbedtls and not axtls. However, I implemented the latest esp32 bin file https://micropython.org/download#esp32 on the esp32 board. Then I tried to speak secured mqtt connection using the ussl.wrap_socket function https://docs.micropython.org/en/latest/library/ussl.html but it speaks only TLS 1.2
I'm a bit confused! If esp32 bin file supports the open source mbedtls then it should speak with the server TLS 1.3 because mbedtls already supports the latest version (TLS 1.3).
Any ideas?

@willcharlton
Copy link

willcharlton commented May 14, 2019

I am also not sure what to make of this. According to docs, the ussl module should contain some constants for cert requirements, but when I look on my ESP32:

>>> import os
>>> os.uname()
(sysname='esp32', nodename='esp32', release='1.10.0', version='v1.10-342-g7359a9e2f on 2019-05-13', machine='ESP32 module with ESP32')
>>> import ussl
>>> dir(ussl)
['__class__', '__name__', 'wrap_socket']

No such constants are available.

Additionally, when umqtt.simple.MQTTClient.connect() calls .wrap_socket() on a socket object, I get complaints about unsupported arguments.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lib/umqtt/simple.py", line 61, in connect
TypeError: extra keyword arguments given

Is there a way I can test which tls library I'm actually using during these attempts?

Is this a platform specific issue? (i.e. is this only present on ESP32 but not on other platforms)

Let me know if/how I can help. Supporting mTLS on devices is paramount for me. Thanks!

@Molaire
Copy link

Molaire commented Jul 23, 2021

I am also not sure what to make of this. According to docs, the ussl module should contain some constants for cert requirements, but when I look on my ESP32:

>>> import os
>>> os.uname()
(sysname='esp32', nodename='esp32', release='1.10.0', version='v1.10-342-g7359a9e2f on 2019-05-13', machine='ESP32 module with ESP32')
>>> import ussl
>>> dir(ussl)
['__class__', '__name__', 'wrap_socket']

No such constants are available.

Additionally, when umqtt.simple.MQTTClient.connect() calls .wrap_socket() on a socket object, I get complaints about unsupported arguments.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lib/umqtt/simple.py", line 61, in connect
TypeError: extra keyword arguments given

Is there a way I can test which tls library I'm actually using during these attempts?

Is this a platform specific issue? (i.e. is this only present on ESP32 but not on other platforms)

Let me know if/how I can help. Supporting mTLS on devices is paramount for me. Thanks!

Did you find an answer? I am facing the same problem with 1.16

@noodlemind
Copy link

ESP32 is returning the same OSError:[Errno 12] ENOMEM for my umqtt client connection with cert key.

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Jul 11, 2022
@daniel-redder
Copy link

daniel-redder commented Dec 6, 2022

I'm also having this issue. Any solutions?

Raspberry Pi Pico latest micropython with umqtt

@bneigher
Copy link

Is there anyone who can provide an ETA on when this is going to be supported?

>>> import os
>>> os.uname()
(sysname='esp32', nodename='esp32', release='1.19.1', version='v1.19.1 on 2022-06-18', machine='ESP32C3 module with ESP32C3')

ca_certs seems to not be a supported parameter for ssl_params in from the micropython-mqtt, specifically boiling down to ussl.wrap_socket not supporting it.

from umqtt.simple import MQTTClient

# Set up the AWS IoT certificate and key files
cert_file = "/cert/device.cert.pem"
key_file = "/cert/device.private.key"
root_ca_file = "/cert/root-CA.crt"  # Path to the root CA certificate file

with open(key_file, 'r') as f:
  PVT_KEY = f.read()
  
with open(cert_file, 'r') as f:
  CERT_KEY = f.read()

client = MQTTClient(client_id, endpoint, ssl=True, ssl_params={
    "cert": CERT_KEY,
    "key": PVT_KEY,
    # "ca_certs": root_ca_file,  # Specify the path to the root CA certificate file <-- need this
    "server_side": False,  # set this to False for client-side SSL
})

@Carglglz
Copy link
Contributor

@bneigher
Copy link

bneigher commented Mar 28, 2023

thanks that seems to have fixed it. I was also using a different library.

import ssl
import time
import machine
from mqtt_as import MQTTClient, config
from ubinascii import hexlify

client_id = hexlify(machine.unique_id()).decode('utf-8')

# Set up the AWS IoT endpoint details
endpoint = "xxxxxxx.iot.yyyy-east-1.amazonaws.com"
topic = "sdk/test/python"

# Set up the AWS IoT certificate and key files
cert_file = "/cert/device.cert.pem"
key_file = "/cert/device.private.key"
root_ca_file = "/cert/root-CA.crt"  # Path to the root CA certificate file

with open(key_file, 'r') as f:
  PVT_KEY = f.read()
  
with open(cert_file, 'r') as f:
  CERT_KEY = f.read()
  
with open(root_ca_file, 'r') as f:
  CA_KEY = f.read()


ssl_params = {
    'key': PVT_KEY,
    'cert': CERT_KEY,
    'cadata': CA_KEY,
    'cert_reqs': ssl.CERT_REQUIRED,
    'do_handshake':True
}
                    
# Connect to AWS IoT MQTT
def connectMQTT():
    print("MQTT CONNECTING")
    config['client_id'] = client_id
    config['server'] = endpoint
    config['ssl_params'] = ssl_params
    client = MQTTClient(config)
    client.connect()
    print("MQTT CONNECTED")
    return client

# Publish a message to the topic
def sendMQTT(client, message):
    client.publish(topic, message)

I'm seeing successful connections in aws, but my published messages are not showing up in aws.. onto the next adventure.

@Carglglz
Copy link
Contributor

@bneigher see also #9259, I think you need to indicate server_hostname in ssl_params, which in your case is endpoint
e.g.

{...
'server_hostname': endpoint }

@bneigher
Copy link

bneigher commented Mar 28, 2023

no dice.. I'm actually noticing that client.isconnected() is False.. so maybe false alarm about it being truly connected. I am definitely connected to my wifi network as I have this code above subsequent to a successful connection to my network

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

No branches or pull requests

10 participants