MQTT over Thread

Today I am attempting to set up an MQTT connection from a Thread device to an MQTT server on the Internet (for better or for worse, if this is a terrible idea I'm open to suggestions).

I've done some preliminary investigation using the Thread CLI example and am now starting to develop code using the Thread API in SDK 2.6.0.  I have a border router running on an RPi with NAT64.

At this point I can do a DNS lookup using otDnsClientResolveIp4Address, sending the request to fd34:e64f:ccd9:02:0:0:808:808 (i.e. 8.8.8.8) and I get back the address of the MQTT server as a synthesized IPv6 address.  I can ping this address and get a response.

The next step is to attempt an MQTT connection. 

I start by calling getaddrinfo() to resolve the IP address of the broker, this fails with -ENOENT, it's the same whether I use hints.ai_family = AF_INET or AF_INET6.

So instead I tried using the address returned by the earlier DNS lookup.  Then I call mqtt_connect() but get -EPROTOTYPE (protocol wrong type for socket).

I see some discussion in DevZone from people trying to do similar things but none quite the same as this.  Perhaps I'm being naive thinking that it should 'just work'?

Any suggestions will be gladly received.

Thanks,

  Frog

Parents Reply Children
  • I looked at the CLI sample again and found that I could request CONFIG_MBEDTLS_LEGACY_CRYPTO_C without breaking OpenThread.  I noticed that the CLI example was built with SDK version 2.5.1 rather than 2.6.0 that I'm using for the project I'm working on.  Dropping back to 2.5.1 in my own project appears to resolve the problem of breaking OpenThread, which is a step forward, but for some reason the TLS negotiation is no longer working - MQTT opens the TCP port but no 'client hello' packet is sent.  I'll continue to investigate that.

  • Thanks for your patience, I've been dealing with some other matters for a few days.

    Looking at the CLI example some more, the default configuration opens a TCP connection and then attempts TLS negotiation with the default ciphersuites (using SDK2.5.1).  However, when I set CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y it seems to break - the initial TCP connection packet should just have the SYN flag set but with LEGACY_C it has SYN, ECN and CWR according to Wireshark, and there's no response from the server.

    I know from this post  PSA crypto features not enabled when CONFIG_MBEDTLS_LEGACY_CRYPTO_C is enabled that specifying LEGACY_C causes some PSA functionality to be lost.  Given that the legacy APIs are deprecated it makes sense that I would aim not to use them but should use the PSA APIs, and logically I'd use SDK 2.6.0 where OpenThread uses PSA too.

    So I'm back to the problem of wanting to specify one additional RSA-based cipersuite in addition to those that OT needs.  As far as I can see (please tell me if I'm wrong) I should be able to use the precompiled openThread library provided that I also provide a PSA suite that at least satisfies OT.

    Since I need an RSA-based cipersuite, is it essential to enable the legacy APIs (which the dependency tree seems to suggest) or is there another way to do this?

  • Hi Frog,

    Welcome back!

    Frog said:
    I'm back to the problem of wanting to specify one additional RSA-based cipersuite in addition to those that OT needs.  As far as I can see (please tell me if I'm wrong) I should be able to use the precompiled openThread library provided that I also provide a PSA suite that at least satisfies OT.

    You are free to do this on your application codes. The certification should be OK according to Certification by inheritance without modifications to binaries, but if you use deprecated Mbed TLS support by setting the CONFIG_OPENTHREAD_NRF_SECURITY_CHOICE Kconfig option to y, but you must build the Thread libraries from source, the Certification by inheritance with modifications to binaries need to be followed.

    Frog said:
    Since I need an RSA-based cipersuite, is it essential to enable the legacy APIs (which the dependency tree seems to suggest) or is there another way to do this?

    As far as I know, using legacy APIs is the shortest way to achieve your target.

    However, it's important to note that combining legacy and PSA crypto APIs in the same application might work, but it's not a recommended or maintained solution. 

    Best regards,

    Charlie

  • Hi Charlie,

      Since last time I have moved from a Thingy91 to a Fanstel BT40NE module which is based on an nRF5340 and has a 21540 FEM, which I've got working with some SDK adjustments as recommended by Fanstel.  I'm more or less back where I was with the MQTT connection - the device sends a hello request to the server but with the default list of ciphersuites.

    I've copied the config from here
    RE: Error -22 in mqtt_connect() - nRF52840dk with Azure IoT Hub using OpenThread and TCP
    and resolved a few issues, now I'm down to three problems that appear to be closely related: MBEDTLS_CIPHER_AES_ENABLED, MBEDTLS_CIPHER_CCM_ENABLED and MBEDTLS_MAC_CMAC_ENABLED.  The error messages such as

    warning: MBEDTLS_CIPHER_AES_ENABLED (defined at C:/nordic/v2.6.1/zephyr/modules/mbedtls\Kconfig.tls-generic:257, modules\mbedtls\Kconfig.tls-generic:257) has direct dependencies (!(NRF_SECURITY || NORDIC_SECURITY_BACKEND) && MBEDTLS_BUILTIN && MBEDTLS_CFG_FILE = "config-tls-generic.h" && MBEDTLS) || (!(NRF_SECURITY || NORDIC_SECURITY_BACKEND) && MBEDTLS_BUILTIN && MBEDTLS_CFG_FILE = "config-tls-generic.h" && MBEDTLS && 0) with value n, but is currently being y-selected by the following symbols:
     - OPENTHREAD_MBEDTLS (defined at subsys/net/l2/openthread/Kconfig:179), with value y, direct dependencies NET_L2_OPENTHREAD && NETWORKING (value: y), and select condition NET_L2_OPENTHREAD && NETWORKING (value: y)

    tell me that OpenThread requires these set to 'y' but they are forced to 'n' because CONFIG_MBEDTLS_BUILTIN=n, in turn because I don't have MBEDTLS_IMPLEMENTATION set and I'm not sure how to do that.

    I'm currently using SDK v2.6.1 and getting ready to move to v2.7.0.

    Are you able to give any guidance please?

  • Hi Frog,

    Could you have a quick try to enable configure NRF_SECURITY_LEGACY_AND_PSA?

    config NRF_SECURITY_LEGACY_AND_PSA
        bool
        default y
        select EXPERIMENTAL
        depends on MBEDTLS_LEGACY_CRYPTO_C && MBEDTLS_PSA_CRYPTO_C
        # This configuration doesn't affect TF-M builds since the PSA
        # APIs are provided by TF-M.
        # When this configuration is enabled we manually enable
        # some symbols in the build_config.h file in the Oberon PSA core.
        # This requires only the Oberon PSA crypto driver to be enabled,
        # it requires the CC3XX platform library to get random data and
        # the trusted storage for ITS support. The depenedencies here
        # match what we enable in the build_config.h file so if we need to
        # modify the dependencies here we also need to modify the build_config.h.
        depends on PSA_CRYPTO_DRIVER_OBERON && !PSA_CRYPTO_DRIVER_CC3XX
        depends on NRF_CC3XX_PLATFORM
        depends on TRUSTED_STORAGE
        depends on !BUILD_WITH_TFM
        help
           This is an option to support legacy mbedTLS and PSA crypto APIs
           at the same time. This is not recommended as it is not fully
           supported in our system. This feature might get changed/removed at
           any time in the future. You are advised to use the PSA APIs
           for any new developments.

           This option doesn't use the nrf_security for the internal
           PSA configuration. It always use the Oberon PSA driver
           for all the crypto operations expect for the PRNG which
           uses the nrf_cc3xx_platform library.
    Best regards,
    Charlie
  • Related