为什么 CC2640 配对失败
两个CC2640 一个做主 一个做从,单独测试从机与dongle 配对和绑定可以正常运行,sniffer抓图如下:
如果两个CC2640 配对,主机好像没有正确发出request, 单步发现主机没有进Passcode CB,只进入processPairState,且:
state = GAPBOND_PAIRING_STATE_BONDED
status = 6
sniffer抓图如下:
从机配置:
uint32_t passkey = 0; // passkey "000000"
uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
uint8_t mitm = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
uint8_t bonding = TRUE;
GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
主机配置:
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
/* TRUE to require passcode or OOB when pairing */
uint8_t mitm = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
uint8_t bonding = TRUE;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
从机回调函数:
static void __SPPBLEServer_processPasscode(uint16_t connectionHandle, uint8_t uiOutputs) { uint32_t passcode; // Create random passcode passcode = Util_GetTRNG(); passcode %= 1000000; passcode = 0; // Display passcode to user if (uiOutputs != 0) { debug_v( "***Passcode:", passcode, 10 ); } // Send passcode response GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode); } static void __SPPBLEServer_processPairState(uint8_t state, uint8_t status) { debug_v( ">>>>>Paired status ", status, 10 ); if( GAPBOND_PAIRING_STATE_STARTED == state ) { debug_s( ">>>>>Pairing started\n" ); } else if( GAPBOND_PAIRING_STATE_COMPLETE == state ) { debug_s( "I am in Pair complete state\n" ); if( SUCCESS == status ) {debug_s( ">>>>>Pairing success\n" );gPairStatus = 1; } else if( 8 == status ) {debug_s( ">>>>>Paired device\n" );gPairStatus = 1; } else {debug_s( ">>>>>Pairing fail\n" );gPairStatus = 0; } /**< terminate connection if pair failed >*/ if( app_state == BLE_STATE_CONNECTED && gPairStatus == 0 ) { GAPRole_TerminateConnection(); } } else if ( GAPBOND_PAIRING_STATE_BONDED == state ) { if (status == SUCCESS) {debug_s( ">>>>>Bonding success\n" ); } } }
主机回调函数:
static void SPPBLEClient_processPairState(uint8_t state, uint8_t status) { if (state == GAPBOND_PAIRING_STATE_STARTED) { debug_s( "Pairing started\n" ); } else if (state == GAPBOND_PAIRING_STATE_COMPLETE) { if (status == SUCCESS) {debug_s( "Pairing success\n" ); } else {debug_v( "Pairing fail:", status, 10 ); } } else if (state == GAPBOND_PAIRING_STATE_BONDED) { if (status == SUCCESS) {debug_s( "Bonding success\n" ); } } } /********************************************************************* * @fn SPPBLEClient_processPasscode * * @brief Process the Passcode request. * * @return none */ static void SPPBLEClient_processPasscode(uint16_t connectionHandle, uint8_t uiOutputs) { uint32_t passcode; // Create random passcode passcode = Util_GetTRNG(); passcode %= 1000000; passcode = 0; debug_s( "process passcode\n" ); // Display passcode to user if (uiOutputs != 0) { debug_v( "Passcode:", passcode, 10 ); } // Send passcode response GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode); }
主机端pair mode 配置成
#define GAPBOND_IO_CAP_KEYBOARD_ONLY 0x02 //!< Keyboard Only
#define GAPBOND_IO_CAP_KEYBOARD_DISPLAY 0x04 //!< Both Keyboard and Display Capable
结果一样,sniffer抓到的数据也一样,除了LL_Encryption Req 的PDU不一样
Derrick Cheng,
你第二个抓的包,在slave发security request之前有些其他的什么交互?能把那些也截图贴上来吗?
看上去是直接进行加密了,所以你之前是不是有配对绑定成功过,然后在测试断开连接,重新连接?你有没有试过把两边的代码都重新烧录一遍,把flash擦除,两边的APP和Stack两个工程都重新烧录一遍试过吗?
总之看上去是之前有绑定过,然后你可能有什么操作,在其中一方把保存在flash里面的link key信息给擦除了或者修改了。
Y:
感谢回复,在slave 发出security request 之前没有其他交互,只有广播包和扫描包。
擦除后重新配对,看起来配对过程没有问题,但是在配对结束后M发出LL_Connect_Update_Req 后又出错了
附件是sniffer抓到的完整数据
Y:
主从的回掉函数和配置有问题吗?
我这边打出的log显示连接后马上又断开了?之后的操作怎么进行的下去呢?
Y Connected
Z Disonnected
Link parameters updated:
Connection Handle: 0
Connection Interval: 6
Connection Latency: 0
Connection Timeout: 200
Bonding success
Starting Discovery...
Derrick Cheng,
所以结合前面的一起来看,不是配对引起的,配对绑定加密都是正常的。
不太清楚你怎么操作的,看上去你这个问题出在connection update request上,你仔细看看你的连接参数请求,那几个参数明显有问题啊,你让master 在发connection update request 吗?然后看看那些参数,slave latency 0xA9C4? 最大的slave latency 是499个(0x01F3)。。。最大的connection interval 是4s (0x0C80),你的log里看起来参数远远超过这个范围了。。。
另外,这些包都是在连接的时候抓的,如果已经断开连接或者一方失连,是不会有下一步的命令发送的。
谢谢,我再debug下
我也注意到了 slave latency 499 这个问题,我理解是因为经过了加密?
Derrick Cheng,
好问题。
我也不能确定。理论上如果是因为加密的话,那么一个包就不应该能解密一部分,但又解密不出另一部分。
我们的packet sniffer应该是无法解密的,但是我也不确定这东西是否会有些奇怪的动作。
比较靠谱的是用那些专用的抓包工具,但是比较贵。
Y:
谢谢,现在配对已经没有问题了,可以正确配对和绑定,但是不知道为什么从sniffer上我还能看到数据的明文?
这里是一个write 和一个notify 已经加密 但是看到的数据任然是明文
"ATP\r"
"ATD=A0E6F84FCDA8\r"
发现个有趣的问题:
1. 从机发起配对,主机输入密码后配对成功,这时擦除从机flash并重新下载firmware后,就不能正常配对了。我的理解是从机认为之前没有配对过,要求主机配对,但是主机认为已经配对过了,所以两边的配对过程(参数)不一致导致从机reject?
2. 为了解决上述问题,我准备提供清除绑定信息的对外接口,结果没有找到清除的API,所以想直接擦除SNV,结果查看工程配置,memory map和boundary information 都显示没有分配SNV,那之前的绑定信息是怎么存储的?
1〉工程里没有配置 OSAL_SNV 这个symbol
2〉Boundary Address
[ Nv Boundary Calculation ]
Reserved Size = 0x00001000 (4096)
Reserved End = 0x0001FFFF (131071)
Reserved Start = 0x0001F000 (126976)
Nv Size = 0x00000000 (0)
Y:
可以帮忙解释下吗?谢谢
Derrick Cheng,
那些专业的sniffer,对于just work方式的配对加密,是可以轻松解密数据的,2540 dongle之前理论上是不能解密加密数据的,但我现在不确定现在是个什么情况。
1. 不确定。正常来说,如果一方删除了配对,是需要重新走一边配对流程的,另一方不能拒绝。你这个需要抓包看。
2. 你可以参考一下这个帖子:
http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/p/111888/304093.aspx#304093