fix(provisioning): fix incorrect AES-GCM IV usage in security2 scheme

Using same IV in AES-GCM across multiple invocation of
encryption/decryption operations can pose a security risk. It can help
to reveal co-relation between different plaintexts.

This commit introduces a change to use part of IV as a monotonic
counter, which must be incremented after every AES-GCM invocation
on both the client and the device side.

Concept of patch version for a security scheme has been introduced here
which can help to differentiate a protocol behavior for the provisioning
entity. The security patch version will be available in the JSON
response for `proto-ver` endpoint request with the field
`sec_patch_ver`.

Please refer to documentation for more details on the changes required
on the provisioning entity side (e.g., PhoneApps).
This commit is contained in:
Mahavir Jain
2025-03-07 13:49:10 +05:30
parent 641f461346
commit 3bd5a22f5a
7 changed files with 182 additions and 46 deletions
+22 -15
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -260,7 +260,15 @@ static cJSON* wifi_prov_get_info_json(void)
/* Version field */
cJSON_AddStringToObject(prov_info_json, "ver", prov_ctx->mgr_info.version);
/* Security field */
int sec_ver = 0;
uint8_t sec_patch_ver = 0;
protocomm_get_sec_version(prov_ctx->pc, &sec_ver, &sec_patch_ver);
assert(sec_ver == prov_ctx->security);
cJSON_AddNumberToObject(prov_info_json, "sec_ver", prov_ctx->security);
cJSON_AddNumberToObject(prov_info_json, "sec_patch_ver", sec_patch_ver);
/* Capabilities field */
cJSON_AddItemToObject(prov_info_json, "cap", prov_capabilities);
@@ -307,19 +315,6 @@ static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const cha
return ret;
}
/* Set version information / capabilities of provisioning service and application */
cJSON *version_json = wifi_prov_get_info_json();
char *version_str = cJSON_Print(version_json);
ret = protocomm_set_version(prov_ctx->pc, "proto-ver", version_str);
free(version_str);
cJSON_Delete(version_json);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set version endpoint");
scheme->prov_stop(prov_ctx->pc);
protocomm_delete(prov_ctx->pc);
return ret;
}
/* Set protocomm security type for endpoint */
if (prov_ctx->security == 0) {
#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0
@@ -356,6 +351,19 @@ static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const cha
return ret;
}
/* Set version information / capabilities of provisioning service and application */
cJSON *version_json = wifi_prov_get_info_json();
char *version_str = cJSON_Print(version_json);
ret = protocomm_set_version(prov_ctx->pc, "proto-ver", version_str);
free(version_str);
cJSON_Delete(version_json);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set version endpoint");
scheme->prov_stop(prov_ctx->pc);
protocomm_delete(prov_ctx->pc);
return ret;
}
prov_ctx->wifi_prov_handlers = malloc(sizeof(wifi_prov_config_handlers_t));
ret = get_wifi_prov_handlers(prov_ctx->wifi_prov_handlers);
if (ret != ESP_OK) {
@@ -1651,7 +1659,6 @@ esp_err_t wifi_prov_mgr_start_provisioning(wifi_prov_security_t security, const
#endif
prov_ctx->security = security;
esp_timer_create_args_t wifi_connect_timer_conf = {
.callback = wifi_connect_timer_cb,
.arg = NULL,