ESP32入门基础之安全连接SMP-client

文章目录

  • 1 gatt_security_client工程的理解
    • 1.1 工程简介
    • 1.2 配置安全客户端的本地隐私
    • 1.3 配置并绑定从设备
    • 1.4 交换秘钥

1 gatt_security_client工程的理解

文章连接GATT Security Client Example Walkthrough

  • 可能涉及到的英文缩写
    临时密钥(Temporary Key:TK)
    短期密钥(Short Term Key:STK)
    长期秘钥(Long-Term Key:LTK)
    身份解析秘钥(Identity Resolving Key:IRK)
    连接签名解析秘钥(Connection Signature Resolving Key:CSRK)

1.1 工程简介

GATT客户端能够扫描(scanning ) 附近的设备,一旦它发现了感兴趣的设备,它就请求一个安全连接。GATT客户端作为主设备(master ),通过发送指定的配对请求向从设备发起连接。远端从设备通常是公开服务和特性的GATT服务器。从服务器使用配对响应(Pairing Response)进行应答,随后进行身份验证和密钥交换。如果还执行绑定(bonding )过程,则为后续连接存储长期密钥(Long Term Keys )。最后根据此安全配置,建立了可支持中间人(MITM)攻击保护的加密通道。

1.2 配置安全客户端的本地隐私

该示例注册一个Application Profile,定义为:

#define PROFILE_NUM 1
#define PROFILE_A_APP_ID 0

通过使用esp_ble_gattc_app_register()函数在app_main()函数中进行注册:

…
ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID);
if (ret){
	ESP_LOGE(GATTC_TAG, "%s gattc app register error, error code = %x\n", __func__, ret);
}

Application Profile注册会触发一个ESP_GATTC_REG_EVT事件,该事件用于通过esp_ble_gap_config_local_privacy()函数配置从设备的本地隐私。

case ESP_GATTC_REG_EVT:
    ESP_LOGI(GATTC_TAG, "REG_EVT");
    esp_ble_gap_config_local_privacy(true);
    break;

这个函数是一个Bluedroid API调用,用于在本地设备上配置默认隐私设置。一旦设置了隐私,ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT事件将被触发,该事件用于设置扫描参数并开始扫描附近的外设:

    case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT:
        if (param->local_privacy_cmpl.status != ESP_BT_STATUS_SUCCESS){
            ESP_LOGE(GATTC_TAG, "config local privacy failed, error code =%x", param->local_privacy_cmpl.status);
            break;
        }
        esp_err_t scan_ret = esp_ble_gap_set_scan_params(&ble_scan_params);
        if (scan_ret){
            ESP_LOGE(GATTC_TAG, "set scan params error, error code = %x", scan_ret);
        }
        break;
    case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
        //the unit of the duration is second
        uint32_t duration = 30;
        esp_ble_gap_start_scanning(duration);
        break;
    }
    case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
        //scan start complete event to indicate scan start successfully or failed
        if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            ESP_LOGE(GATTC_TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status);
            break;
        }
        ESP_LOGI(GATTC_TAG, "Scan start success");
        break;

1.3 配置并绑定从设备

GATT客户端的其余配置将按照常规GATT客户端示例的相同方式正常执行。也就是说,客户端找到感兴趣的设备并打开连接。这时,GATT客户端(通常是主设备)通过向从设备发送配对请求(Pairing Request)来启动配对过程。这个请求应该用配对响应( Pairing Response)来确认。配对过程由BLE协议栈自动实现,不需要额外的用户配置。然而,根据两个设备的I/O Capabilities,可能会在ESP32上生成一个密码密钥,并通过ESP_GAP_BLE_PASSKEY_NOTIF_EVT提供给用户:

 case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:  
 ///the app will receive this evt when the IO  has Output capability and the peer device IO has Input capability.
 ///show the passkey number to the user to input it in the peer device.
      ESP_LOGE(GATTS_TABLE_TAG, "The passkey Notify number:%d", param->ble_security.key_notif.passkey);
      break;

决定使用哪种算法的 input and output capabilities 的组合有如下:
ESP32入门基础之安全连接SMP-client_第1张图片在Just Works模式中,临时密钥被设置为0。当设备上没有连接显示器或键盘时,这是验证设备身份的一种实用方法,而无显示器或键盘就无法显示或输入密码。但是,如果ESP32 GATT客户端带有LCD,则可以显示本地生成的密钥,以便用户在对端设备上输入;如果GATT客户端带有键盘,则可以输入对端设备生成的密钥。此外,如果两个设备都有显示和yes/no确认按钮,并且使用LE Secure Connections,则可以执行数字比较,这样就可以在两个设备上显示独立生成的密钥,并且用户手动检查两个6位确认值是否匹配。

1.4 交换秘钥

当客户端连接到远端设备并且配对成功时,发起者和响应者密钥将交换。对于每个密钥交换消息,一个ESP_GAP_BLE_KEY_EVT事件被触发,可以用来打印接收到的密钥类型:

case ESP_GAP_BLE_KEY_EVT:
    //shows the ble key info share with peer device to the user.
    ESP_LOGI(GATTS_TABLE_TAG, "key type = %s", esp_key_type_to_str(param->ble_security.ble_key.key_type));
    break;       

当密钥交换成功时,配对过程就完成了,可以使用AES-128引擎开始对负载数据进行加密。这会触发ESP_GAP_BLE_AUTH_CMPL_EVT事件,该事件用于打印信息:

case ESP_GAP_BLE_AUTH_CMPL_EVT: {
    esp_bd_addr_t bd_addr;
    memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t));
    ESP_LOGI(GATTS_TABLE_TAG, "remote BD_ADDR: %08x%04x",\
    (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], (bd_addr[4] << 8) + bd_addr[5]);
    ESP_LOGI(GATTS_TABLE_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type);
    ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail");
    break;

你可能感兴趣的:(乐鑫ESP32,安全,网络,web安全,物联网)