如何将STM32 lwip/mqtt api与tls一起使用?

问题描述 投票:0回答:4

我制作了 stm32 + rtos + lwip/mqtt 解决方案,效果很好。现在我想将它与嵌入 tls 安全连接一起使用。我没有找到任何例子。

lwip mqtt api 支持 tls 通信。但没有这样的例子,只是简单的 mqtt 客户端,使用我使用的代码LWIP MQTT Client

我尝试在cubemx、LWIP_ALTCP和LWIP_ALTCP_TLS中启用embedtls和一些选项,将LWIP_ALTCP_TLS_MBEDTLS添加到路径。它编译了。 如何初始化 mbedtls 并添加 tls 证书。此链接需要一些信息altcp tls

有人对 stm32 lwip 堆栈有一些 stm32 lwip/mqtt + tls (mbedtls) 的经验或工作示例吗?

UPD。 这是我的 mqtt 客户端设置代码:

struct mqtt_connect_client_info_t ci;
memset(&ci, 0, sizeof(ci));
ci.client_id = "lwip_test";
ci.client_user = "";
ci.client_pass = "";
ci.keep_alive = 0;
ci.tls_config = altcp_tls_create_config_client((const u8_t*)test_cert, sizeof(test_cert));
// create client
client = mqtt_client_new();
// connect client   
mqtt_client_connect(client, &resolved, port, mqtt_on_connect, (void *)0, &ci);

我给mqtt客户端ca证书和长度。我有一个错误 altcp_tls_create_config_client_common函数(altcp_tls_mbedtls.c),代码为-4480(无法分配内存)。

ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len);
if (ret != 0) {
  LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse ca failed: %d 0x%x", ret, -1*ret));
  altcp_mbedtls_free_config(conf);
  return NULL;
}

我做错了什么,我应该在 mbedtls 模块中设置哪些选项? 我使用默认是由 CubeMX 生成的

ssl mqtt stm32 freertos lwip
4个回答
4
投票

此线程帮助我与 https://www.nongnu.org/lwip/2_0_x/group__mqtt.html 中的其他示例一起使 MQTT 客户端使用 MbedTLS 2 路身份验证。我现在可以订阅/发布到亚马逊 AWS 云。

如果有人感兴趣,这就是我所做的。

  1. 在启用 LwIP 和 MbedTLS 的情况下从 CubeMX 生成代码。重要的是启用 MBEDTLS_PLATFORM_MEMORY、MEMP_MEM_MALLOC 和 LWIP_ALTCP_TLS_MBEDTLS,以便库使用 LwIP 中的替代 calloc/free 函数(它们在

    altcp_mbedtls_mem_init()
    函数中设置)。

  2. 我还使用启用了MBEDTLS_ENTROPY_HARDWARE_ALT、MBEDTLS_NO_PLATFORM_ENTROPY和MBEDTLS_CTR_DRBG_C,因此MBedTLS库可以使用ctr drbg随机数生成器(在

    altcp_tls_create_config()
    函数中初始化)。

  3. 如果您像我一样将 FreeRTOS 与 LwIP 结合使用,则需要启用 MBEDTLS_THREADING_ALT,然后在代码中调用

    mbedtls_threading_set_alt()
    函数以在 MbedTLS 库中启用互斥处理。

  4. 这就是我在代码中所做的事情:

mqtt_client_t *client;
struct mqtt_connect_client_info_t client_info;
ip_addr_t server_ip;

/* Somewhere in the code call this to get IP address of the host */
ip_addr_t ipaddr;
err = dns_gethostbyname("host_name", &ipaddr, mqtt_resolved_cb, NULL);

/* Wait until this callback gets the IP */
static void mqtt_resolved_cb(const char *host, const ip_addr_t *ipaddr,
                             void *callback_arg)
{
  /* If resolved IP is known -> set it */
  if (ipaddr->addr != 0)
  {
    server_ip.addr = ipaddr->addr;
  }
}

/* Then call this to start MQTT client */
void mqtt_test(const ip_addr_t *ipaddr, uint16_t port,
               const uint8_t *ca_cert_str, size_t ca_cert_len,
               const uint8_t *dev_cert_str, size_t dev_cert_len,
               const uint8_t *dev_key_str, size_t dev_key_len,
               const uint8_t *dev_key_pass_str, size_t dev_key_pass_len)
{
  /* Setup an empty client info structure */
  memset(&mqtt.client_info, 0, sizeof(mqtt.client_info));

  /* Set client information */
  mqtt.client_info.client_id = "lwip_test";
  mqtt.client_info.client_user = NULL;
  mqtt.client_info.client_pass = NULL;
  mqtt.client_info.keep_alive = 0;
  mqtt.client_info.will_topic = NULL;
  mqtt.client_info.will_msg = NULL;
  mqtt.client_info.will_retain = 0;
  mqtt.client_info.will_qos = 0;

  /* Set TLS configuration */
  mqtt.client_info.tls_config = altcp_tls_create_config_client_2wayauth(
    ca_cert_str, ca_cert_len,
    dev_key_str, dev_key_len, dev_key_pass_str, dev_key_pass_len,
    dev_cert_str, dev_cert_len);

  /* Allocate memory for MQTT client */
  mqtt.client = mqtt_client_new();

  /* Connect to the server */
  if (mqtt.client != NULL)
  {
    err = mqtt_client_connect(
      mqtt.client, ipaddr, port,
      mqtt_connection_cb, 0, &mqtt.client_info);
  }
}

然后代码在上面示例链接的标准 mqtt 回调中继续。

谢谢,我希望这也能帮助其他人。


1
投票

我有一个相同的配置,所以我可以告诉你,如果你调试代码,你会发现它会在尝试调用calloc时崩溃,如果你的环境与我的环境相同,那么你没有那个系统功能。

我所做的是使用 lwip 中实现的 calloc,特别是在 altcp 模块中。 我通过cubemx MBEDTLS_PLATFORM_MEMORY定义,为了激活altcp_tls_mbedtls_mem.c中定义的ALTCP_MBEDTLS_PLATFORM_ALLOC,然后我可以使用 altcp_mbedtls_mem_init() 函数指定 mbedtls 使用 altcp calloc 和 free。

该函数被调用到altcp_tls_create_config_client中,因此如果您要使用它,则不必调用altcp_mbedtls_mem_init()两次。

这样你应该能够正确地为 mbedtls 分配内存。


0
投票

您似乎遇到了内存分配问题,您可以尝试增加lwipopts.h中的堆内存大小,如下所示:

#define MEM_SIZE (50 * 1024)

0
投票

我正在 YouTube 上创建播放列表。我使用 STM32 作为 DTLS 客户端。 STM32 运行 FreeRTOS,我使用 LwIP 作为 TCP/IP 堆栈。我还使用 MbedTLS 库进行 DTLS 连接。 该播放列表显示了如何相对简单地实现 UDP 连接和 DTLS 连接。该视频已在网上发布,并配有英文字幕。您可以在此处找到 YouTube 播放列表的链接: https://www.youtube.com/watch?v=R5RSv_f1rFc&list=PLkkpebBIQDcF9Zne6kcxewHD98ZzfccIq

您可以使用视频作为 TLS 连接的模板,但需要进行一些小的调整。也许我也会考虑为此制作一个视频。我希望这些视频向您展示如何实现 DTLS 连接或 TLS 连接的示例。

© www.soinside.com 2019 - 2024. All rights reserved.