nrf52832 学习笔记配对和绑定

Posted 不咸不要钱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记配对和绑定相关的知识,希望对你有一定的参考价值。

nrf52832 学习笔记(六)配对和绑定

蓝牙在配对之前都是明文通信的,也就是说主从机之间传输的数据包可以被第三方抓取分析逆向,而且如果没有配对,谁都可以无密码连接,显然是不安全的。

配对

nrf52832 支持主从机配对和绑定操作的,但是做主机时配对和绑定没用过(官方论坛找到一个demo),下面的都是针对nrf52832做从机时的配对操作。

静态密码

日常使用蓝牙对从机进行连接时,会提示输入密码,这个其实就是一种配对过程.

  1. 蓝牙从机中存在一个静态密码.
  2. 主机连接到从机后,从机启动安全连接认证
  3. 主机接收到安全连接认证请求后,产生一个随机数,根据随机数和主机的静态密码计算出一个确认值
  4. 从机同样产生一个随机数,根据随机数和从机的静态密码计算出一个确认值,主从机交换随机数和确认值.
  5. 主从机通过自己的静态密码和交换来的随机数,计算确认值和交换来的确认值对比,如果一致则配对成功,不一致则断开连接
  6. 配对成功后,主从机根据两个随机数和静态密码 生成一个临时密匙,后面蓝牙通信都会经过该密匙加密处理

nrf52832 sdk中添加配对处理,首先在gap初始化中添加静态密码设置

#define STATIC_PASSKEY "123456"
static ble_opt_t m_static_pin_option;

/**@brief Function for the GAP initialization.
 *
 * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
 *          device including the device name, appearance, and the preferred connection parameters.
 */
static void gap_params_init(void)

    ret_code_t              err_code;
	//....其他初始化
                                          
    //设置万能钥匙的存放区																			
	uint8_t passkey[] = STATIC_PASSKEY;                                                     
    m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    APP_ERROR_CHECK(err_code);                                       

然后在协议栈回调函数的连接事件中添加启动安全连接认证函数,同时添加安全参数交换函数和认证失败断开连接处理.

#define IO_CAPS      BLE_GAP_IO_CAPS_DISPLAY_ONLY  //只有显示装置
#define BOND          0                            //不绑定
#define OOB           0                            //没有外带认证数据 例如使用NFC或者二维码交换一些信息
#define MITM          1                            //中间人保护
#define MIN_KEY_SIZE  7                            //密匙最小长度
#define MAX_KEY_SIZE  16                           //密匙最大长度

//配对请求函数,交换配对信息
void pairng_request(void)

    ble_gap_sec_params_t sec_params;
    uint32_t                    err_code;

    memset(&sec_params,0,sizeof(ble_gap_sec_params_t));

    sec_params.bond = BOND;
    sec_params.io_caps = IO_CAPS;
    sec_params.max_key_size = MAX_KEY_SIZE;
    sec_params.min_key_size = MIN_KEY_SIZE;
    sec_params.oob = OOB ;
    sec_params.mitm = MITM;
    err_code=sd_ble_gap_sec_params_reply(m_conn_handle,BLE_GAP_SEC_STATUS_SUCCESS,&sec_params,NULL);
    APP_ERROR_CHECK(err_code);


/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)

    ret_code_t err_code;

    switch (p_ble_evt->header.evt_id)
    
        case BLE_GAP_EVT_CONNECTED:        //主从机连接成功
            NRF_LOG_INFO("Connected"); 
            bsp_board_led_on(CONNECTED_LED);
            bsp_board_led_off(ADVERTISING_LED);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
//            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
//            APP_ERROR_CHECK(err_code);
            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);
            ble_gap_phys_t const phys =
            
                .rx_phys = BLE_GAP_PHY_2MBPS,
                .tx_phys = BLE_GAP_PHY_2MBPS,
            ;
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            
            //启动连接后,连接成功,启动本次连接的安全认证
			ble_gap_sec_params_t params;
            params.bond = 0;
            params.mitm = 1;
            sd_ble_gap_authenticate(m_conn_handle,&params);
            
            break;
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST://PHY更新请求
        
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys =
            
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            ;
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
         break;
        case BLE_GAP_EVT_PHY_UPDATE:         //PHY更新完成
            NRF_LOG_INFO("tx: %d, rx: %d",
                         p_ble_evt->evt.gap_evt.params.phy_update.tx_phy,
                         p_ble_evt->evt.gap_evt.params.phy_update.rx_phy
                         );
            break;
        
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
            bsp_board_led_off(CONNECTED_LED);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            err_code = app_button_disable();
            APP_ERROR_CHECK(err_code);
            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:  //安全参数交换请求
            pairng_request();
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
        
        // 连接参数更新
        case BLE_GAP_EVT_CONN_PARAM_UPDATE:
            NRF_LOG_INFO("conn_Param Update: %d,%d,%d,%d",
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.min_conn_interval,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.max_conn_interval,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.slave_latency,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.conn_sup_timeout
                         );
            break;
        
        case BLE_GAP_EVT_AUTH_STATUS:
			//认证,如果认证失败,则断开连接
            if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
            

            
            else
            
                sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            
          
        default:
            // No implementation needed.
            break;
    

动态密码

动态密码和静态密码基本类似,只是不用在gap初始化时设置静态密码

//#define STATIC_PASSKEY "123456"
//static ble_opt_t m_static_pin_option;

/**@brief Function for the GAP initialization.
 *
 * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
 *          device including the device name, appearance, and the preferred connection parameters.
 */
static void gap_params_init(void)

    ret_code_t              err_code;
	//....其他初始化
                                          
    //设置万能钥匙的存放区																			
	//uint8_t passkey[] = STATIC_PASSKEY;                                                     
    //m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    //err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    //APP_ERROR_CHECK(err_code);                                       

在协议栈回调者函数中添加一个事件处理将随机密码输出.

case BLE_GAP_EVT_PASSKEY_DISPLAY:
            NRF_LOG_INFO("passkey: %c,%c,%c,%c,%c,%c",
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[0],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[1],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[2],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[3],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[4],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[5]
                         );
            break;

绑定

绑定是将第一次配对后产生的长期密匙信息和对应MAC存储在flash中,下次再遇到对应MAC地址就不需要进行配对输入密码操作,直接交换密匙信息即可。配对和绑定整个流程十分复杂,nordic 的SDK中也给了对应的驱动库,和上面的配对不同,下面使用sdk中的pm库文件进行配对绑定操作。

添加库文件

  1. 开启SDK配置项

  2. 添加库文件

  3. 添加文件路径

从机

如果使用静态密码,仍然在gap初始化时设置静态密码

#define STATIC_PASSKEY "123456"
static ble_opt_t m_static_pin_option;

/**@brief Function for the GAP initialization.
 *
 * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
 *          device including the device name, appearance, and the preferred connection parameters.
 */
static void gap_params_init(void)

    ret_code_t              err_code;
	//....其他初始化
                                          
    //设置万能钥匙的存放区																			
	uint8_t passkey[] = STATIC_PASSKEY;                                                     
    m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
    err_code =  sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
    APP_ERROR_CHECK(err_code);                                       

然后在主函数中进行pm管理器初始化

#include "peer_manager.h"
#include "peer_manager_handler.h"
#define SEC_PARAM_BOND                  1                                       /**< Perform bonding. */
#define SEC_PARAM_MITM                  1                                       /**< Man In The Middle protection is enabled. */
#define SEC_PARAM_LESC                  0                                       /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS              0                                       /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_DISPLAY_ONLY            /**< Display Only. */
#define SEC_PARAM_OOB                   0                                       /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE          7                                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE          16                                      /**< Maximum encryption key size. */

/**@brief Function for handling Peer Manager events.
 *
 * @param[in] p_evt  Peer Manager event.
 */
static void pm_evt_handler(pm_evt_t const * p_evt)

    pm_handler_on_pm_evt(p_evt);
    pm_handler_flash_clean(p_evt);

    switch (p_evt->evt_id)
    
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
            advertising_start();
            break;

        default:
            break;
    

///Added for bonding
/**@brief Function for the Peer Manager initialization.
 */
static void peer_manager_init(void)

    ret_code_t err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);

    ble_gap_sec_params_t sec_param;

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    sec_param.bond           = SEC_PARAM_BOND;
    sec_param.mitm           = SEC_PARAM_MITM;
    sec_param.lesc           = SEC_PARAM_LESC;
    sec_param.keypress       = SEC_PARAM_KEYPRESS;
    sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob            = SEC_PARAM_OOB;
    sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_own.enc  = 1;
    sec_param.kdist_own.id   = 1;
    sec_param.kdist_peer.enc = 1;
    sec_param.kdist_peer.id  = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);


最后在连接后启动配对绑定处理函数,也可以由主机启动配对绑定处理函数


/**@brief Function for handling BLE events.
 *
 * @param[in]   p_ble_evt   Bluetooth stack event.
 * @param[in]   p_context   Unused.
 */
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)

    ret_code_t err_code;

    switch (p_ble_evt->header.evt_id)
    
        case BLE_GAP_EVT_CONNECTED:        //主从机连接成功
            NRF_LOG_INFO("Connected"); 
            bsp_board_led_on(CONNECTED_LED);
            bsp_board_led_off(ADVERTISING_LED);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
//            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
//            APP_ERROR_CHECK(err_code);
            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);
            ble_gap_phys_t const phys =
            
                .rx_phys = BLE_GAP_PHY_2MBPS,
                .tx_phys = BLE_GAP_PHY_2MBPS,
            ;
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            
            /启动配对绑定处理函数 
            err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);
            if (err_code != NRF_ERROR_BUSY)
            
                APP_ERROR_CHECK(err_code);
            
            /Added for bonding
            break;
        case BLE_GAP_EVT_PHY_UPDATE_REQUEST://PHY更新请求
        
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys =
            
                .rx_phys = BLE_GAP_PHY_AUTO,
                .tx_phys = BLE_GAP_PHY_AUTO,
            ;
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
         break;
        case BLE_GAP_EVT_PHY_UPDATE:         //PHY更新完成
            NRF_LOG_INFO("tx: %d, rx: %d",
                         p_ble_evt->evt.gap_evt.params.phy_update.tx_phy,
                         p_ble_evt->evt.gap_evt.params.phy_update.rx_phy
                         );
            break;
        
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected");
            bsp_board_led_off(CONNECTED_LED);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            err_code = app_button_disable();
            APP_ERROR_CHECK(err_code);
            advertising_start();
            break;

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:  //安全参数交换请求
            //pairng_request();
            break;

        case BLE_GATTS_EVT_SYS_ATTR_MISSING:
            // No system attributes have been stored.
            err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTC_EVT_TIMEOUT:
            // Disconnect on GATT Client timeout event.
            NRF_LOG_DEBUG("GATT Client Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;

        case BLE_GATTS_EVT_TIMEOUT:
            // Disconnect on GATT Server timeout event.
            NRF_LOG_DEBUG("GATT Server Timeout.");
            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
            break;
        
        // 连接参数更新
        case BLE_GAP_EVT_CONN_PARAM_UPDATE:
            NRF_LOG_INFO("conn_Param Update: %d,%d,%d,%d",
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.min_conn_interval,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.max_conn_interval,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.slave_latency,
                         p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params.conn_sup_timeout
                         );
            break;
        case BLE_GAP_EVT_PASSKEY_DISPLAY:
            NRF_LOG_INFO("passkey: %c,%c,%c,%c,%c,%c",
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[0],
                         p_ble_evt->evt.gap_evt.params.passkey_display.passkey[1],
                            p_ble_evt->evt.gap_evt.params.passkey_display.passkey[2],
                            p_ble_evt->evt.gap_evt.params.passkey_display.passkey[3],
                            p_ble_evt->evt.gap_evt.params.passkey_display.passkey[4],
                            p_ble_evt->evt.gap_evt.params.passkey_display.passkey[5]
                         );
            break;
        case BLE_GAP_EVT_AUTH_STATUS:
			//认证,如果认证失败,则断开连接
            if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
            

            
            else
            
                sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)nrf52832 学习笔记蓝牙主从机连接和连接参数更新

nrf52832 学习笔记蓝牙主机扫描

nrf52832 学习笔记蓝牙主机扫描

nrf52832 学习笔记蓝牙主机发现服务

nrf52832 学习笔记蓝牙主从机连接和连接参数更新

nrf52832 学习笔记开发资料汇总