”静态密码”的设定

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功能。当我们点击该按钮时就会弹出输入密码的配对框。