EllisTheEllice
EllisTheEllice

Reputation: 913

WiFiClientSecure setCaCert does not accept my parameters

I am currently trying to connect my ESP32 to AWS IoT. Therefore, I have to use certificates to encrypt the connection. In theory I know how this will work, but I´m not a C++ pro and I get an error. Of course I tried to google, but I always find the same solution which does not work for me. To be concrete, I try ti declare a cacert in a header file like so:

const char AWS_CERT_CA[] = "-----BEGIN CERTIFICATE-----\n" \
"MIIDQTChkiG9w0CAimfz5m/jAo5gAwIBBgkqBAkPmljZbyjQsAgITBmy4vB4iANF\n" \
"ADA5MGQW1hem5sGQW1hemDVVUzEMQxBBDVhMQsYDVQQQGEwJQDExBBbWF6\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"-----END CERTIFICATE-----\n";

In the main file I try to use it like so:

WiFiClientSecure net = WiFiClientSecure();
void connectToAWS()
{
    // Configure WiFiClientSecure to use the AWS certificates we generated
    net.setCACert(AWS_CERT_CA);
    net.setCertificate(AWS_CERT_CRT);
    net.setPrivateKey(AWS_CERT_PRIVATE);
...

When I try to compile, it gives me the following error:

enter image description here

Obviously, the parameter types are not correct, but why does it work for others (e.g. here and here)? An int as a parameter for the function does not make sense to me. Hope you can help me.

Upvotes: 1

Views: 4172

Answers (2)

EllisTheEllice
EllisTheEllice

Reputation: 913

So it took me quite w while to figure out how I can solve this. The main problem was that I am using an old version of BearSSL, but I was not able to update it. To circumvent this problem, I create files out of my cryptographic information and use these files for creating the secured connection to AWS iot. Furthermore, I do not use MQTT to transfer my metrics, but the REST endpoint. I am sure this is not an optimal solution, but it works so far. Here´s how I´ve done it. Things to understand first:

  • net is an instance of WiFiClientSecure: BearSSL::WiFiClientSecure net = BearSSL::WiFiClientSecure();

My cryptographic information (key, CACert, cert) looks like this:

const char AWS_CA_CERT[]="-----BEGIN CERTIFICATE-----\n" \
...
"rqXRfboQnoZsG4q5WTP468SQvvG5\n" \
"-----END CERTIFICATE-----";

After establishing the Wifi connection, I do the following to establish the secure connection:

bool establishSecureConnection()
{
  if (!SPIFFS.begin())
  {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return false;
  }

  File tempCA = SPIFFS.open("/ca.crt", "w");
  File tempCert = SPIFFS.open("/cert.crt", "w");
  File tempKey = SPIFFS.open("/cert.priv", "w");

  if (!tempCA || !tempCert || !tempKey)
  {
    Serial.println("There was an error opening the file for writing");
    return false;
  }

  if (tempCA.print(AWS_CA_CERT))
  {
    Serial.println("Ca File was written");
  }
  else
  {
    Serial.println("Ca File write failed");
  }
  tempCA.close();

  if (tempCert.print(AWS_CERT))
  {
    Serial.println("cert File was written");
  }
  else
  {
    Serial.println("cert File write failed");
  }
  tempCert.close();

  if (tempKey.print(AWS_PRIVATE_KEY))
  {
    Serial.println("key File was written");
  }
  else
  {
    Serial.println("key File write failed");
  }
  tempKey.close();

  File ca = SPIFFS.open("/ca.crt", "r");
  if (!ca)
  {
    Serial.println("Failed to open ca file for reading");
    return false;
  }

  File cert = SPIFFS.open("/cert.crt", "r");
  if (!cert)
  {
    Serial.println("Failed to open cert file for reading");
    return false;
  }

  File pk = SPIFFS.open("/cert.priv", "r");
  if (!pk)
  {
    Serial.println("Failed to open pk file for reading");
    return false;
  }
  if (net.loadCACert(ca))
  {
    Serial.println("Successfully loaded ca");
  }
  else
  {
    Serial.println("Could not load ca");
    return false;
  }
  if (net.loadCertificate(cert))
  {
    Serial.println("Successfully loaded cert");
  }
  else
  {
    Serial.println("Could not load cert");
    return false;
  }
  if (net.loadPrivateKey(pk))
  {
    Serial.println("Successfully loaded pk");
  }
  else
  {
    Serial.println("Could not load pk");
    return false;
  }

  net.setTimeout(20000);
  if (!net.connect(AWS_IOT_ENDPOINT, 8443))
  {
    Serial.println("connection failed");
    char err_buf[1024];
    Serial.println(net.getLastSSLError(err_buf, 1024));
    Serial.printf("ssl_error: %s\n", err_buf);
    return false;
  }
  else
  {
    Serial.println("Connected to AWS!");
  }
  return true;
}

Upvotes: 1

Tarmo
Tarmo

Reputation: 4762

Firstly, please avoid posting screenshots with compiler output. Instead, please copy the output text and paste it into your post (with relevant formatting).

You appear to be using an older version of the WiFiClientSecure library which has a different interface - setCACert() expects two arguments, the key and its length. Why don't you try that?

net.setCACert((const uint8_t*)AWS_CERT_CA, sizeof(AWS_CERT_CA) - 1);

The - 1 strips the terminating null, as the function appears to take binary blob and those don't usually come with terminators. If authentication doesn't work, try removing that subtraction.

Upvotes: 4

Related Questions