Protocomm Commands are not able to Decrypted by ESP32 During WIFI Provisioing using HTTPD
Posted: Fri Oct 04, 2019 6:22 am
Environment
ESP-IDF : v3.3
Mobile Application for WIFI Provisioning: https://github.com/espressif/esp-idf-provisioning-ios
ESP-IDF Example : example/provisioning/manager
Feature Modified : We used HTTP based wifi_prov_scheme_t with security-1 (along with PoP) feature.
Issue Observed
Few times after connecting mobile-app with esp32 (wifi ap), wifi-scanning failed in mobile application. When we enable debug logs in esp32, we observed below prints,
>> From above prints, we checked esp-idf implementation where we found a genuine design related bug.
Bug:
>> When HTTP server starts in ESP32 and mobile connected with this server for provisioning process, it might possible that HTTP server deletes its current socket and creates new one. Change of this does not reflect in application layer. To mitigate this, ESP32 always ask current socket id in "common_post_handler" under "protocomm_httpd" file.
>> Issue comes when secure-connection made on security endpoint AND HTTP server change its socket AND any command received on "prov_config" endpoint.
>> In current Implementation, ESP32 is freeing up security endpoint data structure and creating new data structure (using free/calloc calls). Doing this would sanitized all security endpoint data (public keys, sym keys , state etc).
>> Hence, request from mobile would not be decrypted as there is no data present on security endpoint. This will gives "security1: Secure session not established" error prints.
>> There will not be any further communication happened and user has to do force reboot to re-initiate communication.
>> One another issue we observed is that, when we hit "connected" button in mobile application (after connected with ESP32), mobile-app start ask for wifi-scan list from esp32. At this stage, if we press back arrow button and again hit "connected" button to reinitialize all process, it fails there and no any processing happened.
We fixed both of these issues as a patch as below and its working fine now
>> We made "sec1_update" api which only does updating session-id in security data-structure if there is a socket change introduced in middle of provisioning process.
Lets us know if you already fixed or method of doing this fix incorrect?
Let us know when we would get resolutions to both of these fixes?
Thanks,
Nirav Agrawal
ESP-IDF : v3.3
Mobile Application for WIFI Provisioning: https://github.com/espressif/esp-idf-provisioning-ios
ESP-IDF Example : example/provisioning/manager
Feature Modified : We used HTTP based wifi_prov_scheme_t with security-1 (along with PoP) feature.
Issue Observed
Few times after connecting mobile-app with esp32 (wifi ap), wifi-scanning failed in mobile application. When we enable debug logs in esp32, we observed below prints,
Code: Select all
E (136368) security1: Secure session not established
E (136368) protocomm: Decryption of response failed for endpoint prov-config
E (136368) protocomm_httpd: Data handler failed
W (136378) httpd_uri: httpd_uri: uri handler execution failed
Bug:
>> When HTTP server starts in ESP32 and mobile connected with this server for provisioning process, it might possible that HTTP server deletes its current socket and creates new one. Change of this does not reflect in application layer. To mitigate this, ESP32 always ask current socket id in "common_post_handler" under "protocomm_httpd" file.
>> Issue comes when secure-connection made on security endpoint AND HTTP server change its socket AND any command received on "prov_config" endpoint.
>> In current Implementation, ESP32 is freeing up security endpoint data structure and creating new data structure (using free/calloc calls). Doing this would sanitized all security endpoint data (public keys, sym keys , state etc).
>> Hence, request from mobile would not be decrypted as there is no data present on security endpoint. This will gives "security1: Secure session not established" error prints.
>> There will not be any further communication happened and user has to do force reboot to re-initiate communication.
>> One another issue we observed is that, when we hit "connected" button in mobile application (after connected with ESP32), mobile-app start ask for wifi-scan list from esp32. At this stage, if we press back arrow button and again hit "connected" button to reinitialize all process, it fails there and no any processing happened.
We fixed both of these issues as a patch as below and its working fine now
>> We made "sec1_update" api which only does updating session-id in security data-structure if there is a socket change introduced in middle of provisioning process.
Code: Select all
static esp_err_t common_post_handler(httpd_req_t *req)
{
esp_err_t ret;
uint8_t *outbuf = NULL;
char *req_body = NULL;
const char *ep_name = NULL;
ssize_t outlen;
int cur_session_id = httpd_req_to_sockfd(req);
ESP_LOGD(TAG, "common_post_handler,cur_session_id:%d, session_id :%d", cur_session_id, session_id );
/* Patch start */
if ((!strcmp((req->uri + 1U), "proto-ver"))) {
session_id = PROTOCOMM_NO_SESSION_ID;
}
if (cur_session_id != session_id) {
if (session_id != PROTOCOMM_NO_SESSION_ID) {
if (pc_httpd->sec && pc_httpd->sec->update) {
ret = pc_httpd->sec->update(session_id, cur_session_id);
// ret = pc_httpd->sec->close_transport_session(session_id);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "Error updating session with new ID: %d",
cur_session_id);
}
}
} else {
if (pc_httpd->sec && pc_httpd->sec->new_transport_session) {
ret = pc_httpd->sec->new_transport_session(cur_session_id);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to launch new session with ID: %d",
cur_session_id);
ret = ESP_FAIL;
goto out;
}
}
}
session_id = cur_session_id;
}
/* Patch end */
if (req->content_len <= 0) {
ESP_LOGE(TAG, "Content length not found");
ret = ESP_FAIL;
goto out;
} else if (req->content_len > MAX_REQ_BODY_LEN) {
ESP_LOGE(TAG, "Request content length should be less than 4kb");
ret = ESP_FAIL;
goto out;
}
req_body = (char *) malloc(req->content_len);
if (!req_body) {
ESP_LOGE(TAG, "Unable to allocate for request length %d", req->content_len);
ret = ESP_ERR_NO_MEM;
goto out;
}
size_t recv_size = 0;
while (recv_size < req->content_len) {
ret = httpd_req_recv(req, req_body + recv_size, req->content_len - recv_size);
if (ret < 0) {
ret = ESP_FAIL;
goto out;
}
recv_size += ret;
}
/* Extract the endpoint name from URI string of type "/ep_name" */
ep_name = req->uri + 1;
ESP_LOGD(TAG, "epname: %s, session %d", ep_name,session_id);
ret = protocomm_req_handle(pc_httpd, ep_name, session_id,
(uint8_t *)req_body, recv_size, &outbuf, &outlen);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Data handler failed");
ret = ESP_FAIL;
goto out;
}
ret = httpd_resp_send(req, (char *)outbuf, outlen);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "HTTP send failed");
ret = ESP_FAIL;
goto out;
}
ret = ESP_OK;
out:
if (req_body) {
free(req_body);
}
if (outbuf) {
free(outbuf);
}
return ret;
}
Lets us know if you already fixed or method of doing this fix incorrect?
Let us know when we would get resolutions to both of these fixes?
Thanks,
Nirav Agrawal