CC2541之配对与绑定

来源:互联网 发布:淘宝能不能卖保健品 编辑:程序博客网 时间:2024/04/30 19:15

本篇博文最后修改时间:2016年2月26日,10:59。


一、简介

本篇以SimpleBLEPeripheral工程为例,介绍配对与绑定。


二、实验平台

协议栈版本:BLE-CC254x-1.4.0

编译软件: IAR 8.20.2

硬件平台: Smart RF开发板

手机平台: 红米1S

安卓系统:Android 4.3

APP: BLE Device Monitor


三、版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.net/feilusia

联系方式:897503845@qq.com

技术交流QQ群:127442605


四、CC2541的配对与绑定简介

1、什么是配对与绑定?

答:

配对——主从机连接的密码配对过程。

绑定——连接一次后就一直绑定着不需要再输入密码。


2、配对与绑定过程是主从机中的哪一端发起的?

答:配对模式配置为“GAPBOND_PAIRING_MODE_INITIATE”的一端发起的,可以是主机,也可以是从机。


3、配对与绑定发生在什么阶段?

答:早期的蓝牙配对与绑定发生在连接之前,BLE的配对与绑定则发生在连接之后。


4、配对与绑定的过程在连接之后,是否会在连接之后、配对之前的阶段造成数据泄露?

答:是的,可能导致数据泄露。

原因是连接之后,有的APP会弹窗配对并要求配对正确方可操作数据,而有的APP虽会弹窗但允许置之不理直接操作数据(一段时间没有配对成功,从机会认为配对超时而断开,主机APP可在这段超时时间内窃取从机数据)。

解决办法:将特征值在属性表中的属性设置为“加密读”或“加密写”,也就是改成“GATT_PERMIT_AUTHEN_READ”或“GATT_PERMIT_AUTHEN_WRITE”。


五、测试代码

1、添加一个绑定与否的状态变量(simpleBLEPeripheral.c)

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. typedef enum  
  2. {  
  3.   PAIRSTATUS_PAIRED = 0,  
  4.   PAIRSTATUS_NO_PAIRED,  
  5. }PAIRSTATUS;  
  6. static PAIRSTATUS gPairStatus = PAIRSTATUS_NO_PAIRED;//配对状态,默认是没配对  

2、修改绑定初始化(simpleBLEPeripheral.c的SimpleBLEPeripheral_Init函数中)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // Setup the GAP Bond Manager  
  2. {  
  3.   uint32 passkey = 0; // passkey "000000"  
  4.   //uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;  
  5.   uint8 pairMode = GAPBOND_PAIRING_MODE_INITIATE;  
  6.   uint8 mitm = TRUE;  
  7.   uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;  
  8.   uint8 bonding = TRUE;  
  9.   GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey );  
  10.   GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode );  
  11.   GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm );  
  12.   GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap );  
  13.   GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding );  
  14. }  
注:

1)GAPBOND_PAIRING_MODE_WAIT_FOR_REQ

这个宏是表示等待对方发起配对请求的模式,如果主从机都是这种模式,则双方都不会发起配对请求。

因此主从机的其中一方必须要配置成GAPBOND_PAIRING_MODE_INITIATE方可进行配对。

从机中往往有机密数据,因此从机端需要配置成GAPBOND_PAIRING_MODE_INITIATE,否则如果配对请求的主动权交予主机,主机一旦不发起请求,那也就无配对过程,导致从机的数据公之于众了。


2)GAPBOND_IO_CAP_DISPLAY_ONLY

这个宏是只显示密码,将密码显示在LCD上给主机看,主机也就知道密码了。

如果设备有按键可以输入密码,也可以选择GAPBOND_IO_CAP_KEYBOARD_ONLY。


3、注册回调函数(simpleBLEPeripheral.c)

1)注册回调函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // GAP Bond Manager Callbacks  
  2. static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =  
  3. {  
  4.   ProcessPasscodeCB,                     // 密码回调  
  5.   ProcessPairStateCB                      // 绑定状态回调  
  6. };  

2)定义密码回调函数和配对状态回调函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. //******************************************************************************    
  2. //name:             ProcessPasscodeCB    
  3. //introduce:        绑定过程中的密码管理回调函数  
  4. //parameter:        deviceAddr:设备地址  
  5. //                      connectionHandle:连接句柄  
  6. //                      uiInputs:  
  7. //                      uiOutputs:  
  8. //return:           none  
  9. //author:       甜甜的大香瓜  
  10. //changetime:       2015.12.8  
  11. //******************************************************************************  
  12. static void ProcessPasscodeCB(uint8 *deviceAddr,uint16 connectionHandle,uint8 uiInputs,uint8 uiOutputs )  
  13. {  
  14.   uint32  passcode;  
  15.   uint8   str[7];  
  16.   
  17.   //设置密码  
  18.   #if 0  
  19.     LL_Rand( ((uint8 *) &passcode), sizeof( uint32 ));  
  20.     passcode %= 1000000;  
  21.   #else  
  22.     passcode = 456890;          
  23.   #endif  
  24.   
  25.   //在LCD上显示  
  26.   if ( uiOutputs != 0 )  
  27.   {  
  28.     HalLcdWriteString( "Passcode:",  HAL_LCD_LINE_1 );  
  29.     HalLcdWriteString( (char *) _ltoa(passcode, str, 10),  HAL_LCD_LINE_2 );  
  30.   }  
  31.     
  32.   //发送密码响应给主机  
  33.   GAPBondMgr_PasscodeRsp( connectionHandle, SUCCESS, passcode );  
  34. }  

密码可以选择固定的456890方式,也可以选择随机函数产生的随机数。


[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. //******************************************************************************    
  2. //name:             ProcessPairStateCB  
  3. //introduce:        绑定过程中的状态管理函数  
  4. //parameter:        connectionHandle:连接句柄                
  5. //                      state:  
  6. //                      status:  
  7. //return:           none  
  8. //author:       甜甜的大香瓜  
  9. //changetime:       2015.12.8  
  10. //******************************************************************************  
  11. static void ProcessPairStateCB( uint16 connHandle, uint8 state, uint8 status )  
  12. {  
  13.   //主机发起连接,会进入开始配对状态  
  14.   if ( state == GAPBOND_PAIRING_STATE_STARTED )  
  15.   {  
  16.     HalLcdWriteString( "Pairing started", HAL_LCD_LINE_1 );  
  17.     gPairStatus = PAIRSTATUS_NO_PAIRED;  
  18.   }  
  19.     
  20.   //当主机提交密码后,会进入配对完成状态    
  21.   else if ( state == GAPBOND_PAIRING_STATE_COMPLETE )  
  22.   {  
  23.     //配对成功  
  24.     if ( status == SUCCESS )      
  25.     {  
  26.       HalLcdWriteString( "Pairing success", HAL_LCD_LINE_1 );  
  27.       gPairStatus = PAIRSTATUS_PAIRED;  
  28.     }  
  29.       
  30.     //已配对过  
  31.     else if(status == SMP_PAIRING_FAILED_UNSPECIFIED)  
  32.     {       
  33.       HalLcdWriteString( "Paired device", HAL_LCD_LINE_1 );  
  34.       gPairStatus = PAIRSTATUS_PAIRED;  
  35.     }  
  36.       
  37.     //配对失败  
  38.     else  
  39.     {  
  40.       HalLcdWriteStringValue( "Pairing fail", status, 10, HAL_LCD_LINE_1 );  
  41.       gPairStatus = PAIRSTATUS_NO_PAIRED;  
  42.     }  
  43.       
  44.     //配对失败则断开连接  
  45.     if(gPairStatus == PAIRSTATUS_NO_PAIRED)  
  46.     {  
  47.       GAPRole_TerminateConnection();  
  48.     }  
  49.   }  
  50.   else if ( state == GAPBOND_PAIRING_STATE_BONDED )  
  51.   {  
  52.     if ( status == SUCCESS )  
  53.     {  
  54.       HalLcdWriteString( "Bonding success", HAL_LCD_LINE_1 );  
  55.     }  
  56.   }  
  57. }  
注:

以上两个函数,第一次连接时的进入先后顺序为:

ProcessPairStateCB——GAPBOND_PAIRING_STATE_STARTED(0x00)

ProcessPasscodeCB

ProcessPairStateCB——GAPBOND_PAIRING_STATE_COMPLETE(0x01)


绑定后再连接时的进入先后顺序为:

ProcessPairStateCB——GAPBOND_PAIRING_STATE_BONDED(0x02)

(其他步骤被忽略了)


3)声明回调函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static void ProcessPasscodeCB(uint8 *deviceAddr,uint16 connectionHandle,uint8 uiInputs,uint8 uiOutputs );  
  2. static void ProcessPairStateCB( uint16 connHandle, uint8 state, uint8 status );  


4、修改特征值char2在属性表中的属性(simpleGATTprofile.c的simpleProfileAttrTbl中)

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // Characteristic Value 2  
  2. {   
  3.   { ATT_BT_UUID_SIZE, simpleProfilechar2UUID },  
  4.   GATT_PERMIT_AUTHEN_READ,//GATT_PERMIT_READ,   
  5.   0,   
  6.   &simpleProfileChar2   
  7. },  


5、在按键处理函数里增加清除绑定的功能

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys )  
  2. {      
  3.   VOID shift;  // Intentionally unreferenced parameter  
  4.   
  5.   if ( keys & HAL_KEY_UP )  
  6.   {  
  7.     GAPBondMgr_SetParameter( GAPBOND_ERASE_ALLBONDS,0, NULL );    
  8.   }   
  9. }  
无论是连接、还是非连接状态按下按键,都是作用在下一次连接上。
也就是在连接时按下按键并不会断开,下次想连接还会弹出输密码的框。


六、实验结果

1、从机发起配对请求



2、APP弹窗配对框时

(看截图左上角的蓝牙图标,实际上是配对请求的弹窗,香瓜在此先置之不理,试试读写特征值数据看看安全性)

1)读无加密的特征值char1



读未加密的特征值char1,成功返回01,说明连接之后、配对之前,该类属性的特征值也是不安全的。


2)读加密过的特征值char2



读加密了的特征值char2,返回错误状态字0x05,说明连接之后、配对之前,该类属性的特征值是安全的。


3)输错密码时

APP端会退回APP扫描设备的页面。

从机端发现APP发送过来的密码不对时,会断开连接。



4)绑定成功之后,第二次连接


绑定状态下,在安全请求之后,直接跳过了密码验证过程进行数据加密。


5)在开始加密请求之后,正式开始加密



七、本篇实验后仍存在的疑问

1、我的抓包出现大量错误通信,因此实验结果中有一些通信过程并没有真正抓到。此类错误暂不明原因,初步怀疑是我工程问题。期待知道大家的测试结果,是否跟我一样?






0 0
原创粉丝点击