3.13.3 Legacy配對
首先,我們回復的paring response中,可以看到我們不支持secure connection,所以我們走的是legacy配對模式。
圖3-74 secure連接不支持
然后,master在pairing confirm包中回復了confirm value。
圖3-75 master發送confirm value
這個數值是master端生成一個隨機數后,將這個隨機數作為輸入,通過c1算法算出來的,叫做Mconfirm,接下來我們本地也需要生成一個隨機數,通過c1算一下,算出來一個Sconfirm發給對方。
圖3-76 配對phase2基本完成
到這一步我們的Sconfirm已經發過去了,流程進行到了這里
圖3-77 just works配對流程
接下來我們卡死在check for confirm value match這里。
圖3-78 confirm value fail
需要研究下C1算法了。
BLE的C1算法是藍牙傳統配對(Legacy Pairing)中用于生成確認值(Mconfirm/Sconfirm)的核心函數,以計算Mconfirm為例:
Mconfirm = c1(TK, Mrand, Pairing Request command, Pairing Response command, initiating device address type, initiating device address, responding device address type, responding device address)
其輸入參數如下:
?C1算法輸入參數?
?臨時密鑰(TK)?
128位臨時密鑰,由配對雙方通過Passkey Entry等方式協商生成(如用戶輸入的6位數字擴展為128位)?。
?隨機數(Rand)?
主設備生成的128位隨機數 ?Mrand? 或從設備生成的 ?Srand??13。
?設備地址(BD_ADDR)?
雙方設備的MAC地址(Initiator Address)和從設備的MAC地址(Responder Address)?23。?
雙方設備的地址類型
Public還是Random的
雙方的配對命令
Pairing Request Command和Pairing Response Command
上面這些參數中,藍牙地址、地址類型、隨機數都是空中包明文傳輸的,只有臨時秘鑰Tk是不可知的,但是在Just Works的場景下,Tk是固定值0,這也是為什么Just Works是不放置中間人攻擊的,適合于安全需求較低的場景。
我們現在出現的情況顯然是,C1計算的值和對端不一致,需要對比一下C1算法的輸入哪里出了問題。
圖3-79 C1算法過程
這里展開說兩句,C1算法需要調用兩次AES-128算法,對于這個算法,一般藍牙controller是支持硬件加速的,所以我們可以采用圖中的方式,將明文通過HCI LE Encrypt Command發送給controller,由controller進行AES-128計算后,通過HCI event返回host, 來減輕HOST的負擔。支持這個命令的前提是,藍牙初始化的時候,當Host詢問controller支持哪些命令的時候,controller得把對應的位置上。
圖3-80 Read Local Supported Commands
在代碼里,我們是使能的:
圖3-81 支持LE ENCRYPT COMMAND
當然,btstack也支持在host來直接進行AES計算,只要打開USE_BTSTACK_AES128這個宏就可以了。
仔細檢查上述變量的值,我們發現了問題所在:
圖3-82 發現參數錯誤
再往前翻一下,很快找到了根源
圖3-83 初始化返回給host的藍牙地址就是反的
原因找到了,我們的藍牙地址是01:23:45:67:89:ab,對方在計算C1的時候也是采用的這個藍牙地址作為參數來進行計算,但是當我們本地進行計算的時候,選用的藍牙地址的來源不是實際的藍牙地址,而是這個從HCI Send Read BD ADDR Command所得到的藍牙地址,導致錯誤。
看了一下CEVA的controller協議棧,果然針對這個命令回復是有bug的:
圖3-84 ceva返回讀藍牙地址命令的問題
修改一下,按照網絡字節序交換一下:
?
圖3-85 修改read bd addr命令回復代碼
這樣之后,后續的配對過程就很順暢了,最終的數據都是加密的:
圖3-86 數據加密了
C1算法就像情侶默契測試:
輸入:雙方生日(設備地址)、戀愛宣言(配對指令)、測試題(隨機數)
陷阱:地址字節序反了就像把生日8月5日記成5月8日
驗證:硬件加密加速相當于找算命先生合八字