Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 1d3ad0e

Browse files
authored
Implemented configuration options for BLE security
* Original PR: #360 by DvdGiessen * Some minor modifications were applied: - added secure_connections to bt_obj_t struct - restored remove_all_bonded_devices() instad of remove_bonded_devices - secure parameters are set inside set_pin() - secure connection is decided based on PIN set - bt_init_args secure argument is removed - removed 'BLE paring passkey: ' REPL message - removed automatic secure connection in case of connection - restored characteristics notification
1 parent 6b9c880 commit 1d3ad0e

File tree

1 file changed

+96
-92
lines changed

1 file changed

+96
-92
lines changed

esp32/mods/modbt.c

Lines changed: 96 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
#define MOD_BT_GATTS_CLOSE_EVT (0x0400)
8181
#define MOD_BT_NVS_NAMESPACE "BT_NVS"
8282
#define MOD_BT_HASH_SIZE (20)
83-
#define MOD_BT_PIN_LENGTH (6)
8483

8584
/******************************************************************************
8685
DEFINE PRIVATE TYPES
@@ -103,6 +102,8 @@ typedef struct {
103102
bool advertising;
104103
bool controller_active;
105104
bool secure;
105+
bool secure_connections;
106+
bool privacy;
106107
} bt_obj_t;
107108

108109
typedef struct {
@@ -255,16 +256,6 @@ static esp_ble_adv_params_t bt_adv_params = {
255256
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
256257
};
257258

258-
static esp_ble_adv_params_t bt_adv_params_sec = {
259-
.adv_int_min = 0x100,
260-
.adv_int_max = 0x100,
261-
.adv_type = ADV_TYPE_IND,
262-
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
263-
.channel_map = ADV_CHNL_ALL,
264-
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
265-
};
266-
267-
268259
static bool mod_bt_allow_resume_deinit;
269260
static uint16_t mod_bt_gatts_mtu_restore = 0;
270261
static bool mod_bt_is_conn_restore_available;
@@ -424,11 +415,7 @@ void bt_resume(bool reconnect)
424415

425416
/* See if there was an averstisment active before Sleep */
426417
if(bt_obj.advertising) {
427-
if (!bt_obj.secure){
428-
esp_ble_gap_start_advertising(&bt_adv_params);
429-
} else {
430-
esp_ble_gap_start_advertising(&bt_adv_params_sec);
431-
}
418+
esp_ble_gap_start_advertising(&bt_adv_params);
432419
}
433420
}
434421

@@ -480,22 +467,6 @@ static void create_hash(uint32_t pin, uint8_t *h_value)
480467
mbedtls_sha1_free(&sha1_context);
481468
}
482469

483-
static bool is_pin_valid(uint32_t pin)
484-
{
485-
int digits = 0;
486-
487-
while(pin != 0)
488-
{
489-
digits++;
490-
pin /= 10;
491-
}
492-
493-
if (digits != MOD_BT_PIN_LENGTH){
494-
return false;
495-
}
496-
497-
return true;
498-
}
499470
static bool pin_changed(uint32_t new_pin)
500471
{
501472
bool ret = false;
@@ -534,20 +505,11 @@ static void remove_all_bonded_devices(void)
534505
for (int i = 0; i < dev_num; i++) {
535506
esp_ble_remove_bond_device(dev_list[i].bd_addr);
536507
}
537-
538508
free(dev_list);
539509
}
540510

541-
static void set_secure_parameters(uint32_t passKey){
542-
543-
if (pin_changed(passKey)) {
544-
remove_all_bonded_devices();
545-
}
546-
547-
uint32_t passkey = passKey;
548-
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
549-
550-
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND;
511+
static void set_secure_parameters(bool secure_connections) {
512+
esp_ble_auth_req_t auth_req = secure_connections ? ESP_LE_AUTH_REQ_SC_MITM_BOND : ESP_LE_AUTH_BOND;
551513
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
552514

553515
esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT;
@@ -558,14 +520,30 @@ static void set_secure_parameters(uint32_t passKey){
558520

559521
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE;
560522
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
561-
523+
562524
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
563525
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
564526

565527
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
566528
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
567529
}
568530

531+
static void set_pin(uint32_t new_pin)
532+
{
533+
if (new_pin > 999999) {
534+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin code with 1-6 digit length is allowed only!"));
535+
}
536+
537+
if (pin_changed(new_pin)) {
538+
remove_all_bonded_devices();
539+
}
540+
541+
uint32_t passkey = new_pin;
542+
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
543+
bt_obj.secure = true;
544+
set_secure_parameters(bt_obj.secure_connections);
545+
}
546+
569547
static void close_connection (int32_t conn_id) {
570548
for (mp_uint_t i = 0; i < MP_STATE_PORT(btc_conn_list).len; i++) {
571549
bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i]));
@@ -650,7 +628,7 @@ static void gap_events_handler (esp_gap_ble_cb_event_t event, esp_ble_gap_cb_par
650628
}
651629
case ESP_GAP_BLE_NC_REQ_EVT:
652630
case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: {
653-
printf("BLE paring passkey : %d\n", param->ble_security.key_notif.passkey);
631+
//printf("BLE paring passkey : %d\n", param->ble_security.key_notif.passkey);
654632
break;
655633
}
656634
case ESP_GAP_BLE_SEC_REQ_EVT: {
@@ -699,7 +677,7 @@ static void gattc_events_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc
699677
status = p_data->reg.status;
700678
bt_obj.gattc_if = gattc_if;
701679
if (bt_obj.secure){
702-
esp_ble_gap_config_local_privacy(true);
680+
esp_ble_gap_config_local_privacy(bt_obj.privacy);
703681
}
704682
break;
705683
case ESP_GATTC_OPEN_EVT:
@@ -874,7 +852,7 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_
874852
case ESP_GATTS_REG_EVT:
875853
bt_obj.gatts_if = gatts_if;
876854
if (bt_obj.secure){
877-
esp_ble_gap_config_local_privacy(true);
855+
esp_ble_gap_config_local_privacy(bt_obj.privacy);
878856
}
879857
break;
880858
case ESP_GATTS_READ_EVT: {
@@ -1007,20 +985,13 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_
1007985
if (bt_obj.trigger & MOD_BT_GATTS_CONN_EVT) {
1008986
mp_irq_queue_interrupt_non_ISR(bluetooth_callback_handler, (void *)&bt_obj);
1009987
}
1010-
if (bt_obj.secure){
1011-
esp_ble_set_encryption(p->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_MITM);
1012-
}
1013988
}
1014989
break;
1015990
case ESP_GATTS_DISCONNECT_EVT:
1016991
bt_obj.gatts_conn_id = -1;
1017992
xEventGroupClearBits(bt_event_group, MOD_BT_GATTS_MTU_EVT);
1018993
if (bt_obj.advertising) {
1019-
if (!bt_obj.secure){
1020-
esp_ble_gap_start_advertising(&bt_adv_params);
1021-
} else {
1022-
esp_ble_gap_start_advertising(&bt_adv_params_sec);
1023-
}
994+
esp_ble_gap_start_advertising(&bt_adv_params);
1024995
}
1025996
bt_obj.events |= MOD_BT_GATTS_DISCONN_EVT;
1026997
xEventGroupSetBits(bt_event_group, MOD_BT_GATTS_DISCONN_EVT);
@@ -1072,7 +1043,7 @@ static mp_obj_t bt_init_helper(bt_obj_t *self, const mp_arg_val_t *args) {
10721043
esp_ble_gatts_app_register(MOD_BT_SERVER_APP_ID);
10731044

10741045
//set MTU
1075-
uint16_t mtu = args[5].u_int;
1046+
uint16_t mtu = args[6].u_int;
10761047
if(mtu > BT_MTU_SIZE_MAX)
10771048
{
10781049
esp_ble_gatt_set_local_mtu(BT_MTU_SIZE_MAX);
@@ -1116,27 +1087,35 @@ static mp_obj_t bt_init_helper(bt_obj_t *self, const mp_arg_val_t *args) {
11161087
}
11171088
}
11181089

1119-
if (args[3].u_bool){
1090+
bt_obj.secure_connections = args[5].u_bool;
1091+
1092+
if (args[3].u_obj != MP_OBJ_NULL){
11201093
bt_obj.secure = true;
11211094

1122-
uint32_t passKey = args[4].u_int;
1123-
if (!is_pin_valid(passKey)){
1124-
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Only 6 digit (0-9) pins are allowed"));
1125-
}
1126-
set_secure_parameters(passKey);
1095+
// modified default advertisement parameters for secure
1096+
bt_adv_params.adv_int_min = 0x100;
1097+
bt_adv_params.adv_int_max = 0x100;
1098+
bt_adv_params.own_addr_type = args[4].u_bool ? BLE_ADDR_TYPE_RANDOM : BLE_ADDR_TYPE_PUBLIC;
1099+
1100+
set_pin(mp_obj_get_int(args[3].u_obj));
1101+
bt_obj.privacy = args[4].u_bool;
1102+
set_secure_parameters(bt_obj.secure_connections);
1103+
} else {
1104+
bt_obj.secure = false;
11271105
}
11281106

11291107
return mp_const_none;
11301108
}
11311109

11321110
STATIC const mp_arg_t bt_init_args[] = {
1133-
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
1134-
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = E_BT_STACK_MODE_BLE} },
1135-
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1136-
{ MP_QSTR_modem_sleep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1137-
{ MP_QSTR_secure, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
1138-
{ MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 123456} },
1139-
{ MP_QSTR_mtu, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BT_MTU_SIZE_MAX} },
1111+
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
1112+
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = E_BT_STACK_MODE_BLE} },
1113+
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1114+
{ MP_QSTR_modem_sleep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1115+
{ MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1116+
{ MP_QSTR_privacy, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
1117+
{ MP_QSTR_secure_connections, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
1118+
{ MP_QSTR_mtu, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BT_MTU_SIZE_MAX} },
11401119

11411120
};
11421121
STATIC mp_obj_t bt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
@@ -1156,7 +1135,7 @@ STATIC mp_obj_t bt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint
11561135
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
11571136
}
11581137

1159-
if (args[4].u_bool) {
1138+
if (args[4].u_obj != MP_OBJ_NULL) {
11601139
if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) == 0) {
11611140
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError,"Secure BLE not available for 512K RAM devices"));
11621141
}
@@ -1496,35 +1475,47 @@ static mp_obj_t modbt_connect(mp_obj_t addr)
14961475

14971476
STATIC mp_obj_t bt_set_advertisement_params (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
14981477
static const mp_arg_t allowed_args[] = {
1499-
{ MP_QSTR_adv_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x20} },
1500-
{ MP_QSTR_adv_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x40} },
1501-
{ MP_QSTR_adv_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_TYPE_IND} },
1502-
{ MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC} },
1503-
{ MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_CHNL_ALL} },
1504-
{ MP_QSTR_adv_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY} },
1478+
{ MP_QSTR_adv_int_min, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1479+
{ MP_QSTR_adv_int_max, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1480+
{ MP_QSTR_adv_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1481+
{ MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1482+
{ MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
1483+
{ MP_QSTR_adv_filter_policy, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
15051484
};
15061485

15071486
// parse args
15081487
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
15091488
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
1510-
1489+
15111490
// adv_int_min
1512-
bt_adv_params.adv_int_min = (uint16_t)args[0].u_int;
1513-
1491+
if (args[0].u_obj != MP_OBJ_NULL) {
1492+
bt_adv_params.adv_int_min = (uint16_t) mp_obj_get_int(args[0].u_obj);
1493+
}
1494+
15141495
// adv_int_max
1515-
bt_adv_params.adv_int_max = (uint16_t)args[1].u_int;
1496+
if (args[1].u_obj != MP_OBJ_NULL) {
1497+
bt_adv_params.adv_int_max = (uint16_t) mp_obj_get_int(args[1].u_obj);
1498+
}
15161499

15171500
// adv_type
1518-
bt_adv_params.adv_type = (esp_ble_adv_type_t)args[2].u_int;
1519-
1501+
if (args[2].u_obj != MP_OBJ_NULL) {
1502+
bt_adv_params.adv_type = (esp_ble_adv_type_t) mp_obj_get_int(args[2].u_obj);
1503+
}
1504+
15201505
// own_addr_type
1521-
bt_adv_params.own_addr_type = (esp_ble_addr_type_t)args[3].u_int;
1522-
1506+
if (args[3].u_obj != MP_OBJ_NULL) {
1507+
bt_adv_params.own_addr_type = (esp_ble_addr_type_t) mp_obj_get_int(args[3].u_obj);
1508+
}
1509+
15231510
// channel_map
1524-
bt_adv_params.channel_map = (esp_ble_adv_channel_t)args[4].u_int;
1525-
1511+
if (args[4].u_obj != MP_OBJ_NULL) {
1512+
bt_adv_params.channel_map = (esp_ble_adv_channel_t) mp_obj_get_int(args[4].u_obj);
1513+
}
1514+
15261515
// adv_filter_policy
1527-
bt_adv_params.adv_filter_policy = (esp_ble_adv_filter_t)args[5].u_int;
1516+
if (args[5].u_obj != MP_OBJ_NULL) {
1517+
bt_adv_params.adv_filter_policy = (esp_ble_adv_filter_t) mp_obj_get_int(args[5].u_obj);
1518+
}
15281519

15291520
return mp_const_none;
15301521
}
@@ -1657,15 +1648,18 @@ STATIC mp_obj_t bt_set_advertisement_raw(mp_obj_t self_in, mp_obj_t raw_data) {
16571648
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bt_set_advertisement_raw_obj, bt_set_advertisement_raw);
16581649

16591650

1651+
STATIC mp_obj_t bt_set_pin(mp_obj_t self_in, mp_obj_t arg) {
1652+
set_pin(mp_obj_get_int(arg));
1653+
return mp_const_none;
1654+
}
1655+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(bt_set_pin_obj, bt_set_pin);
1656+
1657+
16601658
STATIC mp_obj_t bt_advertise(mp_obj_t self_in, mp_obj_t enable) {
16611659
if (mp_obj_is_true(enable)) {
16621660
// some sensible time to wait for the advertisement configuration to complete
16631661
mp_hal_delay_ms(50);
1664-
if (!bt_obj.secure){
1665-
esp_ble_gap_start_advertising(&bt_adv_params);
1666-
} else {
1667-
esp_ble_gap_start_advertising(&bt_adv_params_sec);
1668-
}
1662+
esp_ble_gap_start_advertising(&bt_adv_params);
16691663
bt_obj.advertising = true;
16701664
} else {
16711665
esp_ble_gap_stop_advertising();
@@ -2107,6 +2101,7 @@ STATIC const mp_map_elem_t bt_locals_dict_table[] = {
21072101
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_advertisement_params),(mp_obj_t)&bt_set_advertisement_params_obj },
21082102
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_advertisement), (mp_obj_t)&bt_set_advertisement_obj },
21092103
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_advertisement_raw), (mp_obj_t)&bt_set_advertisement_raw_obj },
2104+
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_pin), (mp_obj_t)&bt_set_pin_obj },
21102105
{ MP_OBJ_NEW_QSTR(MP_QSTR_advertise), (mp_obj_t)&bt_advertise_obj },
21112106
{ MP_OBJ_NEW_QSTR(MP_QSTR_service), (mp_obj_t)&bt_service_obj },
21122107
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&bt_callback_obj },
@@ -2160,6 +2155,15 @@ STATIC const mp_map_elem_t bt_locals_dict_table[] = {
21602155
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROP_AUTH), MP_OBJ_NEW_SMALL_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) },
21612156
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROP_EXT_PROP), MP_OBJ_NEW_SMALL_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) },
21622157

2158+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_READ), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_READ) },
2159+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_READ_ENCRYPTED) },
2160+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_READ_ENC_MITM) },
2161+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_WRITE), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_WRITE) },
2162+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) },
2163+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_WRITE_ENC_MITM) },
2164+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_WRITE_SIGNED) },
2165+
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_OBJ_NEW_SMALL_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) },
2166+
21632167
// Defined at https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
21642168
{ MP_OBJ_NEW_QSTR(MP_QSTR_CHAR_CONFIG_NOTIFY), MP_OBJ_NEW_SMALL_INT(1 << 0) },
21652169
{ MP_OBJ_NEW_QSTR(MP_QSTR_CHAR_CONFIG_INDICATE), MP_OBJ_NEW_SMALL_INT(1 << 1) },

0 commit comments

Comments
 (0)