-->
Page 1 of 1

Issue setting CA Certificate in WiFiClientSecure

PostPosted: Mon Aug 07, 2017 3:28 pm
by clegg
Hi, I am trying to setup a TLS/SSL connection with a remote server using the ESP8266 as the client. I am using the WiFiClientSecure class, and am trying to verify the certificate the server sends back. I am using the platformio command line tool. I am using the esp8266 staging platform to get the latest(ish) source for the ESP8266 Arduino core. I have placed my code at the end of this post for reference.

It seems I am unable to set the CA certificate using WiFiClientSecure::setCACert. While the function returns true (there appears to be a bug in the axTLS library that causes it to not return errors in some cases), I see the following when I enable debug output:

Code: Select allSet CA Cert
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: Invalid X509 ASN.1 file (X509 not ok)
Error: maximum number of CA certs added (10) - change of compile-time configuration required
CA Cert set


I am not quite sure what is the cause of the issue as axTLS does not return an error code here. I have tried it with a CA certificate generated using openssl s_client (then translated to DER format, and placed in a C file using xxd -i), and the CA certificate in the example. Both produce the same result in setCACertificate.

I was wondering if anyone else had encountered this issue or if anyone has any suggestions. Thanks

My code:
Code: Select all#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <time.h>

#include "wifi-information.hpp"
extern const uint8_t * ca_certificate;
extern const uint32_t ca_certificate_len;

static DHT_Unified g_dht(D4, DHT11);
static WiFiClientSecure g_client;

void initSerialPort(HardwareSerial& serial);
void initWifi(ESP8266WiFiClass& wifi,
              const String& ssid,
              const String& password);
void initDhtSensor(DHT_Unified& dht);

void setup()
{
  const WifiInformation& wifiInfo = WifiInformation::instance();
  initSerialPort(Serial);
  initWifi(WiFi, wifiInfo.ssid(), wifiInfo.password());
  initDhtSensor(g_dht);

  Serial.print("Configure time..");
  /* Need to synchronize time so TLS can verify certificates */
  /* First parameter is offset from GMT, second is daylight savings (ignored,
   * and then servers (up to three, minimum two).
   */
  configTime(-(4*3600), 1, "pool.ntp.org", "time.nist.gov");

  /* Wait until we have the current time */
  time_t now = time(nullptr);
  while (now < 1000)
  {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println(" Done");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.println(asctime(&timeinfo));

  Serial.println("Set CA Cert");
  if (!g_client.setCACert(ca_certificate, ca_certificate_len ))
  {
    Serial.println("Failed to load CA certificate");
    while(true) yield();
  }
  Serial.println("CA Cert set");
}

void loop()
{
  // Substituted domain name below
  const char * host = "www.example-domain.com";
  const int port = 443;

  Serial.print("Connecting to ");
  Serial.println(host);
  if(!g_client.connect(host, port))
  {
    Serial.println("Connection failed");
    return;
  }

  if(g_client.verifyCertChain(host))
  {
    Serial.println("Server certificate verified");
  }
  else
  {
    Serial.println("ERROR: certificate verification failed!");
    return;
  }

  g_client.stop();
}

void initSerialPort(HardwareSerial& serial)
{
  serial.begin(115200);
  serial.setDebugOutput(true);
  delay(10);
}

void initWifi(ESP8266WiFiClass& wifi,
              const String& ssid,
              const String& password)
{
  wifi.begin(ssid.c_str(), password.c_str());

  Serial.print("Connecting to ");
  Serial.println(ssid);

  while(wifi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  Serial.println("Connected");
}

void initDhtSensor(DHT_Unified& dht)
{
  dht.begin();
  Serial.println("DHT Initialized");
}

Re: Issue setting CA Certificate in WiFiClientSecure

PostPosted: Tue Aug 08, 2017 4:36 am
by gbafamily1
esp8266 staging platform to get the latest(ish) source for the ESP8266 Arduino core.


As far as I know the staging version is old. Or are you referring to 2.4.0rc1? I suggest using the latest version in git. I don't know how to do this using platformio so I only use platformio when using 2.3.0. I use the Arduino IDE when working with the git version.

Does the HTTPSRequestCACert example work? I just add my ssid and password and it works.

EDIT: I just learned platformio supports `platform = espressif8266_stage` which means platformio pulls core files from https://github.com/esp8266/arduino. See the following link for the details. HTTPSRequestCACert works fine using espressif8266_stage.

http://docs.platformio.org/en/latest/pl ... ng-version

Re: Issue setting CA Certificate in WiFiClientSecure

PostPosted: Tue Aug 08, 2017 8:41 am
by clegg
The staging repo appears to be slightly off from the main repo:

https://github.com/platformio/platformi ... ressif8266

The CA certificate from the example on the main repo did not work. I can try copying it exactly. If that doesn't work I can install the Arduino IDE to see if that works.

Re: Issue setting CA Certificate in WiFiClientSecure

PostPosted: Mon Aug 06, 2018 12:55 pm
by RexBrown
I noticed that you are using the PROGMEM keyword to put the certificate in Flash. You should be using the function that is created to retrieve the cert from flash as follows (this is from my code so the actual cert and length parameters are of course yours):

bool res = client.setCACert_P(CACert, CACertLen);

This seems to work for me. However I am having an unrelated problem in the validation of the cert (at least I think it is unrelated..) where dates that are after 2050 (which use the generalizedtime format) are interpreted incorrectly and cause a verify cert error.