BLE-NRF51822教程5-靜態密碼設定
nordicBLE交流群498676838
這一講介紹配對的一些相關理論知識,並且介紹如何?”靜態密碼”的設定
程式是基於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
#defineSTATIC_PASSKEY "123456" /**< Static pin. */
//改結構體中可以設定靜態密碼
staticble_opt_t m_static_pin_option;
定義了這兩個參數後,我們需要設定一下靜態密碼,設定的操作需要在協議棧初始化之後 所以我們將設定密碼操作放在 gap_params_init()函數的最後
如下:
static void gap_params_init(void)
{
//前面都是設定一些裝置名稱以及一些後續需要協商的串連參數
//詳細解釋在 串口透傳剖析 中有說明
uint32_t err_code;
ble_gap_conn_params_tgap_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_tpasskey[] = 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
//這裡設定只有顯示屏(其實沒有,但是我們用的是事Crowdsourced Security Testing道的靜態密碼所以不// 需要顯示)
#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 下的uartdemo,所以我們將具有notify 性質RX 特徵值的 cccd(用戶端配置描述符)設定為需要認證和加密的安全鏈路。
因為手機端使能notify是需要寫CCCD的
那麼當手連上板子後 點擊rx特徵值的notify 按鈕後主機會發一個 寫命令寫板子上的rx特徵值的cccd,因為初試鏈路是不完全的,那麼這時手機就會返回寫出錯,然後啟動配對過程。
設定如下:
在添加RX特徵值的函數中做如下的簡單就可以了。
這裡只截取部分代碼:
static uint32_t rx_char_add(ble_nus_t * p_nus, constble_nus_init_t * p_nus_init)
{
/**@snippet [Addingproprietary characteristic to S110 SoftDevice] */
ble_gatts_char_md_tchar_md;
ble_gatts_attr_md_tcccd_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t ble_uuid;
ble_gatts_attr_md_tattr_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做如下修改
staticvoidon_ble_evt(ble_evt_t * p_ble_evt)
{
uint32_terr_code;
switch(p_ble_evt->header.evt_id)
{
caseBLE_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;
caseBLE_GAP_EVT_DISCONNECTED:
err_code= bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
m_conn_handle= BLE_CONN_HANDLE_INVALID;
break;
caseBLE_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;
caseBLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have beenstored.
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功能。當我們點擊該按鈕時就會彈出輸入密碼的配對框。
http://www.bkjia.com/PHPjc/1074169.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1074169.htmlTechArticleBLE-NRF51822教程5-靜態密碼設定 nordicBLE交流群498676838 這一講介紹配對的一些相關理論知識,並且介紹如何?”靜態密碼”的設定 程式是基...