Esp-idf: mbedtls_ssl_handshake error specifying failed to open new connection 0x2700 (IDFGH-4195)

Created on 2 Nov 2020  路  13Comments  路  Source: espressif/esp-idf

Hello,

I'm trying to established connection with a local server in order to test OTA on my ESP32. When I performed the algorithm only with HTTP, it works perfect. However, trying to add the cert.pem to the esp_http_client_config throws the following error:

E (65381) esp-tls: mbedtls_ssl_handshake returned -0x2700 E (65383) esp-tls: Failed to open new connection E (65383) TRANS_SSL: Failed to open a new connection E (65384) HTTP_CLIENT: Connection failed, sock < 0 E (65389) esp_https_ota: Failed to open HTTP connection: ESP_ERR_HTTP_CONNECT E (65395) esp_https_ota: Failed to establish HTTP connection

My task is coded as followed:

`
void check_update_task(void *pvParameter) {

while(1) {

printf("Looking for a new firmware...\n");

// configure the esp_http_client
esp_http_client_config_t config= { };
config.url = UPDATE_JSON_URL;
config.event_handler = _http_event_handler;
esp_http_client_handle_t client = esp_http_client_init(&config);

// downloading the json file
esp_err_t err = esp_http_client_perform(client);
if(err == ESP_OK) {
   cJSON *json = cJSON_Parse(rcv_buffer);
   if(json == NULL) printf("downloaded file is not a valid json, aborting...\n");
   else {  
     cJSON *version = cJSON_GetObjectItemCaseSensitive(json, "version");
     cJSON *file = cJSON_GetObjectItemCaseSensitive(json, "file");
     // check the version
     if(!cJSON_IsNumber(version)) printf("unable to read new version, aborting...\n");
     else {
       auto new_version = version->valuedouble;
       if(new_version > FIRMWARE_VERSION) {
         printf("current firmware version (%.1f) is lower than the available one (%.1f), upgrading...\n", FIRMWARE_VERSION, new_version);
         if(cJSON_IsString(file) && (file->valuestring != NULL)) {

           printf("downloading and installing new firmware from: %s ...\n", file->valuestring);

           esp_http_client_config_t ota_client_config= { }; 

           ota_client_config.url = file->valuestring;
           ota_client_config.cert_pem = server_cert_pem_start;

           esp_err_t ret = esp_https_ota(&ota_client_config);
           if (ret == ESP_OK) {
             printf("OTA OK, restarting...\n");
             esp_restart();
           } else if (ret == ESP_FAIL) {
             printf("ESP_FAIL...\n");
           } else if (ret == ESP_ERR_INVALID_ARG) {
             printf("ESP_ERR_INVALID_ARG...\n");
           } else if (ret == ESP_ERR_OTA_VALIDATE_FAILED) {
             printf("ESP_ERR_OTA_VALIDATE_FAILED...\n");
           } else if (ret == ESP_ERR_NO_MEM) {
             printf("ESP_ERR_NO_MEM...\n");
           } else if (ret == ESP_ERR_FLASH_OP_TIMEOUT ) {
             printf("ESP_ERR_FLASH_OP_TIMEOUT ...\n");
           } else {
             printf("OTA failed...\n");
             printf("ESP_ERR_FLASH_OP_FAIL...\n");
           }
         }
         else printf("unable to read the new file name, aborting...\n");
       }
       else printf("current firmware version (%.1f) is greater or equal to the available one (%.1f), nothing to do...\n", FIRMWARE_VERSION, new_version);
     }
   }
}
else printf("unable to download the json file, aborting...\n");

// cleanup
esp_http_client_cleanup(client);

printf("\n");
    vTaskDelay(30000 / portTICK_PERIOD_MS);
}

}`

Most helpful comment

Interim my colleague (CC @shubhamkulkarni97) pointed out that there is no server certificate attached in your reference code for first request.

esp_http_client_config_t config= { };
config.url = UPDATE_JSON_URL;
config.event_handler = _http_event_handler;
esp_http_client_handle_t client = esp_http_client_init(&config);

Is this UPDATE_JSON_URL plain http url? Anyhow I think trying this in default IDF provided example would definitely be helpful.

All 13 comments

@CarSanoja Thanks for reporting and thanks @chegewara for the note.

https://esp32.com/viewtopic.php?f=2&t=15788&hilit=0x2700#p61358

Thank you for your quick reply, I already checked the source but I noticed that both files are the same in my server (cert and chain files), I'm working with self-signed certificates generated automatically with OpenSSL in my computer. Basically when I launch the server (Flask basic server) I pointed into the cert.pem and key.pem

Thanks for your help in advance

@CarSanoja

Can you please check if you can download firmware image hosted on your server from some client using curl or wget?

For example:
curl -v -O --cacert </path/to/server_cert.pem> <https://ip-addr:port/fw.bin>

Some useful links:
https://github.com/espressif/esp-idf/tree/master/examples/system/ota#run-https-server
https://github.com/espressif/esp-idf/tree/master/examples/system/ota#troubleshooting

Hello @mahavirj , thanks for your suggestions,

I tried running the following command and the results were:

curl -v -O --cacert cert.pem https://192.168.43.54:5000/update

image

As I mentioned, I just created a self-signed certificate, it does not seems to be downloading the binary file, however, if I disable the HHTPS protocol on the server and I just used the HTTP everything works fine

curl -v -O --cacert cert.pem http://192.168.43.54:5000/update

image

If I misunderstood anything please let me know to try it again, thanks again!

I just read that the ESP32 have problems working with self-signed certificates.

One important aspect is that - at least in my tests - the ESP seems to be unable to deal with self-signed certificates or a self-created CA. So for tests I've been using a server certificate signed by LetsEncrypt.

What is size of self-signed certificate? Im not sure it is still valid, but IIRC there was problem with certificates bigger than 2048 bytes.

@CarSanoja

Pointers from my earlier comment provides instructions for setting up server with self signed certificate. I do not suspect issue there because they are also used in some of the automated tests, e.g. https://github.com/espressif/esp-idf/blob/master/examples/system/ota/simple_ota_example/example_test.py.

Is it possible for you to try default IDF provided examples (e.g. https://github.com/espressif/esp-idf/tree/master/examples/system/ota/simple_ota_example) with your URL/Certificate?

If that does not work, then please help to provide detailed instructions you used to generate server credentials, along with openssl version and your host machine details (e.g. Linux/Windows etc.).

Thanks.

Interim my colleague (CC @shubhamkulkarni97) pointed out that there is no server certificate attached in your reference code for first request.

esp_http_client_config_t config= { };
config.url = UPDATE_JSON_URL;
config.event_handler = _http_event_handler;
esp_http_client_handle_t client = esp_http_client_init(&config);

Is this UPDATE_JSON_URL plain http url? Anyhow I think trying this in default IDF provided example would definitely be helpful.

Hello @mahavirj , @chegewara

Thank you very much for following up my issue, I really appreciate it. You were right, I was missing the cert parameter in the first request. Also, checking the example code, I realized I was missing a line of code:

#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
config.skip_cert_common_name_check = true;
#endif

After adding this line, everything works and ESP32 is looking for updates and is able to download the binary file. It seems to me that by default he is enabled in the sample OTA code, so he is also skipping the certificate validation.

@CarSanoja

Glad that it fixed problem for you.

However certificate common name check should not be disabled. If you see instructions for generating server credentials at https://github.com/espressif/esp-idf/tree/master/examples/system/ota#run-https-server you will find note:

When prompted for the Common Name (CN), enter the name of the server that the ESP32 will connect to. Regarding this example, it is probably the IP address. The HTTPS client will make sure that the CN matches the address given in the HTTPS URL.

We have this piece of code for internal testing purpose (example test case pointer I had shared earlier), so that regeneration of certificate is not required for every test run. For production cases, we recommend setting config.skip_cert_common_name_check = false.

Mahavir

@CarSanoja If there are no followup questions, do you mind closing the issue?

Closing, please feel to reopen for any followup.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

waayst picture waayst  路  4Comments

howroyd picture howroyd  路  3Comments

jakkubu picture jakkubu  路  4Comments

jakkra picture jakkra  路  3Comments

okasha55 picture okasha55  路  3Comments