airgradienthq / arduino

Firmware of open-source hardware air quality monitors AirGradient ONE (indoor) and AirGradient Open Air (outdoor).
https://www.airgradient.com/documentation/
Other
220 stars 114 forks source link

MQTT over TLS fails with "esp-tls-mbedtls: No server verification option..." #193

Open kpe opened 4 months ago

kpe commented 4 months ago

I've been trying to connect my stock firmware 3.1.4 Airgradient ONE, to a cloud MQTT server (hivemq), but it looks like there is some issue with TLS:

[MqttClient] Info: Init uri: mqtts://username:password@some-uuid-here.s1.eu.hivemq.cloud:8883
Other event id:7
Connect to MQTT broker successful
Delete old MQTT task
Create new MQTT task
E (1391467) esp-tls-mbedtls: No server verification option set in esp_tls_cfg_t structure. Check esp_tls API reference
E (1391467) esp-tls-mbedtls: Failed to set client configurations, returned [0x8017] (ESP_ERR_MBEDTLS_SSL_SETUP_FAILED)
E (1391584) esp-tls: create_ssl_handle failed
E (1391632) esp-tls: Failed to open new connection
E (1391686) TRANSPORT_BASE: Failed to open a new connection
E (1391751) MQTT_CLIENT: Error transport connect
MQTT_EVENT_ERROR
[MqttClient] Error: Reported from esp-tls: 32791
[MqttClient] Error: Reported from tls stack: 0
[MqttClient] Error: Captured as transport's socket errno: 0
[MqttClient] Info: MQTT_EVENT_DISCONNECTED
[MqttClient] Warning: Connection failed count 1

After some struggle, I've got it working by explicitly providing the root ca in esp_mqtt_client_config_t.cert_pem, by first extracting it from the MQTT instance:

openssl s_client -connect uuid.s1.eu.hivemq.cloud:8883 -showcerts < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > trust.crt

# take the first/root certificate only
 cat trust.crt | head -n $(cat trust.crt | grep -n 'END CERT' | head -n1 | cut -d ':' -f1) > ca.crt

xxd -i ca.crt > src/ca_trust.h

# manually add a 0x00 termination in ca/ca_trsut.h and the following changes

and manually adding a 0x00 termination in the ca_crt in ca/ca_trust.h and then patching src/MqttClient.cpp like this:


diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp
index 66c71e6..df19248 100644
--- a/src/MqttClient.cpp
+++ b/src/MqttClient.cpp
@@ -15,6 +15,8 @@ MqttClient::MqttClient(Stream &debugLog) : PrintLog(debugLog, "MqttClient") {
 #endif
 }

+#include "./ca_trust.h" // unsigned char ca_crt[] // xxd -i ca.crt > src/ca_trust.h
+
 MqttClient::~MqttClient() {}

 bool MqttClient::begin(String uri) {
@@ -31,9 +33,11 @@ bool MqttClient::begin(String uri) {
   logInfo("Init uri: " + uri);

 #ifdef ESP32
+
   /** config esp_mqtt client */
   esp_mqtt_client_config_t config = {
       .uri = this->uri.c_str(),
+      .cert_pem = (const char *)ca_crt,
   };

   /** init client */
@@ -283,6 +287,8 @@ static void __mqtt_event_handler(void *handler_args, esp_event_base_t base,
   esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;
   esp_mqtt_client_handle_t client = event->client;

+  mqtt->logInfo("Event id: " + String(event_id));
+
   int msg_id;
   switch ((esp_mqtt_event_id_t)event_id) {
   case MQTT_EVENT_CONNECTED:

its just a hack however.