最近项目很急好久没有看core文档了。
AUTHENTICATION AND ENCRYPTION重新写一下,个人理解,不对请指正,大家一起进步
配对(Pairing)、认证(Authentication)和加密(Encryption)
两个设备之间没有link key时会进行配对然后进行加密;有link key时直接使用link key进行认证,然后进行加密
(一)配对Pairing
配对就是两个设备产生link key的过程。
配对方式分为两种:普通配对(即BT2.0)和安全简单配对(Secure Simple Pairing即BT2.1)
1、普通配对
(1)使用PIN、一个随机数和一个BD_ADDR产生一个Kinit;当两个设备的Kinit都产生后才会产生Link key
Kinit产生的过程:Initiator发送LMP_in_rand(里面是IN_RAND)给Responder,Responder同意配对,回复LMP_accepted,然后根据Responder的BD_ADDR和IN_RAND(Initiator发送的LMP_in_rand里的)以及PIN产生Kinit
注意:PIN是Initiator和Responder两端用户输入的或者固定在设备里不变的。
特殊情况:
A、如果Responder有固定的PIN,流程是这样的:
Initiator发送LMP_in_rand给Responder,此时Responder有自己固定的PIN,所以他不接受Initiator的LMP_in_rand,这里Responder不需要回复reject,直接发送自己的LMP_in_rand给Initiator,然后Initiator的PIN是可变的情况下,Initiator会回复LMP_accepted。这时候Kinit就是根据Initiator的BD_ADDR和IN_RAND(Responder发送的LMP_in_rand里的)以及PIN产生的。
B、如果Initiator和Responder都有自己固定的PIN,这时候流程是这样:
Initiator发送LMP_in_rand给Responder,此时Responder有自己固定的PIN,所以他不接受Initiator的LMP_in_rand,Responder直接发送自己的LMP_in_rand给Initiator,而Initiator也有自己固定的PIN,所以也不接受Responder的LMP_in_rand,此时Initiator就需要回复LMP_not_accepted(error code:Pairing not Allowed (0x18))
C、Responder拒绝配对,这时候流程是这样的:
Initiator发送LMP_in_rand给Responder,此时Responder拒绝配对,就会回复LMP_not_accepted(error code:Pairing not Allowed (0x18))
(2)产生Link key
Link key有两种:combination key或者unit key
unit key:即KA,是设备第一次运行时通过E21算法产生的,然后被保存在设备里,一般不会变化,如下图:设备A和B之间认证用的link key就是KA,设备A将KA异或Kinit的结果发送给设备B ,设备B拿到后,将这个结果再和Kinit进行异或,得到KBA,这样KBA=KA
注意:如果设备B和设备A输入的PIN不同,那么Kinit就会不同,解析出来的KBA != KA
combination key:
a、设备A通过E21算法使用设备A的随机数LK_RANDA和设备A的地址BD_ADDRA,产生一个随机数LK_KA
设备B通过E21算法使用设备B的随机数LK_RANDB和设备B的地址BD_ADDRB,产生一个随机数LK_KB
b、设备A将LK_RANDA和Kinit(即图中的K)异或得到CA,设备B将LK_RANDB和Kinit(即图中的K)异或得到CB
c、然后设备A把CA发给设备B,设备B把CB发给设备A
d、设备A用CB异或Kinit,得到设备B的随机数LK_RANDB,设备B用CA异或Kinit,得到设备A的随机数LK_RANDA
e、设备A通过E21算法使用设备B的随机数LK_RANDB和设备B的地址BD_ADDRB,产生一个随机数LK_KB
设备B通过E21算法使用设备A的随机数LK_RANDA和设备B的地址BD_ADDRA,产生一个随机数LK_KA
这样,设备A就有了设备B的LK_KB,设备B就有了设备A的LK_KA。
f、设备A和设备B都进行LK_KA异或LK_KB分别得到KAB和KBA,这两个应该是相等的,如果设备B和设备A输入的PIN不同,那么Kinit就会不同,解析出来的KAB != KBA
设备A和设备B的交互使用的是:LMP_unit_key和LMP_comb_key
LMP_unit_key:就是Kinit和unit key(KA)异或得到的
LMP_comb_key:设备A是CA=LK_RANDA和Kinit(即图中的K)异或;设备B是CB=LK_RANDB和Kinit(即图中的K)异或
注意:
A、设备A和设备B一个发送LMP_unit_key,另一个发送LMP_comb_key,那么Link key就是unit key
B、设备A和设备B都发送LMP_unit_key,谁是master,Link key就是谁的unit key
C、设备A和设备B都发送LMP_comb_key,Link key就按照上面combination key的方式产生。
配对只是产生link key,判断link key是否正确就需要进行认证Authentication
(3)改变link key
只有combination key可以通过发送LMP_comb_key改变,unit key只能通过配对才能改变
改变Link key成功:
改变Link key失败:
改变Link key成功后,新的link key会变成Kinit,直到下次新的link key产生后,新的Link key就会变成Kinit(Kinit和新的Link key异或就是LMP_comb_key的内容),并且使用新的link key进行认证和加密(如果encryption是enabled)
普通配对的流程如下图所示:
配对的前提是没有link key(即对方来配对,本地controller发送HCI_Link_Key_Request请求link key,但是本地没有link key,所以回复HCI_Link_Key_Request_Negative_Reply)
1、然后本地controller请求从host获取pincode(HCI_PIN_Code_Request)
2、用户输入pincode以后,host会将pincode发送到controller(HCI_PIN_Code_Request_Reply)
3、本地controller发送LMP_in_rand给Responder
4、Responder也会请求host输入pincode(HCI_PIN_Code_Request)
5、Responder端用户输入pincode后,同样会把pincode发送到自己的controller (HCI_PIN_Code_Request_Reply)
6、然后Responder回复LMP_accepted
7、之后Inititor发送LMP_comb_key,Responder回复LMP_comb_key,两端产生link key
8、然后进入认证的部分,认证完成后将link key通知host(HCI_Link_Key_Notification)