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
  • Hi Frog,

    If you search MQTT_TRANSPORT_SECURE in NCS source codes, you will find some samples about to properly set up TLS connection in MQTT.

    Hope this will give you some hint.

    Best regards,

    Charlie

  • Currently I'm able to request a subset of the default ciphersuites, which is a step in the right direction.  The suite that I want to use isn't in that list though.  Looking in ssl_cipersuites.c I see that I need (at least) CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED

    although this depends on CONFIG_MBEDTLS_RSA_C and CONFIG_MBEDTLS_PKCS1_V15, and ultimately on CONFIG_MBEDTLS_LEGACY_CRYPTO_C.  The last of these breaks OpenThread.

    I see that this is a reversal of the situation described here
    PSA crypto features not enabled when CONFIG_MBEDTLS_LEGACY_CRYPTO_C is enabled
    where CONFIG_MBEDTLS_LEGACY_CRYPTO_C used to be required by OT.

    It's my intention to use PSA throughout, so I have CONFIG_OPENTHREAD_CRYPTO_PSA and CONFIG_MBEDTLS_PSA_CRYPTO_C and a few CONFIG_PSA_WANT... so I'm not clear on why I would need LEGACY_CRYPTO_C - are you able to shed any light on this?

  • 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
  • Reply
    • 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
    Children
    No Data
    Related