BLE-NRF51822教程5-静态密码设置
這一講介紹配對的一些相關理論知識,并且介紹如何實現”靜態密碼”的設定
程序是基于sdk9.0?下的?uart demo
另外?測試使用的手機app是?iOS下的lightblue。
這里準確的說法應該是叫配對碼,而不是密碼。輸入這個這個配對碼是配對過程中可選的一部分
介紹如何設置靜態密碼前先介紹一下配對的相關知識(后面都直接叫密碼,而不是配對碼)
起初未提供安全性的兩個設備如果希望做一些需要安全性的工作,就必須先配對。配對涉及兩個設備的身份認證,鏈路加密。如果配對時設置了綁定位,隨后還會有一個秘鑰分配。分配的秘鑰用戶可以存儲在flash中這樣兩個設備再第二次重連時的安全啟動會更快。而不需要像第一次一樣需要再啟動整個配對過程。
配對的第一個過程首先是配對信息的交換,這些信息用于確定認證方式,以及后續是否需要分配密鑰以及分配哪些密鑰。
交換的信息包括:
兩端設備的輸入輸出能力如:是否有顯示屏,鍵盤等。
是否需要綁定(如果設置了綁定位配對的)。
是否需要MITM,是否使用OOB等
這些信息會讓BLE協議棧確定一種認證方式:
比如:
??? 1:如果兩端設備的輸入輸出能力有限,比如都沒有鍵盤和顯示器,認證方式就是just work,這其實就是沒有認證,
??? 2:如果兩端設備一個有顯示頻,而另一個有鍵盤,而配對中設置了MITM保護。那么認證方式就是passkey entery。
? ? ? 一端會顯示一個配對碼,另一需要輸入這個配對碼。之后的配對才能正確進行下去。
??? 3:如果設置了OOB,那么這個配對碼就是通過另外的通信方式(如NFC)來發送的,而不是像上面一樣一端顯示一端輸入。
?這一講的密碼設置就是第二種情況。顯示的密碼是可以隨機的也可以是靜態的。由于設備并沒有顯示器。但是我們仍然可以設置輸入輸出能力為有顯示器,因為我們使用的是靜態密碼。
配對的過程不僅只是輸入配對碼這樣,后續還會根據輸入的配對碼,以及兩端設備交換的隨機數來生成鏈路密鑰來加密鏈路以及分配后續的長期密鑰,身份解析密鑰等需要的密鑰
配對相關的理論比較多,上面的描述只是一個大概的過程。配對過程的詳細介紹在藍牙規范的 安全 章節中。
根據上面的理論描述,我們來總結一下:
??? 我們需要的輸入“密碼”這個功能,其實是配對過程中的一部分。而配對過程又是需要首先交換配對信息,然后協議棧會根據交換的信息才決定是否有輸入密碼這一過程。
?那么我們要做的有如下幾步:
? 1: 首先設置要輸入的靜態密碼
??2: 設置配對時會交換的信息:根據上面的介紹如果我們需要手機輸入密碼,那么配對時就要設置只具有顯示器(這樣就會是一端顯示,一端輸入,雖然我們真的沒顯示器,但是設置的是靜態密碼所以也是可以的),設置需要MITM攻擊保護。
? 3:觸發配對。
下面先介紹如何設置靜態密碼:
?//首先定義一下靜態密碼,配對密碼只能是 6-digit ASCII string
?#define STATIC_PASSKEY ? ? ? ?"123456" ? ? ? /**< Static pin. */
?//改結構體中可以設置靜態密碼
?static?ble_opt_t ? m_static_pin_option;?????????????????
? 定義了這兩個參數后,我們需要設置一下靜態密碼,設置的操作需要在協議棧初始化之后 所以我們將設置密碼操作放在??? gap_params_init()函數的最后
如下:
static void gap_params_init(void)
{
??? //前面都是設置一些設備名以及一些后續需要協商的連接參數
??? //詳細解釋在 串口透傳剖析 中有說明
??? uint32_t ? ? ? ? ? ?err_code;
??? ble_gap_conn_params_t?? gap_conn_params;
??? ble_gap_conn_sec_mode_t sec_mode;
??? BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
? err_code=sd_ble_gap_device_name_set(&sec_mode,
(constuint8_t*DEVICE_NAME,trlen(DEVICE_NAME));
??? APP_ERROR_CHECK(err_code);
? ? memset(&gap_conn_params, 0, sizeof(gap_conn_params));
? ? gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
? ? gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
? ? gap_conn_params.slave_latency???? = SLAVE_LATENCY;
? ? gap_conn_params.conn_sup_timeout? = CONN_SUP_TIMEOUT;
? ? err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
? ? APP_ERROR_CHECK(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 SEC_PARAM_BOND????????????????? 0
//因為要輸入密碼,就是一種MITM攻擊保護,所以這里設置MITM
#define SEC_PARAM_MITM????????????????? 1
//這里設置只有顯示屏(其實沒有,但是我們用的是事先知道的靜態密碼所以不//?需要顯示)
#define SEC_PARAM_IO_CAPABILITIES????? BLE_GAP_IO_CAPS_DISPLAY_ONLY
//不使用帶外數據
#define SEC_PARAM_OOB ? ? ? ? ? ? ? ? 0
//鏈路加密密鑰的長度
#define SEC_PARAM_MIN_KEY_SIZE ? ? ? ? ? 7?
#define SEC_PARAM_MAX_KEY_SIZE ? ? ? ? ? 16??
定義了宏之后我們需要在設置參數,寫一個如下的函數。
m_sec_params 是一個全局變量
ble_gap_sec_params_t m_sec_params;
static void sec_params_init(void)
{
??? m_sec_params.bond???????? = SEC_PARAM_BOND;
??? m_sec_params.mitm???????? = SEC_PARAM_MITM;
??? m_sec_params.io_caps????? = SEC_PARAM_IO_CAPABILITIES;
??? m_sec_params.oob????????? = SEC_PARAM_OOB;?
??? m_sec_params.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
??? m_sec_params.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
}
將該函數放在?main函數的初始化流程中的conn_params_init();?函數之后。
設置的這個全局變量會在配對啟動后的信息交換中使用(因為其內部值就是要交換的信息)。
到這里我們設置完了配對啟動后會交換的信息。但是怎么把這個信息給對端設備呢? 先看完最后一步的觸發配對的問題,再來解決將配對信息發給對端設備的問題。
最后一步觸發配對:
配對的觸發有以下幾種情況:
??? 1:主機直接發起。
??? 2:從機發起安全請求,如果之前綁定過,那么主機會直接用用保存的LTK加密鏈路,如果沒有那么主機會發起配對請求。
3:BLE中的有一個安全模式的概念。當某個屬性被設置為需要認證的加密鏈路訪問時,那么當在主機訪問從機的屬**器時,如果鏈路是不安全的就會返回錯誤,然后主機會發起配對請求從而實現安全要求。
我們采用的就是第三種 被動等待主機觸發的方式,那么首先要做的就是將一些屬性設置為需要安全的鏈路才能訪問,那么手機在訪問時就會觸發配對過程了。
因為我們是基于?9.0SDK?下的uart demo,所以我們將具有notify?性質RX?特征值的?cccd(客戶端配置描述符)設置為需要認證和加密的安全鏈路。
因為手機端使能notify是需要寫CCCD的
那么當手連上板子后 點擊rx特征值的notify?按鈕后主機會發一個 寫命令寫板子上的rx特征值的cccd,因為初試鏈路是不完全的,那么這時手機就會返回寫出錯,然后啟動配對過程。
設置如下:
在添加RX特征值的函數中做如下的簡單就可以了。
? 這里只截取部分代碼:
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_OPEN(&cccd_md.write_perm);
//將上面的一行修改成下面這行
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);
??? cccd_md.vloc = BLE_GATTS_VLOC_STACK;
? ? ?memset(&char_md, 0, sizeof(char_md));
··············
··············
············
}
這樣當對端設備(如手機)使能開發板的上rx特征值的notify功能時,就會因為沒有寫權限而觸發配對,手機會發來配對請求,然后板子回復配對信息,怎么回復? 這就是第二步中最后留下的問題。如何將配對信息交給對端設備(手機)。
當手機發來配對請求時,這對板子來說是一個事件,即配對事件。最終由dispatch派發函數交給各個服務或模塊的事件處理函數。
那么我們要做的就是在收到這個配對請求事件后回復第二步中設置的配對信息就可以了。在main.c?文件中的的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:
? ? ? ? ? ?//注釋掉原本的不支持配對的函數,改為如下的配對回復函數
? ? ? ? ? ?//err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
???????? //BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);?????
?? ??????err_code=sd_ble_gap_sec_params_reply(m_conn_handle,
??????????????? BLE_GAP_SEC_STATUS_SUCCESS,&m_sec_params,NULL);
????????????????? APP_ERROR_CHECK(err_code);
? ? ? ? ? ?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特征值。因為該特征值是用來將板子數據通過Notify方式傳給手機的,那么首先要點擊手機上的notify按鈕去使能板子的notify功能。當我們點擊該按鈕時就會彈出輸入密碼的配對框。
總結
以上是生活随笔為你收集整理的BLE-NRF51822教程5-静态密码设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BLE-NRF51822教程4-串口BL
- 下一篇: BLE-NRF51822教程6-创建一个