此篇博客介绍 ESP-IDF 里的 BLE 安全 & 代码梳理,BLE 安全涉及以下三个相互关联的概念:
pairing :关注安全特性和所需密钥类型的交换,比如支不支持 SC,支不支持 MITM 保护,支不支持 OOB,以及它的输入输出能力等。此外,配对过程还负责共享密钥的生成和交换。一旦共享秘钥交换完成,便会建立一个临时的加密链接来交换短期和长期密钥。
bonding:为后续连接存储交换密钥,从而无需再次传输密钥。
encryption:使用 AES-128 engine 和共享秘钥对明文数据进行加密。
1 Pairing
区别于传统蓝牙的配对过程,BLE 的配对过程发生在连接过程之后,实现的是链路层的安全。
配对过程分为三个阶段:
• Phase 1: Pairing Feature Exchange
• Phase 2 (LE legacy pairing): Short Term Key (STK) Generation
• Phase 2 (LE Secure Connections): Long Term Key (LTK) Generation
• Phase 3: Transport Specific Key Distribution
配对特性交换用于交换 IO 能力(IO capabilities),OOB 身份验证数据可用性(OOB
authentication data availability),认证要求(authentication requirements),密钥大小要求以及分配哪种传输特定密钥(transport specific keys)。
其中,IO 能力,OOB 身份验证数据可用性和认证要求用于决定在第二阶段使用哪种密钥生成方法。
- Just Works
- Numeric Comparison (Only for LE Secure Connections)
- Passkey Entry
- Out Of Band (OOB)
LE 传统配对使用和生成 2 个密钥:
- Temporary Key (TK): 在配对过程中使用的 128 位临时密钥,用于生成 STK
- Short Term Key (STK): 配对后用于加密连接的 128 位临时密钥
LE 安全连接配对使用和生成 1 个密钥:
- Long Term Key(LTK): 在配对后和后续连接用于加密连接的 128 位密钥
阶段 3 是可选执行的,用于分发传输特定密钥,例如:身份解析密钥(IRK)值和身份地址信息。
阶段 3 只能在使用以下方式加密的链接上执行:
- 当使用 LE 传统配对时在阶段 2 生成的 STK
- 当使用 LE 安全连接配对时在阶段 2 生成的 LTK
- 当使用 BR/EDR 配对时生成的共享连接密钥
1.1 配对特性交换
发起设备通过发送配对请求命令(Pairing Request)给响应设备来开始配对特性交换过程。
- IO Capability: 描述设备是否具有输入/输出功能,例如显示器或键盘。
- OOB Flag: 描述设备是否支持带外密钥交换,例如使用 NFC 或 Wi-Fi 交换密钥作为TK。
- Authorization Request: 指示请求的安全属性,例如绑定,安全连接(SC),MITM 保护或在配对请求和响应数据包中不存在任何安全属性。
- Maximum Encryption Key Size: 最大加密密钥大小(以字节为单位)。
- Initiator Key Distribution/Generation: 表明发起者在传输特定密钥阶段请求分配/生成哪些密钥。
- Responder Key Distribution/Generation: 表明发起者在传输特定密钥阶段请求响应者分配/生成 哪些密钥。
1.1.1 IO Capabilities
IO Capabilities 是由设备的输入能力和输出能力组合而成,表示的是设备的输入输出的能力。
1.1.2 Selecting Key Generation Method
2 BLE 中的安全
安全应由主设备的 Security Manager 发起,从设备为响应设备。从设备可以请求主设备发起配对或者其他的安全步骤。
从设备可以通过向主设备发送 Security Request 来请求安全。
Definition of Keys and Values
LE 安全使用下面的密钥和值进行加密,签名和随机寻址:
- Identity Resolving Key (IRK) :用于生成和解析随机地址的 128 位的密钥
- Connection Signature Resolving Key (CSRK):用于对数据进行签名并验证接收设备上的签名的 128 位的密钥
- Long Term Key (LTK):用于为加密连接生成贡献性会话密钥的 128 位的密钥。
- Encrypted Diversifier (EDIV):是一个 16 位存储值,用于标识 LE 传统配对期间分配的 LTK。 每次分配唯一的 LTK 时都会生成一个新的 EDIV。
- Random Number (Rand):是一个 64 位存储值,用于标识 LE 传统配对期间分配的 LTK。 每次分配唯一的 LTK 时都会生成一个新的 Rand
3 示例说明
以 gatt_security_server 为例说明:
/* set the security iocap & auth_req & key size & init key response key parameters to the stack*/
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND; //bonding with peer device after authentication
esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //set the IO capability to No output No input
uint8_t key_size = 16; //the key size should be 7~16 bytes
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
//set static passkey
uint32_t passkey = 123456;
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE;
uint8_t oob_support = ESP_BLE_OOB_DISABLE;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));
-
IO Capability
esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE;//set the IO capability to No Input No Output
IO 能力可以取下面所列的值:
ESP_IO_CAP_OUT 0 /*!< DisplayOnly */ ESP_IO_CAP_IO 1 /*!< DisplayYesNo */ ESP_IO_CAP_IN 2 /*!< KeyboardOnly */ ESP_IO_CAP_NONE 3 /*!< NoInputNoOutput */ ESP_IO_CAP_KBDISP 4 /*!< Keyboard display */
-
Authorization Request:
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //bonding with peer device after authentication
该值由 绑定、MTIM 保护 和安全连接组合而成,可取下面所列的值:
ESP_LE_AUTH_NO_BOND: No bonding. ESP_LE_AUTH_BOND: Bonding is performed. ESP_LE_AUTH_REQ_MITM: MITM Protection is enabled. ESP_LE_AUTH_REQ_SC_ONLY: Secure Connections without bonding enabled. ESP_LE_AUTH_REQ_SC_BOND: Secure Connections with bonding enabled. ESP_LE_AUTH_REQ_SC_MITM: Secure Connections with MITM Protection and no bonding enabled. ESP_LE_AUTH_REQ_SC_MITM_BOND: Secure Connections with MITM Protection and bonding enabled.
-
Maximum Encryption Key Size:
uint8_t key_size = 16; //the key size should be 7~16 bytes
-
Initiator Key Distribution/Generation:
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
The initiator distributes the LTK and IRK keys by the setting the EncKey and IdKey masks.
-
Responder Key Distribution/Generation:
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
The responder distributes the LTK and IRK keys by the setting the EncKey and IdKey masks.
例如,设置 IO 能力为 DisplayYesNo,手机作为 master 连接到 ESP32,这种情景使用的配对方式为 numeric comparison。
esp_ble_io_cap_t iocap = ESP_IO_CAP_IO;
ESP32 侧 log:
I (972) SEC_GATTS_DEMO: app_main init bluetooth
I (1102) SEC_GATTS_DEMO: The number handle = 8
I (1122) SEC_GATTS_DEMO: advertising start success
I (17702) SEC_GATTS_DEMO: ESP_GATTS_CONNECT_EVT
E (21542) BT_SMP: Value for numeric comparison = 793111
I (21552) SEC_GATTS_DEMO: ESP_GAP_BLE_NC_REQ_EVT, the passkey Notify number:793111
W (37342) BT_SMP: FOR LE SC LTK IS USED INSTEAD OF STK
I (37542) SEC_GATTS_DEMO: key type = ESP_LE_KEY_LENC
I (37542) SEC_GATTS_DEMO: key type = ESP_LE_KEY_PENC
I (37542) SEC_GATTS_DEMO: key type = ESP_LE_KEY_LID
I (37742) SEC_GATTS_DEMO: key type = ESP_LE_KEY_PID
I (37772) SEC_GATTS_DEMO: remote BD_ADDR: 4512670adc33
I (37772) SEC_GATTS_DEMO: address type = 1
I (37772) SEC_GATTS_DEMO: pair status = success
I (37782) SEC_GATTS_DEMO: auth mode = ESP_LE_AUTH_REQ_SC_MITM_BOND
I (37792) SEC_GATTS_DEMO: Bonded devices number : 1
I (37792) SEC_GATTS_DEMO: Bonded devices list : 1
I (37802) SEC_GATTS_DEMO: 45 12 67 0a dc 33
手机侧: