BLE-NRF51822教程9—動態密碼(配對碼)

本講教程也是在 sdk中的的uart例子 的基礎上修改實現動態密碼(其實是配對碼)的功能。Uart例子在以下目錄中

XXX\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_uart

 

關於配對的一些理論知識在靜態密碼教程中有介紹。這裏就不再贅述。

 

因爲是動態密碼,板子上沒有顯示屏,所以通過串口將動態密碼打印出來,然後手機正確輸入才能配對成功。

 

無論是靜態密碼還是動態密碼(配對碼,後面統一叫密碼)都是可以看做是配對過程中的一種認證方式即”我是我”,因爲這樣可以一定程度上避免他人連接你的設備,因爲他們看不到設備上顯示的配對碼,而你自己去可以看到。

 

配對碼的輸入是配對過程中生成TK的一種方式即Passkey Entry。另外還有Just Works和Out of Band 兩種方式。TK的生成是爲了後續再生成STK用來加密鏈路然後分發LTK,IRK,CSRK。(如果配對信息交換是沒是指明綁定也就不需要後續的這裏密鑰的分發了)

 

既然有三種方式可選,那麼協議是如何決定選擇哪種的呢。這個就和配對時交換的配對信息有關了。我們使用的是Passkey Entry 即輸入配對碼的方式,那麼只要將 配對信息中的 OOB設置爲0 ,MITM設置爲 1, bond設置爲0(教程只是演示配對中的配對碼的輸入不需要後面的密鑰分發過程),然後將自己的 I/O能力設置爲 DisplayOnly  就行了。

 

:至於各種可能的組合會導致選擇什麼樣的方式在規範的安全管理部分有詳細的對照表可參考。

 

根據上面的描述,我們首先就是要配置配對時要交換的配對信息

 

#define IO_CAPS      BLE_GAP_IO_CAPS_DISPLAY_ONLY  //只有顯示裝置

#define BOND         0                               //不綁定

#define OOB          0                          

#define MITM         1

 

 然後就是在程序中回覆配對信息。

實現如下函數來回復配對請求信息並將自己的配對信息傳給對方。

 

void resp_pair_request(){

    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 = 16;

    sec_params.min_key_size = 7;

    sec_params.oob = BOND;

    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);

}

 

 

 

將該函數添加到BLE_GAP_EVT_SEC_PARAMS_REQUEST事件處理部分中去。這樣在主機請求配對時,從機就可以將自己的配對信息發送給主機了。

 

信息交換完後,設備低層的協議棧就會自動產生6爲隨機的密碼(配對碼),並將配對碼通過事件BLE_GAP_EVT_PASSKEY_DISPLAY 上拋給app,然後就可以在app中將密碼通過串口將密碼打印出來了。

 

上面說的兩個事件的處理我們都在 on_ble_evt 事件處理函數中處理。紅色代碼部分爲處理函數。

static void on_ble_evt(ble_evt_t * p_ble_evt)

{

    uint32_t                         err_code;

   

    switch (p_ble_evt->header.evt_id)

    {

        case BLE_GAP_EVT_CONNECTED:

            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);

            APP_ERROR_CHECK(err_code);

            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

            break;

           

        case BLE_GAP_EVT_DISCONNECTED:

            err_code = bsp_indication_set(BSP_INDICATE_IDLE);

            APP_ERROR_CHECK(err_code);

            m_conn_handle = BLE_CONN_HANDLE_INVALID;

            break;

 

        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:

            printf("receive pair request\n");

           resp_pair_request();

            break;

       case BLE_GAP_EVT_PASSKEY_DISPLAY:

          printf("show passkey: ")

         for ( int i = 0; i < 6; i++){                                   printf("%c",p_ble_evt->evt.gap_evt.params. \

                   passkey_display.passkey[i]);

         }

             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;

 

        default:

            // No implementation needed.

            break;

    }

}

 

然後添加觸發配對代碼。 這裏實現的很簡單。就是將Rx特徵值的cccd的寫設置成需要鏈路加密和MITM。這樣在未配對的情況下手機使能Notify時設備就會回覆權限不足,然後手機就會發一個配對請求過來從而實現配對和鏈路的加密。

 

修改ble_nus.c文件中的rx_char_add函數。

static uint32_t rx_char_add(ble_nus_t * p_nus,

 const ble_nus_init_t * p_nus_init)

{

    /**@snippet [Adding proprietary characteristic to S110 SoftDevice] */

    ble_gatts_char_md_t char_md;

    ble_gatts_attr_md_t cccd_md;

    ble_gatts_attr_t    attr_char_value;

    ble_uuid_t          ble_uuid;

    ble_gatts_attr_md_t attr_md;

 

    memset(&cccd_md, 0, sizeof(cccd_md));

 

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

//設置權限

    BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);

   // BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

   …………

   …………

 

}

 

之後燒錄程序後,在手機執行使能Notify時就會觸發配對,串口會打印出隨機密碼,手機正確輸入後便是成功配對。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章