配网流程(Provisioning)是向蓝牙 Mesh 网络(如灯泡)添加新的未经配置设备的过程。该过程由配网器(Provisioner) 进行管理。配网器和未经配置设备遵循蓝牙 Mesh 规格中定义的固定过程。配网器向未经配置设备提供使其成为蓝牙 Mesh 节点的配置数据(provisioning data)。
配网器通常是运行配网器应用程序的智能手机或其它移动计算设备。尽管每个网络只需要一台配网器来执行配网,但可用的配网器可以有多台。
完整的配网过程必须在更高的层面完成两项重要任务:
蓝牙 Mesh 规格中定义了配网协议,该协议定义了配网流程中用于在配网器和新的未经配置设备之间进行通信的标准流程以及 PDU。下图描绘了完整蓝牙 Mesh 协议栈之外的配网协议栈。
从下到上的组件如下:
配网承载层实现了配网 PDU 在配网器和未经配置设备之间的传输。定义的两个配网承载层包括:
PB-ADV:指通过蓝牙广播信道进行设备配置的配网承载层。PB-ADV 承载层用于发送通用配网 (Generic Provisioning) PDU。支持 PB-ADV 的设备应尽可能执行占空比接近 100% 的被动扫描,以避免遗漏任何发送来的通用配网 PDU。
PB-GATT:指使用来自代理协议的蓝牙 Mesh 代理(proxy)PDU 来进行设备配置的配网承载层。代理协议能使节点通过面向连接的低功耗蓝牙(Bluetooth Low Energy)承载层来收发网络 PDU、mesh Beacon、代理配置消息和配网 PDU。PB-GATT 在 GATT 操作中包含了配网 PDU,涉及 GATT 配网服务,同时能在配网器不支持 PB-ADV 时供其使用。
定义对于配网 PDU、行为和安全性的要求。了解配网协议将有助于您根据应用需求选择合适的验证方法。
配网协议定义了 10 种配网PDU:
配网流程包括五个阶段:
Beacon 是低功耗蓝牙的传统应用场景。想象一下,一个GAP外设(如智能手表或活动跟踪器)希望与GAP中央设备(如智能手机或平板电脑)连接。 GAP外设切换到广播状态并开始发送其广播数据包。GAP中央设备扫描广播数据包以发现其它设备并接收相关基本信息。蓝牙 Mesh 配置使用的也是相同的广播机制。
如果未经配置的设备支持 PB-ADV 承载层,则其作为未经配置设备 Beacon 进行广播。这涉及指定的数据包格式,且未经配置设备通过此方式来使自身被配网器 (Provisioner) 发现。
当未经配置设备使用 PB-GATT 承载层时,一项称为“Mesh 配置服务”的 GATT 服务会支持整个配网流程,同时支持与配网器的交互。在发送 Beacon 信号阶段,未经配置设备会发送包括 mesh 配置服务 UUID 的广播数据包,它会被配网器通过标准的低功耗蓝牙扫描程序发现。
在发送 Beacon 信号之后,配网器和未经配置设备会建立 PB-ADV 或 PB-GATT 配网承载层(provisioning bearer)。然后,配网器发送一个配置邀请 PDU,设备通过配置功能 PDU 对其作出响应。
配置邀请 PDU 包括 Attention Duration 字段,其指示了未经配置设备的主要元素应采用某种视觉指示方式,并在多长的时间内吸引用户的注意力。
配置功能 PDU 包括:
上图中的流程图让人联想到低功耗蓝牙中的配对过程。 低功耗蓝牙配对采用的配对特性交换类似于蓝牙Mesh 配置程序中的配置邀请阶段。在配置邀请阶段,目的是向配网器(Provisioner) 提供有关未经配置设备功能的信息。有了这些信息,配网器就能决定下一步该如何进行。
信息加密涉及两项基本技术:对称加密(也称为密钥加密)和非对称加密(也称为公钥加密)。
在蓝牙 Mesh 用例中,大多数设备基于嵌入式芯片组或模块,因此无法使用计算成本昂贵的非对称加密技术来对每个消息进行加密/解密。对称加密更适合于不具备非对称加密所需处理能力的设备,但如何安全地交换并使用密钥仍然是一大问题。蓝牙mesh采用了非对称和对称加密结合的方式来解决这一问题。
在交换公钥阶段,有两种交换 ECDH 公钥的可能方式。它们可以通过蓝牙链路、或 OOB 隧道进行交换。在配置邀请阶段,未经配置的设备已经报告了是否支持通过 OOB 隧道发送自身公钥。如果是,则配置设备可继续使用它,并通过发送配置开始 PDU 来通知未经配置的设备。
如果未经配置设备的公钥可通过 OOB 隧道获得,则临时公钥从配网器发送到设备,并采用合适的 OOB 技术(例如二维码),从未经配置的设备中读取静态公钥,如图所示。
否则,双方的公钥都会经由下图中所示的蓝牙链路进行交换。
ECDHSecret = P-256 (私钥,对等公钥)
在该等式中,P-256即FIPS 186-3中定义的FIPS-P256曲线。
在此步骤中,配网器使用所选的验证方法,对未经配置设备进行验证。有三种可用的验证方法(OOB, Out-Of-Band):输出 OOB(Output OOB)、输入OOB(Input OOB)、以及静态OOB(Static OOB)或无OOB(No OOB)。
若选择的是输出带外(Output OOB)验证方法,则未经配置设备会选择一个随机数,并通过与其功能兼容的方式输出该数字。例如,如果未经配置设备是一个灯泡,则它能够闪烁指定的次数。如果设备具有 LCD 屏幕,则可以将随机数显示为多位数值。配网器(Provisioner)的用户需要输入观察到的数字,来验证未经配置的设备。输出带外验证方法的工作流程如下图所示。
输入随机数后,配网器(Provisioner)生成并检查确认值。无论采用哪种验证方式,整个验证步骤中的检查确认值(check confirmation value)计算方式都是相同的。
输入带外(Input OOB)验证方法与输出带外(Output OOB)方法类似,但设备的角色相反。配网器(Provisioner)生成并显示随机数,然后提示用户采取适当的操作,将随机数输入未经配置的设备。以照明开关为例,用户可以在一定时间内数次按下按钮,以这种形式输入随机数。
与输出带外验证(Output OOB)相比,输入带外(Input OOB)方法需要发送一个附加的配置协议PDU。在完成认证操作之后,未经配置的设备向配网器发送一个配置输入完成 PDU(Provisioning Input Complete PDU),通知其随机数已输入完成。随后进入到执行检查确认值操作的步骤。
在输入带外或输出带外都不可用的情况下,配网器(Provisioner)和未经配置的设备可采用静态带外(Static OOB)验证或无带外(No OOB)验证:采用静态OOB信息;或静态OOB信息不可用,直接以数值 0 代替。在此情况下,配网器和未经配置的设备各自生成一个随机数,然后进行检查确认值操作。
无论采用何种验证方法,都会进行确认值生成和检查。根据蓝牙 Mesh 规格,配网器(Provisioner) 和未经配置设备应分别计算确认值。这两个值被称为 ConfirmationProvisioner 和 ConfirmationDevice。这两个值的计算都使用一系列相同的函数,不同之处仅在于所使用的随机数输入。
让我们来看看用于确认值生成的算法。下图是一个流程图,其中包括了几轮AES-CMAC和SALT生成[1]。该流程图对于 ConfirmationProvisioner 和 ConfirmationDevice 值均适用。
当确认值生成之后,两台设备就会进行交换,并且都会检查接收值的完整性。图4表示确认值检查的过程。
确认过程的开始就是配网器(Provisioner)将其随机数 RandomProvisioner 发送到未经配置的设备。未经配置设备使用它来重新计算确认值,并与之前接收的确认值进行比较,进行验证。
然后,配网器(Provisioner) 使用相同的过程来重新计算确认值,并通过比较计算所得值与先前接收值来进行验证。
认证步骤完成之后,就可以确保在配网器(Provisioner)和未经配置设备之间建立的承载层的安全,然后就进入配网(Provisioning)过程中最重要的一步:导出并分发配置数据(provisioning data)。配网器(Provisioner) 负责生成配置数据,配置数据由多个数据项组成,包括一个称为网络密钥 (NetKey) 的安全密钥。下表列出了配置数据字段。
字段 | 大小(字节) | 注释 |
---|---|---|
网络密钥 | 16 | 简称 NetKey。NetKey 确保网络层(network layer)通信的安全,并在网络中所有节点(node)之间共享。是否拥有给定的 NetKey 定义了给定蓝牙 Mesh 网络或子网的成员资格。为设备赋予网络的 NetKey 是配网(Provisioning)流程的主要结果之一。 配网器(Provisioner) 在对要添加到网络中的首台设备进行配置时创建 NetKey。 |
设备密钥 | 16 | 简称 DevKey,只有配网器(Provisioner)和被配置的设备拥有的唯一安全密钥 。 |
密钥索引 | 2 | 由于 NetKey 太长,无法在单段消息中传输。为使消息传递尽可能高效,会向密钥分配一个全球唯一的12位索引值,称为密钥索引,用作密钥的短标识符。消息中包括密钥索引值,它可能以配置客户端(Configuration Clients)维护的密钥列表为参考。 |
标志 | 1 | 标志位掩码 - 指示关联密钥的状态。 |
IV 索引 | 4 | IV(初始化向量)索引是一个32位的值,被网络中的所有节点 (node)共享。其目的是在计算消息随机值时提供熵(随机性)。 |
单播地址 | 2 | 新节点中主要元素的单播地址(Unicast Address)。 |
为安全地进行配置数据分发,配网器(Provisioner)采用AES-CCM [2],借助共享的会话密钥(SessionKey)对配置数据(provisioning data)进行加密,配网器和未经配置设备都会进行计算。 AES-CCM需要三个输入参数:会话密钥、会话随机数和纯文本。纯文本参数值包含需要被加密的配置数据。设备密钥(DevKey)、会话密钥(SessionKey)和会话随机数(SessionNonce)的值通过图所示的过程导出。
从图中可以看出:
配网器(Provisioner)和未经配置设备都需要生成会话密钥(SessionKey)和会话随机数(SessionNonce)。当 SessionKey 和 SessionNonce 值准备就绪时,配网器将对包含导出配置数据的配置数据 PDU (Provisioning Date PDU) 进行加密,并将其发送至未经配置的设备。此处,相同的 SessionKey 和 SessionNonce 值也可用来对接收到的数据进行解密。
至此,配网流程完成。两台对等设备都已知晓新的设备密钥(DevKey)和全网的网络密钥(NetKey),这就意味着我们的新设备已成为蓝牙 Mesh 网络中的节点(node)和成员。