1# BLE50 GATT Security Client Example Walkthrough 2 3## Introduction 4 5* This document presents a review of the GATT Security Client code example for the ESP32C3 or BLE5.0 supported Chip. 6* The GATT Client is capable of scanning for nearby devices and once it has found a device of interest, it requests a secure connection. The GATT client behaves as a central device that initiates a connection to a peripheral by sending a *Aux Connect Pairing Request* as specified by the [Bluetooth Core Specification Version 5.0](https://www.bluetooth.com/specifications/bluetooth-core-specification). 7* The peripheral device is normally a GATT Server that exposes Services and Characteristics. The peripheral replies with a *Aux Connect Pairing Response* followed by authentication and exchange of keys. If the bonding process is also executed, the Long Term Keys are stored for subsequent connections. Finally an encrypted channel is established which can support protection against Man-In-The-Middle (MITM) attacks depending on the security configuration. 8* The code is implemented using an Application Profile that upon registration, allows to set the local privacy configuration as events are triggered during the life time of the program. 9 10This document only includes a description of the security aspects of the BLE5.0 Security GATT Client implementation, for the more infor about extended scan , periodic scan please refer to [Periodic_Sync_Example Walkthrough] (../../peroidic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md). 11 12##include 13 14```c 15#include <stdint.h> 16#include <string.h> 17#include <stdbool.h> 18#include <stdio.h> 19#include "nvs.h" 20#include "nvs_flash.h" 21#include "esp_bt.h" 22#include "esp_gap_ble_api.h" 23#include "esp_gattc_api.h" 24#include "esp_gatt_defs.h" 25#include "esp_bt_main.h" 26#include "esp_gatt_common_api.h" 27#include "esp_log.h" 28#include "freertos/FreeRTOS.h" 29``` 30These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“bt.h”`, `“esp_bt_main.h”`, `"esp_gap_ble_api.h"` and `“esp_gattc_api.h”`, which expose the BLE APIs required to implement this example. 31 32* `bt.h`: configures the BT controller and VHCI from the host side. 33* `esp_bt_main.h`: initializes and enables the Bluedroid stack. 34* `esp_gap_ble_api.h`: implements the GAP configuration, such as advertising and connection parameters. 35* `esp_gattc_api.h`: implements the GATT Client configuration, such as connecting to peripherals and searching for services. 36 37## Configuring Local Privacy of the Security Client 38 39The example registers one Application Profile defined as: 40 41```c 42#define PROFILE_NUM 1 43#define PROFILE_A_APP_ID 0 44``` 45 46The registration takes place in the ``app_main()`` function by using the ``esp_ble_gattc_app_register()`` function: 47 48```c 49… 50ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID); 51if (ret){ 52 ESP_LOGE(GATTC_TAG, "%s gattc app register error, error code = %x\n", __func__, ret); 53} 54… 55``` 56 57The Application Profile registration triggers an ``ESP_GATTC_REG_EVT`` event which is managed by the ``esp_gattc_cb()`` callback function and forwarded to the Profile A event handler ``gattc_profile_event_handler()``. Here, the event is used to configure the local privacy of the slave device by using the ``esp_ble_gap_config_local_privacy()`` function. 58 59```c 60case ESP_GATTC_REG_EVT: 61 ESP_LOGI(GATTC_TAG, "REG_EVT"); 62 esp_ble_gap_config_local_privacy(true); 63 break; 64``` 65 66This function is a Bluedroid API call for configuring default privacy settings on the local device. Once the privacy is set, an ``ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT`` is triggered which is used to set scan parameters and start scanning for nearby peripherals: 67 68```c 69 case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT: 70 if (param->local_privacy_cmpl.status != ESP_BT_STATUS_SUCCESS){ 71 ESP_LOGE(GATTC_TAG, "config local privacy failed, error code =%x", param->local_priva 72cy_cmpl.status); 73 break; 74 } 75 esp_err_t scan_ret = esp_ble_gap_set_ext_scan_params(&ext_scan_params); 76 if (scan_ret){ 77 ESP_LOGE(GATTC_TAG, "set extend scan params error, error code = %x", scan_ret); 78 } 79 break; 80 case ESP_GAP_BLE_SET_EXT_SCAN_PARAMS_COMPLETE_EVT: { 81 if (param->set_ext_scan_params.status != ESP_BT_STATUS_SUCCESS) { 82 ESP_LOGE(GATTC_TAG, "extend scan parameters set failed, error status = %x", param->se 83t_ext_scan_params.status); 84 break; 85 } 86 //the unit of the duration is second 87 esp_ble_gap_start_ext_scan(EXT_SCAN_DURATION, EXT_SCAN_PERIOD); 88 break; 89 } 90 case ESP_GAP_BLE_EXT_SCAN_START_COMPLETE_EVT: 91 if (param->ext_scan_start.status != ESP_BT_STATUS_SUCCESS) { 92 ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.st 93atus); 94 95``` 96 97## Configuring and Bonding to a Slave Device 98 99The rest of the configuration for the GATT Client is performed normally in the same way as the regular GATT Client example. That is, the client finds a device of interest and opens a connection. At this point the GATT client, which is usually the central, initiates the pairing process by sending a Pairing Request to the peripheral device. This request should be acknowledged with a Pairing Response. The Pairing process is implemented automatically by the stack and no extra user configuration is needed. However, depending on the I/O capabilities of both devices, a passkey might be generated on the ESP32 which is presented to the user with the ``ESP_GAP_BLE_PASSKEY_NOTIF_EVT``: 100 101```c 102 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: 103 ///the app will receive this evt when the IO has Output capability and the peer device IO has Input capability. 104 ///show the passkey number to the user to input it in the peer device. 105 ESP_LOGE(GATTS_TABLE_TAG, "The passkey Notify number:%d", param->ble_security.key_notif.passkey); 106 break; 107 108``` 109The combination of input and output capabilities that determine which algorithm is used are: 110 111| | Display Only | Display Yes/No | Keyboard Only | No Input No Output | Keyboard Display| 112| :-- | :------------- | :------------- | :------------- | :----------------- | :-------------- | 113| **Display Only** | Just Works | Just Works | Passkey Entry | Just Works | Passkey Entry | 114| **Display Yes/No** | Just Works | Just Works | Passkey Entry | Just Works | Passkey Entry | 115| **Keyboard Only** | Passkey Entry | Passkey Entry | Passkey Entry | Just Works | Passkey Entry | 116| **No Input No Output** | Just Works | Just Works | Just Works | Just Works | Just Works | 117| **Keyboard Display** | Passkey Entry | Passkey Entry | Passkey Entry | Just Works | Passkey Entry | 118 119In the Just Works method, the Temporary Key is set to 0. This is a practical way to authenticate devices when no display or keyboards are attached to them, so that there is no way to show or enter a passkey. However, if the ESP32 GATT Client has an LCD, it can present the passkey generated locally so that the user can input it on the other peer device, or if the GATT Client has a keyboard, it can input the passkey generated by the other peer device. Additionally, a numeric comparison can be performed if both devices have a display and yes/no confirm buttons and LE Secure Connections are used, that way an independently generated passkey is displayed on both devices and the user manually checks that both 6-digit confirmation values match. 120 121## Exchanging Keys 122 123When the client connects to a remote device and the pairing is done successfully, The initiator and responder keys as decided during pairing req / rsp are exchanged. For each key exchange message, an ``ESP_GAP_BLE_KEY_EVT`` event is triggered which can be used to print the type of key received: 124 125```c 126case ESP_GAP_BLE_KEY_EVT: 127 //shows the ble key info share with peer device to the user. 128 ESP_LOGI(GATTS_TABLE_TAG, "key type = %s", esp_key_type_to_str(param->ble_security.ble_key.key_type)); 129 break; 130``` 131 132When the keys are exchanged successfully, the pairing process is completed and encryption of payload data can be started using the AES-128 engine. This triggers an ``ESP_GAP_BLE_AUTH_CMPL_EVT`` event which is used to print information: 133 134```c 135case ESP_GAP_BLE_AUTH_CMPL_EVT: { 136 esp_bd_addr_t bd_addr; 137 memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t)); 138 ESP_LOGI(GATTS_TABLE_TAG, "remote BD_ADDR: %08x%04x",\ 139 (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], (bd_addr[4] << 8) + bd_addr[5]); 140 ESP_LOGI(GATTS_TABLE_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type); 141 ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail"); 142 break; 143``` 144 145## Conclusion 146 147In this document, a review of the security aspects of the BLE5.0 GATT Client has been realized. BLE security encompasses Pairing, Bonding and Encryption. In order to establish a secure link between a central and a peripheral device, the local privacy of the GATT client is set, which allows the BLE stack to set necessary security parameters automatically without the need of additional user configuration. The combination of features and capabilities of the peer devices results in the selection of the appropriate pairing method which the BLE stack then executes. Immediately, the required keys are generated and exchanged and the encryption of subsequent messages is started using the AES-128 engine. These steps trigger different events that are managed by the GATT and GAP event handlers which can be used to print useful information such as the types of keys exchanged and the pairing status. The rest of the security GATT client functionality such as registering for notifications of characteristics is implemented in the same way as in [Periodic Sync Example Walkthrough](../../peroidic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md). 148