如何在 tls 中使用 STM32 lwip/mqtt api?

Posted

技术标签:

【中文标题】如何在 tls 中使用 STM32 lwip/mqtt api?【英文标题】:How to use STM32 lwip/mqtt api with tls? 【发布时间】:2020-07-20 14:51:00 【问题描述】:

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

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

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

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

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 生成的

【问题讨论】:

【参考方案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 正确分配内存。

【讨论】:

【参考方案2】:

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

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

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

    我还启用了 MBEDTLS_ENTROPY_HARDWARE_ALT、MBEDTLS_NO_PLATFORM_ENTROPY 和 MBEDTLS_CTR_DRBG_C,因此 MbedTLS 库可以使用 ctr drbg 随机数生成器(在 altcp_tls_create_config() 函数中初始化)。

    如果您像我一样将 FreeRTOS 与您的 LwIP 一起使用,则必须启用 MBEDTLS_THREADING_ALT,然后在您的代码中调用 mbedtls_threading_set_alt() 函数以在 MbedTLS 库中启用互斥体处理。

    这就是我在代码中所做的:

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 回调中继续。

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

【讨论】:

【参考方案3】:

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

#define MEM_SIZE (50 * 1024)

【讨论】:

以上是关于如何在 tls 中使用 STM32 lwip/mqtt api?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CubeMX STM32 中使用 LL(低级)驱动程序?

如何在STM32F4中使用Backup SRAM作为EEPROM

如何在 stm32cubeide 中启动 GDB 服务器?

STM32如何升级固件?

傻瓜式教程:如何使用“多合一”开发工具STM32CubeIDE

如何在STM32 Cube IDE中使用另一个全局变量Array中声明的全局变量而不会出现任何错误?