配网(Provisioning)是将未配网设备添加到mesh网络的过程,由配置器管理。 配网器为未配网设备提供配网数据(provisioning data),使其成为mesh节点。 供应数据包括网络密钥、当前IV索引和每个元素的单播地址。
配网器(Provisioner) 通常是智能手机或其他移动计算设备。 尽管网络上只需要一个配网器来进行配置,但可以使用多个配网器。 在多个配网器之间共享和协调缓存数据是需要特定的方法实现的。
要配置设备,必须在配网器和设备之间存在一个配网承载器。配网器可以通过设备的UUID和其他可能提供的补充信息来识别设备。
配网承载器建立后,配网器使用椭圆曲线 Diffie-Hellman (ECDH)协议与设备建立密钥。然后,它使用特定于该设备的 OOB 信息对设备进行身份验证。这种OOB信息可以包括设备的公钥、长密码、将值输入设备的要求或在该设备上输出值的要求。此类 OOB 信息还支持对该设备进行身份验证。一旦设备通过身份验证,配置数据就会被传输到使用从该共享密钥派生的密钥加密的设备。设备密钥派生自 ECDHSecret 和 ProvisioningSalt。

配网协议使用分层架构,如上图所示。设备的配网是使用配网协议发送配网 PDU 的完成的。配网PDU 使用通用配网层或代理协议层传输到未配网设备。这些层定义了如何将配网 PDU 作为可以分段和重组的指令进行传输。这些指令通过配网承载器发送。配网承载器定义了如何建立会话,以便可以将来自通用配网层的指令传送到某个设备。在配网协议架构的底部是承载器。
除非另有说明,否则该层中的所有多字节数值应为“大端”模式。
配网承载层
配网承载层支持在配网器和未配网设备之间传输配网 PDU。
蓝牙mesh规范定义了两种承载器:广播承载器(PB-ADV)和GATT承载器(PB-GATT)。
未配网设备至少支持
PB-ADV或PB-GATT之一。 但强烈建议同时支持PB-ADV和PB-GATT。配网器应至少支持
PB-ADV或PB-GATT之一。 强烈建议支持PB-ADV。
广播承载器(PB-ADV)
PB-ADV 是一种配网承载器,通过广播通道方式使用通用配网 PDU给设备配网。供网机制是基于会话的。未配网设备同一时间只能支持一个会话。配网器没有这样的限制。PB-ADV 承载器用于传输通用配网 PDU。PB-ADV 承载器的 MTU(最大传输单元)大小为 24 个字节。
当使用 PB-ADV 时,通用广播PDU应该使用PB-ADV广播类型进行发送,类型定义在«PB-ADV»。
支持 PB-ADV 的设备应以尽可能接近 100% 的占空比执行被动扫描,以避免丢失任何传入的 通用配网 PDU。
PB-ADV AD 类型包含一个 PB-ADV PDU。 该 AD 类型的格式在下表中定义。
| 字段 | 长度(字节) | 描述 |
|---|---|---|
| Length | 1 | Length of the AD Type and Contents |
| AD Type | 1 | «PB-ADV» |
| Contents | 变动 | PB-ADV PDU |
任何使用 PB-ADV AD 类型的广播都应是不可连接和不可扫描的非定向广播事件。如果节点在可连接或可扫描的广播数据中接收到 PB-ADV AD 类型,则应忽略该消息。
下表定义了 PB-ADV PDU 的格式
| 字段 | 长度(字节) | 描述 |
|---|---|---|
| Link ID | 4 | The identifier of a link |
| Transaction Number | 1 | The number for identifying a transaction |
| Generic Provisioning PDU | 1-24 | Generic Provisioning PDU being transferred |
Link ID 用于标识两个设备之间的链路。
Transaction Number 字段包含一个八位字节的值,用于标识设备发送的每个单独的 Generic Provisioning PDU。当一个配网PDU无法通过单个 PB-ADV PDU传输完时,配网PDU 会被分段,并且所有分段都使用相同的事务编号(Transaction Number)字段值发送。当一个供应 PDU 被重传时,事务编号字段不会改变。
定义传输特定消息以建立和终止两个设备之间的链接。
发送 PB-ADV PDU 时应执行以下规则:
当
PB-ADV PDU包含一个配网承载器控制 PDU 时,Transaction Number字段应设置为 0 并在接收时忽略。当配网器第一次通过开放的配网链路发送配网 PDU 时,它应该以
Transaction Number字段值 0x00 开始。对于在配网链接期间发送的每一个新的配网 PDU,配网器应将其Transaction Number字段值加一。如果该字段值已达到 0x7F,则在发送下一个配网 PDU 时应回到 0x00。当未配网设备第一次通过开放配网链路发送配网 PDU 时,它应以事务编号字段值 0x80 开始。 设备应在配网链路期间为它发送的每个新配网 PDU 将字段值加一。 如果该字段值已达到 0xFF,则在发送下一个配网 PDU 时应回到 0x80。
当一个设备正在接收一个配网 PDU时,它应该将
Transaction Number字段设置为在事务期间接收到的PB-ADV PDU的Transaction Number字段的值。当设备发送事务确认 PDU 时,事务编号字段应设置为传输时已被确认的配网 PDU 的
PB-ADV PDU的事务编号字段的值。
GATT承载器(PB-GATT)
PB-GATT 是一种配网承载器,用于给使用代理 PDU 的设备配网,以将配网 PDU 封装到 Mesh Provisioning Service 中。
由于应用程序接口的限制,当配网器不支持 PB-ADV 时,PB-GATT可以提供支持。
注意:建议配网器和设备之间的连接间隔在250到1000毫秒之间,以使设备能够以极低的功耗运行并允许设备计算Diffie-Hellman共享密钥而不会浪费维持空闲链路的大量能量。
Mesh Provisioning Server 应该能够在单个写命令 ATT PDU 中接收单个代理 PDU。
Mesh Provisioning Server 应使用单个 Handle 值通知 ATT PDU 将配网 PDU 发送到配网器。
如果协商的 ATT_MTU 小于所需的代理 PDU 大小,则 Mesh Provisioning Data In 和 Mesh Provisioning Out 特性的传输总是需要分段和重组。每个 PDU 应在处理前完成重新组装。
Mesh Provisioning Server 要能够在一个或多个 ATT PDU 中接收代理 PDU。
Mesh Provision Server 应根据消息的大小和协商的 ATT_MTU 使用一个或多个 Handle 值通知 ATT PDU 向 Provision Client 发送代理 PDU。
通用配网层(Generic Provisioning layer)
通用配网层负责通过不可靠的无连接配网承载器传输通用配网 PDU。 该层还定义了通用配网 PDU。
通用配网PDU(Generic Provisioning PDU) 格式由一个 Generic Provisioning Control (GPC) 字段和一个可变长度的 Generic Provisioning Payload 字段组成,如下图所示。

| 字段 | 长度(字节) | 描述 |
|---|---|---|
| Generic Provisioning Control | 1–17 | 通用配网控制字段 |
| Generic Provisioning Payload | 0–64 | 通用配网负载 (配网PDU的某一段) |
Generic Provisioning Control 字段的第一个八位字节的两个最低有效位包含一个 Generic Provisioning Control Format (GPCF) 字段,该字段确定 Generic Provisioning Control 字段的格式。GPCF 字段是一个枚举,其值如下表所示。
| 值(0b/二进制) | 描述 |
|---|---|
| 0b00 | 事务开始(Transaction Start ) |
| 0b01 | 事务确认 (Transaction Acknowledgment ) |
| 0b10 | 事务继续(Transaction Continuation) |
| 0b11 | 配网承载器控制(Provisioning Bearer Control) |
通用配网 PDU 类型
1.事务开始PDU (Transaction Start PDU )
Transaction Start PDU 用于启动分段消息的传输。 Transaction Start PDU 的 Generic Provisioning Control 字段如下图和下表所示。

各字段的解释如下:
| 字段 | 长度(bit位) | 描述 |
|---|---|---|
| SegN | 6 | The last segment number |
| GPCF | 2 | 0b00 = Transaction Start |
| TotalLength | 16 | Provisioning PDU 中的字节数 |
| FCS | 8 | Provisioning PDU的帧校验序列 |
SegN 字段应设置为该事务的最后一个段号(从零开始)。
GPCF 字段应设置为 0b00。
TotalLength 字段应设置为 Provisioning PDU 中的字节数。
当使用 PB-ADV 传输时,FCS 字段按照 3GPP TS 27.010 的多项式 (x8 + x2 + x1 + 1) 的定义进行计算,并且仅在 Provisioning PDU 上计算。
Generic Provisioning Payload 应包含 Provisioning PDU 的段 0。
2.事务确认PDU (Transaction Acknowledgment )
Transaction Acknowledgement PDU 用于确认 Provisioning PDU。 事务确认 PDU 的通用供应控制字段如下图 和下表所示。

| 字段 | 长度(bit位) | 描述 |
|---|---|---|
| Padding | 6 | 0b000000;所有其他值 禁止 |
| GPCF | 2 | 0b01 = Transaction Acknowledgment |
Generic Provisioning Payload 的长度为零。事务确认不包含任何负载,Data段为空。
3.事务继续PDU(Transaction Continuation)
Transaction Continuation PDU 用于发送Provisioning PDU 的附加段。 事务继续 PDU 的通用供应控制字段如下图和下表中显示。

| 字段 | 长度(bit位) | 描述 |
|---|---|---|
| SegmentIndex | 6 | 事务段号 |
| GPCF | 2 | 0b10 = Transaction Continuation |
Generic Provisioning Payload 应包含 Provisioning PDU 的 SegmentIndex。
4.配网承载器控制PDU(Provisioning Bearer Control)
配网承载器控制 PDU 用于管理没有固有会话管理的承载器上的会话。 配置承载控制 PDU 的通用配置控制字段在下图和下表中说明。 配网承载器控制 PDU 在以下部分中定义。

| 字段 | 长度(bit位) | 描述 |
|---|---|---|
| BearerOpcode | 6 | 配网承载器控制PDU操作码 |
| GPCF | 2 | 0b11 = Provisioning Bearer Control |
| Parameters | 可变的 | 每个 BearerOpcode 定义的参数 |
BearerOpcode 定义的参数如下表
| 值 | 消息 | 描述 |
|---|---|---|
| 0x00 | Link Open | 建立一个承载器与设备之间的会话 |
| 0x01 | Link ACK | 确定承载器的会话 |
| 0x02 | Link Close | 关掉承载器的会话 |
| 0x03–0x3F | 保留(RFU) | 保留,供以后使用 |
Generic Provisioning Payload 的长度为零。
每条消息的参数在以下部分中定义。
4.1链接开启消息(Link Open message)
Link Open 消息用于在配网器 和未配网设备之间建立链接。 设备应使用 Link ACK 消息确认该消息。

Device UUID:16字节,这是所选未配网设备的设备 UUID。
4.2链接确认消息(Link ACK)
发送 Link Ack 消息以确认收到 Link Open 消息。 此消息没有参数。

4.3链接关闭消息(Link Close)
Link Close消息用于关闭链接。 如果此消息未被确认,发送者应至少重复此消息 3 次。 链接的双方都可能发送此消息。 无论Reason字段的设置如何,都应接受和处理该消息。

Reason:1字节,描述关闭链接的原因。
Reason字段的定义如下:
| 值 | 原因 | 说明 |
|---|---|---|
| 0x00 | Success | 配网成功 |
| 0x01 | Timeout | 配网事务超时 |
| 0x02 | Fail | 配网失败 |
| 0x03–0xFF | Unrecognized | 保留值,无法识别 |
链接建立过程
链路建立过程(Link Establishment procedure)用于为没有固有会话管理的承载器建立会话。 会话通过链路 ID 来标识,链路 ID在会话期间是不变的,并且链路 ID是随机生成以防止会话之间的冲突。
在配网器和未配网设备之间建立链接,用于发送配网消息。 未配网的设备由设备 UUID 标识。
配网器应扫描未配网设备。在收到未配网设备信标后,配网器可以通过设备UUID与设备建立一个链接。
当设备为 Link Open 消息发送 Link ACK 时,该链路对设备打开。 当接收到 Link ACK的 Link ID 与 Link Open 消息中发送的 Link ID 相同时,该 Link 对 Provisioner 开放。 当链路打开并且设备已收到任何 Provisioning PDU 时,设备正在被配网。
当链路未打开,并且设备接收到 Link Open 消息时,设备应通过使用与 PB-ADV PDU 中设置的相同 Link ID 的 Link ACK 消息来回复此消息。
当链路打开且设备未在配网,并且设备接收到具有相同 Link ID 的 Link Open 消息时,设备应通过使用与 PB-ADV PDU 中设置具有相同 Link ID 的 Link ACK 消息进行回复。
当链接打开时,设备应启动链接计时器,设置为 60 秒。 当链接定时器到期时,设备将关闭链接。 当设备收到任何 Provisioning PDU 或 Link Close 消息时,设备应取消链接定时器。
要打开链接,Provisioner 应启动链接建立计时器,设置为 60 秒,然后开始发送 Link Open 消息。 配网器可以随时中止这个过程。 Link Open 消息包含设备的设备 UUID。 在广播承载器 PB-ADV 上,PB-ADV PDU 格式包括一个 Link ID 字段。

通用配网行为
每个通用配网 PDU 应在 20 到 50 毫秒之间的随机延迟后发送。每个 Provisioning PDU 作为单独的事务传输。 一个事务可能由一个或多个段组成。
发送Provisioning PDU 所需的段数由Provisioning PDU 的大小决定。 段的索引从 0 到 63。段 0 应使用事务开始(Transaction Start) PDU 发送。 所有其他段应使用事务继续(Transaction Continuation) PDU 发送。
配网PDU的段号放在通用配网PDU的负载字段中。每个承载器在传输通用配网 PDU时,都有它自己的MTU长度限制。每个通用配网 PDU都应该以最大长度进行传输,事务的最后一段除外。
发送方应按顺序发送事务的所有段。 如果发送方没有收到事务确认(Transaction Acknowledgment)消息,发送方应重新发送事务的所有段。
如果发送方收到事务确认消息,则事务处理完成。
如果发送方收到其他 PDU 类型的消息,则该消息应被忽略。
如果发送方在发送事务中的第一条消息后 30 秒内未收到事务确认消息,则发送方应取消这个事务,取消配置过程并关闭链接。
接收方应根据事务开始 PDU 确定事务的段数。
在 PB-ADV 承载器上,当接收方收到一个事务的所有段时,接收方应对接收到的 Provisioning PDU 计算 FCS,如果与 Transaction Start PDU 中的 FCS 字段匹配,则在 20 到 50 毫秒之间的随机延迟之后,发送 Transaction Acknowledgement PDU 。
当一个给定事务的事务确认 PDU 已被发送并且已接收到同一事务的另一个段时,应发送另一个事务确认 PDU,并且应忽略接收到的段。
注释:当事务确认 PDU已发送 ,说明已经处理了该事务的所有消息,如果再收到这个事务的消息,说明是已经处理过的消息,自然应该忽略。发送了事务确认PDU,发送方依然在发送事务消息,说明发送方没有收到确认,在进行重发操作,所以发送另外一个事务确认PDU,再告诉发送方进行事务确认。
配网协议
本节定义了对配网 PDU、行为和安全性的要求。
配网PDU(Provisioning PDUs)
Provisioning PDU 用于在 Provisioner 和设备之间进行通信。
Provisioning PDU 的第一个字节是 Type 字段,定义了 Provisioning PDU 的参数格式。
Provisioning PDU 格式定义定义如下:

| 字段 | 长度(bit位) | 描述 |
|---|---|---|
| Padding | 6 | 0b00. 其他值是禁止的 |
| Type | 2 | 配网PDU类型值(0x03) |
| Parameters | 可变的 | 消息参数 |
配网消息均是以03开头,表示该消息是配网协议消息。
Parameters字段各值的含义如下:
| 类型 | 名称 | 描述 |
|---|---|---|
| 0x00 | Provisioning Invite | 邀请设备加入mesh网络 |
| 0x01 | Provisioning Capabilities | 表示设备的配网能力 |
| 0x02 | Provisioning Start | 表示配网器根据设备能力选择的配网方式(ECDH) |
| 0x03 | Provisioning Public Key | 包含设备或配网器的公钥(两端都要发) |
| 0x04 | Provisioning Input Complete | 表示用户已完成输入值 |
| 0x05 | Provisioning Confirmation | 包含设备或配网器的配网确认值 |
| 0x06 | Provisioning Random | 包含设备或配网器的配网随机值 |
| 0x07 | Provisioning Data | 包括分配的主元素单播地址,网络密钥及索引, 标志和IV索引 |
| 0x08 | Provisioning Complete | 表示配网完成 |
| 0x09 | Provisioning Failed | 表示配网失败 |
| 0x0A–0xFF | RFU | 保留供将来使用 |
配网邀请(Provisioning Invite)
配网器发送此 PDU 以向设备指示配网过程正式开始。 该 PDU 的参数格式如下。
Attention Duration :1字节,提示时间定时器状态(Attention Timer state)。
配网能力(Provisioning Capabilities)
设备发送此 PDU 以向 Provisioner 指示其支持的配置能力。配网能力PDU参数格式如下:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Number of Elements | 1 | 设备支持的元素个数 |
| Algorithms | 2 | 支持的算法和其他功能 |
| Public Key Type | 1 | 支持的公钥类型 |
| Static OOB Type | 1 | 支持的静态 OOB 类型 |
| Output OOB Size | 1 | 支持的最大输出 OOB 大小 |
| Output OOB Action | 2 | 支持的输出 OOB 操作 |
| Input OOB Size | 1 | 支持的输入 OOB 的最大字节大小 |
| Input OOB Action | 2 | 支持的输入 OOB 操作 |
元素个数字段值范围:0x01–0xFF;0x00是禁止的。
支持的算法:FIPS P-256 椭圆曲线。目前仅支持这一种。设备应至少支持一种算法。
支持的公钥类型:仅支持0,代表可用的公钥 OOB 信息。公钥 OOB 信息的大小由所选算法确定。
支持的静态 OOB 类型:仅支持0,代表可用的静态 OOB 信息。
静态 OOB 信息的最大大小为 16 个字节。
- 当在 Output OOB Action 字段中设置了输出数字并且未设置输出字母时,Output OOB Size 定义了可以输出的位数(例如,屏显示或喇叭说出)。
- 当在 Output OOB Action 字段中未设置输出数字并且设置了输出字母时,Output OOB Size 定义了可以输出的数字和大写字母的数量。
- 当在 Output OOB Action 字段中设置了输出数字并且设置了输出字母时,Output OOB Size 定义了可以输出的数字和大写字母的数量。
Output OOB Size的值定义如下:
| 值 | 描述 |
|---|---|
| 0x00 | 设备不支持输出OOB |
| 0x01–0x08 | 设备支持的最大输出 OOB 大小 |
| 0x09–0xFF | 保留供以后使用 |
Output OOB Action的值定义如下:
| 位 | 描述 | 数据类型 |
|---|---|---|
| 0 | Blink(眨眼) | 数字 |
| 1 | Beep(哔哔的声音) | 数字 |
| 2 | Vibrate(震动) | 数字 |
| 3 | Output Numeric(输出数字) | 数字 |
| 4 | Output Alphanumeric(输出字母) | 字母 |
| 5-15 | 保留供以后使用 | 保留供以后使用 |
- 当在 Input OOB Action 字段中设置了 Input Numeric 值且未设置 Input Alphanumeric 时,Input OOB Size 定义了可以输入的位数。
- 当在 Input OOB Action 字段中未设置 Input Numeric 值且设置了 Input Alphanumeric 时,Input OOB Size 定义了可以输入的数字和大写字母的数量。
- 当在 Input OOB Action 字段中设置了 Input Numeric 值且设置了 Input Alphanumeric 时,Input OOB Size 定义了可以输入的数字和大写字母的数量。
Input OOB Size字段定义如下:
| 值 | 描述 |
|---|---|
| 0x00 | 该设备不支持输入OOB |
| 0x01–0x08 | 设备支持的最大输入 OOB 大小 |
| 0x09–0xFF | 保留供将来使用 |
Input OOB Actions定义如下
| 位 | 描述 | 数据类型 |
|---|---|---|
| 0 | Push(按) | 数字 |
| 1 | Twist(旋转) | 数字 |
| 2 | Input Numeric | 数字 |
| 3 | Input Alphanumeric | 字母 |
| 4-15 | 保留供将来使用 | 保留供将来使用 |
配网开始(Provisioning Start)
配网器发送此 PDU 以指示它从 Provisioning Capabilities PDU 中选择的配网方式。 该 PDU 的参数格式定义如下。
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Algorithm | 1 | 用于配网的算法 |
| Public Key | 1 | 使用的公钥 |
| Authentication Method | 1 | 使用的认证方法 |
| Authentication Action | 1 | 选择的Output OOB Action或Input OOB Action或 0x00 |
| Authentication Size | 1 | 使用的Output OOB 的大小或Input OOB 的大小或 0x00 |
算法(Algorithm)值的定义:0x00,FIPS P-256 椭圆曲线;0x01–0xFF,保留供以后使用。
公钥值的定义:
| 值 | 描述 |
|---|---|
| 0x00 | 未使用 OOB 公钥 |
| 0x01 | 使用 OOB 公钥 |
| 0x02–0xFF | 禁止 |
认证方法值定义如下:
| 值 | 描述 |
|---|---|
| 0x00 | 未使用 OOB 身份验证 |
| 0x01 | 使用静态 OOB 身份验证 |
| 0x02 | 使用输出 OOB 身份验证 |
| 0x03 | 使用输入 OOB 身份认证 |
| 0x04–0xFF | 禁止 |
当认证方法
Authentication Method使用0x00 (Authentication with No OOB) 方法时,Authentication Action字段应设置为 0x00,Authentication Size字段应设置为 0x00。当使用认证方法 0x01(静态 OOB 认证)方法时,认证大小应设置为 0x00,认证操作字段应设置为 0x00。
当使用认证方法 0x02(Output OOB Authentication)时,应使用下表中定义的值来确定认证动作(
Authentication Action)和认证大小(Authentication Size)。
认证方法采用Output OOB Action时,Authentication Action字段的值在下表中定义。
| 值 | 描述 |
|---|---|
| 0x00 | Blink(眨眼) |
| 0x01 | Beep(哔哔的声音) |
| 0x02 | Vibrate(震动) |
| 0x03 | Output Numeric(输出数字) |
| 0x04 | Output Alphanumeric(输出字母) |
| 0x05–0xFF | 保留供将来使用 |
认证方法采用Output OOB Action时,Authentication Size字段的值在下表中定义。
| 值 | 描述 |
|---|---|
| 0x00 | 禁止 |
| 0x01–0x08 | 要使用的 Output OOB Size |
| 0x09–0xFF | 保留供将来使用 |
- 当使用认证方法 0x03(Input OOB Authentication)时,应使用下表中定义的值来确定认证动作(
Authentication Action)和认证大小(Authentication Size)。
认证方法采用Input OOB Action时,Authentication Action字段的值在下表中定义。
| 值 | 描述 |
|---|---|
| 0x00 | Push(按) |
| 0x01 | Twist(旋转) |
| 0x02 | Input Numeric(输入数字) |
| 0x03 | Input Alphanumeric(输入字母) |
| 0x04–0xFF | 保留供将来使用 |
认证方法采用Input OOB Action时,Authentication Size字段的值在下表中定义。
| 值 | 描述 |
|---|---|
| 0x00 | 禁止 |
| 0x01–0x08 | 要使用的输入 OOB 大小 |
| 0x09–0xFF | 保留供将来使用 |
配置公钥(Provisioning Public Key)
配网器发送此 PDU 以传递要在 ECDH 计算中使用的公钥。 该 PDU 的参数格式在下表中定义。
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Public Key X | 32 | FIPS P-256 算法的公钥的 X 组件 |
| Public Key Y | 32 | FIPS P-256 算法的公钥的 Y 组件 |
配网输入数据完成(Provisioning Input Complete)
当用户完成输入操作时,设备会发送此 PDU。此 PDU 没有参数。
配网确认(Provisioning Confirmation)
配网器或者设备将此PDU发送给对方,以确认到目前为止交换的值,包括 OOB Authentication 值和尚未交换的随机数。
Confirmation字段:16字节,到目前为止交换的值,包括 OOB 身份验证值
配网随机数(Provisioning Random)
配网器或者设备将此PDU发送给对方,以判断确认(Confirmation)是否有效。
Random字段:16字节,确认(confirmation)的最终输入。
配网数据(Provisioning Data)
配网器发送此PDU将配网数据发送到设备。
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Encrypted Provisioning Data | 25 | 网络密钥、NetKey 索引、密钥刷新标志、IV 更新标志、IV 索引的当前值和主元素的单播地址 |
| Provisioning Data MIC | 8 | PDU 完整性校验值 |
配网完成(Provisioning Complete)
设备发送此 PDU 以表明它已成功接收并处理了配网数据。此 PDU 没有参数。
配网失败(Provisioning Failed)
如果设备未能处理接收到的供应协议 PDU,则设备发送此 PDU。
Error Code:1字节,设备遇到的配网协议中的特定错误。
| 值 | 名称 | 描述 |
|---|---|---|
| 0x00 | Prohibited | 禁止 |
| 0x01 | Invalid PDU | 设备无法识别配网协议 PDU |
| 0x02 | Invalid Format | 协议 PDU 的参数超出预期值或 PDU 的长度与预期不同 |
| 0x03 | Unexpected PDU | 当前配网步骤中不期望收到的 PDU |
| 0x04 | Confirmation Failed | 计算的确认值未成功验证 |
| 0x05 | Out of Resources | 由于设备资源不足,无法继续配网协议 |
| 0x06 | Decryption Failed | 数据块未成功解密 |
| 0x07 | Unexpected Error | 发生了可能无法恢复的意外错误 |
| 0x08 | Cannot AssignAddresses | 设备无法为所有元素分配连续的单播地址 |
| 0x09–0xFF | RFU | 保留供将来使用 |
配网行为(Provisioning behavior)
配网使用五个步骤执行:信标、邀请、交换公钥、身份验证和供应数据的分发。

信标阶段(Beaconing)
支持 PB-ADV、尚未配网且不在配网过程中的设备应广播未配置设备信标。当设备尚未被配置时,建议使用匿名广告、不可解析的私有地址或可解析的私有地址。 该信标可以指示 OOB 数据的可用性,允许配网器在下一步之前提示用户收集该 OOB 数据。
邀请阶段(Invitation)
在建立配网承载器后,配网器应该发送配网邀请PDU,设备在收到配网邀请PDU后,要回复配网能力PDU进行响应。配网邀请PDU包含一个Attention Duration字段,用于确定设备主元素使用Attention计时器识别自己的配网时间。如果配网配网承载器被丢弃,则设备应将主元素的Attention定时器状态设置为 0x00(关闭)。配网能力 PDU 包括设备支持的元素数量、支持的安全算法集、使用 OOB 技术的公钥的可用性、设备向用户输出值的能力、 该设备允许用户输入值的能力,并且该设备是否具有可用于身份验证的 OOB 数据块。

交换公钥阶段(Exchanging public keys)
根据未配网设备公钥的可用性,此步骤在配网器端有两种可能性。结合身份验证步骤的三种可能性,有六种可能的交换/身份验证路径。
一旦配网器确定了使用六种路径中的哪一种来给设备配网,配网器将发送一个配网开始PDU。
在收到来自配网器的配网开始(Provisioning Start) PDU 后,设备应将 Attention Timer 设置为 0x00。
配网器应从新设备在配网能力 PDU 中提供给它的算法中选择一个算法。如果配网器无法识别PDU中算法字段位代表的含义,则应忽略该位并仅从其支持的算法中进行选择。配网器应该选健壮性最强的算法。如果使用 OOB 技术无法获得公钥,则在配网器和未配网设备之间交换公钥。对于每次交换,配网器和未配网的设备都应生成一个新的密钥对。
如果OOB技术未传输密钥 ,则设备应发送其公钥。
当未配网设备的公钥未知时,公钥交换的消息序列如下图所示。

另外,如果公钥是通过OOB机制获得的,则配网器将生成一个新的密钥对,密钥对的公钥应该由配网器发送给设备,并使用适当的 OOB 技术从设备中读取静态公钥。
当未配网设备的公钥为 OOB 时,公钥交换的消息序列如下图所示。

<img src="https://upload-images.jianshu.io/upload_images/1520118-c496b8454cc0e805.png" alt="OOB技术获取公钥" style="zoom:30%;" />
配网器和设备应该相互检查对方提供的公钥或者OOB获取的公钥是否有效。当配网器或者设备收到无效的公钥,配网失败。
在已知公钥并经过验证后,(ECDHSecret) 应使用以下公式计算:
ECDHSecret = P-256(私钥,对方公钥)
计算完 ECDHSecret 后,配网器和未配网的设备将删除其在此步骤中生成的私钥-公钥对。
身份认证阶段(Authentication)
如果使用Output OOB authentication(输出 OOB 身份验证),则设备在收到配网器的Provisioning Start PDU后,作出响应,将使用某种方式在设备上输出单个数字或多个数字值。 输出动作的示例可以包括发出噪音、闪烁灯光、发出声音或在显示器上显示符号。
例如,如果设备是包含 LED 的门锁,则可以让该 LED 闪烁的方式使用Output OOB authentication(输出 OOB 身份验证)。
- 当使用 Authentication Method 0x02(Authentication with Output OOB)并且当 Authentication Action 的 Output OOB Action 值等于 Blink、Beep 或 Vibrate 时,设备应选择一个介于 0 和 10 之间的随机整数,即身份验证大小专有。该随机数应作为事件序列输出(例如,通过闪烁、哔哔声或以 500 毫秒开启和 500 毫秒关闭的占空比振动),序列之间的间隔至少为 3 秒,以允许用户确定序列的结尾。
- 当 Authentication Action 的 Output OOB Action 值等于 Output Numeric 时,使用由 Authentication Size 值确定的多个数字(即 ASCII 字符代码 0x30-0x39)输出(例如,显示或说出)该值。
- 当 Authentication Action 的 Output OOB Action 值等于 Output Alphanumeric 时,则使用由 Authentication Size 值确定的多个 ASCII 数字和大写字母(即 ASCII 字符代码 0x30-0x39 和 0x41-0x5A)输出该值。
配网操作者应该输入观察到的数字来验证该设备。
一旦输入了数字,就会进行确认交换,然后进行随机数字交换。 确认值是当前为止交换的所有值的加密哈希、尚未公开的随机数和输入的数字。 一旦交换了随机数,每个设备就可以验证对方。
来自输出 OOB、输入 OOB 或静态 OOB 的验证值在 AuthValue 中用于计算确认值,如下所述。
配网器的确认(confirmation)值通过以下方式计算:
设备的确认值通过以下方式计算:
其中:
ConfirmationKey = k1(ECDHSecret, ConfirmationSalt, “prck”)
ConfirmationSalt = s1(ConfirmationInputs)
ConfirmationInputs = ProvisioningInvitePDUValue || ProvisioningCapabilitiesPDUValue || ProvisioningStartPDUValue || PublicKeyProvisioner || PublicKeyDevice
ProvisioningInvitePDUValue 是发送或接收的 Provisioning Invite PDU 字段(不包括操作码)的值。
ProvisioningCapabilitiesPDUValue 是已发送或接收的 Provisioning Capabilities PDU 字段(不包括操作码)的值。
ProvisioningStartPDUValue 是已发送或接收的 Provisioning Start PDU 字段(不包括操作码)的值。
PublicKeyProvisioner 是由 Provisioner 发送的 Public Key PDU 中的 Public Key X 和 Public Key Y 字段的值。
PublicKeyDevice 是来自设备发送的公钥 PDU 或交付的 OOB 公钥的公钥 X 和公钥 Y 字段的值。
RandomProvisioner 是由 Provisioner 的随机数生成器生成的一串随机位。
RandomDevice 是由设备的随机数生成器生成的一串随机位。
AuthValue 是一个 128 位的值。 AuthValue 的计算取决于所使用的输出 OOB 操作、输入 OOB 操作或静态 OOB 类型的数据类型。
如果数据类型是二进制,则 AuthValue 是一个字节数组。 如果该值小于 128 位,则其余位应设置为 0。
例如,如果值为 [0x12, 0x34, 0x56],则 AuthValue 是一个由 [0x12, 0x34, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00]。
如果数据类型是 Numeric,则该数字应表示为无符号的 128 位值。
如果数据类型是字母数字,则 AuthValue 应该是字符的 ASCII 代码的串联。
例如,如果Authentication是 Output OOB 方法与 Output OOB Action 中的 Blink 一起使用,并且输出值为 5,则 AuthValue 应为 0x000000000000000000000000000000005。 然后按照
大端定义对 AuthValue 进行编码,以计算确认值,从而生成一个由 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00、0x00、0x05]。例如,如果 Authentication 是 Output OOB 方法与 Output OOB Action 中的 Display Number 一起使用,并且显示的数字为 019655,则 AuthValue 应为 0x00000000000000000000000000004CC7。然后按照
大端定义对 AuthValue 进行编码,以计算确认值,从而生成一个由 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00、0x4C、0xC7]。例如,如果 Authentication 是 Output OOB 方法与 Output OOB Action 中的 Display String 一起使用,并且显示的字符串是“123ABC”,则 AuthValue 应为 0x313233414243000000000000000000000,从而得到一个由 [0x31, 0x32, 0x33, 0x41, 0x42、0x43、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00]。
例如,如果使用 Authentication 是 No OOB 方法,则 AuthValue 应设置为 0x00000000000000000000000000000000,表示未通过身份验证,导致数组由 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]。
配网器在收到 Provisioning Confirmation PDU 后应发送 Provisioning Random PDU。 设备应在根据收到的随机数验证确认值后发送 Provisioning Random。
使用 Output OOB 进行身份验证的消息时序图如下所示。

当使用的 Authentication Method是 0x03 (Authentication with Input OOB) 方法并且
- 当 Authentication Action 的 Input OOB Action 值等于 Push 时,配网器应选择 0 到 10 的 Authentication Size 的幂次方之间的随机整数。该随机数应按按压动作的数量输入。
- 当 Authentication Action 的 Input OOB Action 值等于 Twist 时,配网器应选择 0 到 10 的 Authentication Size 次方的随机整数。该随机数应输入扭转动作的次数,直到输入控件上的值。
- 当 Authentication Action 的 Input OOB Action 值等于 Input Numeric 时,通过输入由 Authentication Size 值确定的多个数字(可能使用数字键盘)来输入该值。
- 当 Authentication Action 的 Input OOB Action 值等于 Input Alphanumeric 时,通过输入由 Authentication Size 值确定的多个 ASCII 数字和大写字母(可能使用字母数字键盘)来输入该值。
当 Authentication Action 的 Input OOB Action 值等于 Push 或 Twist 时,超过 5 秒没有检测到进一步的输入动作后,该值被认为已输入。当 Authentication Action 值的 Input OOB Action 等于 Input Numeric 或 Input Alphanumeric 时,该值被认为是在该设备上本地输入的(例如,通过按下 Enter 键)。
例如,灯开关可以允许用户通过按适当次数的按钮来输入随机数。
一旦执行了数字输入,设备将向配网器发送 Provisioning Input Complete PDU 以确认设备具有输入值。执行确认交换,然后执行随机数交换。确认值是当前为止交换的所有值的加密哈希、尚未公开的随机数和已输入的数字。一旦交换了随机数,每个设备就可以验证对方。
使用 Input OOB 进行身份验证的消息时序图如下所示。

如果使用static OOB 身份验证,或者 No OOB 身份验证,则配网器应使用确认和随机数交换。如果静态 OOB 值可用,则该值应包含在确认值中。 如果没有可用的静态 OOB 值,则该值应为零。
使用静态 OOB 或无 OOB 进行身份验证的消息时序图如下所示。

分发配网数据(Distribution of provisioning data)
一旦设备通过身份验证,配网器和设备将使用计算出的 Diffie-Hellman 共享密钥 ECDHSecret ,并从该共享密钥生成会话密钥。 然后,该会话密钥将用于加密和验证配网数据。 然后,配网器应向设备发送包含加密和验证的配网数据的 Provisioning Data PDU。
配网数据格式如下表定义:
| 字段 | 长度(字节) | 注释 |
|---|---|---|
| Network Key | 16 | NetKey |
| Key Index | 2 | Index of the NetKey |
| Flags | 1 | Flags bitmask |
| IV Index | 4 | Current value of the IV Index |
| Unicast Address | 2 | Unicast address of the primary element |
网络密钥Network Key应包含网络密钥NetKey。
Key Index字段应标识 Network Key 的全局 NetKey Index。
Flags字段定义如下:
| Bit位 | 定义 |
|---|---|
| 0 | Key Refresh Flag 0: Key Refresh Phase 0 1: Key Refresh Phase 2 |
| 1 | IV Update Flag 0: Normal operation 1: IV Update active |
| 2-7 | 保留供将来使用 |
IV 索引字段应包含网络中当前的 IV 索引值。
Unicast Address应包含被添加到网络的节点的主要元素的单播地址。
Session key 应使用以下公式得出:
ProvisioningSalt = s1(ConfirmationSalt || RandomProvisioner || RandomDevice)
SessionKey = k1(ECDHSecret, ProvisioningSalt, “prsk”)
nonce应该是最低13个字节
SessionNonce = k1(ECDHSecret, ProvisioningSalt, “prsn”)
配网数据应该使用下面公司加密和验证
Provisioning Data = Network Key || Key Index || Flags || IV Index || Unicast Address
Encrypted Provisioning Data, Provisioning Data MIC = AES-CCM (SessionKey, SessionNonce, Provisioning Data)
配网数据的MIC值长度是8字节。
加密的配网数据和配网数据 MIC应用作Provisioning Data PDU 中的字段。配网器应将Provisioning Data PDU 发送到设备。
设备应该计算 device key。
分发配网数据的流程如下图:

配网器和设备根据已建立的 Diffie-Hellman 共享密钥 ECDHSecret 使用 k1 密钥推导函数计算设备密钥。
在接收到来自配网器的 Provisioning Data PDU 后,设备应解密和验证配网数据。 在成功验证配网数据后,设备应设置网络密钥(由密钥索引标识),设置 IV 索引,根据 IV 更新标志设置 IV 更新过程状态,根据密钥刷新标志设置密钥刷新阶段 ,并使用从网络中得到的单播地址值的连续地址范围,将单播地址分配给从主元素开始的所有设备元素。成功完成地址分配过程后,设备应以 Provisioning Complete PDU 进行响应,以确认其已被配网。 如果地址分配无法成功完成,则设备应假定配置失败,并以错误代码参数设置为无法分配地址的 Provisioning Failed PDU 进行响应。
在处理来自配网器的
Provisioning Data PDU之后,在 IV 更新过程中定义的用于更改 IV 更新过程状态的 96 小时时间限制不适用。
在接收到来自设备的 Provisioning Complete PDU 后,配网器应假定配网过程已成功完成,并且设备正在使用从单播地址的值开始的连续地址范围。地址范围的长度在 Provisioning Capabilities PDU 中报告给配网器。
作为程序的最后一步,配网器应断开配网承载器。 该设备现在是网状网络中的一个节点。
配网器不得重复使用已分配给设备的单播地址,并在 Provisioning Data PDU 中发送单播地址,直到配网器从同一设备 收到 Unprovisioned Device 信标 或 收到来自Mesh Provisioning Service 的标识设备用的Device UUID服务数据 。
配网安全性(Provisioning security)
所有设备和配网器都应支持 FIPS P-256 椭圆曲线算法。
配网可能是安全的或不安全的。安全配网需要以下方法:
- FIPS P-256 椭圆曲线算法,不带内传输的公钥类型(即选择“使用 OOB 公钥”),以及任意大小的静态 OOB。
- FIPS P-256 椭圆曲线算法; 输入数字、输入字母数字、输出数字或输出字母数字的 OOB 操作; 和 OOB 大小至少为 6 个字节。
建议设备和配网器支持 安全配网(Secure Provisioning)。 配网器可能仅支持安全配网来配置设备。 不支持安全配网的设备将无法由仅支持安全配网的配网器进行配网。
FIPS P-256 椭圆曲线定义
椭圆曲线由 p、a 和 b 指定,形式为:
对于 b 的每个值,可以开发出一条唯一的曲线。 在 NIST P-256 中:
b 已定义,其生成方法可以使用 SHA-1 验证。使用给定的种子 s 并使用
给出以下参数:
- 素数模p,阶r,基点x-坐标Gx,基点y-坐标Gy。
- 整数 p 和 r 以十进制形式给出; 位串和字段元素以十六进制给出。
p = 115792089210356248762697446949407573530086143415290314195533631308867097853951
r = 115792089210356248762697446949407573529996955224135760342422259061068512044369
b = 5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b
Gx = 6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296
Gy = 4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5
函数 P-256 定义如下。 给定一个整数 u,0 < u < r,以及曲线 E 上的一个点 V,值 P-256(u, V) 被计算为点 V 的第 u 个倍数 uV 的 x 坐标。
私钥应介于 1 和 r/2 之间,其中 r 是椭圆曲线上阿贝尔群的阶数(即介于 1 和 2256/2 之间)。
配网密钥派生(Provisioning key derivation)
ConfirmationKey的派生过程

SessionKey和SessionNonce的派生过程

配网错误
无论配网协议因何原因失败,设备应永久删除所有存储的细节信息。没有恢复过程,配网器必须从头开始整个配网过程。
在处理协议错误时,配网协议是不对称的。
当配网器遇到配网协议错误时,应立即断开配网承载器。在意外情况导致配网承载器关闭时,配网协议失败。
当设备在配网协议中遇到除超时以外的错误时,它应发送带有适当错误代码的配网失败 PDU,并等待配网承载器关闭。 此时,从配网器接收到的任何配网协议 PDU 都被认为是非法的。
配网器收到配网失败PDU 后,应假定配网失败并立即断开配网承载器。
配网协议应具有 60 秒的最小超时,每次发送或接收配网协议 PDU 时都会重置该超时。当设备收到第一个配网 PDU 和配网器发送第一个配网PDU 时,超时计时开始。如果在超时到期之前没有收到 PDU,则协议失败。 在协议超时的情况下,设备不应发送配网失败 PDU。