1# Gatt Security Server Example Walkthrough
2
3## Introduction
4
5In this document, a description of the security GATT Server BLE example for the ESP32 is presented. The security configuration enables a GATT Server acting as a slave device to bond with a master and establish an encrypted link between them. This functionality is defined by the [Bluetooth Specification version 4.2](https://www.bluetooth.com/specifications/bluetooth-core-specification) and implemented on the ESP-IDF BLE stack, specifically on the Security Manager Protocol (SMP) API.
6
7BLE security involves three interrelated concepts: pairing, bonding and encryption. Pairing concerns with the exchange of security features and types of keys needed. In addition, the pairing procedure takes care of the generation and exchange of shared keys. The core specification defines the legacy pairing and Secure Connections pairing (introduced in Bluetooth 4.2), which are both supported by ESP32. Once the exchange of shared keys is completed, a temporary encrypted link is established to exchange short term and long term keys. Bonding refers to storing the exchanged keys for subsequent connections so that they do not have to be transmitted again. Finally, encryption pertains to the ciphering of plain text data using the AES-128 engine and the shared keys. Server attributes may also be defined to allow only encrypted write and read messages. At any point of the communication, a slave device can always ask to start encryption by issuing a security request to the other peer device, which returns a security response by calling an API.
8
9This document only describes the security configuration. The rest of the GATT server functionalities, such as defining the service table, are explained in the GATT Server example walkthrough documentation. For a better understanding of this example workflow, it is recommended that the reader is familiar with the pairing feature exchange and key generation defined in the section 3.5 of the [Bluetooth Specification Version 4.2](https://www.bluetooth.com/specifications/bluetooth-core-specification) [Vol 3, Part H].
10
11## Setting Security Parameters
12
13The ESP32 requires a series of security parameters in order to define how the pairing request and response are going to be built. The Pairing Response packet built by the GATT Server includes fields such as the input/output capabilities, Secure Connections pairing, authenticated Man-In-The-Middle (MITM) protection or no security requirements (see Section 2.3.1 of the [Bluetooth Specification Version 4.2](https://www.bluetooth.com/specifications/bluetooth-core-specification) [Vol 3, Part H]). In this example, this procedure is done in the `app_main()` function. The pairing request is sent by the initiator which in this case is a remote GATT client. The ESP32 server implemented in this example receives this request and replies with a pairing response, which contains the same security parameters in order for both devices to agree on the resources available and the applicable pairing algorithm (*Just Works* or *Passkey Entry*). Both the pairing request and response commands have the following parameters:
14
15* *IO Capability*: describes if the device has input/output capabilities such as a display or a keyboard.
16* *OOB Flag*: describes if the device supports Out of Band passkey exchange, for example using NFC or Wi-Fi to exchange keys as TKs.
17* *Authorization Request*: indicates the requested security properties such as Bonding, Secure Connections (SC), MITM protection or none that will be present in the Pairing Request and Response packets.
18* *Maximum Encryption Key Size*: maximum encryption key size in octets.
19* *Initiator Key Distribution/Generation*: indicates which keys the initiator is requesting to distribute/generate or use during the Transport Specific Key Distribution phase. In the pairing request, these keys are requested, while in the pairing response, these keys are confirmed to be distributed.
20* *Responder Key Distribution/Generation*: indicates which keys the initiator is requesting the responder to distribute/generate or use during the Transport Specific Key Distribution phase. In the pairing request, these keys are requested, while in the pairing response, these keys are confirmed to be distributed.
21
22In code, these parameters are defined as follows:
23
24* *IO Capability*:
25
26	```c
27	esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE;//set the IO capability to No Input No Output
28	```
29
30	The possible values for *IO Capabilities* are:
31
32	```c
33	ESP_IO_CAP_OUT         0   /*!< DisplayOnly */
34	ESP_IO_CAP_IO          1   /*!< DisplayYesNo */
35	ESP_IO_CAP_IN          2   /*!< KeyboardOnly */
36	ESP_IO_CAP_NONE        3   /*!< NoInputNoOutput */
37	ESP_IO_CAP_KBDISP      4   /*!< Keyboard display */
38	```
39
40* *Authorization Request*:
41
42	```c
43	esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //bonding with peer device after authentication
44	```
45
46	The possible values for *Authorization Request* are a combination of Bonding, MITM protection and Secure Connections requests:
47
48	```c
49	ESP_LE_AUTH_NO_BOND: No bonding.
50	ESP_LE_AUTH_BOND: Bonding is performed.
51	ESP_LE_AUTH_REQ_MITM: MITM Protection is enabled.
52	ESP_LE_AUTH_REQ_SC_ONLY: Secure Connections without bonding enabled.
53	ESP_LE_AUTH_REQ_SC_BOND: Secure Connections with bonding enabled.
54	ESP_LE_AUTH_REQ_SC_MITM: Secure Connections with MITM Protection and no bonding enabled.
55	ESP_LE_AUTH_REQ_SC_MITM_BOND: Secure Connections with MITM Protection and bonding enabled.
56	```
57
58* *Maximum Encryption Key Size*:
59
60	```c
61	uint8_t key_size = 16;      //the key size should be 7~16 bytes
62	```
63
64* *Initiator Key Distribution/Generation*:
65
66	```c
67	uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
68	```
69
70	The initiator distributes the LTK and IRK keys by the setting the EncKey and IdKey masks.
71
72* *Responder Key Distribution/Generation*:
73
74	```c
75	uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
76	```
77
78	The responder distributes the LTK and IRK keys by the setting the *EncKey* and *IdKey* masks.
79
80	Once defined, the parameters are set using the `esp_ble_gap_set_security_param()` function. This function sets the parameter type, the parameter value and the parameter length:
81
82	```c
83	esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
84	esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
85	esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
86	esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
87	esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
88	```
89
90	This information is enough for the BLE stack to perform the pairing process, including pairing confirmation and key generation. The procedure is invisible to the user and executed automatically by the stack.
91
92## Connecting and Bonding to a Peer Device
93
94The security parameters set previously are stored locally to be used later when the master device connects to the slave. Every time a remote device connects to the local GATT server, the connection event `ESP_GATTS_CONNECT_EVT` is triggered. This event is employed to perform the pairing and bonding process by invoking the `esp_ble_set_encryption()` function which takes as parameters the remote device address and the type of encryption that will be performed. The BLE stack then executes the actual pairing process in the background. In this example, the encryption includes MITM protection.
95
96```c
97case ESP_GATTS_CONNECT_EVT:
98     //start security connect with peer device when receive the connect event sent by the master.
99    esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_MITM);
100    break;
101```
102The types of encryptions available are:
103
104* `ESP_BLE_SEC_NONE`
105* `ESP_BLE_SEC_ENCRYPT`
106* `ESP_BLE_SEC_ENCRYPT_NO_MITM`
107* `ESP_BLE_SEC_ENCRYPT_MITM`
108
109The difference between `ESP_BLE_SEC_ENCRYPT` and `ESP_BLE_SEC_ENCRYPT_NO_MITM` lies in the fact that a previous connection might have a security level that needs to be upgraded, therefore requires to exchange keys again.
110
111In this example, the I/O capabilities are set to *No Input No Output*, therefore the *Just Works* pairing method, which doesn't not require the generation of a random 6-digit passkey, is used (For details, please refer to the the table below). The user may modify the example to set the I/O capabilities to use other than *No Input No Output*. Therefore, depending on the I/O capabilities of the remote device, a passkey might be generated on the ESP32 which is presented to the user with the `ESP_GAP_BLE_PASSKEY_NOTIF_EVT`:
112
113```c
114case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:
115     ///the app will receive this evt when the IO  has Output capability and the peer device IO has Input capability.
116     ///show the passkey number to the user to input it in the peer device.
117     ESP_LOGE(GATTS_TABLE_TAG, "The passkey Notify number:%d", param->ble_security.key_notif.passkey);
118     break;
119```
120
121The combination of input and output capabilities that determine which algorithm is used are:
122
123|                        | Display Only   | Display Yes/No | Keyboard Only  | No Input No Output | Keyboard Display|
124| :--                    | :------------- | :------------- | :------------- | :----------------- | :-------------- |
125| **Display Only**       | Just Works     | Just Works     | Passkey Entry  | Just Works         | Passkey Entry   |
126| **Display Yes/No**     | Just Works     | Just Works     | Passkey Entry  | Just Works         | Passkey Entry   |
127| **Keyboard Only**      | Passkey Entry  | Passkey Entry  | Passkey Entry  | Just Works         | Passkey Entry   |
128| **No Input No Output** | Just Works     | Just Works     | Just Works     | Just Works         | Just Works      |
129| **Keyboard Display**   | Passkey Entry  | Passkey Entry  | Passkey Entry  | Just Works         | Passkey Entry   |
130
131
132## Exchanging Keys
133
134When the client connects to the server and the pairing is done successfully, the keys indicated by the `init_key` and `rsp_key` security parameters are exchanged. In this example the following keys are generated and distributed:
135
136* Local device LTK
137* Local device IRK
138* Local device CSRK
139* Peer device LTK
140* Peer device IRK
141
142Note that for this example only, the peer device CSRK is not 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:
143
144```c
145case ESP_GAP_BLE_KEY_EVT:
146     //shows the ble key info share with peer device to the user.
147     ESP_LOGI(GATTS_TABLE_TAG, "key type = %s", esp_key_type_to_str(param->ble_security.ble_key.key_type));
148     break;
149```
150
151When the keys are exchanged successfully, the pairing process is done. This triggers an `ESP_GAP_BLE_AUTH_CMPL_EVT` event, which is used to print information such as remote device, address type and pair status:
152
153```c
154case ESP_GAP_BLE_AUTH_CMPL_EVT: {
155     esp_bd_addr_t bd_addr;
156     memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr,
157            sizeof(esp_bd_addr_t));
158     ESP_LOGI(GATTS_TABLE_TAG, "remote BD_ADDR: %08x%04x",\
159              (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) +
160              bd_addr[3],
161              (bd_addr[4] << 8) + bd_addr[5]);
162     ESP_LOGI(GATTS_TABLE_TAG, "address type = %d",
163              param->ble_security.auth_cmpl.addr_type);
164              ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",
165              param->ble_security.auth_cmpl.success ? "success" : "fail");
166     break;
167}
168```
169
170## Security Permission for Attributes
171
172When defining the attributes of the server, different permissions can be set to the write and read events. Attributes permissions can be:
173
174* Permission to read
175* Permission to read with encryption
176* Permission to read with encryption and MITM protection
177* Permission to write
178* Permission to write with encryption
179* Permission to write with encryption and MITM protection
180* Permission to signed write
181* Permission to signed write with MITM protection
182
183These permissions are defined in the API as:
184
185* `ESP_GATT_PERM_READ`
186* `ESP_GATT_PERM_READ_ENCRYPTED`
187* `ESP_GATT_PERM_READ_ENC_MITM`
188* `ESP_GATT_PERM_WRITE`
189* `ESP_GATT_PERM_WRITE_ENCRYPTED`
190* `ESP_GATT_PERM_WRITE_ENC_MITM`
191* `ESP_GATT_PERM_WRITE_SIGNED`
192* `ESP_GATT_PERM_WRITE_SIGNED_MITM`
193
194When creating the services table, each attribute can have permissions to read or write, with or without encryption. When an attribute has encrypted permissions and a peer device that does not have the required security clearance tries to read or write to that attribute, the local host sends an Insufficient Authorization Error. In the example, the following attributes are defined with permissions with encryption:
195
196```c
197198// Body Sensor Location Characteristic Value
199    [HRS_IDX_BOBY_SENSOR_LOC_VAL]   = {
200    {ESP_GATT_AUTO_RSP},
201    {ESP_UUID_LEN_16,
202    (uint8_t *)&body_sensor_location_uuid,
203    ESP_GATT_PERM_READ_ENCRYPTED,
204    sizeof(uint8_t),
205    sizeof(body_sensor_loc_val),
206    (uint8_t *)body_sensor_loc_val}
207    },
208209// Heart Rate Control Point Characteristic Value
210    [HRS_IDX_HR_CTNL_PT_VAL]        = {
211    {ESP_GATT_AUTO_RSP},
212    {ESP_UUID_LEN_16,
213    (uint8_t *)&heart_rate_ctrl_point,
214    ESP_GATT_PERM_WRITE_ENCRYPTED|ESP_GATT_PERM_READ_ENCRYPTED,
215    sizeof(uint8_t),
216    sizeof(heart_ctrl_point),
217    (uint8_t *)heart_ctrl_point}
218    },
219220```
221
222## Security Requests
223
224During the communication between a master and a slave device, the slave might request to start encryption at any moment by issuing a security request command. This command will trigger an `ESP_GAP_BLE_SEC_REQ_EVT` event on the master, which will reply a positive (true) security response to the peer device to accept the request or a negative (false) one to reject the request. In this example, this event is used to reply a start encryption response by using the `esp_ble_gap_security_rsp()` API call.
225
226```c
227case ESP_GAP_BLE_SEC_REQ_EVT:
228     /* send the positive (true) security response to the peer device to accept the security request.
229     If not accept the security request, should send the security response with negative(false) accept value*/
230     esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
231     break;
232```
233## Conclusion
234
235In this document, a review of the security aspects of the GATT Server has been realized. BLE security encompasses Pairing, Bonding and Encryption. In order to establish a secured link between a master and a slave device, security parameters that define the capabilities and features each device possess are set. 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 and these keys. 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. In addition, attribute permissions are appointed to allow only encrypted read and write events when needed. The rest of the Security GATT server functionalities such as defining services and characteristics are implemented in the same way as presented in the GATT Server example.