Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BearSSL client secure example for establishing TLS1.2 connection using rootCA Cert and client private key and certificate #5347

Closed
5 of 6 tasks
mih380 opened this issue Nov 18, 2018 · 6 comments

Comments

@mih380
Copy link

mih380 commented Nov 18, 2018

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: [ESP-12]
  • Core Version: [2.4.2]
  • Development Env: [Arduino IDE]
  • Operating System: [Windows]

Settings in IDE

  • Module: [Adafruit Feather Huzzah ESP8266]
  • Flash Size: [4MB]
  • lwip Variant: [v2 Lower Memory]
  • CPU Frequency: [160MHz]
  • Upload Using: [|SERIAL]
  • Upload Speed: [115200]

Problem Description

I am trying to establish a TLS1.2 connection using BearSSLClientSecure. I have an aws IOT instance running with MQTT as a broker. I have the RootCA.Cert along with clientKey and client certificate with me. I was successfully able to establish a TLS connection using my cellular module BG96 and was able to post data through this. I am using the same certificate to establish a TLS1.2 connection but now with an ESP8266 hardware. I have tried the following code which is mostly a modification of BearSSL_Validation example. I am unable to establish a connection to the same AWS IOT instance. Below is the code that I have tried.

MCVE Sketch

#include <ESP8266WiFi.h>
#include <time.h>

const char *ssid = "SSID";
const char *pass = "Pssword";

const char *   host = "a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com";
const uint16_t  port = 8443;
const char *   path = "/topics/mj?qos=1";

// Set time via NTP, as required for x.509 validation
time_t setClock() {
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
  return now;
}

void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_t port, const char *path) {
  if (!path) {
    path = "/";
  }

  Serial.printf("Trying: %s:8443...", host);
  client->connect(host, port);
  if (!client->connected()) {
    Serial.printf("*** Can't connect. ***\n-------\n");
    return;
  }
  Serial.printf("Connected!\n-------\n");
  client->write("POST ");
  client->write(path);
  client->write(" HTTP/1.0\r\nHost: ");
  client->write(host);
  client->write("\r\nUser-Agent: ESP8266\r\n");
  client->write("\r\n");
  uint32_t to = millis() + 5000;
  if (client->connected()) {
    do {
      char tmp[32];
      memset(tmp, 0, 32);
      int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
      yield();
      if (rlen < 0) {
        break;
      }
      // Only print out first line up to \r, then abort connection
      char *nl = strchr(tmp, '\r');
      if (nl) {
        *nl = 0;
        Serial.print(tmp);
        break;
      }
      Serial.print(tmp);
    } while (millis() < to);
  }
  client->stop();
  Serial.printf("\n-------\n\n");
}

void fetchCertAuthority() {
  static const char ca_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
................................................................................................................................................................
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)EOF";

static const char client_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDWjCCAkKgAwIBAgIVAKAEpMzTvgSj6Cfki29+Bwd2GcxJMA0GCSqGSIb3DQEB
CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t
..........................................................................................................................................................................
uWjzrmLkeAn4+hsX3w/m48Pw67s5iWEztffx9pXT386SfnBrzrJnHXa5frr6bA==
-----END CERTIFICATE-----
)EOF";

static const char client_key[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAuqHZchnoHXQYOvkN0xViIi9ARmp3y9FLkA7thSbu5pQOedzq
fN5zFHUAMC0ye5pXzZ0rtu5+PrpMsxfXcClx6Dcqiwc1Ug1vI5bWzeI1AviRSM+k
........................................................................................................................................................
/7EpcQKBgQCnEaef7D1/f+lAh00Vh4X3wW8icOPYZHycyKpCQ2E0gZ6alayezpD/
ffpUFwfAgpu52YmS4sh0SRSKXfvdaw+NQBYG7nnnGGp3mkJ43e847Se4f7oRL5ZT
uhdis+by3+AZsbVRujicleG9PaKizWujYvlsOQImqhrX5BcZESadFQ==
-----END RSA PRIVATE KEY-----
)KEY";



    BearSSL::WiFiClientSecure client;
    BearSSLX509List cert(ca_cert);
    client.setTrustAnchors(&cert);
    BearSSLX509List client_crt(client_cert);
    BearSSLPrivateKey key(client_key);
    client.setClientRSACert(&client_crt, &key);
    setClock();
    fetchURL(&client, host, port, path);
    
}

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");

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


  fetchCertAuthority();

}

void loop() {
  // put your main code here, to run repeatedly:

}

Debug Messages

SDK:2.2.1(cfd48f3)/Core:2.4.2/lwIP:2.0.3(STABLE-2_0_3_RELEASE/glue:arduino-2.4.1-13-g163bb82)/BearSSL:6d1cefc


Connecting to SSID
scandone
wifi evt: 2
.....scandone
state: 0 -> 2 (b0)
.state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
cnt 

connected with SSID, channel 1
dhcp client start...
wifi evt: 0
....................pm open,type:2 0
..........................................ip:192.168.50.186,mask:255.255.255.0,gw:192.168.50.1
wifi evt: 3
.
WiFi connected
IP address: 
192.168.50.186
Waiting for NTP time sync: .............
Current time: Sun Nov 18 14:31:26 2018
Trying: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com:8443...[hostByName] request IP for: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com
[hostByName] Host: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com IP: 54.169.210.212
:ref 1
:wr 240 240 0
:wrc 240 240 0
:ack 240
:rn 536
:rd 5, 536, 0
:rdi 536, 5
:rd 531, 536, 5
:rdi 531, 531
:c0 531, 536
:rn 536
:rch 536, 536
:rch 1072, 536
:rd 1608, 1608, 0
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 536
:rch 536, 536
:rch 1072, 536
:rd 1608, 1608, 0
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 536
:rch 536, 536
:rch 1072, 536
:rd 1608, 1608, 0
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 3
*** Can't connect. ***
-------
:ur 1
:close
:del

@earlephilhower
Copy link
Collaborator

Can you also dump the last error (client->getLastSSLError(buff, len)) as your sketch isn't runnable by anyone but yourself. Also, make sure you're running at 160MHz since Azure is probably using EC.

@mih380
Copy link
Author

mih380 commented Nov 19, 2018

Hi @earlephilhower,
I have edited my sketch and implemented client->getLastSSLError(). I am getting 62 as an output for this command.
Also attached is a screen shot that shows my settings. I am running the board on 160Mhz. Do let me know if you find something weird in the setting, the same can be found as a screen shot on below mentioned google drive link.

https://drive.google.com/file/d/1jWN1ouvIQBxxkoDSQ25ZXUdn_V-q6w1b/view?usp=sharing

#include <ESP8266WiFi.h>
#include <time.h>

const char *ssid = "SSID";
const char *pass = "PASS";

const char *   host = "a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com";
const uint16_t  port = 8443;
const char *   path = "/topics/mj?qos=1";

// Set time via NTP, as required for x.509 validation
time_t setClock() {
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
  return now;
}

void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_t port, const char *path) {
  if (!path) {
    path = "/";
  }
 
  Serial.printf("Trying: %s:8443...", host);
  client->connect(host, port);

  if (!client->connected()) { 
    
    Serial.printf("*** Can't connect. ***\n-------\n");
    Serial.printf("---------- \n"); 
    Serial.printf("client->getLastSSLError() output is : ");
    Serial.println (client->getLastSSLError());  
    Serial.printf("\n ----------");
    
    return;
  }
  
  Serial.printf("Connected!\n-------\n");
  client->write("POST ");
  client->write(path);
  client->write(" HTTP/1.0\r\nHost: ");
  client->write(host);
  client->write("\r\nUser-Agent: ESP8266\r\n");
  client->write("\r\n");
  uint32_t to = millis() + 5000;
  if (client->connected()) {
    do {
      char tmp[32];
      memset(tmp, 0, 32);
      int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
      yield();
      if (rlen < 0) {
        break;
      }
      // Only print out first line up to \r, then abort connection
      char *nl = strchr(tmp, '\r');
      if (nl) {
        *nl = 0;
        Serial.print(tmp);
        break;
      }
      Serial.print(tmp);
    } while (millis() < to);
  }
  client->stop();
  Serial.printf("\n-------\n\n");
}

void fetchCertAuthority() {
  static const char ca_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3

vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)EOF";

static const char client_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDWjCCAkKgAwIBAgIVAKAEpMzTvgSj6Cfki29+Bwd2GcxJMA0GCSqGSIb3DQEB

uWjzrmLkeAn4+hsX3w/m48Pw67s5iWEztffx9pXT386SfnBrzrJnHXa5frr6bA==
-----END CERTIFICATE-----
)EOF";

static const char client_key[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAuqHZchnoHXQYOvkN0xViIi9ARmp3y9FLkA7thSbu5pQOedzq
fN5zFHUAMC0ye5pXzZ0rtu5+PrpMsxfXcClx6Dcqiwc1Ug1vI5bWzeI1AviRSM+k

uhdis+by3+AZsbVRujicleG9PaKizWujYvlsOQImqhrX5BcZESadFQ==
-----END RSA PRIVATE KEY-----
)KEY";



    BearSSL::WiFiClientSecure client;
    BearSSLX509List cert(ca_cert);
    client.setTrustAnchors(&cert);
    BearSSLX509List client_crt(client_cert);
    BearSSLPrivateKey key(client_key);
    client.setClientRSACert(&client_crt, &key);
    setClock();
    fetchURL(&client, host, port, path);    
}

void setup(){
  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  Serial.println();
  Serial.println();

  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");

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


  fetchCertAuthority();
  

}

void loop() {
  // put your main code here, to run repeatedly:

}

Debug Message



SDK:2.2.1(cfd48f3)/Core:2.4.2/lwIP:2.0.3(STABLE-2_0_3_RELEASE/glue:arduino-2.4.1-13-g163bb82)/BearSSL:6d1cefc


Connecting to The Jariwala's
sta config unchanwifi evt: 2
gedscandone
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 4
cnt 

connected with SSID, channel 1
dhcp client start...
wifi evt: 0
ip:192.168.50.119,mask:255.255.255.0,gw:192.168.50.1
wifi evt: 3
.
WiFi connected
IP address: 
192.168.50.119
Waiting for NTP time sync: .
Current time: Mon Nov 19 11:01:03 2018
Trying: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com:8443...[hostByName] request IP for: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com
[hostByName] Host: a2sy7u3nxkdvrh-ats.iot.ap-southeast-1.amazonaws.com IP: 52.221.124.73
:ref 1
:wr 240 240 0
:wrc 240 240 0
:ack 240
:rn 536
:rch 536, 536
:rch 1072, 536
:rch 1608, 536
:rd 5, 2144, 0
:rdi 536, 5
:rd 2139, 2144, 5
:rdi 531, 531
:c 531, 536, 2144
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 536
:rch 536, 536
:rch 1072, 536
:rd 1608, 1608, 0
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 536
:rch 536, 536
:rch 1072, 536
:rd 1608, 1608, 0
:rdi 536, 536
:c 536, 536, 1608
:rdi 536, 536
:c 536, 536, 1072
:rdi 536, 536
:c0 536, 536
:rn 3
*** Can't connect. ***
-------
---------- 
client->getLastSSLError() output is : 62

 ----------:ur 1
:close
:del
pm open,type:2 0

client->getLastSSLError(buff, len)

I also tried using the code mentioned in the comment above but I keep getting an error

buff was not declared in scope

Could you please let me know what buff should actually point to and is it okay to define len any random length?

@earlephilhower
Copy link
Collaborator

Your root cert isn't correct, per the error code (the 2nd form would actually copy the text string to a buffer you'd have to create):
/** \brief X.509 status: chain could not be linked to a trust anchor. */
#define BR_ERR_X509_NOT_TRUSTED 62

You need to get the root CA that verifies the azure domain you're connecting to and use that, not the specific cert of the machine handling the connection in their cloud. Use OpenSSL debug mode and you can have it dump the certs as it goes through the supplied chain.

@devyte
Copy link
Collaborator

devyte commented Nov 19, 2018

Closing due to user error.

@kadarpik
Copy link

World has changed in 20 years dramatically, we have many salesmen in every group, as in this thread, salesman automatically suggests official certificate, not asking even if a user is willing to use self signed certificate - there is actually no difference in the closed and global system at all from security point of view.

@kadarpik
Copy link

kadarpik commented Dec 11, 2022

Your root cert isn't correct, per the error code (the 2nd form would actually copy the text string to a buffer you'd have to create): /** \brief X.509 status: chain could not be linked to a trust anchor. */ #define BR_ERR_X509_NOT_TRUSTED 62

You need to get the root CA that verifies the azure domain you're connecting to and use that, not the specific cert of the machine handling the connection in their cloud. Use OpenSSL debug mode and you can have it dump the certs as it goes through the supplied chain.

Why ? You can use self signed as well !!! If you are controlling the server and ESP it is 100% secure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants