Unsucessful HTTPS connection with own CA

martinius96
Posts: 33
Joined: Thu Dec 13, 2018 1:39 am

Unsucessful HTTPS connection with own CA

Postby martinius96 » Thu Dec 13, 2018 1:47 am

Hello there, I am working on Bachelor work.
I am making web application, where ESP32 is sending and also reading some datas from website.
ESP32 is client. I am using WifiClientSecure.h library for HTTPS connection.
I have tried to put Let's Encrypt certificate to my website, Global Root CA was DST ROOT CA x3.
I have downloaded its .pem certificate and put it to code.
It is working without any problem.

Nowadays I have tried to generate own certificates for server, CA, client. I have installed that generated CA certificate to Windows laptop and connection is working. I also added that CA .pem to code for ESP32 but connection is unsucessful. Certificate is valid isn't revoked or something like that. On Windows, Android working everything great.
Errors are:

Code: Select all

[E][ssl_client.cpp:32] handle_error(): X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[E][ssl_client.cpp:34] handle_error(): MbedTLS message code: -9984
[E][WiFiClientSecure.cpp:108] connect(): lwip_connect_r: 11
Code I am using it on Enterprise network (eduroam):

Code: Select all

#include <WiFi.h> //Wifi kniznica - pripojenie na wifi, HTTP konektivita - Webclient
#include <SPI.h>
#include <WiFiClientSecure.h>
#include "esp_wpa2.h" //doplnkova kniznica pre WPA/WPA2 Enterprise siete pod protokolom 802.1x
#include <Wire.h>
#include "SparkFun_Si7021_Breakout_Library.h" //Kniznica pre SHT21 senzor
//Identita a meno su totozne
//Metoda overenia Eduroamu: 1. krok PEAP + 2. krok MsCHAPv2
#define EAP_IDENTITY "identity" //identita - bez @tuke.sk pri pripojeni z inej organizacie, pouzit login@tuke.sk
#define EAP_PASSWORD "password" //heslo pouzivatela
const char* ssid = "INTRAK"; // Eduroam SSID
const char* host = "www.esp32.sk"; //adresa externeho webservera
const int rele = 23; //nastavenie premennej na GPIO pin 23
int pocitadlo = 0; //pocitadlo pre timeout
int rssi;
Weather sensor; //instancia pre senzor
#ifdef __cplusplus 
extern "C" { //externa cast jazyka C
  #endif
  uint8_t temprature_sens_read(); //systemove volanie funkcie teplomera
  #ifdef __cplusplus
  }
#endif
const char* test_root_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIICSjCCAbMCFHGiBSCT7reuv03fRC18PtDIqmdXMA0GCSqGSIb3DQEBCwUAMGQx\n" \
"CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApGYWtlIFN0YXRlMRYwFAYDVQQHDA1GYWtl\n" \
"IExvY2FsaXR5MRUwEwYDVQQKDAxGYWtlIENvbXBhbnkxETAPBgNVBAMMCGVzcDMy\n" \
"LnNrMB4XDTE4MTIxMzAwMTgxMFoXDTIzMTIxMjAwMTgxMFowZDELMAkGA1UEBhMC\n" \
"VVMxEzARBgNVBAgMCkZha2UgU3RhdGUxFjAUBgNVBAcMDUZha2UgTG9jYWxpdHkx\n" \
"FTATBgNVBAoMDEZha2UgQ29tcGFueTERMA8GA1UEAwwIZXNwMzIuc2swgZ8wDQYJ\n" \
"KoZIhvcNAQEBBQADgY0AMIGJAoGBAJYEKHi3PD8EDgj39wO02LDpSaim41BOu1GR\n" \
"ZoCScLPq8++l9DdTD31sVm37XCxQul8XUUpHpfKr2Ibspwv+AMj/fy12Rf49hZBg\n" \
"ey0qQrCbKJPC74nEIQHd7Y3/P++j8XRFUC0P3Pla+pSo6u2sEQrBtE23rJjXn3JQ\n" \
"Gcu7MSRtAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAI9CjtIxFQcaU9D8N2qBGvhP8\n" \
"PR4fC2dLPTRpyhpvbh5ABXwiOIVfN5zZFfCXPCHgXbcoYiSe9clutXFl9CZVFO1b\n" \
"cqXm2M29OwlZ38FL1n1GXvsbtPZCNjvjIoh8GJQtrbrB2TGCib55aKgDInLHJGPl\n" \
"RpwC0wffnU3m28c1clI=\n" \
"-----END CERTIFICATE-----\n";



// You can use x.509 client certificates if you want
//const char* test_client_key = "";   //to verify the client
//const char* test_client_cert = "";  //to verify the client



WiFiClientSecure client;
void setup() { //cast setupu prebieha iba raz
  Serial.begin(115200); //pocet znakov/s v serial monitore - UART
  delay(10); //vyckaj na inicializaciu
  sensor.begin();
  Serial.println();
  Serial.print("Pripajam sa na wifi siet: ");
  Serial.println(ssid); //informativne vypisy o nazve wifi siete
  WiFi.disconnect(true);  //odpoj sa od wifi pred nastavenim noveho pripojenia
  WiFi.mode(WIFI_STA); //nastavenie modu wifi modulu - vyzadovane v ESP32 Arduino Core v poslednych 2 verziach
  //pinMode(LED_BUILTIN, OUTPUT); nastavenie vystupu - zabudovana led
  pinMode(rele, OUTPUT);
  esp_wifi_sta_wpa2_ent_set_identity((uint8_t *)EAP_IDENTITY, strlen(EAP_IDENTITY)); //nastavenie identity
  esp_wifi_sta_wpa2_ent_set_username((uint8_t *)EAP_IDENTITY, strlen(EAP_IDENTITY)); //nastavenie mena - identita a meno a zhoduju
  esp_wifi_sta_wpa2_ent_set_password((uint8_t *)EAP_PASSWORD, strlen(EAP_PASSWORD)); //nastavenie hesla
  esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT(); //crypto funkcie (sha1, sha256.....) - z kniznice esp esp_wpa2.h
  esp_wifi_sta_wpa2_ent_enable(&config); //nakonfiguruj sietove pripojenie
  WiFi.begin(ssid);
  while (WiFi.status() != WL_CONNECTED) { //pokym nie je zariadenie autentizovane a autorizovane, pozdrz program a posielaj . do vypisu
    delay(500); // pauza 500ms
    Serial.print("."); // vypis znaku
    pocitadlo++; //inkrementuj pocitadlo
    if(pocitadlo>=60){ //po 30 sekundach restartuj dosku softverovym resetom, ak nedojde k pripojeniu
      ESP.restart();
    }
  }
  client.setCACert(test_root_ca);
  
   
   
   
    //client.setCertificate(test_client_key); // for client verification
  //client.setPrivateKey(test_client_cert);  // for client verification
  
  
  
  
  Serial.println("");
  Serial.println("WiFi pripojene");
  Serial.println("IP addresa nastavena: "); 
  Serial.println(WiFi.localIP()); //vypis pridelenu IP od DHCP sluzby
}

void restart(){
  Serial.print("Pripajam sa na: ");
  Serial.println(host);
  if (client.connect(host, 443)) { //ak je spojenie uspesne na server na porte 80 vykonaj blok prikazov
    Serial.println("Pripojenie pre kontrolu resetu uspesne");  
    String url = "/values/reset.txt"; //citanie z URL adresy na serveri
    client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: NodeMCU\r\n" + "Connection: close\r\n\r\n");
    //vykonanie GET HTTP requestu s verziou HTTP hlavicky, adresa hosta, user-agent zariadenia, ukoncenie HTTP hlavicky
    while (client.connected()) {
      String hlavicka = client.readStringUntil('\n'); //vypis hlavicky po riadkoch, verzia, engine, info o serveri, dlzka response atd...
      Serial.println(hlavicka);
      if (hlavicka == "\r") {
        break; //prazdny riadok za hlavickou, ukonc cyklus
      }
    }
  String premenna = client.readStringUntil('\n'); //riadok za HTTP hlavickou - nasa premenna, s ktorou pracujeme
  Serial.println(premenna);
  if(premenna=="RST"){ //za normalnych okolnosti je v premennej OK, ignoruje sa, pokym z webu nie je vyziadany reset, ktory zmeni obsah na RST.
    Serial.println("Restart vyziadany");
    client.stop(); //ukonc vsetky HTTP spojenia
    if (client.connect(host, 443)) {
      Serial.println("Potvrdzujem reset");
      String url = "/esp32/potvrdreset.php"; //potvrd reset tymto HTTP requestom, ktory opat nastavi do textoveho suboru text OK
      client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: NodeMCU\r\n" + "Connection: close\r\n\r\n");
      delay(1000);
      Serial.println("Restartujem...");
      ESP.restart(); //softverovy restart zariadenia
    }else{
      Serial.println("Nepodarilo sa potvrdit reset - pripojenie zlyhalo");
    }
  }
  }else{
    Serial.println("Nepodarilo sa nacitat stav resetu");
  } 
  client.stop();
}

  void stav_rele(){
 Serial.print("Pripajam sa na: ");
  Serial.println(host);
  if (client.connect(host, 443)) {
    Serial.println("Pripojenie pre stav rele uspesne");
    String url = "/values/stav.txt";
    client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: NodeMCU\r\n" + "Connection: close\r\n\r\n");
    while (client.connected()) {
      String hlavicka = client.readStringUntil('\n');
      Serial.println(hlavicka);
      if (hlavicka == "\r") {
        break;
      }
    }
   String premenna = client.readStringUntil('\n');
   Serial.println(premenna);
   if(premenna=="ZAP"){ //rozhodovanie medzi ZAP a VYP stavom citaneho z .txt suboru
    Serial.println("ZAPINAM RELE");
    digitalWrite(rele, HIGH);
   // digitalWrite(LED_BUILTIN, HIGH);
   }else if(premenna=="VYP"){
    Serial.println("VYPINAM RELE");
    digitalWrite(rele, LOW);
   // digitalWrite(LED_BUILTIN, LOW);
   }
  }else{
      Serial.println("Nepodarilo sa nacitat stav rele");
    } 
    client.stop(); //ukonc spojenia
}

void odoslanie(){
   float vlhkost = sensor.getRH();
  float teplotadnu = sensor.getTemp();
  String hum = String(vlhkost);
  String temp2 = String(teplotadnu);
  float teplota = (temprature_sens_read() - 32) / 1.8; //teplota cpu, povodna extern C funkcia - konstanta / konstanta
    String temp = String(teplota); //Pomocna premenna typu String, kolizia pri vyskladani GET requestmi s roznymi datovymi typmi String - float, int ....
    int sonda = hallRead(); //nacitanie udajov z hallovej sondy, systemova funkcia
    String hall = String(sonda); //prevedenie na String do pomocnej funkcie
    unsigned long beh = millis();
    String uptime = String(beh);
  if (client.connect(host, 443)) { //ak je pripojenie uspesne
    Serial.println("Pripojenie pre odoslanie dat uspesne");
    String url = "/esp32/zapisdata.php?teplota="+temp+"&hall="+hall+"&temp2="+temp2+"&hum="+hum+"&uptime="+uptime+"&signal="+rssi+"&ssid="+ssid; //vyskladany HTTP request s dvomi hodnotami, oddelene ampersandom & - pre rozlisenie na strane webu
    client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: NodeMCU\r\n" + "Connection: close\r\n\r\n");
  }else{ //ak je pripojenie neuspesne, informuj do UART monitoru
      Serial.println("Nepodarilo sa odoslat data"); //informativny vypis
    } 
    client.stop();
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) { //ak je pripojenie uspesne
    pocitadlo = 0; //vynuluj pocitadlo
    Serial.println("Wifi je stale pripojene s IP: "); 
    Serial.println(WiFi.localIP());   //informuj pouzivatela o jeho IP v kazdej slucke
    rssi = WiFi.RSSI();
    Serial.print("Sila signalu (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  }else if (WiFi.status() != WL_CONNECTED) { //ak nie je uspesne, opakuj spojenie
    Serial.println("Spojenie stratene - Pripajanie k wifi..."); 
    WiFi.begin(ssid);      
  }
  while (WiFi.status() != WL_CONNECTED) { //pozdrz program, pokym sa doska pripoji
    delay(500);
    Serial.print(".");
    pocitadlo++;
    if(pocitadlo>=60){ //po 30 sekundach restartuj dosku softverovym resetom, ak nedojde k pripojeniu
    ESP.restart();
    }
  }
  odoslanie(); //volanie funkcie pre odosielanie
  stav_rele(); //volanie funkcie pre citanie stavu rele
  restart(); //volanie funkcie pre citanie vyziadania resetu
  delay(2000); //pockaj 2 sekundy pred novou sluckou
}
Where is the problem? What I am doing wrong?
I have generated certificates with OpenSSL with following commands:

Code: Select all

openssl genrsa -out myCA.key 1024
openssl req -x509 -config certificate-authority-options.conf -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem
openssl x509 -outform pem -in myCA.pem -out myCA.crt

openssl genrsa -out server.key 1024
openssl req -config options.conf -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out server.pem -days 1825 -sha256 -extfile server.ext
openssl x509 -outform pem -in server.pem -out server.crt

openssl genrsa -out client.key 1024
openssl req -config options.conf -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out client.pem -days 1825 -sha256 -extfile client.ext
.EXT files consist of:

Code: Select all

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = esp32.sk
DNS.2 = www.esp32.sk
OPTIONS conf files:

Code: Select all

[req]
prompt = no
distinguished_name = req_distinguished_name

[req_distinguished_name]
C = US
ST = Fake State
L = Fake Locality
O = Fake Company
# OU = Org Unit Name
# emailAddress = info@example.com
CN = esp32.sk


copercini
Posts: 25
Joined: Wed Dec 21, 2016 4:44 pm

Re: Unsucessful HTTPS connection with own CA

Postby copercini » Sat Dec 15, 2018 2:44 pm

have you tried with

Code: Select all

const char* host = "esp32.sk";
without www?

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Unsucessful HTTPS connection with own CA

Postby chegewara » Sun Dec 16, 2018 6:19 am

If I had guessing I would say it's key length. Try with 2048.

martinius96
Posts: 33
Joined: Thu Dec 13, 2018 1:39 am

Re: Unsucessful HTTPS connection with own CA

Postby martinius96 » Thu Dec 27, 2018 1:27 am

Yes, problem was at key. 2048-bit working for rsa and 256-bit for EC working too.

Who is online

Users browsing this forum: PepeTheGreat and 58 guests