Skip to content

ussl.wrapsocket and mbedtls #3646

Description

@tsc87

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?

Activity

  1. dpgeorge commented on Mar 5, 2018

    @dpgeorge
    Member

    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.

  2. Sunrise17 commented on Apr 11, 2018

    @Sunrise17

    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.

  3. dpgeorge commented on Jul 10, 2018

    @dpgeorge
    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

  4. m0ot commented on Apr 2, 2019

    @m0ot

    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?

  5. willcharlton commented on May 14, 2019

    @willcharlton

    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!

  6. Molaire commented on Jul 23, 2021

    @Molaire

    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

  7. noodlemind commented on Sep 28, 2021

    @noodlemind

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

  8. added
    extmodRelates to extmod/ directory in source
    on Jul 11, 2022
  9. daniel-redder commented on Dec 6, 2022

    @daniel-redder

    I'm also having this issue. Any solutions?

    Raspberry Pi Pico latest micropython with umqtt

  10. bneigher commented on Mar 28, 2023

    @bneigher

    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
    })
  11. Carglglz commented on Mar 28, 2023

    @Carglglz
    Contributor
  12. bneigher commented on Mar 28, 2023

    @bneigher

    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.

  13. Carglglz commented on Mar 28, 2023

    @Carglglz
    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 }
    
  14. bneigher commented on Mar 28, 2023

    @bneigher

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    extmodRelates to extmod/ directory in source

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions