1

I would like to connect ESP8266 with Azure IoT Hub Device via X509 certificate. Currently, I can connect using the symmetric key connection to my device, but I have devices that I want to authenticate with X509 certificate.

I found a solution, but is for Arduino Nano 33 IoT, which is probably using another chip and it has encryption slot.

I am trying to do this using the Azure IoT SDK C library, but without much success. Here is a code that is using Mqtt and WiFiClientSecure plus BearSSL in order to connect via certificate. Unfortunately, the only solution that I found was to generate ECCX09 certificate with a chip that have encryption and to just use the thumbprint. Here is my try to use the certificate:

// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT

// C99 libraries
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <cstdlib>

// Libraries for MQTT client, WiFi connection and SAS-token generation.
#include <ESP8266WiFi.h>
#include <ArduinoBearSSL.h>
#include <ArduinoMqttClient.h>

// Additional sample headers 
#include "secrets.h"

// Utility macros and defines
#define LED_PIN 2

// Translate iot_configs.h defines into variables used by the sample
static const char* ssid = SECRET_WIFI_SSID;
static const char* password = SECRET_WIFI_PASS;
static const char* host = SECRET_BROKER;
static const String device_id = SECRET_DEVICE_ID;

// Memory allocated for the sample's variables and structures.
static WiFiClientSecure wifi_client;
static BearSSLClient ssl_client(wifi_client);
static MqttClient mqtt_client(ssl_client);

// Auxiliary functions
static void connectToWiFi()
{
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to WIFI SSID ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
}

/*
 * Establishses connection with the MQTT Broker (IoT Hub)
 * Some errors you may receive:
 * -- (-.2) Either a connectivity error or an error in the url of the broker
 * -- (-.5) Check credentials - has the SAS Token expired? Do you have the right connection string copied into arduino_secrets?
 */
void connectToMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(host);
  Serial.println(" ");
  
  while (!mqtt_client.connect(host, 8883)) {
  // failed, retry
    Serial.print(".");
    Serial.println(mqtt_client.connectError());
    delay(5000);
  }
  Serial.println();
  
  Serial.println("You're connected to the MQTT broker");
  Serial.println();
  
  // subscribe to a topic
  mqtt_client.subscribe("devices/" + device_id + "/messages/devicebound/#");
}

unsigned long getTime() {
  // get the current time from the WiFi module
  // return WiFi.getTime();
  return time(NULL);
}

static void establishConnection() 
{
  // Set the username to "<broker>/<device id>/?api-version=2018-06-30"
  String username;
  
  // Set the client id used for MQTT as the device id
  mqtt_client.setId(device_id);
  
  username += host;
  username += "/";
  username += device_id;
  username += "/api-version=2018-06-30";
  mqtt_client.setUsernamePassword(username, "");
  
  if(WiFi.status() != WL_CONNECTED) {
    connectToWiFi();
  }

  if (!mqtt_client.connected()) {
    // MQTT client is disconnected, connect
    connectToMQTT();
  }
}

// Arduino setup and loop main functions.

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  Serial.begin(9600);

  // Set the X.509 certificate
  // ssl_client.setEccCert(CLIENT_CERT);
  ssl_client.setEccSlot(0, CLIENT_CERT);

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);
  
  establishConnection();
}

void loop() {}

This fails on setting the Certificate and to use the ecc slot 0, because I am using ESP8266 that does not have cryptography in it (or at least I do not know). I saw in the library that there is another method in the BearSSL - void setEccCert(br_x509_certificate cert); , but I do not know how to initialize br_x509_certificate (here is the ref).

I decided to try something else, too, reading the certificate with SPIFFS, then adding to WiFiClientSecure. Unfortunately, I cannot load the private key to make client connection.

#include "FS.h"             // File system commands to access files stored on flash memory
#include <ESP8266WiFi.h>    // WiFi Client to connect to the internet
#include <PubSubClient.h>   // MQTT Client to connect to AWS IoT Core
#include <NTPClient.h>      // Network Time Protocol Client, used to validate certificates
#include <WiFiUdp.h>        // UDP to communicate with the NTP server
#include "secrets.h"

// Utility macros and defines
#define NTP_SERVERS "pool.ntp.org", "time.nist.gov"

// Translate secrets.h defines into variables used by the sample
static const char* ssid = SECRET_WIFI_SSID;
static const char* password = SECRET_WIFI_PASS;
static const char* iot_hub_broker = SECRET_BROKER;

// callback function that will be called when the device receive a message
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// Memory allocated client variables
static WiFiUDP ntp_UDP;
static NTPClient time_client(ntp_UDP, "pool.ntp.org");
static WiFiClientSecure esp_client;
static PubSubClient mqtt_client(iot_hub_broker, 8883, callback, esp_client);

// Auxiliary functions
static void configureX509CertificateConnection() {
  time_client.begin();
  while(!time_client.update()) {
    time_client.forceUpdate();
  }

  esp_client.setX509Time(time_client.getEpochTime());
  Serial.println("Time client and ESP client are set up.");

  // Attempt to mount the file system
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount file system");
    return;
  }

  // Load certificate file from file system
  File cert = SPIFFS.open("temperature-sensor-1-all.pem", "r");
  if (!cert) {
    Serial.println("Failed to open certificate from file system");
  } else {
    Serial.println("Successfully opened certificate file");
  }

  // Load private key file from file system
  File private_key = SPIFFS.open("/temperature-sensor-1-private.pem", "r");
  if (!private_key) {
    Serial.println("Failed to open private key from file system");
  }
  else {
    Serial.println("Successfully opened private key file");
  }

  delay(1000);

  // Load private key to client connection
  if (esp_client.loadPrivateKey(private_key)) {
    Serial.println("Private key loaded to client connection");
  }
  else {
    Serial.println("Private key not loaded to client connection");
  }
}

static void connectToWiFi() {
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to WiFi: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
}

/*
 * Establishses connection with the MQTT Broker (IoT Hub)
 * Some errors you may receive:
 * -- (-.2) Either a connectivity error or an error in the url of the broker
 * -- (-.5) Check credentials - has the SAS Token expired? Do you have the right connection string copied into arduino_secrets?
 */
void connectToMQTT() {
}

static void establishConnection() {
  if (WiFi.status() != WL_CONNECTED) {
    connectToWiFi();
  }

  configureX509CertificateConnection();
}

// Arduino setup and loop main functions.
void setup() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  Serial.begin(115200);

  establishConnection();
}

void loop() {}

P.S. I have it up and running on Raspberry Pi, but I have to make some experiments using the Arduino and ESP8266.

P.S.2. I am using Arduino with Atmega328P with integrated ESP8266 chip, but working only with the ESP8266. Additionally, I am using Arduino IDE 1.8.19 and installed the Azure IoT SDK C library (and some other required ones).

P.S.3. Additionally, I could find X509 certificate sample, but it is using the Paho Mqtt Client and I am not able reproduce it on Arduino.

0

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.