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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.