综述
启动配置(配网)是将一个没有被配网的设备增加到一个mesh网络中,由配网者(provisioner)管理。
provisioner将配网信息提供给未配网者。配网数据包含网络秘钥,当前的IV索引以及每一个元素的单播地址。(疑问:是该未配置节点分配的元素单播地址,还是整个网络中各个元素的单播地址)
provisioner通常是智能手机或者其他可移动的计算设备。尽管配网过程只需要一个provisioner,但是网络中可以有多个provisioner。共享数据的方法和协调多个provisioner的实现是特定的。(mesh规范中不给出)
配网承载层建立之后,provisioner和设备之间通过ECDH(Elliptic Curve Diffie-Hellman,椭圆曲线算法)协议建立了共享秘钥。
然后使用设备特定的OOB信息(Out Of Bound,带外数据)完成认证。这里OOB信息可以包含一个设备公钥,一个长秘密(long secret),向设备输入一个值,或者由设备输出一个值。
一旦设备完成认证,配网数据就通过之前建立的共享秘钥生成的秘钥加密后发送给设备。设备秘钥由ECDHSecret和ProvisioningSalt求出。
配网协议有一个层次结构。设配通过发送配网PDU的配网协议完成配网。配网PDU通过通用配网层发送给未配网设备。这个通用配网层定义了配网PDU如果被发送,分片和重组。
这里的通信交换建立在配网承载层。配网承载层定义了如何建立会话(session),这样就可以使由通用配网层递交的数据可以被分发到一个单独的设备上。
最后,配网协议的架构最低是承载层。
启动配置承载层
广播方式(PB-ADV)
GATT方式(PB-GATT)
通用启动配置层
通用启动配置PDU类型
链路建立过程
链路建立过程用于给承载层建立起会话(session)。一个会话由链路ID唯一标识。链路ID在会话时间内是静态不变的。而且为了防止不同会话间的冲突,链路ID是随机生成的。
一个链路建立在provisioner和被配网设备之间,用于发送配网消息。未配网设备有设备UUID做标识区分。
provisioner扫描未配网设备。当收到一个未配网设备发出的beacon时,provisioner将于设备建立一个链路,通过设备UUID做标识。
链路建立开始于provisioner发送一个LinkOpen消息。LinkOpen消息中包含了设备UUID。对于广播方式的配网,PB-ADV PDU中包含了LinkID字段。
除非已经被配网(设备已经接受到一个Provisioning Invite PDU),设备在收到LinkOpen消息时应该接受并且使用相同的LinkID回复一个LinkACK消息。
链路建立后,可以通过发送LinkClose消息在任何时间关闭链路。链路的任何一侧都可以发送LinkClose消息。
通用启动配置行为
启动配置协议
启动配置PDU
启动配置行为
配网过程包含5个步骤:0.beacon,1.invitation(邀请),2.exchange public keys(交换秘钥),3.authentication(认证),4.distribution of the provisioning data(发送配网数据)。
Beacon
一个支持PB-ADV的未配网而且没有处于配网过程的设备,可以广播Unprovisioned Device Beacon。
当一个设备没有被配网,建议使用匿名的广播,不可解析的私有地址或者可解析的私有地址。
该Beacon可以指示OOB数据的能力,这样便可以使provisioner要求用户在下一步操作前收集OOB数据。
Invitation
在建立了配网承载层后,provisioner会发送一个配网邀请包(Provisioning Invite PDU),设备将使用配网能力包(Provisioning Capability PDU)回应。
配网邀请包包含一个额外的持续时间字段,用于确定设备的主元素有多长时间使用Attention Timer识别自身。
如果配网承载层停止(be dropped),设备应该设置主元素的Attention Timer状态为0x00(off)。
配网能力包包含设备支持的元素个数信息,支持的安全算法集,公钥使用OOB技术的能力,设备输出一个值给用户的能力(output OOB),设备允许用户输入一个值的能力(input OOB),设备是否有一块OOB数据用于认证(static OOB)。
当使用来自Output OOB Action字段的值(闪灯,蜂鸣,或者震动)时,设备要随机选择一个大于1的整形数字,这个数字将以连续事件的方式输出(比如,闪灯,蜂鸣或者整栋以一个500ms开,500ms关的循环)。并且在允许用户决定事件结束要有3秒钟时间。(output OOB 应该至少持续3秒?)。当使用数值(Numeric, 纯数字)方式输出时,输出值用数字表示(例如,ASCII字符编码0x30-0x39)。当使用文字数字(Alphanumeric,含有字母的数字)时,输出的值使用ASCII数字和大写字母(例如,ASCII字符编码0x30-0x39和0x41-0x5A)。
input OOB(没有看懂。。。个人理解: the number of push action && the number of twist action.被配网设备的配网能力input,所以应该向为配网设备输入OOB信息,可以是纯数字,也可以是数字加字母形式,因此对被配网设备要求了输入能力。)
Exchanging public keys
对于provisioner该步骤由于未配网设备提供公钥能力的不同有两种可能性。随之,认证步骤将有三种不同可能性。因此有六种可能的叫交换/认证路径。
一旦provisioner确定自己可以为设备配网,它将发出一个Provisioning Start PDU,该PDU中详细描述了使用六种路径中的那一条路径。
设备收到Provisioning Start PDU后,需要设置Attention Timer为0x00。
Provisioner需要从被配网设备发送的Provisioning Capability PDU中选择一种算法。如果Provisioner不理解算法位字段中的位集(bit set),那么它可以忽略该bit,并且选择它理解的算法。Provisioner应该选择最健壮的算法。
如果公钥不能使用OOB技术,那么该公钥将在所有设备间交换。
如果不同OOB下发,设备需要发送公钥。
当未配网设备公钥未知时公钥交换的消息序列如下图说明:
如果通过OOB机制的公钥可用,那么临时的公钥应该从Provisioner传输给设备,并且应该从设备使用的合适OOB技术上读出一个静态的公钥。
当未配网设备通过OOB方式完成公钥交换时,消息序列如下图说明:
一旦对侧设备的公钥已知,ECDHSecret可以如下计算出:
ECDHSecret = P-256(private key, peer public key)
Authentication
如果使用Output OOB认证,那么Provisioning Start PDU应该包含一个对于设备按规定动作输出一个或多个数字只的请求。输出的动作可以包括发出声音,闪烁灯,或者在屏幕显示符号。
例如,如果一个含有一个LED灯的门锁设备,那么它可以通过闪烁LED的方式来使用Output OOB认证。
设备需要选择一个随机数,然后输出该数字。provisioner的用户可以输入观察到的用于认证的数字。一旦数字被输入,一个随着随机数字交换而交换的确认动作将被执行。
确认值是所有到目前的交换值,明文形式的随机数,和被输入的数字的hash加密值。一旦随机数被交换,每个设备都可以认证对侧。
来自Output OOB,Input OOB或者static OOB的认证值将在AuthValue中使用,用于计算上面说的确认值。
Provisioner的确认计算:
ConfirmationProvisioner = AES-CMACconfirmationKey(RandomProvisioner || AuthValue)
设备的确认计算:
ConfirmationDevice = AES-CMACconfirmationKey(RandomDevice || AuthValue)
其中,
ConfirmationKey = k1(ECDH_Secret, ConfirmationSalt, "prck")
ConfirmationSalt = s1(ConfirmationInputs)
ConfirmationInputs = ProvisioningInvitePDUValue || ProvisingCapabilitiesPDUValue || ProvisionStartPDUValue || PublicKeyProvisioner || PublicKeyDevice
这其中,
ProvisioningInvitePDUValue是Provisioning Invite PDU字段除去操作码后的值。
ProvisioningCapabilitiesPDUValue是Provisioning Capabilities PDU字段去除操作码后的值。
ProvisioningStartPDUValue是Provisioning Start PDU字段去除操作码后的值。
PublicKeyProvisoner是由Provisioner发送的公钥PDU中PbulicKeyX和PublicKeyY的值。
PbulicKeyDevice是有设备发送的公钥PDU中的PublicKeyX和PublicKeyY字段的值(或者分发出来的OOB公钥)
RandomProvisioner是一个随机bit数的字符串,由provisioner的随机数生成器生成。
RandomDevice是一个随机bit数的字符串,由设备的随机数生成器生成。
AuthValue是128bit的值。它的计算依赖与OOB动作的数据类型。
如果数据类型是二进制,那么AuthValue是一个octet的数组。如果该值比128bit少,那么剩余的bit用0填充。
如果数据类型是纯数字,那么该数字应该是一个无符号128bit值。
如果数据类型是数字和文本,那么AuthValue应该对字符和ASCII码相关连。
5->0x05
019655->0x4CC7
"123ABC"->
如果没有使用Output OOB方式认证,AuthValue应该被设置为全0。
Provisioner在收到Provisioning Confirmation PDU后会发送Provisioning Random PDU。设备在验证了确认值后会发送Provisioning Random。
使用OutPut OOB方式认证的消息序列如下图:
如果使用Input OOB方式认证,那么Provisioner需要生成一个随机数,并且展示给用户。用户用一种合适的方式将该值输入到设备。
例如,一个灯的开关可以让用户通过按压开关一定次数来输入随机数。
一旦随机数被输入,设备将发送Provisioning Input Complete PDU给Provisioner确认。一个伴随随机数交换的确认交换被执行。
Input OOB方式认证的消息序列如下图:
使用静态OOB或者没有OOB使用时,Provisioner会按上述立即(无其他操作)进行确认和随机数交换。如果静态OOB值可用,那么该值将作为确认值的一部分。如果没有可用的静态OOB值,那么该值应该全为0。
静态OOB或者没有OOB时的消息序列如下图: