任何一个出厂的mesh设备是一个未配网设备(Unprovisioned Device),需要使用配网者(Provisioner)对未配网设备进行配网,使其成为mesh网络中的一个节点。要使未配网设备成为一个节点,需要配网者为其分配一个NetKey(表示该设备属于哪一个子网),一个IV Index(表示该设备是有效的),一个Unicast Address(作为该节点的唯一标识)。配网的流程其实就是配网者如何安全有效不冲突地将这些数据下发给未配网设备。
1. 配网数据格式
配网有两种方式,一种是通过ADV广播的方式进行配网(PB-ADV),另一种是通过GATT连接的方式进行配网(PB-GATT)。
1.1. Unprovisioned Beacon
任意一个未配网设备上电后都会无限制地发送未配网Beacon(Unprovisioned Beacon),表明他期待配网者让他加入网络。未配网Beacon的数据格式如下:
Field | Size(octets) | Description |
Length | 1 | 表示后面数据的长度 |
AD Type | 1 | Mesh Beacon类型 |
Beacon Type | 1 | 0x00,表示当前Beacon类型为未配网Beacon |
Device UUID | 16 | 设备唯一标识符 |
OOB Information | 2 | 该设备支持的带外通信方式 |
URI Hash | 4 | URI的前4位,作为带外信息的Public Key,此域为可选项 |
未配网设备除了发送Unprovisioned Beacon外,还会广播一个单独的不可连接广播包,里面包含了Uniform Resource Identifier(URI),配网者可以使用这个URI值作为公钥与设备通信。Beacon中的URI hash字段表示应该使用哪个URI值,其中:
OOB Info域一共16个bit位,每个位代表的含义如下:
Bit | Description |
0 | Other |
1 | Electronic/URI |
2 | 2D machine-readable code |
3 | Bar code |
4 | Near Field Communication(NFC) |
5 | Number |
6 | String |
7 | RFU |
8 | RFU |
9 | RFU |
10 | RFU |
11 | On box |
12 | Inside box |
13 | On piece of paper |
14 | Inside manual |
15 | On device |
1.2. PB-GATT
手机端通过GATT连接的方式进行配网,数据通过proxy协议交互,Proxy PDU格式的Message Type设置为0x03,表示之后的Data域为Provisioning PDUs。
1.3. PB-ADV
通过ADV的方式进行配网,数据格式如下:
Field | Size(octets) | Description |
Length | 1 | 表示后面数据的长度 |
AD Type | 1 | PB-ADV类型 |
Link ID | 4 | 链路的标识符 |
Transaction Number | 1 | 事务的标识符 |
Generic Provisioning PDU | 1-24 | 配网PDU |
可以看到ADV配网PDU的最大长度仍为31字节。
每一条独立的配网PDU具有不同的Transaction Number,但是分段消息的不同分段具有相同的Transaction Number。
配网者发送的Provisioning PDU中的Transaction Number范围为0x00-0x7F。0x7F的下一个TN为0x00。
未配网设备发送的Provisioning PDU中的Transaction Number范围为0x80-0xFF。0xFF的下一个TN为0x80。
在PB-ADV中最后一个字段为Generic Provisioning PDU,其详细的数据格式如下:
Field | Size(octets) | Description |
Generic Provisioning Control | 1-17 | 配网数据控制域 |
Generic Provisioning Payload | 0-64 | 配网数据载荷 |
可以看出实际的Generic Provisioning PDU会大于24字节,因此这里会有分段的行为。
Generic Provisioning PDU共有四种形式:
① Transaction Start
表示开始传输分段消息,其数据格式如下:
Field | Size(bits) | Description |
SegN | 6 | 最后一个分段的分段号 |
GPCF | 2 | 0b00,表示这条消息为Transaction Start消息 |
TotalLength | 16 | Provisioning PDU的大小 |
FCS | 8 | Frame Check Sequence |
Data | Provisioning PDU的第一个分段 |
② Transaction Acknowledgment
用于响应Provisioning PDU消息,其数据格式如下:
Padding=0b000000,GPCF=0b01,Data域为空。
③ Transaction Continuation
表示传输分段消息附加段,其数据格式如下:
Field | Size(bits) | Description |
SegmentIndex | 6 | 当前分段的分段号 |
GPCF | 2 | 0b10,表示这条消息为Transaction Continuation消息 |
Data | Provisioning PDU的分段载荷 |
④ Transaction Bearer Control
用于管理承载层的会话,即建立配网者与未配网设备的通道,其数据格式如下:
Field | Size(bits) | Description |
BearerOpcode | 6 | 控制消息的操作码 0x00:Link Open 0x01:Link ACK 0x02:Link Close 0x03-0x3F:RFU |
GPCF | 2 | 0b11,表示这条消息为Transaction Bearer Control消息 |
Parameters | variable | Control消息的参数 |
Control消息有以下三种:
A. Link Open
配网者发起,要求与未配网设备建立一个链接,设备收到后需要响应一个Link Ack消息,一个设备只能同时处理一个Link(??),因此在Link存在期间,无视Link Open消息。其数据格式如下:
Device UUID为配网者选择的设备的UUID。
B. Link ACK
未配网设备收到配网者的Link Open消息后,响应的消息。数据格式如下:
C. Link Close
配网者和未配网设备都可发起,该消息至少发送三次,不需要ack。用于告知对端链路关闭,当前配网流程结束及配网的结果。
其数据格式如下:
参数域为关闭原因,其具体含义如下:
Reason Value | Reason | Notes |
0x00 | Success | 配网成功 |
0x01 | Timeout | 配网超时 |
0x02 | Fail | Control配网失败 |
0x03-0xFF | Unrecognized | 未定义的原因 |
1.4. Provisioning PDUs
PB-ADV通过Transaction Start/Acknowledgment/Continuation/Bearer Control来进行链路的建立和分段数据的发送,同样的功能PB-GATT使用Proxy协议来实现。两种方法的最终目的是为了传输Provisioning PDUs,来进行配网数据的交换。
Provisioning PDUs的消息格式如下:
Field | Size(bits) | Description |
Padding | 2 | 0b00 |
Type | 6 | Provisioning PDUs的类型 0x00:Provisioning Invite 0x01:Provisioning Capabilities 0x02:Provisioning Start 0x03:Provisioning Public Key 0x04:Provisioning Input Complete 0x05:Provisioning Confirmation 0x06:Provisioning Random 0x07:Provisioning Data 0x08:Provisioning Complete 0x09:Provisioning Failed 0x0A-0xFF:RFU |
Parameters | variable | Provisioning PDUs的消息参数 |
配网PDU根据功能不同分为以下几种类型。
① Provisioning Invite
配网者发起,表明配网程序开始。
参数Attention Duration为Attention Timer state,表示未配网设备收到后需要用多长的时间来表征自己。
其值含义如下:
Value | Description |
0x00 | Attention Timer关闭 |
0x01-0xFF | Timer开启的剩余时间,单位1s |
② Provisioning Capabilities
未配网设备发送此消息告诉配网者当前节点支持的配网功能。
Field | Size(octets) | Notes |
Number of Elenments | 1 | 当前设备有多少个元素,取值范围为0x01-0xFF。配网者可以通过此字段计算出下一个未配网设备的首元素地址 |
Algorithms | 2 | 支持的算法 |
Public Key Type | 1 | 支持的Public Key类型 |
Static OOB Type | 1 | 支持的Static OOB类型 |
Output OOB Size | 1 | 设备支持的最大Output OOB的长度 0x00:不支持output OOB 0x01-0x08:设备支持的最大Output OOB的长度 0x09-0xFF:RFU |
Output OOB Action | 2 | 设备支持的Output OOB的行为 |
Input OOB Size | 1 | 设备支持的最大Input OOB的长度 0x00:不支持Input OOB 0x01-0x08:设备支持的最大Input OOB的长度 0x09-0xFF:RFU |
Input OOB Action | 2 | 设备支持的Input OOB的行为 |
③ Provisioning Start
配网者发送此消息告诉未配网设备选择的配网方式。
Field | Size(octets) | Notes |
Algorithms | 1 | 使用的算法 0x00:使用FIPS P-256 Elliptic Curve 0x01-0xFF:RFU |
Public Key | 1 | 是否使用Public Key 0x00:不使用OOB Public Key 0x01:使用OOB Public Key 0x02-0xFF:无效值 |
Authentication Method | 1 | 授权方式选择 0x00:使用No OOB方式授权 0x01:使用Static OOB方式授权 0x02:使用Output OOB方式授权 0x03:使用Input OOB方式授权 0x04-0xFF:无效值 |
Authentication Action | 1 | 授权行为 若授权方式为No/Static OOB,Action=0x00。 若授权方式为Output OOB,取值含义如下: 0x00:Blink 0x01:Beep 0x02:Vibrate 0x03:Output Numeric 0x04:Output Alphanumeric 0x05-0xFF:RFU 若授权方式为Input OOB,取值含义如下: 0x00:Push 0x01:Twist 0x02:Input Numeric 0x03:Input Alphanumeric 0x04-0xFF:RFU |
Authentication Size | 1 | 授权码的长度 若授权方式为No/Static OOB,Size=0x00。 若授权方式为Output/Input OOB,取值含义如下: 0x00:无效 0x01-0x08:授权码长度 0x09-0xFF:RFU |
④ Provisioning Public Key
配网者发送此消息,传输Public Key。
⑤ Provisioning Input Complete
未配网设备发送此消息,表明Input操作完成,参数域为空。
⑥ Provisioning Confirmation
发送给对端的OOB授权码数据。
Output OOB方式:未配网设备展示授权码,配网者输入授权码,配网者响应Confirmation消息。
Input OOB方式:配网者展示授权码,未配网设备输入授权码,未配网设备响应Input Complete消息,然后配网者响应Confirmation消息。
⑦ Provisioning Random
发送给对端的随机值认证确认信息。
未配网设备收到配网者发送的Confirmation信息,然后响应Confirmation信息回配网者,此时配网者收到后发送Random消息,未配网设备收到后验证Confirmation信息,验证完毕后再响应Random消息回配网者,然后配网者也进行Confirmation的验证操作。
⑧ Provisioning Data
配网者传递给未配网设备的配网信息。
配网信息中Provisioning Data主要有以下信息:
Field | Size(Octets) | Notes |
Network Key | 16 | 配网者分配的NetKey |
Key Index | 2 | NetKey对应的Index值 |
Flags | 1 | 网络更新状态的标志位 Key Refresh Flag=0:表示当前网络处于Key Refresh Phase 0。 Key Refresh Flag=1:表示当前网络处于Key Refresh Phase 2。 IV Update Flag=0:表示当前网络未进行IV Update。 IV Update Flag=1:表示当前网络正在进行IV Update。 |
IV Index | 4 | 当前的IV Index值 |
Unicast Address | 2 | 配网者分配的首元素的单播地址 |
⑨ Provisioning Complete
未配网设备发送此消息表明配网成功。参数域为空。
⑩ Provisioning Failed
未配网设备发送此消息表明配网失败。参数域为失败原因。
Value | Name | Description |
0x00 | Prohibited | 无效值 |
0x01 | Invalid PDU | 配网的PDU不能识别 |
0x02 | Invalid Format | 数据设置为无效值 |
0x03 | Unexpected PDU | 配网流程中未收到期待的消息类型 |
0x04 | Confirmation Failed | 计算的确认值未通过验证 |
0x05 | Out of Resources | 设备资源不足 |
0x06 | Decryption Failed | 数据解密失败 |
0x07 | Unexpected Error | 未覆盖到的错误类型 |
0x08 | Cannot Assign Addresses | 连续的单播地址不能被分配 |
0x09-0xFF | RFU | Reserved for Future Use |
2. 配网流程
2.1 链路建立流程
PV-ADV在交换配网数据之前需要建立一个链接(Link),使用Transaction Bearer Control消息来建立链路。未配网设备发出的Unprovisioned Beacon里面包含了UUID等信息,配网者收到多个Unprovisioned Beacon后,需要选择一个设备,然后开始配网,选择了这个设备的第一件事就是建立链路。链路建立的流程如下:
① 配网者选择一个Unprovisioned Beacon,然后向该设备发送一个Link Open消息,该消息带有该设备的Device UUID,并在PB-ADV的Link ID字段填上一个未使用的ID值。
② 未配网设备收到Link Open消息后,需要响应一个Link ACK消息,其消息的Link ID字段为接收的Link Open的Link ID。
③ Link通道建立完成后,两者之间进行配网流程。
④ 配网结束发送Link Close关闭通道。
每一个Generic Provisioning PDU发送时都要附加20-50ms的延时。对于分段消息,发送端通过Transaction Start和Transaction Continuation发送所有分段,接收端收到所有分段后计算FCS,然后再响应Transaction Acknowledgment消息。
2.2 配网流程
未配网设备发送的Unprovisioned Beacon被配网者选中后,第一步是建立通道,通道建立完毕后便进行配网数据的分发。主要分为四个阶段,A、配网邀请,B、Public Key交换,C、OOB认证,D、配网数据分发。其流程示意图如下:
① Link通道链路建立完成后,配网者发送Provisioning Invite PDU,未配网设备收到后开启Attention Timer,可以是闪灯,震动或者声音来提醒配网者你配置的是这个设备,接着再响应Provisioning Capabilities PDU告诉配网者,这个设备支持的配网方式。
② 配网者发送Provisioning Start PDU告诉设备配网端选择的配网方式,未配网设备收到此消息后,需要停止Attention Timer。Provisioning Start PDU选择的方式有选择最优的算法,OOB方式等。然后进入第二阶段Public Key交换。
③ 若设备的能力中不能通过OOB的方式传输Public Key,即Public Key Type域为0x00,此时配网者发送Provision Public Key消息,设备端收到后响应Provision Public Key消息,使两端交换Public Key。
④ 若设备能通过OOB的方式传输Public Key,比如NFC等,则配网者通过OOB的方式将Public Key传输至未配网设备端。
⑤ 设备端收到Public Key后,两端计算值。接下来进入第三阶段OOB认证。
⑥ OOB认证有四种方式,当配网者选择No OOB认证的方式时,配网者发送Provisioning Confirmation消息,参数域为空,设备收到后响应Provisioning Confirmation消息,表示确认。
⑦ 当配网者选择Static OOB认证的方式时,配网者发送Provisioning Confirmation消息,参数域为Static授权数据,设备收到后响应Provisioning Confirmation消息,表示确认。
⑧ 当配网者选择Output OOB认证的方式时,收到Start PDU消息后,设备按照被选择的Output Action,做出相应的操作,比如闪灯,声音,震动,屏上显示数字或字符等,配网者将观察到的数据通过Provisioning Confirmation发送给未配网设备,设备收到并确认后响应Provisioning Confirmation消息。
⑨ 当配网者选择Input OOB认证的方式时,配网者发送完Start PDU后,在配网端显示授权信息,如屏幕显示数字或者字母等,设备端收到Start PDU后,弹框需要用户输入观察到的授权码,输入完毕后,通过Provisioning Input Complete消息发送给配网者告诉配网者这边输入完毕,配网者收到后发送Provisioning Confirmation发送给未配网设备,设备收到并确认后响应Provisioning Confirmation消息。
⑩ 配网者收到未配网设备响应的Provisioning Confirmation消息后,确认无误后,发送Provisioning Random消息,其参数域值为。
⑪ 设备端收到Random消息后,验证无误后,响应Provisioning Random消息,其参数域值为。
⑫ 配网者收到后验证random值的有效性。开始进入第四阶段,配网数据的的分发。配网者发送Provisioning Data PDU,包含设备需要的配网信息,其中的信息通过授权后的数据信息进行加密传输。
⑬ 设备收到数据后,响应Provisioning Complete消息,配网结束。
⑭ 若配网期间出现错误,发送Provisioning Failed消息给对端,配网结束。
⑮ 配网结束后,发送Link Close消息关闭链路。
ECDHSecret值计算如下:
ConfirmationProvisioner和ConfirmationDevice值计算如下:
其中:
2.3 总结
配网者的功能就是产生一个Network Key,提供给节点Network Key,IV Index,Unicast Address,使其从未配网状态变成一个可使用的Mesh设备。其中流程中的OOB授权等都只是为了保证配网数据的安全。配网成功后则需要配置客户端进行进一步的配置。一般来说配网者和配置客户端为同一个设备。配网者也有属于自己的Device Key,但是配网者的Device Key只是用来与其他配网者之间的通信加密。配网者的Device Key通过OOB的方式交换,所有配网者之间的交互所使用的Device key需要统一协调管理。