2

I'm using Arduino IDE v2.1.1 and Arduino MKR wifi 1010. Everything works fine and at this moment I have a need to protect the wifi connection with ssl certificate. I have generated the ssl certificate using the openssl tool and now I have following files that needs to be set in the controller:

  • ca.crt
  • client.crt
  • client.key

how can I set these three files to the MKR wifi 1010 to enable the SSL certificate protected communication? I couldn't find the tutorial or example on the internet.

let me explain how I do that at the moment. I do have a valid self-signed CA certificate and I'm trying to establish a SSL / TLS connection using the CA sertificate only. This is my code which doesn't work unfortunately:

#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoMqttClient.h>
#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include "secrets.h"

char wifiSsid[] = SECRET_WiFi_SSID;
char wifiPass[] = SECRET_WiFi_PASS;
char mqttUserId[] = MQTT_USERID;
char mqttPass[] = MQTT_PASS;
int status = WL_IDLE_STATUS;
const char* rootCAcertificate  = \
"-----BEGIN CERTIFICATE-----\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"-----END CERTIFICATE-----\n";

bool dev_debug_mode = IS_DEBUG;

WiFiClient    wifiClient;         // Used for the TCP socket connection
BearSSLClient bearSslClient(wifiClient); // Used for SSL/TLS connection, integrates with ECCX08
MqttClient    mqttClient(bearSslClient); // Used for MQTT protocol usage

const char mqttBroker[] = MQTT_BROKER_HOST;
int mqttPort = 8883;

const char deviceRegisterTopic[] = "device/register";

//set interval for sending the Observation (the measurement from the sensor) messages (milliseconds)
const long interval = 3000;

unsigned long previousMillis = 0;

bool deviceIsRegistered = false;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (dev_debug_mode && !Serial) {
    ; // wait for serial port to connect. Needed for native USB port only - development mode. It has to be removed when releasing to live!!!
  }

  // Check the crypto chip module presence (needed for BearSSL)
  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  bearSslClient.setEccSlot(0, rootCAcertificate); // inserting a certificate into the slot 0 (zero)

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

  // attempt to connect to the Wifi network
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to network: ");
    Serial.println(wifiSsid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(wifiSsid, wifiPass);

    Serial.print("Attempt status: ");
    Serial.println(status);

    if(status != WL_CONNECTED) {
      // waiting 10 seconds before trying to connect if it is needed:
      delay(10000);
    }
  }

  // WiFi network connection established! sending some messages to the console
  Serial.println("You're connected to the network");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(mqttBroker);
  Serial.println(mqttPort);

  mqttClient.setId(mqttUserId);

  // adding first level of proptection using MQTT broker username and password
  mqttClient.setUsernamePassword(mqttUserId, mqttPass);

  delay(30000);
  while (!mqttClient.connect(mqttBroker, mqttPort)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    delay(10000);
  }

  // MQTT broker connection established! sending some messages to the console
  Serial.println("You're connected to the MQTT broker!");
  Serial.println();
}

void loop() {

  // call poll() regularly to allow the library to send MQTT keep alive which
  // avoids being disconnected by the broker
  mqttClient.poll();

  // if this current device is not registered yet, registering the device for the first time
  if(!deviceIsRegistered) {
    Serial.print("Sending Device Register message to topic: ");
    Serial.println(deviceRegisterTopic);
    // DO SOMETHING
  }

  unsigned long currentMillis = millis();

  // sending the actual measurement data to the FHIR Server with some time interval, like few seconds. To be defined later.
  if (currentMillis - previousMillis >= interval) {

    // save the last time a message was sent
    previousMillis = currentMillis;

    Serial.println();
  }
}

// ================================== Auxiliary functions ===================================
unsigned long getTime() {
   Serial.print("Current WiFi time:");
   Serial.println(WiFi.getTime());
  // Get the current time from the WiFi module
  return WiFi.getTime();
}

in the code above, I'm using the BearSSLClient and the certificate is set manually (I prefer this way as it is more transparent for me) bearSslClient.setEccSlot(0, certificate); - this is how the certificate is set. Also I do the following call: ArduinoBearSSL.onGetTime(getTime); - to get the proper time. The CA certificate is validated using the openssl tool. It is a valid self-signed root certificate. Please, any help is much appreciated. I'm really confused as it should work since the certificate is a valid self-signed certificate and it is confirmed and verified using the openssl tool. When something should work but it doesnt work and I don't have any details except the -2 error message it makes me feel completely crazy ((((

@b1n3t thank's dude for your help. I appreaciate that. Let me start with one thing, I do software developent for more than 16 years, but I was working with hardware like microcontrollers and i8086 architecture based hardware more than 10 years ago. I was never investigating the SSL / TLS issues deeply. Now, I go through your questions one by one: yes, I'm sure that Arduino's internal clock is accurate because I have configured myself a mutual TLS connection to the AWS (Amazon) MQTT broker with this clock engaged and everything works fine. The private key might not be properly stored within the ECC608, this might be the issue because I'm not 100% sure that I've done that right. Yes, I have verified that mosquitto MQTT broker's domain and port are accessible from the device, because it connnects successfully without the mutual TLS. I can send message back anf force from the device to the mosquitto MQTT broker server without mutual TLS and without SSL. Yes, I have configured the linux server to enable the 8883 for external connection. I have used the MQTT Explorer tool to establish a mutual TLS connection using the CA root certificate, client and server certificates from another physical device over my LAN network, everything works smoothly, it connects with the CA and client certificate to the MQTT broker server and I can send and receive messages. All is good here. Let me capture the logs and get back. Broker is configured to trust the CA, however all the certificates are self-signed. I have been struggling with this for about five days now and I figured out few important things: the ECC608 is by default (from the factory) in the unlocked state, it can't be used until it is locked (manually from the code). The certificate sign request should be generated on the MRK WiFi 1010 device and the private key is stored internally within the MKR WiFi 1010 device, tha'ts very important detail. Afte that, the CSR should be passed to the certification provider and the sercret certificate should be generated based on that CSR (certificate sign request). Another very important detail is that the self-signed certificate that I'm using for the development might be an issue as it is marked ALWAYS as invalid just because it is self-signed.

update 22 September

I'm still struggling with this problem. At this moment, everything is setup and configured on the microcontroller side. The microcontroller can connect to any online test MQTT broker via ssl/tls protocol. I have checked that and double checked. Everything is good on the microcontroller side. My MQTT broker is configured to use TLS v 1.2 it is deployed live, the cetificate is valid, it is generated by the zerossl trusted authority and it just works. I can connect from the test clients to my Mosquitto MQTT broker. I have tried multiple clients and everythig works fine. At this point, I have verified that client is valid and server is valid, both can connect to another party using TLS secure protocol. But, when I'm trying to pair my microcontroller with my Mosquitto MQTT broker - TLS SSL error is thrown, saying that the handshake failed. ssl tls 1.2 error ACCEPT_SR_KEY_EXCH ssl handshake failure. I have tried to debug it using the Wireshark, but there are no details at all. when I try to debug the SSL/TLS using the Wireshark, I see that there is a Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done and it repeats in a sequence again:

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

any help is appreciated.

enter image description here

2
  • 2
    Can you provide me with the following details? I have also dealt with the -2 message recently so those might help troubleshooting. Are you sure that Arduino's internal clock is accurate? Are you storing your private key inside the ECC608? Error -2 means a connection issue at the socket level. Did you ensure your MQTT broker's domain and port are accessible from the device? Did you make sure that port 8883 is open and a firewall doesn't block MQTT traffic over SSL? Can you share your MQTT Broker logs? Can you capture SSL traffic with WireShark and share? Is the broker configured to trust CA?
    – b1n3t
    Commented Aug 31, 2023 at 19:55
  • 1
    @b1n3t really appreciate your input, can't answer in the comments because it has a limit of characters, that's why I have update the post with the answers. Commented Aug 31, 2023 at 20:19

1 Answer 1

1

seems like you have made quite a progress. Frankly, I believe that the problem lies behind not storing your private key in the ECC608.

If the private key is not correctly stored in the ECC608 TLS Handshake will fail. You mentioned the ECC608 is unlocked by default. You're correct that to use the secure functionalities of the chip, it has to be locked. However, as far as I know once it's locked, it can't be unlocked. Make sure you've followed the necessary steps to store your private key in the ECC608 and then locked it to secure the key. I think you can use ArduinoECCX08 library since it seems to have ECCX08.begin(), ECCX08.lock(), ECCX08.generatePrivateKey(slot) functions. Your approach to generating the CSR directly on the MKR WiFi 1010 device is on point. This method ensures the private key never leaves the device. Consequently, only the public part is sent to the CA, even if it's self-signed. With the CSR, obtain your device certificate. This certificate, coupled with the private key securely housed in the ECC608, should facilitate the TLS handshake.

TL;DR: Make sure that you've stored the private key appropriately in the ECC608. Before locking the ECC608, test to ensure that the private key functions as expected. Check your MQTT Broker Logs for further debugging (when provided and when I get time for that I will try my best to pinpoint the error) and try using WireShark to capture SSL traffic.

That is as far as my knowledge goes, all the best luck to you. I hope that I could be of help dude.

2
  • hi. can you please take a look at the updates in my question from today. This ssl/tls issue is still not solved and I don't have any idea how to handle that. Commented Sep 22, 2023 at 7:22
  • @SemenShekhovtsov i'm kinda busy for a couple of days, when i have time i will try my best to be of help.
    – b1n3t
    Commented Sep 23, 2023 at 13:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.