”静态密码”的设定
sdk9.0 下的 uart demo
app是 IOS下的lightblue。
(后面都直接叫密码,而不是配对码)
flash中这样两个设备再第二次重连时的安全启动会更快。而不需要像第一次一样需要再启动整个配对过程。
(如果设置了绑定位配对的)。
MITM,是否使用OOB等
BLE协议栈确定一种认证方式:
just work,这其实就是没有认证,
MITM保护。那么认证方式就是passkey entery。
一端会显示一个配对码,另一需要输入这个配对码。之后的配对才能正确进行下去。
OOB,那么这个配对码就是通过另外的通信方式(如NFC)来发送的,而不是像上面一样一端显示一端输入。
这一讲的密码设置就是第二种情况。显示的密码是可以随机的也可以是静态的。由于设备并没有显示器。但是我们仍然可以设置输入输出能力为有显示器,因为我们使用的是静态密码。
1: 首先设置要输入的静态密码
2: 设置配对时会交换的信息:根据上面的介绍如果我们需要手机输入密码,那么配对时就要设置只具有显示器(这样就会是一端显示,一端输入,虽然我们真的没显示器,但是设置的是静态密码所以也是可以的),设置需要MITM攻击保护。
如何设置静态密码:
//首先定义一下静态密码,配对密码只能是 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
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(); 函数之后。
(因为其内部值就是要交换的信息)。
触发配对:
LTK加密链路,如果没有那么主机会发起配对请求。
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.
NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;
default:
// No implementation needed.
break;
}
}
到这里所有需要配置的都设置完了。程序运行后。手机连接上板子,然后访问rx特征值。因为该特征值是用来将板子数据通过Notify方式传给手机的,那么首先要点击手机上的notify按钮去使能板子的notify功能。当我们点击该按钮时就会弹出输入密码的配对框。