Skip to content

Commit 3bd64da

Browse files
committed
esp_rmaker_local_ctrl: Added support for sec1
Also created a service which has POP as a param. The clients such as phone app can use this POP to connect to the device if the security type is sec1. For sec0, this service is not created.
1 parent 7226359 commit 3bd64da

File tree

8 files changed

+244
-2
lines changed

8 files changed

+244
-2
lines changed

CHANGES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changes
22

3+
## 12-Jan-2022 (esp_rmaker_local_ctrl: Added support for sec1)
4+
5+
This commit adds support for security1 for local control. This can be enabled by setting
6+
`CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_1` when using local control feature (this is the
7+
default security level when enabling local control). This would also require the latest
8+
phone apps which have the support for security1.
9+
10+
You can check the docs [here](https://rainmaker.espressif.com/docs/local-control.html) for more details.
11+
312
## 24-Aug-2021 (esp_rmaker_user_mapping: Add checks for user id for better security)
413

514
This commit adds some logic to detect a reset to factory or a user change during the

components/esp_rainmaker/Kconfig.projbuild

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@ menu "ESP RainMaker Config"
7777
help
7878
The port number to be used for http for local control.
7979

80+
choice ESP_RMAKER_LOCAL_CTRL_SECURITY
81+
prompt "Local Control Security Type"
82+
depends on ESP_RMAKER_LOCAL_CTRL_ENABLE
83+
default ESP_RMAKER_LOCAL_CTRL_SECURITY_1
84+
help
85+
Security type to be selected for local control.
86+
87+
config ESP_RMAKER_LOCAL_CTRL_SECURITY_0
88+
bool "sec0"
89+
config ESP_RMAKER_LOCAL_CTRL_SECURITY_1
90+
bool "sec1"
91+
endchoice
92+
93+
config ESP_RMAKER_LOCAL_CTRL_SECURITY
94+
int
95+
default 0 if ESP_RMAKER_LOCAL_CTRL_SECURITY_0
96+
default 1 if ESP_RMAKER_LOCAL_CTRL_SECURITY_1
97+
8098
choice ESP_RMAKER_CONSOLE_UART_NUM
8199
prompt "UART for console input"
82100
default ESP_RMAKER_CONSOLE_UART_NUM_0

components/esp_rainmaker/include/esp_rmaker_standard_params.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ extern "C"
4848
#define ESP_RMAKER_DEF_REBOOT_NAME "Reboot"
4949
#define ESP_RMAKER_DEF_FACTORY_RESET_NAME "Factory-Reset"
5050
#define ESP_RMAKER_DEF_WIFI_RESET_NAME "Wi-Fi-Reset"
51+
#define ESP_RMAKER_DEF_LOCAL_CONTROL_POP "POP"
52+
#define ESP_RMAKER_DEF_LOCAL_CONTROL_TYPE "Type"
5153

5254
/**
5355
* Create standard name param
@@ -302,6 +304,32 @@ esp_rmaker_param_t *esp_rmaker_factory_reset_param_create(const char *param_name
302304
*/
303305
esp_rmaker_param_t *esp_rmaker_wifi_reset_param_create(const char *param_name);
304306

307+
/**
308+
* Create standard Local Control POP param
309+
*
310+
* This will create the standard Local Control POP parameter.
311+
*
312+
* @param[in] param_name Name of the parameter
313+
* @param[in] val Default Value of the parameter (Eg. "abcd1234"). Can be kept NULL.
314+
*
315+
* @return Parameter handle on success.
316+
* @return NULL in case of failures.
317+
*/
318+
esp_rmaker_param_t *esp_rmaker_local_control_pop_param_create(const char *param_name, const char *val);
319+
320+
/**
321+
* Create standard Local Control Type param
322+
*
323+
* This will create the standard Local Control security type parameter.
324+
*
325+
* @param[in] param_name Name of the parameter
326+
* @param[in] val Default Value of the parameter
327+
*
328+
* @return Parameter handle on success.
329+
* @return NULL in case of failures.
330+
*/
331+
esp_rmaker_param_t *esp_rmaker_local_control_type_param_create(const char *param_name, int val);
332+
305333
#ifdef __cplusplus
306334
}
307335
#endif

components/esp_rainmaker/include/esp_rmaker_standard_services.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ esp_rmaker_device_t *esp_rmaker_create_schedule_service(const char *serv_name, e
8585

8686
esp_rmaker_device_t *esp_rmaker_create_system_service(const char *serv_name, void *priv_data);
8787

88+
/** Create a standard Local Control service
89+
*
90+
* This creates a Local Control service with the mandatory parameters. The default parameter names will be used.
91+
* Refer \ref esp_rmaker_standard_params.h for default names.
92+
*
93+
* @param[in] serv_name The unique service name
94+
* @param[in] pop Proof of possession
95+
* @param[in] sec_type Security type
96+
* @param[in] priv_data (Optional) Private data associated with the service. This should stay
97+
* allocated throughout the lifetime of the service.
98+
*
99+
* @return service_handle on success.
100+
* @return NULL in case of any error.
101+
*/
102+
esp_rmaker_device_t *esp_rmaker_create_local_control_service(const char *serv_name, const char *pop, int sec_type, void *priv_data);
103+
88104
#ifdef __cplusplus
89105
}
90106
#endif

components/esp_rainmaker/include/esp_rmaker_standard_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ extern "C"
4747
#define ESP_RMAKER_PARAM_REBOOT "esp.param.reboot"
4848
#define ESP_RMAKER_PARAM_FACTORY_RESET "esp.param.factory-reset"
4949
#define ESP_RMAKER_PARAM_WIFI_RESET "esp.param.wifi-reset"
50+
#define ESP_RMAKER_PARAM_LOCAL_CONTROL_POP "esp.param.local_control_pop"
51+
#define ESP_RMAKER_PARAM_LOCAL_CONTROL_TYPE "esp.param.local_control_type"
5052

5153

5254
/********** STANDARD DEVICE TYPES **********/
@@ -62,6 +64,7 @@ extern "C"
6264
#define ESP_RMAKER_SERVICE_TIME "esp.service.time"
6365
#define ESP_RMAKER_SERVICE_SCHEDULE "esp.service.schedule"
6466
#define ESP_RMAKER_SERVICE_SYSTEM "esp.service.system"
67+
#define ESP_RMAKER_SERVICE_LOCAL_CONTROL "esp.service.local_control"
6568

6669
#ifdef __cplusplus
6770
}

components/esp_rainmaker/src/core/esp_rmaker_local_ctrl.c

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,40 @@
1414

1515
#include <stdlib.h>
1616
#include <esp_log.h>
17+
#include <nvs.h>
1718
#include <esp_event.h>
1819
#include <esp_local_ctrl.h>
1920
#include <wifi_provisioning/manager.h>
2021
#include <esp_rmaker_internal.h>
22+
#include <esp_rmaker_standard_services.h>
2123
#include <esp_https_server.h>
2224
#include <mdns.h>
2325

26+
#include <esp_idf_version.h>
27+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
28+
// Features supported in 4.2
29+
30+
#define ESP_RMAKER_LOCAL_CTRL_SECURITY_TYPE CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY
31+
32+
#else
33+
34+
#if CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY != 0
35+
#warning "Local control security type is not supported in idf versions below 4.2. Using sec0 by default."
36+
#endif
37+
#define ESP_RMAKER_LOCAL_CTRL_SECURITY_TYPE 0
38+
39+
#endif /* !IDF4.2 */
40+
2441
static const char * TAG = "esp_rmaker_local";
2542

2643
/* Random Port number that will be used by the local control http instance
2744
* for internal control communication.
2845
*/
2946
#define ESP_RMAKER_LOCAL_CTRL_HTTP_CTRL_PORT 12312
47+
#define ESP_RMAKER_NVS_PART_NAME "nvs"
48+
#define ESP_RMAKER_NVS_LOCAL_CTRL_NAMESPACE "local_ctrl"
49+
#define ESP_RMAKER_NVS_LOCAL_CTRL_POP "pop"
50+
#define ESP_RMAKER_POP_LEN 9
3051

3152
/* Custom allowed property types */
3253
enum property_types {
@@ -123,19 +144,106 @@ static esp_err_t set_property_values(size_t props_count,
123144
return ret;
124145
}
125146

147+
static char *__esp_rmaker_local_ctrl_get_nvs(const char *key)
148+
{
149+
char *val = NULL;
150+
nvs_handle handle;
151+
esp_err_t err = nvs_open_from_partition(ESP_RMAKER_NVS_PART_NAME, ESP_RMAKER_NVS_LOCAL_CTRL_NAMESPACE, NVS_READONLY, &handle);
152+
if (err != ESP_OK) {
153+
return NULL;
154+
}
155+
size_t len = 0;
156+
if ((err = nvs_get_blob(handle, key, NULL, &len)) == ESP_OK) {
157+
val = calloc(1, len + 1); /* +1 for NULL termination */
158+
if (val) {
159+
nvs_get_blob(handle, key, val, &len);
160+
}
161+
}
162+
nvs_close(handle);
163+
return val;
164+
165+
}
166+
167+
static esp_err_t __esp_rmaker_local_ctrl_set_nvs(const char *key, const char *val)
168+
{
169+
nvs_handle handle;
170+
esp_err_t err = nvs_open_from_partition(ESP_RMAKER_NVS_PART_NAME, ESP_RMAKER_NVS_LOCAL_CTRL_NAMESPACE, NVS_READWRITE, &handle);
171+
if (err != ESP_OK) {
172+
return err;
173+
}
174+
err = nvs_set_blob(handle, key, val, strlen(val));
175+
nvs_commit(handle);
176+
nvs_close(handle);
177+
return err;
178+
}
179+
180+
static char *esp_rmaker_local_ctrl_get_pop()
181+
{
182+
char *pop = __esp_rmaker_local_ctrl_get_nvs(ESP_RMAKER_NVS_LOCAL_CTRL_POP);
183+
if (pop) {
184+
return pop;
185+
}
186+
187+
ESP_LOGI(TAG, "Couldn't find POP in NVS. Generating a new one.");
188+
pop = (char *)calloc(1, ESP_RMAKER_POP_LEN);
189+
if (!pop) {
190+
ESP_LOGE(TAG, "Couldn't allocate POP");
191+
return NULL;
192+
}
193+
uint8_t random_bytes[ESP_RMAKER_POP_LEN] = {0};
194+
esp_fill_random(&random_bytes, sizeof(random_bytes));
195+
snprintf(pop, ESP_RMAKER_POP_LEN, "%02x%02x%02x%02x", random_bytes[0], random_bytes[1], random_bytes[2], random_bytes[3]);
196+
197+
__esp_rmaker_local_ctrl_set_nvs(ESP_RMAKER_NVS_LOCAL_CTRL_POP, pop);
198+
return pop;
199+
}
200+
201+
static int esp_rmaker_local_ctrl_get_security_type()
202+
{
203+
return ESP_RMAKER_LOCAL_CTRL_SECURITY_TYPE;
204+
}
205+
206+
static esp_err_t esp_rmaker_local_ctrl_service_enable(void)
207+
{
208+
char *pop_str = esp_rmaker_local_ctrl_get_pop();
209+
if (!pop_str) {
210+
ESP_LOGE(TAG, "Get POP failed");
211+
return ESP_FAIL;
212+
}
213+
int sec_ver = esp_rmaker_local_ctrl_get_security_type();
214+
215+
esp_rmaker_device_t *local_ctrl_service = esp_rmaker_create_local_control_service("Local Control", pop_str, sec_ver, NULL);
216+
if (!local_ctrl_service) {
217+
ESP_LOGE(TAG, "Failed to create Schedule Service");
218+
free(pop_str);
219+
return ESP_FAIL;
220+
}
221+
free(pop_str);
222+
223+
esp_err_t err = esp_rmaker_node_add_device(esp_rmaker_get_node(), local_ctrl_service);
224+
if (err != ESP_OK) {
225+
ESP_LOGE(TAG, "Failed to add service Service");
226+
return err;
227+
}
228+
229+
ESP_LOGD(TAG, "Local Control Service Enabled");
230+
return err;
231+
}
232+
126233
static esp_err_t __esp_rmaker_start_local_ctrl_service(const char *serv_name)
127234
{
128235
if (!serv_name) {
129236
ESP_LOGE(TAG, "Service name cannot be empty.");
130237
return ESP_ERR_INVALID_ARG;
131238
}
132-
ESP_LOGI(TAG, "Starting ESP Local control with HTTP Transport.");
239+
240+
ESP_LOGI(TAG, "Starting ESP Local control with HTTP Transport and security version: %d", esp_rmaker_local_ctrl_get_security_type());
133241
/* Set the configuration */
134242
static httpd_ssl_config_t https_conf = HTTPD_SSL_CONFIG_DEFAULT();
135243
https_conf.transport_mode = HTTPD_SSL_TRANSPORT_INSECURE;
136244
https_conf.port_insecure = CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT;
137245
https_conf.httpd.ctrl_port = ESP_RMAKER_LOCAL_CTRL_HTTP_CTRL_PORT;
138-
246+
139247
mdns_init();
140248
mdns_hostname_set(serv_name);
141249

@@ -155,8 +263,40 @@ static esp_err_t __esp_rmaker_start_local_ctrl_service(const char *serv_name)
155263
.max_properties = 10
156264
};
157265

266+
/* If sec1, add security type details to the config */
267+
protocomm_security_pop_t *pop = NULL;
268+
#if ESP_RMAKER_LOCAL_CTRL_SECURITY_TYPE == 1
269+
char *pop_str = esp_rmaker_local_ctrl_get_pop();
270+
/* Note: pop_str shouldn't be freed. If it gets freed, the pointer which is internally copied in esp_local_ctrl_start() will become invalid which would cause corruption. */
271+
272+
int sec_ver = esp_rmaker_local_ctrl_get_security_type();
273+
274+
if (sec_ver != 0 && pop_str) {
275+
pop = (protocomm_security_pop_t *)calloc(1, sizeof(protocomm_security_pop_t));
276+
if (!pop) {
277+
ESP_LOGE(TAG, "Failed to allocate pop");
278+
free(pop_str);
279+
return ESP_ERR_NO_MEM;
280+
}
281+
pop->data = (uint8_t *)pop_str;
282+
pop->len = strlen(pop_str);
283+
}
284+
285+
config.proto_sec.version = sec_ver;
286+
config.proto_sec.custom_handle = NULL;
287+
config.proto_sec.pop = pop;
288+
#endif
289+
158290
/* Start esp_local_ctrl service */
159291
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
292+
293+
/* Add node_id in mdns */
294+
mdns_service_txt_item_set("_esp_local_ctrl", "_tcp", "node_id", esp_rmaker_get_node_id());
295+
296+
if (pop) {
297+
free(pop);
298+
}
299+
160300
ESP_LOGI(TAG, "esp_local_ctrl service started with name : %s", serv_name);
161301

162302
/* Create the Node Config property */
@@ -230,6 +370,10 @@ esp_err_t esp_rmaker_init_local_ctrl_service(void)
230370

231371
esp_err_t esp_rmaker_start_local_ctrl_service(const char *serv_name)
232372
{
373+
if (ESP_RMAKER_LOCAL_CTRL_SECURITY_TYPE == 1) {
374+
esp_rmaker_local_ctrl_service_enable();
375+
}
376+
233377
if (!wait_for_wifi_prov) {
234378
return __esp_rmaker_start_local_ctrl_service(serv_name);
235379
}

components/esp_rainmaker/src/standard_types/esp_rmaker_standard_params.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,17 @@ esp_rmaker_param_t *esp_rmaker_wifi_reset_param_create(const char *param_name)
181181
esp_rmaker_bool(false), PROP_FLAG_READ | PROP_FLAG_WRITE);
182182
return param;
183183
}
184+
185+
esp_rmaker_param_t *esp_rmaker_local_control_pop_param_create(const char *param_name, const char *val)
186+
{
187+
esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, ESP_RMAKER_PARAM_LOCAL_CONTROL_POP,
188+
esp_rmaker_str(val), PROP_FLAG_READ);
189+
return param;
190+
}
191+
192+
esp_rmaker_param_t *esp_rmaker_local_control_type_param_create(const char *param_name, int val)
193+
{
194+
esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, ESP_RMAKER_PARAM_LOCAL_CONTROL_TYPE,
195+
esp_rmaker_int(val), PROP_FLAG_READ);
196+
return param;
197+
}

components/esp_rainmaker/src/standard_types/esp_rmaker_standard_services.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,13 @@ esp_rmaker_device_t *esp_rmaker_create_system_service(const char *serv_name, voi
5555
{
5656
return esp_rmaker_service_create(serv_name, ESP_RMAKER_SERVICE_SYSTEM, priv_data);
5757
}
58+
59+
esp_rmaker_device_t *esp_rmaker_create_local_control_service(const char *serv_name, const char *pop, int sec_type, void *priv_data)
60+
{
61+
esp_rmaker_device_t *service = esp_rmaker_service_create(serv_name, ESP_RMAKER_SERVICE_LOCAL_CONTROL, priv_data);
62+
if (service) {
63+
esp_rmaker_device_add_param(service, esp_rmaker_local_control_pop_param_create(ESP_RMAKER_DEF_LOCAL_CONTROL_POP, pop));
64+
esp_rmaker_device_add_param(service, esp_rmaker_local_control_type_param_create(ESP_RMAKER_DEF_LOCAL_CONTROL_TYPE, sec_type));
65+
}
66+
return service;
67+
}

0 commit comments

Comments
 (0)