基于Telink 8258配合Wireshark抓包测试SIG Mesh的IV Index Update过程
IV Index
- 什么是IV Index
- IV Index更新过程
- IV Index恢复过程
- IV Index更新测试模式
- 基于Telink8258进行IV Index更新测试
- 正常工作模式
- 触发 IV Index更新
- IV Index更新进行中
- IV Index更新过程切换至保持状态
- IV Index更新完成
Wireshark抓包方法:使用Nordic的nRF52840 Dongle配合Wireshark对蓝牙设备抓包(BLE)
什么是IV Index
Mesh网络要求network PDU的sequence number要一直累加,而sequence number是3byte表示。当使用很长一段时间后,sequence number接近最大值的时候,就需要考虑更新IV Index,否则sequence number就会归0,导致接收端认为是一个无效的message。从某种程度上,可以理解IV Index为sequence number的扩展位。
IV Index为应用层和网络层中用于身份验证加密(AES-CCM)的随机数提供熵,network layer和access layer的加解密过程都需要用到IV Index。因此,必须经常更改它,以避免在nonce中重复使用序列号。IV更新过程由主子网成员中的任何节点发起。当节点认为它有耗尽序列号的风险,或者它确定另一个节点接近耗尽它的序列号时,可以执行此操作。节点更改其IV Index,并向网格中的其他节点发送IV Index正在更新的指示。然后通过网格中的相同或其他节点更改回正常操作。节点发送信息越少,启动的IV更新过程也越少。
IV Update过程有两种操作状态:
正常操作状态:IV Update Flag = 0
IV Update状态: IV Update Flag = 1
IV Index更新过程
在正常运行状态下,安全网络信标和Friend更新消息中的IV更新标志设置为0。此时,节点应使用当前的IV Index进行传输,并处理来自当前IV Index和当前IV Index - 1的消息。
如果一个正常操作的节点收到了一个比已知IV index+1还大的值,那可能是启动了IV index恢复过程。如果处于正常运行状态的节点接收到安全网络信标,其IV索引等于上一次已知的IV索引+1,并且IV更新标志设置为0,则该节点可以更新其IV而不进入IV更新状态,或者它可以启动IV索引恢复过程,或者它可以忽略安全网络信标。如果此节点是主子网的成员,并且在次子网上接收到安全网络信标IV Index大于主子网安全网络的最后一个已知IV索引的子网信标应被忽略。
如果处于“正常运行”状态的节点接收到安全网络信标,其IV索引值小于上一个已知IV索引值或大于上一个已知IV索引值+ 42,则忽略安全网络信标,即允许节点离开网络48周。如果节点离开网络超过48周(一个节点启动IV更新程序的频率不得超过每192小时一次,42*192 = 8064小时,即48周),需要重新配网。
在正常操作状态下运行96小时后,节点可以通过IV Index加1的方式从正常操作状态过渡到正在进行的IV更新状态来启动IV更新过程。在序列号耗尽之前至少96小时(Telink SDK中当节点检测自己的sequence number超过了IV_UPDATE_START_SNO (0xC00000) 后,会主动发起IV更新过程。每次IV Update后,IV Index会加1),要发生从正常操作状态到IV更新进行中状态的转换。
Telink SDK通过is_sno_exhausted()函数判断sequence是否即将耗尽:
处于正常操作状态的节点,在收到IV Update Flag为1(表示IV更新正在进行状态)的安全网络信标时,应尽快转换到IV更新正在进行状态。处于IV更新正在进行状态下的节点,在收到IV Update Flag为0(表示正常操作状态)的安全网络信标时,应该尽快(至少96小时)转换到正常操作状态。
在IV更新进行中状态下,安全网络信标和Friend更新消息中的IV更新标志设置为1。此时,节点应使用当前的IV Index - 1进行传输,并处理来自当前IV Index - 1和当前IV Index的消息。例如,如果节点从正常操作转换到IV更新正在进行状态之前的IV Index为0x00101847,转换状态后,节点的 IV Update Flag置为1,IV Index为0x00101848,节点应该使用0x00101847来传输消息,接收并处理IV Index为0x00101847, IV Update Flag为1的消息和IV Index为0x00101848, IV Update Flag为0的消息。这也就意味着允许其他所有正常操作状态的节点可以使用旧的IV Index发送消息给当前节点,并且当前节点可以使用旧的IV Index发送消息给其他节点。
节点处于IV更新正在进行状态运行至少96小时并且未到达144小时之前,节点应在不改变IV Index的状态下切换回正常操作状态。在转换的时间点,节点将序列号重置为0x000000。例如,在转换回正常操作状态时,IV Update Flag应该为0,当前IV Index为0x00101848,节点应该使用0x00101848来传输消息,接收并处理IV Index为0x00101847, IV Update Flag为1的消息和IV Index为0x00101848, IV Update Flag为0的消息。这也就意味着允许当前节点可以发送消息给其他正常操作状态下及IV更新正在进行状态下的节点,也可以接收其他处于正常操作状态下及IV更新正在进行状态下的节点消息。
IV Update更新过程如下:
当节点发送分段访问消息或分段控制消息而未收到相应的分段确认消息时,节点应将从IV更新进行中状态切换到正常操作状态的过程推迟,直到收到分段确认消息或达到该消息传递的超时时间。这个要求是必要的,因为在完成IV Update过程后,序列号被重置为0x000000,并且SeqAuth值将无效。
当一个节点被添加到网络中时,该节点被赋予一个IV Index。如果节点在网络正常运行状态下加入网络,则节点至少应在正常运行状态下运行96小时。当网络处于IV更新进行中状态时,将节点添加到网络中,则该节点应被赋予新的IV Index值(更新后的),并正常运行至少96小时。
IV Index恢复过程
节点应支持IV Index恢复过程,因为长时间远离网络的节点可能会错过IV更新过程,从而无法与其他节点进行通信。为了恢复IV Index,节点必须侦听包含网络ID和当前IV Index的安全网络信标。当接收到一个主子网的安全网络信标,且其IV Index大于或等于当前已知的IV Index时,节点将根据该安全网络信标中的值设置当前的IV Index和当前的IV Update过程状态。在IV Index恢复过程更新了IV Index之后,在IV更新过程中定义的更改IV更新过程状态的96小时时间限制不再适用。
考虑到节点每10秒集体发送一次安全网络信标,低占空比节点在发送和接收mesh消息之前必须平均监听5秒才能恢复当前的IV Index。如果一个低功耗节点没有足够的电量来监听5秒,那么它必须通过每96小时至少轮询一次它的朋友节点来保持当前IV Index的最新状态。
节点在192小时内只能执行一次IV Index恢复过程。
如下,当两个节点无法通讯时,此时light设备的IV Index值为7 ,switch设备的值为8。light设备收到switch设备的网络安全信标(IV Update Flag为0)时,会进行IV Index恢复过程,忽略96小时限制,不进行 IV Index更新过程,直接将自身的IV Index值改为8之后,两个节点可以通讯。
IV Index更新测试模式
为了有效地测试IV更新过程,节点应支持与蓝牙认证过程相关的IV更新测试模式。测试模式的激活应在本地进行(通过硬件或软件接口)。IV Update测试模式只取消了96小时的限制;设备的所有其他行为应保持不变。
在IV更新测试模式下定义了两个信号:转换到IV更新进行中状态信号和转换到正常状态信号。忽略96小时限制,节点收到转换到IV更新进行中状态信号时,切换到IV更新进行中状态;节点收到转换到正常状态信号时,切换到正常状态。
基于Telink8258进行IV Index更新测试
使用两个设备测试IV Index更新过程,一个设备使用8258_mesh工程,一个设备使用8258_mesh_switch工程,两个工程打开IV_UPDATE_TEST_EN宏。打开后取消了96小时的限制,改为3分钟。测试时使用8258_mesh_switch工程的设备触发IV Index更新。
enum{IV_UPDATE_NORMAL= 0,IV_UPDATE_STEP1 = 1, // triggerIV_UPDATE_STEP2 = 2, // change to normal from update status // also need to keep 96 hours
};#define IV_UPDATE_START_SNO (0xC00000)
#if IV_UPDATE_TEST_EN
#define IV_UPDATE_KEEP_TMIE_MIN_S (3*60)// 3 minutes
#define IV_UPDATE_KEEP_TMIE_MIN_RX_S (3*60)// 3 minutes
#else
#define IV_UPDATE_KEEP_TMIE_MIN_S (96*3600)//(96*3600) // 96 hour
#define IV_UPDATE_KEEP_TMIE_MIN_RX_S (96*3600)//(96*3600) // 96 hour
#endif
switch工程按键触发IV Index更新函数:
void mesh_iv_update_test_initiate(u8 key_code)
{if(KEY_SW2 == key_code){ // dispatch just when you press the button if(IV_UPDATE_NORMAL == iv_idx_st.update_proc_flag){#if 1if(mesh_adv_tx_cmd_sno < IV_UPDATE_START_SNO){mesh_adv_tx_cmd_sno = IV_UPDATE_START_SNO;}LOG_MSG_LIB(TL_LOG_IV_UPDATE,(u8 *)&iv_idx_st, sizeof(iv_idx_st),"SW:trigger to step1 later,current iv is: ");#elsemesh_increase_ivi(iv_idx_st.cur);mesh_iv_update_set_start_flag(1); // should be keep search flag when trigger by self after power up.LOG_MSG_INFO(TL_LOG_IV_UPDATE,(u8 *)&iv_idx_st, sizeof(iv_idx_st),"SW:IV index enter step1: ");#endif}else{LOG_MSG_INFO(TL_LOG_IV_UPDATE,(u8 *)&iv_idx_st, sizeof(iv_idx_st),"IV is in step:%d! ",iv_idx_st.update_proc_flag);}cfg_led_event(LED_EVENT_FLASH_1HZ_1S);}if(KEY_SW1 == key_code){ // dispatch just when you press the button LOG_MSG_INFO(TL_LOG_IV_UPDATE,(u8 *)&iv_idx_st, sizeof(iv_idx_st),"printf IV:step:%d! ",iv_idx_st.update_proc_flag);}
}
使用Wireshark抓包,抓包过滤器为:
((pbadv)||(provisioning)||(btmesh)||(beacon)) && ((btle.advertising_address == a4:c1:38:a2:9f:32) || (btle.advertising_address == a4:c1:38:19:22:4b))
正常工作模式
测试时正常工作模式下 IV Index值均为8,更新后 IV Index的值为9,因此先添加好两组key值。
未触发IV Index更新时,seq值为27,两个设备的网络安全信标中IV Update Flag均为0,
switch设备正常工作模式:
light设备正常工作模式:
触发 IV Index更新
switch设备通过按键触发更新,进入step1:
此时switch设备发送mesh消息时使用的还是更新前的IV Index值,即为8(IVI值为0),seq值为12582912(0xC00000)。
light设备收到switch设备的beacon消息后进入step1:
IV Index更新进行中
此时两个设备的网络安全信标中的IV Index值均为9,同时IV Update Flag值均为1。
此时,switch设备发送的消息使用的还是更新前的IV Index值,即为8(IVI值为0),seq值为12582914(0xC00002)。
IV Index更新过程切换至保持状态
如果已经在IV Index更新进行中状态中一定时间(3分钟测试)后,转换为更新后保持状态step2,此时使用新的 IV Index传输,同时IV Update Flag值为0。
switch设备进入step2状态:
switch传输mesh消息时使用新的 IV Index,即为9(IVI值为1),同时seq值重新从0开始。
switch设备网络安全信标:
light设备进入step2状态:
light设备网络安全信标:
处于保持状态step2时,无法再次进入IV Index更新过程。
IV Index更新完成
在step2状态保持一定时间后,完成整个IV Index更新过程,恢复至step0状态。