一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Bluetooth LE安全機(jī)制以及在nRF Connect SDK中的應(yīng)用

jf_14701710 ? 來源:jf_14701710 ? 作者:jf_14701710 ? 2025-07-04 10:11 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一. 低功耗藍(lán)牙Bluetooth LE安全必須應(yīng)對(duì) 的3 種常見攻擊類型:

身份追蹤,被動(dòng)竊聽(嗅探)和主動(dòng)竊聽(中間人MITM)

身份跟蹤:利用藍(lán)牙地址來跟蹤設(shè)備。這可以通過使用隨機(jī)變化的可解析私有地址(Resolvable Random Private Address)來避免,其中只有綁定/可信設(shè)備才能解析私有地址。 IRK(身份解析密鑰)用于生成和解析私有地址。

被動(dòng)竊聽(嗅探):就是攻擊者偷偷竊聽設(shè)備之間的數(shù)據(jù)傳輸。 可以通過加密對(duì)等設(shè)備之間的通信來防止這種情況。 這里的挑戰(zhàn)是對(duì)等設(shè)備如何生成和/或交換密鑰以建立安全地加密連接。 Bluetooth LE 傳統(tǒng)配對(duì)的密碼生成和交換存在不足,然后提出了LE secure Connections。

主動(dòng)竊聽(中間人MITM):在主動(dòng)竊聽(或中間人)攻擊中,攻擊者冒充合法設(shè)備來欺騙另外兩個(gè)設(shè)備,與他們建立連接。 為了防止這種情況,我們需要確保我們正在通信的設(shè)備實(shí)際上是我們想要與之通信的設(shè)備,而不是未經(jīng)身份驗(yàn)證的設(shè)備??煽康纳矸蒡?yàn)證過程可以有效的防止中間人攻擊。中間人攻擊的示例,如下圖:

wKgZPGhnOEuAYFwiAAA5s7ynZqs79.jpeg

二. BLE安全相關(guān)術(shù)語:

臨時(shí)密鑰 (Temporary Key,TK): 臨時(shí)密鑰的生成取決于所選的配對(duì)方法。每次配對(duì)過程發(fā)生時(shí)都會(huì)生成 TK(僅用于傳統(tǒng)配對(duì))。

短期密鑰 (Short Term Key,STK): 此密鑰由設(shè)備之間交換的 TK 生成。每次配對(duì)過程發(fā)生時(shí)都會(huì)生成 STK,并用于加密當(dāng)前連接中的數(shù)據(jù)(僅用于傳統(tǒng)配對(duì))。

長期密鑰 (LongTerm Key,LTK): 此密鑰在傳統(tǒng)配對(duì)的第三階段和 LE 安全連接的第二階段期間生成和存儲(chǔ),是一個(gè) 128 位密鑰,用于生成session key。它存儲(chǔ)在綁定的兩個(gè)設(shè)備中的每一個(gè)上,并用于兩個(gè)設(shè)備之間的后續(xù)加密連接。

加密多樣化(Encrypted Diversifier,EDIV)和 隨機(jī)值(Random Number,Rand): 這兩個(gè)值用于創(chuàng)建和識(shí)別 LTK。它們也會(huì)在綁定過程中儲(chǔ)存起來。

身份解析密鑰 (ldentity Resolving Key,IRK): 用于生成和解析隨機(jī)私有可解析地址(Resolvable Random Private Address)。該密鑰對(duì)于每個(gè)設(shè)備都是唯一的,因此主設(shè)備的 IRK 將存儲(chǔ)在從設(shè)備端,而從設(shè)備的IRK 將存儲(chǔ)在主設(shè)備端。

連接簽名解析密鑰(Connection Signature Resolving Key,CSRK): 如果啟用,該密鑰將存儲(chǔ)在兩個(gè)綁定設(shè)備中的每一個(gè)上,用于對(duì)數(shù)據(jù)進(jìn)行簽名并驗(yàn)證附加到另一端數(shù)據(jù)的簽名(used in signing data sent over an unencrypted link )。

ECDH(Elliptic-curve Diffie–Hellman)橢圓曲線diffie-hellman密鑰交換算法

三. 可解析隨機(jī)私有地址(Resolvable Random Private Address)

可解析隨機(jī)私有地址可以防止被未知設(shè)備掃描和追蹤

wKgZO2hnOEyAO3FnAAAmdPEJG-I27.jpeg

如圖,由兩部分組成:高位24bits是隨機(jī)數(shù)部分,其中最高兩個(gè)bit為"10",用于標(biāo)識(shí)地址類型;低位24bits是隨機(jī)數(shù)和IRK經(jīng)過hash運(yùn)算得到的hash值,運(yùn)算的公式為hash = ah(IRK, prand)。

當(dāng)對(duì)端Bluetooth LE設(shè)備掃描到該類型的藍(lán)牙地址后,會(huì)使用保存在本機(jī)的IRK,和該地址中的prand,進(jìn)行同樣的hash運(yùn)算,并將運(yùn)算結(jié)果和地址中的hash字段比較,相同的時(shí)候,才進(jìn)行后續(xù)的操作。這個(gè)過程稱作resolve(解析),這也是Non-resolvable private address/Resolvable private address命名的由來。以T_GAP(private_addr_int)為周期,定時(shí)更新。哪怕在廣播、掃描、已連接等過程中,也可能改變。

四. Bluetooth LE安全等級(jí)

Bluetooth LE 在安全模式 1 中定義了 4 個(gè)安全級(jí)別:

1 級(jí):無安全性(開放文本,意味著無需身份驗(yàn)證且無需加密)

2級(jí):未經(jīng)身份驗(yàn)證的配對(duì)加密

3 級(jí):經(jīng)過身份驗(yàn)證的配對(duì)加密

4 級(jí):經(jīng)過身份驗(yàn)證的 LE 安全連接配對(duì)加密(LE Secure Connections)

安全等級(jí)1代表沒有加密。安全等級(jí)2,3對(duì)應(yīng)傳統(tǒng)配對(duì)(Legacy pairing),安全等級(jí)4對(duì)應(yīng)LE安全連接(LE Secure Connections)

傳統(tǒng)配對(duì)(Legacy pairing) 和LE安全連接(LE Secure Connections)

在藍(lán)牙 v4.2 之前,傳統(tǒng)配對(duì)是Bluetooth LE中唯一可用的配對(duì)方法。它非常簡單,但存在風(fēng)險(xiǎn),因?yàn)橛糜诩用苕溄拥亩唐诿荑€ (STK) 很容易被破解。在傳統(tǒng)配對(duì)中使用 Just Works 時(shí),TK 設(shè)置為 0,這在竊聽或中間人 (MITM) 方面不提供任何保護(hù)。攻擊者可以輕松暴力破解 STK 并竊聽連接,而且也沒有辦法驗(yàn)證設(shè)備。

使用密鑰輸入會(huì)好一些,因?yàn)?TK 現(xiàn)在是一個(gè) 6 位數(shù)字,由用戶在設(shè)備之間傳遞。例如,其中一個(gè)設(shè)備在其屏幕上顯示該數(shù)字,用戶使用鍵盤在其他設(shè)備上輸入該數(shù)字。不幸的是,攻擊者可以輕松嗅探正在交換的值,然后很容易找出 STK 并解密連接。即使無法直接確定 TK,也可以通過嘗試所有 999999 種組合輕松破解密鑰。

在帶外配對(duì)(OOB)中,TK 通過Bluetooth LE以外的其他方式進(jìn)行交換,例如使用 NFC。此方法支持使用最大 128 位的 TK,從而提高了連接的安全性。交換期間使用的 OOB 通道的安全性也決定了Bluetooth LE 連接的安全性。如果 OOB 通道受到保護(hù)以免遭受竊聽和 MITM 攻擊,那么Bluetooth LE鏈路也是如此。

藍(lán)牙 SIG 不推薦使用傳統(tǒng)配對(duì),但如果必須使用,請使用 OOB 方式。OOB身份驗(yàn)證與傳統(tǒng)配對(duì)配合使用可被視為安全的方法。

因此,在藍(lán)牙 v4.2 中引入了 LE 安全連接(LE Secure Connections)。 LE 安全連接不使用 TK 和 STK,而是使用橢圓曲線 Diffie-Hellman (ECDH) 加密技術(shù)來生成公鑰-私鑰對(duì)。設(shè)備交換公鑰。它們將使用四種配對(duì)方法之一(Just Works, Passkey entry, OOB or Numeric Comparison)來驗(yàn)證對(duì)等設(shè)備的真實(shí)性,并根據(jù) Diffie-Hellman 密鑰和身份驗(yàn)證數(shù)據(jù)生成 LTK。

盡管 Just Works 在使用 LE 安全連接時(shí)更安全,但它仍然不提供身份驗(yàn)證,因此不建議將其用作配對(duì)方法。密鑰輸入(Passkey entry)配對(duì)方式,使用密鑰、ECDH 公鑰和 128 位任意數(shù)字來驗(yàn)證連接。這意味著它比傳統(tǒng)配對(duì)要安全得多。使用 OOB 配對(duì)仍然是推薦的選項(xiàng),因?yàn)橹灰?OOB 通道是安全的,它就會(huì)提供保護(hù),就像在傳統(tǒng)配對(duì)中一樣。

此外,此功能引入了一種稱為數(shù)字比較(Numeric Comparison)的新配對(duì)方式。雖然它遵循與 Just Works 配對(duì)方式相同的程序,但它在最后增加了另一個(gè)步驟來防止 MITM 攻擊,即讓用戶根據(jù)兩個(gè)對(duì)等點(diǎn)上顯示的值,進(jìn)行手動(dòng)檢查和確認(rèn)。

對(duì)等點(diǎn)之間交換的唯一數(shù)據(jù)是公鑰。使用 ECDH 公鑰加密使得破解 LTK 變得極其困難,與傳統(tǒng)配對(duì)相比,這是一個(gè)顯著的改進(jìn)。

注:盡管大多數(shù)設(shè)備都支持 LE 安全連接,但仍有一些藍(lán)牙 LE 產(chǎn)品僅支持傳統(tǒng)配對(duì)。因此,除了 LE 安全連接之外,啟用對(duì)傳統(tǒng)配對(duì)的支持也是一個(gè)好主意,以便在您的應(yīng)用程序中實(shí)現(xiàn)更好的兼容性。

五. SMP安全管理協(xié)議

在藍(lán)牙核心規(guī)范中,有三個(gè)主要的架構(gòu)層:控制器、主機(jī)和應(yīng)用程序,如下圖所示。在主機(jī)層,有一個(gè)名為安全管理器 (SM) 的模塊,它定義了配對(duì)和密鑰分發(fā)的方法和協(xié)議、相應(yīng)的安全工具箱,以及安全管理器協(xié)議 (SMP)。SMP定義了配對(duì)命令幀格式、幀結(jié)構(gòu)和超時(shí)限制,用于配對(duì)和傳輸特定的密鑰分發(fā)。

wKgZPGhnOE2AVEgrAADFQn2HyzA07.jpeg

SMP具體命令如下圖:

wKgZO2hnOE2AZOslAAAfKb-pgSc68.jpegwKgZPGhnOE6AWYW1AADIQl_Vjhc25.jpeg

六. Bluetooth LE配對(duì)過程

配對(duì)是為了創(chuàng)建密鑰,然后可以使用這些密鑰來加密鏈接。配對(duì)過程中還可能傳輸特定的密鑰和數(shù)據(jù),以便雙方共享一些機(jī)密信息。這些機(jī)密信息可用于在未來重新連接時(shí)加密鏈接、驗(yàn)證簽名或執(zhí)行隨機(jī)地址解析。

Bluetooth LE配對(duì)之前需要先建立連接。配對(duì)過程可以分為三個(gè)過程,前兩個(gè)過程是必須的,第三個(gè)過程是可選的。

Phase1 Pairing Feature Exchange: 配對(duì)特征交換

Phase2 (LE legacy pairing): Short Term Key (STK) Generation: STK密鑰生成

Phase2 (LE Secure Connections): Long Term Key (LTK) Generation: LTK密鑰生成

Phase3 Transport Specific Key Distribution: 傳輸特定密鑰分發(fā)(在傳統(tǒng)配對(duì)中,LTK 也在該階段被派發(fā))

配對(duì)過程如下圖所示:

wKgZO2hnOE-ACf0MAABzDj9Vb6s11.jpeg

(1) 配對(duì)特征交換(Pairing Feature Exchange)

配對(duì)命令

兩個(gè)設(shè)備之間的配對(duì)信息交換是通過配對(duì)請求(pairing request)和配對(duì)響應(yīng)(pairing response)數(shù)據(jù)包完成的。只有主機(jī)才能發(fā)送配對(duì)請求命令,從機(jī)發(fā)送配對(duì)響應(yīng)命令進(jìn)行回復(fù)。如果從機(jī)也想發(fā)起配對(duì),那么可以發(fā)送安全請求(security request )命令,主機(jī)收到這條命令后,可以選擇發(fā)送配對(duì)請求,也可以拒絕。處理邏輯如下:

wKgZPGhnOE-AZUYSAAB2shO-wa039.jpeg

主機(jī),從機(jī)都可以調(diào)用int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec)函數(shù)來發(fā)起配對(duì)。這個(gè)函數(shù)的處理邏輯里面會(huì)判斷當(dāng)前的身份是主機(jī)還是從機(jī),從而發(fā)送不同的命令。

配對(duì)命令格式

Pairing Feature Exchange主要交換I/O能力,是否支持OOB,是否支持綁定,是否支持MITM,是否支持安全連接(SC)等,還有分發(fā)密鑰的相關(guān)的信息。格式如下:

wKgZO2hnOFCAZDN1AAAvmdwPZe458.jpeg

1)I/O能力包括:

DisplayOnly:僅有顯示能力

DisplayYesNo:有顯示能力,并可選擇“是”或“否”

KeyboardOnly:僅有鍵盤輸入能力

NoInputNoOutput:沒有輸入和輸出能力

KeyboardDisplay:有鍵盤輸入和顯示能力

I/O能力編碼,如下圖:

wKgZPGhnOFGAFXa2AABP6k0Tcds08.jpeg

2)OOB 數(shù)據(jù)flag如下圖:

wKgZO2hnOFKAD5wBAABFjQVlsd093.jpeg

3)AuthReq中各個(gè)字段的含義如下:

Bonding Flags:指示是否支持綁定

MITM:如果設(shè)備需要請求 MITM 保護(hù),則必須設(shè)置此位字段。這將啟用設(shè)備的身份驗(yàn)證。

SC:代表安全連接,如果支持安全連接功能,則設(shè)置此字段。如果設(shè)備支持 LE 安全連接配對(duì),則必須將 SC 字段設(shè)置為 1,否則必須將其設(shè)置為 0。如果兩個(gè)設(shè)備都支持 LE 安全連接配對(duì),則必須使用 LE 安全連接配對(duì),否則將使用 LE 傳統(tǒng)配對(duì)。

Keypress:僅在 Passkey Entry 協(xié)議中使用,其他協(xié)議將忽略它。設(shè)置此字段后,輸入 passkey 時(shí)將使用按鍵通知。這將一次交換一位(one bit)passkey,這是藍(lán)牙 4.2 相對(duì)于之前的機(jī)制(藍(lán)牙 4.1 或更早版本)的一項(xiàng)重要增強(qiáng)。藍(lán)牙 4.2之前的處理中,整個(gè)passkey在一次確認(rèn)操作中交換。這增強(qiáng)了passkey交換機(jī)制,現(xiàn)在在 MITM 攻擊中預(yù)測passkey變得更加困難。

CT2:表示加密過程可以使用名為 h7 的安全功能。

RFU:保留以備將來使用。

4)最大加密密鑰大小 (Maximum Encryption Key Size):由于不同設(shè)備的處理能力不同,此字節(jié)表示設(shè)備可以處理的最大密鑰大小。大小可以是 7 到 16 個(gè)字節(jié)。Nordic支持16個(gè)字節(jié)。

發(fā)起方密鑰分發(fā)(Initiator Key Distribution):此字段表示發(fā)起方希望在后續(xù)階段生成和分發(fā)哪些密鑰。

響應(yīng)方密鑰分發(fā) (Responder Key Distribution):此字段表示發(fā)起方希望請求響應(yīng)方生成和分發(fā)哪些密鑰。

密鑰的種類如下:

wKgZPGhnOFKAKFeMAAAhJjeo2oo50.jpeg

EncKey代表LTK;IdKey代表IRK ;SignKey代表 CSRK;Bluetooth LE中LinkKey不被分發(fā)。

配對(duì)模式選擇

通過綜合考慮雙方的OOB標(biāo)志、MITM標(biāo)志和I/O能力,來決定使用哪種配對(duì)方法。OOB和MITM標(biāo)志首先確定是直接使用OOB配對(duì)方法還是根據(jù)I/O能力確定配對(duì)方法。如下圖所示:

wKgZO2hnOFOAT7u7AACAy9-9lkE98.jpegwKgZPGhnOFSAakRfAAC-V1ccQ_E54.jpeg

1) Initiator和Responder兩方都設(shè)定了OOB flag的情況下,選用OOB

2) Initiator和Responder一方設(shè)定了OOB flag的情況下,需要判斷SC flag

Secure connection的情況下,選用OOB。

Legacy的情況下,需要去判斷MITM flag,只要一方設(shè)定了MITM flag,就要通過I/O能力去選擇pairing mothed。如果兩方都沒有設(shè)定MITM flag,那么直接用Just works

3) Initiator和Responder都沒有設(shè)OOB的情況下,判斷MITM flag

只要一方設(shè)定了MITM,需要去判斷I/O能力

兩方都沒設(shè)定MITM的情況下,使用Just Works

(2) 密鑰生成階段

傳統(tǒng)配對(duì)方式,生成STK,流程如下:

wKgZO2hnOFSAdFTiAABmYBjRjSU74.jpeg

傳統(tǒng)配對(duì)方式中,首先交換臨時(shí)密鑰 (TK),用于生成短期密鑰 (STK),然后使用短期密鑰 (STK) 加密鏈路,傳輸長期密鑰(LTK)。

1.1傳統(tǒng)配對(duì)定義了三種不同的方法來交互 TK,它們是Just works,Passkey Entry和Out of Band (OOB)。

Just Works:TK默認(rèn)為0,不提供身份驗(yàn)證,因此無法防御 MITM 攻擊。

Passkey Entry :一臺(tái)設(shè)備上顯示 6 位數(shù)字密碼(passkey),另一臺(tái)設(shè)備上需要輸入。設(shè)備的 I/O 能力決定了哪臺(tái)設(shè)備顯示數(shù)字以及哪臺(tái)設(shè)備輸入數(shù)字。用戶輸入的6位數(shù)字passkey,用前導(dǎo)零填充以得出 128 位TK值。

Out of Band:在設(shè)備之間通過帶外通信,傳遞完整 128 位TK值,例如使用 NFC傳輸。

注:Just Works 配對(duì)不提供身份驗(yàn)證,無法防御 MITM 攻擊。

1.2 傳統(tǒng)配對(duì)的認(rèn)證(authentication)過程:

首先,每個(gè)設(shè)備計(jì)算一個(gè) 128 位的確認(rèn)值(confirm value)。確認(rèn)值是使用名為 c1 的函數(shù)計(jì)算的,該函數(shù)接受多個(gè)參數(shù),包括 TK。除了 TK 值之外,還包括兩個(gè)設(shè)備都知道的字段以及一個(gè)隨機(jī)數(shù),在這個(gè)階段,只有創(chuàng)建確認(rèn)值的設(shè)備知道這個(gè)隨機(jī)數(shù)。在主機(jī)上,這個(gè)值稱為LP_RAND_I。在從機(jī)上,稱為LP_RAND_R。

然后,主機(jī)將其確認(rèn)值 (LP_CONFIRM_I) 發(fā)送到從機(jī),從機(jī)以其確認(rèn)值 (LP_CONFIRM_R) 進(jìn)行響應(yīng)。

收到 LP_CONFIRM_R 后,主機(jī)發(fā)送自己的隨機(jī)數(shù) LP_RAND_I給從機(jī)。從機(jī)計(jì)算出LP_CONFIRM_I 值,并將其與主機(jī)端發(fā)送過來的 LP_CONFIRM_I 值進(jìn)行比較。如果它們匹配,則從機(jī)已對(duì)主機(jī)進(jìn)行了身份驗(yàn)證,因此它將發(fā)送自己的隨機(jī)數(shù)LP_RAND_R進(jìn)行響應(yīng)。主機(jī)計(jì)算 LP_CONFIRM_R 值并將其與之前收到的值進(jìn)行比較。如果它們匹配,則主機(jī)完成了對(duì)從機(jī)的身份驗(yàn)證。

以Passkey為例,認(rèn)證流程如下:

1.3 傳統(tǒng)配對(duì)中,STK的生成公式如下:

STK=s1(TK,LP_RAND_R,LP_RAND_I)

注意:TK值是不會(huì)被藍(lán)牙鏈路傳輸?shù)?,這確保了一定的安全性。TK的密碼強(qiáng)度直接影響了STK的密碼強(qiáng)度,顯然OOB要好一些。

安全配對(duì)方式, 生成LTK,流程如下:

wKgZPGhnOFWAES95AAB_QwcDyug02.jpeg

LE 安全連接使用橢圓曲線 Diffie-Hellman (ECDH) 密鑰交換算法交換數(shù)據(jù),然后使用數(shù)據(jù)創(chuàng)建對(duì)稱密鑰,稱為長期密鑰 (LTK)。

2.1 Public Key Exchange

發(fā)起配對(duì)的設(shè)備(發(fā)起者)將其公鑰發(fā)送給另一臺(tái)設(shè)備(響應(yīng)者),后者用其公鑰進(jìn)行回復(fù)。公鑰在收到后進(jìn)行檢驗(yàn),以檢查它們是否在正確的橢圓曲線上。注意,LE 安全連接僅使用 P-256 曲線。

2.2 Calculate DHKey

每個(gè)設(shè)備都會(huì)計(jì)算一個(gè)稱為 Diffie-Hellman key (DHKey) 的密鑰。假設(shè)一方是Alice,一方是Bob,Alice 和 Bob 這兩個(gè)設(shè)備按以下方式計(jì)算 DHKey:

Alice: DHKey = P256(SKa, PKb)
Bob: DHKey = P256(SKb, PKa)

兩個(gè)設(shè)備 A 和 B 的私鑰分別表示為 SKa 和 SKb。PKa和PKb是它們的公鑰,交換之后,雙方都知道對(duì)方的公鑰。基于公鑰和私鑰作為參數(shù),兩邊能計(jì)算出相同的DHkey。DHKey 是一個(gè)對(duì)稱共享密鑰。

.3 Authentication Stage 1

不同的配對(duì)模式,對(duì)應(yīng)的算法略有不同。LE安全配對(duì)有4種模式,除了前面提到的傳統(tǒng)配對(duì)中的3種模式以外,還引入了一種新模式,稱為數(shù)字比較(Numeric Comparison)

1) Just Works 和Numeric Comparison身份驗(yàn)證階段1:

首先,設(shè)備 B 生成一個(gè)偽隨機(jī)數(shù) Nb,并將其與兩個(gè)設(shè)備的公鑰一起,作為 f4 (函數(shù))的參數(shù),來計(jì)算確認(rèn)值Cb 。Cb=f4(PKb, PKa, Nb, 0),然后將 Cb 發(fā)送到設(shè)備 A。由于設(shè)備 A 不知道 Nb 的值,因此它無法在此階段對(duì)確認(rèn)值執(zhí)行任何操作。

設(shè)備 A 現(xiàn)在將其自己的偽隨機(jī)數(shù) Na 發(fā)送到設(shè)備 B,設(shè)備 B 則用其隨機(jī)數(shù) Nb 回復(fù)?,F(xiàn)在,設(shè)備 A 擁有 f4 函數(shù)的所有參數(shù),因此它使用在公鑰交換期間獲取的公鑰和剛剛收到的另一臺(tái)設(shè)備的隨機(jī)數(shù) Nb 重新計(jì)算確認(rèn)值。它將計(jì)算出的確認(rèn)值與從設(shè)備 B 收到的 Cb 值進(jìn)行比較。如果它們不相同,則配對(duì)中止。

如果使用 Just Works,則身份驗(yàn)證第 1 階段已完成。如果使用Numeric Comparison,則還需要執(zhí)行一步。

每個(gè)設(shè)備使用兩個(gè)公鑰 PKa 和 PKb 以及兩個(gè)偽隨機(jī)數(shù) Na 和 Nb,通過g2 函數(shù)計(jì)算出一個(gè)六位數(shù)字。然后,每個(gè)設(shè)備顯示其計(jì)算出的數(shù)字。用戶被邀請確認(rèn)兩個(gè)設(shè)備是否顯示相同的六位數(shù)字,也可以通過按下特定按鈕來實(shí)現(xiàn)。通過指示兩個(gè)數(shù)字相同,用戶確認(rèn)參與通信的兩個(gè)設(shè)備確實(shí)是用戶嘗試配對(duì)的設(shè)備。換句話說,用戶參與了配對(duì)設(shè)備的身份驗(yàn)證。對(duì)設(shè)備進(jìn)行身份驗(yàn)證后,就會(huì)進(jìn)入身份驗(yàn)證階段 2。

另一方面,如果用戶發(fā)現(xiàn)兩個(gè)數(shù)字不相同,則身份驗(yàn)證階段 1 失敗,并且終止該過程。

具體流程如下圖所示:

wKgZO2hnOFaAbiyYAACx15O1tuI93.jpeg

2) Passkey Entry身份驗(yàn)證階段1:

用戶輸入密碼(Passkey)后,設(shè)備會(huì)計(jì)算、交換和檢查確認(rèn)值 Ca 和 Cb。但是,與 Just Works/Numeric Comparison 中的單次確認(rèn)不同,使用密碼(Passkey)輸入,確認(rèn)過程是迭代和增量的。

在每次迭代過程中,每個(gè)設(shè)備都會(huì)生成一個(gè) 128 位隨機(jī)數(shù) Na 或 Nb,并且每次將密鑰值的一位納入確認(rèn)值的計(jì)算中。確認(rèn)值函數(shù) f4 的輸入包括兩個(gè)公鑰、本次迭代的隨機(jī)數(shù)以及從本次迭代的密碼位值派生的值。

每次迭代都會(huì)交換和檢查確認(rèn)值。Cai=f4(Pka, PKb, Nai, rbi),Cbi=f4(PKb, PKa, Nbi, rbi)(i=0 to 19)(ra=rb=passkey)rai和rbi是passkey二進(jìn)制值對(duì)應(yīng)的每一位。

六位密碼(passkey)對(duì)應(yīng) 20 位二進(jìn)制數(shù)字(999999=0xF423F),因此計(jì)算、交換和檢查完整確認(rèn)值的過程需要迭代20次,每次迭代都會(huì)合并或披露密碼的新位。這種方法稱為“逐步披露”,其優(yōu)點(diǎn)是 MITM 攻擊在實(shí)際應(yīng)用中更加困難,大多數(shù)攻擊在攻擊者尚未看到完整和最終確認(rèn)值的情況下就會(huì)提前失敗。缺點(diǎn)是計(jì)算過程比較復(fù)雜,數(shù)據(jù)交互的次數(shù)較多,耗時(shí)耗電。

具體流程如下圖所示:

wKgZPGhnOFeAEe7nAACyHf2nmR445.jpeg

3) OOB身份驗(yàn)證階段1:

使用 OOB 方式,整個(gè)過程使用非藍(lán)牙的數(shù)據(jù)交換機(jī)制進(jìn)行的。

使用帶內(nèi)接收的公鑰和帶外接收的隨機(jī)數(shù) ra 和 rb 重新計(jì)算接收到的確認(rèn)值 Ca 和 Cb,這個(gè)是基于OOB雙向數(shù)據(jù)傳輸?shù)那闆r。如果 OOB 通信只能在一個(gè)方向上進(jìn)行(單方向傳輸數(shù)據(jù)),則接收 OOB 數(shù)據(jù)的設(shè)備的認(rèn)證將基于該設(shè)備知道通過 OOB 發(fā)送的隨機(jī)數(shù) r(ra或rb)。在這種情況下,r 必須是保密的:r 可以每次重新創(chuàng)建,或者必須限制對(duì)發(fā)送 r 的設(shè)備的訪問。如果設(shè)備未發(fā)送 r,則設(shè)備會(huì)將其假定為 0。計(jì)算出的確認(rèn)值必須與接收到的 OOB 值匹配。如果兩者之一不匹配,配對(duì)將中止。

2.4 Authentication Stage 2

身份驗(yàn)證階段 2 有四個(gè)步驟。

1)使用函數(shù) f5 計(jì)算長期密鑰 (LTK) 和 MacKey ,MacKey || LTK = f5(DHKey, Na, Nb, BD_ADDR_C, BD_ADDR_P)

2)設(shè)備 A 計(jì)算稱為 Ea 的檢查值并將其發(fā)送到設(shè)備 B,在設(shè)備 B 中重新計(jì)算該值并將其與收到的值進(jìn)行比較

3)設(shè)備 B 計(jì)算稱為 Eb 的檢查值并將其發(fā)送到設(shè)備 A,在設(shè)備 A 中重新計(jì)算該值并將其與收到的值進(jìn)行比較

4)使用計(jì)算出的 LTK 在鏈路上啟動(dòng)加密,為階段 3 做好準(zhǔn)備

如果步驟 2 或 3 中的任何一個(gè)檢查失敗,配對(duì)將中止。具體流程如下圖所示:

wKgZO2hnOFeAcit0AAC5_TuOYjw49.jpeg

(3) 密鑰分發(fā)

對(duì)于傳統(tǒng)配對(duì)和LE安全連接,它們分發(fā)的內(nèi)容是有區(qū)別的。另外,傳統(tǒng)配對(duì)密鑰分發(fā)的鏈路是通過STK加密的;LE安全連接的密鑰分發(fā)是通過LTK加密的。傳統(tǒng)配對(duì)可能分發(fā)的內(nèi)容如下:

LTK by the Peripheral

EDIV AND Rand by the Peripheral

IRK by the Peripheral

BD_ADDR by the Peripheral

CSRK by the Peripheral

LTK by the Central

EDIV and Rand by the Central

IRK by the Central

BD_ADDR by the Central

CSRK by the Central

LE安全連接可能分發(fā)的內(nèi)容如下:

IRK by the Peripheral

BD_ADDR by the Peripheral

CSRK by the Peripheral

IRK by the Central

BD_ADDR by the Central

CSRK by the Central

七. Bluetooth LE綁定

創(chuàng)建綁定后,每個(gè)設(shè)備都會(huì)存儲(chǔ)已分發(fā)的密鑰信息,并在下一次連接中使用這些密鑰,這樣就可以跳過配對(duì)過程,從而節(jié)省能源并減少用戶操作設(shè)備時(shí)必須等待的時(shí)間。

LTK 存儲(chǔ)在安全數(shù)據(jù)庫中,并通過 EDIV 和 Rand 值進(jìn)行標(biāo)識(shí)。執(zhí)行綁定后,每次后續(xù)重新連接都將使用已分發(fā)的 LTK 生成的密鑰來加密鏈接。

NCS中可以通過配置編譯選項(xiàng)使能綁定功能(CONFIG_BT_BONDABLE=y)。注意,綁定信息存儲(chǔ)在settings區(qū),更具體的是bt settings區(qū)域,所以,使能綁定功能的同時(shí)也要使能bt settings區(qū)。具體信息如下:

wKgZPGhnOFiAeapjAAA72Uxf3Gg40.jpegwKgZO2hnOFmAPBZFAAC6xTJv6DM14.jpegwKgZPGhnOFmARdGhAABB4AbmBb497.jpeg

如果要?jiǎng)h除綁定信息,可以調(diào)用int bt_unpair(uint8_t id, const bt_addr_le_t *addr)函數(shù),函數(shù)說明和使用示例如下:

/**
* @brief Clear pairing information.
*
* @param id  Local identity (mostly just BT_ID_DEFAULT).
* @param addr Remote address, NULL or BT_ADDR_LE_ANY to clear all remote devices.
*
* @return 0 on success or negative error value on failure.
*/
int bt_unpair(unit8_t id, const bt_addr_le_t *addr);
void button_changed(unit32_t button_state,unit32_t has_changed)
{
     int err;
     unit32_t buttons = button_state & has_changed;

     if(buttons & KEY_BOND_REMOVE_MASK) {
        err = bt_unpair(BT_ID_DEFAULT,NULL);
        if (err) {
          printk("Bond remove failed err: %dn", err);
        } else {
            printk("All bond removedn");
        }
     }
}
static int remove_peers(unit8_t identity)
{
    LOG_INF("Remove peer on identity %u", identity);

    int err = bt_unpair(get_bt_stack_peer_id(identity), BT_ADDR_LE_ANY);
    if (err) {
        LOG_ERR("Failed to remove");
    }
    return err;
}

八. NCS中如何開啟和使用SMP相關(guān)功能

(1) 開啟SMP功能

SMP協(xié)議對(duì)應(yīng)的代碼主要位于zephyrsubsysbluetoothhostsmp.c

設(shè)置CONFIG_BT_SMP=y可以加入smp.c到當(dāng)前工程。

config BT_SMP
    bool "Security Manager Protocol support"
    select BT_CRYPTO
    select BT_RPA
    select BT_ECC
    help
      This option enables support for the Security Manager Protocol
      (SMP), making it possible to pair devices over LE.
if(CONFIG_BT_CONN)
  zephyr_library_sources(
    conn.c
    12cap.c
    att.c
    gatt.c
    )
  if(CONFIG_BT_SMP)
    zephyr_library_sources(
      smp.c
      keys.c
      )
  else()
    zephyr_library_sources(
      smp_null.c
      )
  endif()
endif()

NCS中SMP的主要例子包括:

nrfsamplesbluetoothcentral_hids

nrfsamplesbluetoothperipheral_uart

nrfsamplesbluetoothperipheral_mds

nrfsamplesbluetoothperipheral_nfc_pairing

nrfsamplesbluetoothcentral_nfc_pairing

zephyrsamplesbluetoothperipheral_sc_only

zephyrsubsysbluetoothshell

Bluetooth LE例子里,只要設(shè)置了CONFIG_BT_SMP=y,至少支持just works

(2) 如何設(shè)置SC(安全連接)標(biāo)志

NCS中使能SMP的Nordic的例子里,默認(rèn)都是SC。SC需要用到很多安全算法,Nordic的芯片都能支持。為了保證Bluetooth LE通信的安全性,我們建議用SC的方式。但如果客戶資源(RAM,flash)不夠用,且對(duì)Bluetooth LE安全要求不高的情況下,可以關(guān)閉SC,使用傳統(tǒng)配對(duì)。

SC設(shè)置相關(guān)代碼段:

int bt_smp_init(void)
{
	static struct bt_pub_key_cb pub_key_cb = {
		.func           = bt_smp_pkey_ready,
	};

	sc_supported = le_sc_supported();
	if (IS_ENABLED(CONFIG_BT_SMP_SC_PAIR_ONLY) && !sc_supported) {
		LOG_ERR("SC Pair Only Mode selected but LE SC not supported");
		return -ENOENT;
	}

	if (IS_ENABLED(CONFIG_BT_SMP_USB_HCI_CTLR_WORKAROUND)) {
		LOG_WRN("BT_SMP_USB_HCI_CTLR_WORKAROUND is enabled, which "
			"exposes a security vulnerability!");
	}

	LOG_DBG("LE SC %s", sc_supported ? "enabled" : "disabled");

	if (!IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
		bt_pub_key_gen(&pub_key_cb);
	}

	return smp_self_test();
}
static bool le_sc_supported(void)
{
	/*
	 * If controller based ECC is to be used it must support
	 * "LE Read Local P-256 Public Key" and "LE Generate DH Key" commands.
	 * Otherwise LE SC are not supported.
	 */
	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
		return false;
	}

	return BT_CMD_TEST(bt_dev.supported_commands, 34, 1) &&
	       BT_CMD_TEST(bt_dev.supported_commands, 34, 2);
}
static void read_supported_commands_complete(struct net_buf *buf)
{
	struct bt_hci_rp_read_supported_commands *rp = (void *)buf->data;

	LOG_DBG("status 0x%02x", rp->status);

	memcpy(bt_dev.supported_commands, rp->commands,
	       sizeof(bt_dev.supported_commands));

	/* Report additional HCI commands used for ECDH as
	 * supported if TinyCrypt ECC is used for emulation.
	 */
	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
		bt_hci_ecc_supported_commands(bt_dev.supported_commands);
	}
}
void bt_hci_ecc_supported_commands(uint8_t *supported_commands)
{
	/* LE Read Local P-256 Public Key */
	supported_commands[34] |= BIT(1);
	/* LE Generate DH Key v1 */
	supported_commands[34] |= BIT(2);
	/* LE Generate DH Key v2 */
	supported_commands[41] |= BIT(2);
}
#if defined(CONFIG_BT_CTLR_ECDH)
	case BT_HCI_OP_LE_P256_PUBLIC_KEY:
		return hci_cmd_le_read_local_p256_public_key();
	case BT_HCI_OP_LE_GENERATE_DHKEY:
		return hci_cmd_le_generate_dhkey((void *)cmd_params);
	case BT_HCI_OP_LE_GENERATE_DHKEY_V2:
		return hci_cmd_le_generate_dhkey_v2((void *)cmd_params);
#endif

1) 使用OOB的情況下,通過設(shè)置CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY=y去指定非SC。

config BT_SMP_OOB_LEGACY_PAIR_ONLY
    bool "Force Out Of Band Legacy pairing"
    depends on !(BT_SMP_SC_PAIR_ONLY || BT_SMP_SC_ONLY)
    help
      This option disables Legacy and LE SC pairing and forces legacy OOB.

2) 不使用OOB的情況下,設(shè)置CONFIG_BT_CTLR_ECDH=n和CONFIG_BT_TINYCRYPT_ECC=n。關(guān)閉安全算法的情況下,系統(tǒng)會(huì)使用傳統(tǒng)配對(duì)。

config BT_CTLR_ECDH
    bool "Elliptic Curve Diffie-Hellman (ECDH)"
    depends on BT_CTLR_ECDH_SUPPORT
    default y
    help
      Enable support for Bluetooth v4.2 Elliptic Curve Diffie-Hellman
      feature in the controller.
config BT_TINYCRYPT_ECDH
    bool "Emulate ECDH in the Host using TinyCrypt library"
    select TINYCRYPT
    select TINYCRYPT_ECC_DH
    select BT_LONG_WQ
    depends on BT_ECC && (BT_HCI_RAW || BT_HCI_HOST)
    default y if BT_CTLR && !BT_CTLR_ECDH
    help
    If this option is set TinyCrypt library is used for emulating the
    ECDH HCI commands and events need by e.g LE Secure Connections.
    In builds including the BLE Host, if not set the controller crypto is
    used for ECDH and if the controller doesn't support the required HCI
    commands the LE Secure Connections support will be disable.
    In builds including the HCI RAW interface and the BLE Controller, this
    option injects support for the 2 HCI commands required for LE Secure
    Connections so that Hosts can make use of those. The option defaults
    to enable for a combined build with Zephyr's own controller, since it
    does not have any special ECC support itself (at least not currently).

另外,調(diào)用int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec)函數(shù)時(shí),第二個(gè)參數(shù)如果是BT_SECURITY_L4,且I/O能力滿足條件,則會(huì)發(fā)起SC;否則,使用傳統(tǒng)配對(duì)。

/** @brief Set security level for a connection.
 *
 *  This function enable security (encryption) for a connection. If the device
 *  has bond information for the peer with sufficiently strong key encryption
 *  will be enabled. If the connection is already encrypted with sufficiently
 *  strong key this function does nothing.
 *
 *  If the device has no bond information for the peer and is not already paired
 *  then the pairing procedure will be initiated. Note that @p sec has no effect
 *  on the security level selected for the pairing process. The selection is
 *  instead controlled by the values of the registered @ref bt_conn_auth_cb. If
 *  the device has bond information or is already paired and the keys are too
 *  weak then the pairing procedure will be initiated.
 *
 *  This function may return error if required level of security is not possible
 *  to achieve due to local or remote device limitation (e.g., input output
 *  capabilities), or if the maximum number of paired devices has been reached.
 *
 *  This function may return error if the pairing procedure has already been
 *  initiated by the local device or the peer device.
 *
 *  @note When @kconfig{CONFIG_BT_SMP_SC_ONLY} is enabled then the security
 *        level will always be level 4.
 *
 *  @note When @kconfig{CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY} is enabled then the
 *        security level will always be level 3.
 *
 *  @note When @ref BT_SECURITY_FORCE_PAIR within @p sec is enabled then the pairing
 *        procedure will always be initiated.
 *
 *  @param conn Connection object.
 *  @param sec Requested security level.
 *
 *  @return 0 on success or negative error
 */
int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec);

注:是否使用SC,需要兩方協(xié)商,一方不能決定。

(3) 如何設(shè)置MITM標(biāo)志

通過設(shè)定CONFIG_BT_SMP_ENFORCE_MITM=y編譯選項(xiàng),可以強(qiáng)制設(shè)置MITM標(biāo)志。

config BT_SMP_ENFORCE_MITM
    bool "Enforce MITM protection"
    default y
    help
      with this option enabled, the Security Manager will set MITM option in
      the Authentication Requirements Flags whenever local IO Capabilities
      allow the generated key to be authenticated.
static uint8_t get_auth(struct bt_smp *smp, uint8_t auth)
{
	struct bt_conn *conn = smp->chan.chan.conn;

	if (sc_supported) {
		auth &= BT_SMP_AUTH_MASK_SC;
	} else {
		auth &= BT_SMP_AUTH_MASK;
	}

	if ((get_io_capa(smp) == BT_SMP_IO_NO_INPUT_OUTPUT) ||
	    (!IS_ENABLED(CONFIG_BT_SMP_ENFORCE_MITM) &&
	    (conn->required_sec_level < BT_SECURITY_L3))) {
		auth &= ~(BT_SMP_AUTH_MITM);
	} else {
		auth |= BT_SMP_AUTH_MITM;
	}

	if (latch_bondable(smp)) {
		auth |= BT_SMP_AUTH_BONDING;
	} else {
		auth &= ~BT_SMP_AUTH_BONDING;
	}

	if (IS_ENABLED(CONFIG_BT_PASSKEY_KEYPRESS)) {
		auth |= BT_SMP_AUTH_KEYPRESS;
	} else {
		auth &= ~BT_SMP_AUTH_KEYPRESS;
	}

	return auth;
}

當(dāng)CONFIG_BT_SMP_ENFORCE_MITM=n時(shí),SC flag和I/O能力共同決定了MITM flag。

下圖中Authenticated對(duì)應(yīng)的MITM=1,Unauthenticated對(duì)應(yīng)的MITM=0。

wKgZO2hnOFqAZRUeAAFLt207zdM16.jpeg

(4) 如何設(shè)置OOB數(shù)據(jù) flag

準(zhǔn)備好OOB數(shù)據(jù)后,通過調(diào)用API函數(shù)設(shè)置此flag。SC和非SC的設(shè)置函數(shù)分別如下:

/** @brief Allow/disallow remote LE SC OOB data to be used for pairing.
 *
 *  Set/clear the OOB data flag for LE SC SMP Pairing Request/Response data.
 *
 *  @param enable Value allowing/disallowing remote LE SC OOB data.
 */
void bt_le_oob_set_sc_flag(bool enable);
/** @brief Allow/disallow remote legacy OOB data to be used for pairing.
 *
 *  Set/clear the OOB data flag for legacy SMP Pairing Request/Response data.
 *
 *  @param enable Value allowing/disallowing remote legacy OOB data.
 */
void bt_le_oob_set_legacy_flag(bool enable);

/** @brief Set OOB Temporary Key to be used for pairing
 *
 *  This function allows to set OOB data for the LE legacy pairing procedure.
 *  The function should only be called in response to the oob_data_request()
 *  callback provided that the legacy method is user pairing.
 *
 *  @param conn Connection object
 *  @param tk Pointer to 16 byte long TK array
 *
 *  @return Zero on success or -EINVAL if NULL
 */

OOB數(shù)據(jù) flag設(shè)置相關(guān)的代碼片段:

void bt_le_oob_set_sc_flag(bool enable)
{
	sc_oobd_present = enable;
}

void bt_le_oob_set_legacy_flag(bool enable)
{
	legacy_oobd_present = enable;
}
	/* At this point is it unknown if pairing will be legacy or LE SC so
	 * set OOB flag if any OOB data is present and assume to peer device
	 * provides OOB data that will match it's pairing type.
	 */
	req->oob_flag = (legacy_oobd_present || sc_oobd_present) ?
				BT_SMP_OOB_PRESENT : BT_SMP_OOB_NOT_PRESENT;
	if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
		rsp->oob_flag = sc_oobd_present ? BT_SMP_OOB_PRESENT :
				BT_SMP_OOB_NOT_PRESENT;
	} else {
		rsp->oob_flag = legacy_oobd_present ? BT_SMP_OOB_PRESENT :
				BT_SMP_OOB_NOT_PRESENT;
	}

從配對(duì)的過程來看,OOB的數(shù)據(jù)在兩個(gè)階段中使用,一個(gè)階段是帶外數(shù)據(jù)交互,另一個(gè)階段是身份驗(yàn)證的過程中充當(dāng)參數(shù)。

非SC的OOB帶外需要交互TK值。TK值實(shí)際上也是一個(gè)Random Number。

SC 的OOB帶外需要交互Random Number和Confirm Value。

另外還有一些附加的輔助信息。我們peripheral_nfc_pairing和central_nfc_pairing例子里面,NFC的信息如下(兼容支持SC和非SC):

/**
 * @brief LE OOB record payload descriptor.
 */
struct nfc_ndef_le_oob_rec_payload_desc {
	bt_addr_le_t *addr;
	enum nfc_ndef_le_oob_rec_le_role *le_role;
	struct bt_le_oob_sc_data *le_sc_data;
	uint8_t *tk_value;
	uint16_t *appearance;
	uint8_t *flags;
	const char *local_name;
};
/** .. include_startingpoint_nfc_tnep_ch_tag_rst */
static int carrier_prepare(void)
{
	static struct nfc_ndef_le_oob_rec_payload_desc rec_payload;

	NFC_NDEF_LE_OOB_RECORD_DESC_DEF(oob_rec, '0', &rec_payload);
	NFC_NDEF_CH_AC_RECORD_DESC_DEF(oob_ac, NFC_AC_CPS_ACTIVE, 1, "0", 0);

	memset(&rec_payload, 0, sizeof(rec_payload));

	rec_payload.addr = &oob_local.addr;
	rec_payload.le_sc_data = &oob_local.le_sc_data;
	rec_payload.tk_value = tk_value;
	rec_payload.local_name = bt_get_name();
	rec_payload.le_role = NFC_NDEF_LE_OOB_REC_LE_ROLE(
		NFC_NDEF_LE_OOB_REC_LE_ROLE_PERIPH_ONLY);
	rec_payload.appearance = NFC_NDEF_LE_OOB_REC_APPEARANCE(
		CONFIG_BT_DEVICE_APPEARANCE);
	rec_payload.flags = NFC_NDEF_LE_OOB_REC_FLAGS(BT_LE_AD_NO_BREDR);

	return nfc_tnep_ch_carrier_set(&NFC_NDEF_CH_AC_RECORD_DESC(oob_ac),
				       &NFC_NDEF_LE_OOB_RECORD_DESC(oob_rec),
				       1);
}
/** LE Secure Connections pairing Out of Band data. */
struct bt_le_oob_sc_data {
	/** Random Number. */
	uint8_t r[16];

	/** Confirm Value. */
	uint8_t c[16];
};

/** LE Out of Band information. */
struct bt_le_oob {
	/** LE address. If privacy is enabled this is a Resolvable Private
	 *  Address.
	 */
	bt_addr_le_t addr;

	/** LE Secure Connections pairing Out of Band data. */
	struct bt_le_oob_sc_data le_sc_data;
};

通過int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob)或int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv, struct bt_le_oob *oob)可以從controller獲取本地生成的SC OOB數(shù)據(jù)。這個(gè)數(shù)據(jù)需要寫入帶外設(shè)備,如NFC 設(shè)備。

/**
 * @brief Get local LE Out of Band (OOB) information.
 *
 * This function allows to get local information that are useful for
 * Out of Band pairing or connection creation.
 *
 * If privacy @kconfig{CONFIG_BT_PRIVACY} is enabled this will result in
 * generating new Resolvable Private Address (RPA) that is valid for
 * @kconfig{CONFIG_BT_RPA_TIMEOUT} seconds. This address will be used for
 * advertising started by @ref bt_le_adv_start, active scanning and
 * connection creation.
 *
 * @note If privacy is enabled the RPA cannot be refreshed in the following
 *       cases:
 *       - Creating a connection in progress, wait for the connected callback.
 *      In addition when extended advertising @kconfig{CONFIG_BT_EXT_ADV} is
 *      not enabled or not supported by the controller:
 *       - Advertiser is enabled using a Random Static Identity Address for a
 *         different local identity.
 *       - The local identity conflicts with the local identity used by other
 *         roles.
 *
 * @param[in]  id  Local identity, in most cases BT_ID_DEFAULT.
 * @param[out] oob LE OOB information
 *
 * @return Zero on success or error code otherwise, positive in case of
 *         protocol error or negative (POSIX) in case of stack internal error.
 */
int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob);
/**
 * @brief Get local LE Out of Band (OOB) information.
 *
 * This function allows to get local information that are useful for
 * Out of Band pairing or connection creation.
 *
 * If privacy @kconfig{CONFIG_BT_PRIVACY} is enabled this will result in
 * generating new Resolvable Private Address (RPA) that is valid for
 * @kconfig{CONFIG_BT_RPA_TIMEOUT} seconds. This address will be used by the
 * advertising set.
 *
 * @note When generating OOB information for multiple advertising set all
 *       OOB information needs to be generated at the same time.
 *
 * @note If privacy is enabled the RPA cannot be refreshed in the following
 *       cases:
 *       - Creating a connection in progress, wait for the connected callback.
 *
 * @param[in]  adv The advertising set object
 * @param[out] oob LE OOB information
 *
 * @return Zero on success or error code otherwise, positive in case
 * of protocol error or negative (POSIX) in case of stack internal error.
 */
int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv,
				struct bt_le_oob *oob);

通過調(diào)用int bt_le_oob_set_sc_data(struct bt_conn *conn, const struct bt_le_oob_sc_data *oobd_local, const struct bt_le_oob_sc_data *oobd_remote)可以設(shè)置SC OOB配對(duì)過程中,身份認(rèn)證階段所需要的數(shù)據(jù)。

/** @brief Set OOB data during LE Secure Connections (SC) pairing procedure
 *
 *  This function allows to set OOB data during the LE SC pairing procedure.
 *  The function should only be called in response to the oob_data_request()
 *  callback provided that LE SC method is used for pairing.
 *
 *  The user should submit OOB data according to the information received in the
 *  callback. This may yield three different configurations: with only local OOB
 *  data present, with only remote OOB data present or with both local and
 *  remote OOB data present.
 *
 *  @param conn Connection object
 *  @param oobd_local Local OOB data or NULL if not present
 *  @param oobd_remote Remote OOB data or NULL if not present
 *
 *  @return Zero on success or error code otherwise, positive in case of
 *          protocol error or negative (POSIX) in case of stack internal error.
 */
int bt_le_oob_set_sc_data(struct bt_conn *conn,
			  const struct bt_le_oob_sc_data *oobd_local,
			  const struct bt_le_oob_sc_data *oobd_remote);

非SC的OOB,通過int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk)設(shè)置身份認(rèn)證階段所需要的tk。

/** @brief Set OOB Temporary Key to be used for pairing
 *
 *  This function allows to set OOB data for the LE legacy pairing procedure.
 *  The function should only be called in response to the oob_data_request()
 *  callback provided that the legacy method is user pairing.
 *
 *  @param conn Connection object
 *  @param tk Pointer to 16 byte long TK array
 *
 *  @return Zero on success or -EINVAL if NULL
 */
int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk);

(5) 如何設(shè)置IO能力

IO能力有如下5種:

#define BT_SMP_IO_DISPLAY_ONLY			0x00
#define BT_SMP_IO_DISPLAY_YESNO			0x01
#define BT_SMP_IO_KEYBOARD_ONLY			0x02
#define BT_SMP_IO_NO_INPUT_OUTPUT		0x03
#define BT_SMP_IO_KEYBOARD_DISPLAY		0x04

首先看看獲取IO能力函數(shù)uint8_t get_io_capa(struct bt_smp *smp)的實(shí)現(xiàn),如下圖:

static uint8_t get_io_capa(struct bt_smp *smp)
{
	const struct bt_conn_auth_cb *smp_auth_cb = latch_auth_cb(smp);

	if (!smp_auth_cb) {
		goto no_callbacks;
	}

	/* Passkey Confirmation is valid only for LE SC */
	if (smp_auth_cb->passkey_display && smp_auth_cb->passkey_entry &&
	    (smp_auth_cb->passkey_confirm || !sc_supported)) {
		return BT_SMP_IO_KEYBOARD_DISPLAY;
	}

	/* DisplayYesNo is useful only for LE SC */
	if (sc_supported && smp_auth_cb->passkey_display &&
	    smp_auth_cb->passkey_confirm) {
		return BT_SMP_IO_DISPLAY_YESNO;
	}

	if (smp_auth_cb->passkey_entry) {
		if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
		    fixed_passkey != BT_PASSKEY_INVALID) {
			return BT_SMP_IO_KEYBOARD_DISPLAY;
		} else {
			return BT_SMP_IO_KEYBOARD_ONLY;
		}
	}

	if (smp_auth_cb->passkey_display) {
		return BT_SMP_IO_DISPLAY_ONLY;
	}

no_callbacks:
	if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
	    fixed_passkey != BT_PASSKEY_INVALID) {
		return BT_SMP_IO_DISPLAY_ONLY;
	} else {
		return BT_SMP_IO_NO_INPUT_OUTPUT;
	}
}

上面的代碼能看到一個(gè)關(guān)鍵的結(jié)構(gòu)體struct bt_conn_auth_cb,結(jié)構(gòu)體的定義如下圖:

結(jié)構(gòu)體對(duì)應(yīng)變量的成員都是callback函數(shù)。部分callback函數(shù)定義與否,決定了本設(shè)備的IO能力。

1)no callbacks的情況下,如果沒有設(shè)置CONFIG_BT_FIXED_PASSKEY,那么IO能力就是BT_SMP_IO_NO_INPUT_OUTPUT;如果設(shè)置CONFIG_BT_FIXED_PASSKEY=y且fixed_passkey != BT_PASSKEY_INVALID,那么IO能力就是BT_SMP_IO_DISPLAY_ONLY

config BT_FOEXED_PASSKEY
    bool "Use a fixed passkey for pairing"
    help
      With this option enabled, the application will be able to call the
      bt_passley_set() API to set a fixed passkey. If set, the
      pairing_confirm() callback will be called for all incoming pairings.

注:如果使用fixed passkey,應(yīng)用需要調(diào)用bt_passkey_set()函數(shù)去設(shè)置passkey。沒有IO能力的設(shè)備,通過使用fixed passkey,可以偽裝成有display能力的設(shè)備走passkey entry的配對(duì)流程。本設(shè)備和對(duì)方設(shè)備需要共同知道這個(gè)passkey,因?yàn)樗鼪]有真正被顯示出來(對(duì)方也需要有輸入passkey的能力),且passkey不能暴露給不可信賴的第三方。

2)非no callbacks的情況下,如果定義了passkey_display,passkey_entry和passkey_confirm三個(gè) callbacks,那么IO能力是BT_SMP_IO_KEYBOARD_DISPLAY;如果定義了passkey_display和passkey_entry兩個(gè)callbacks且非SC, 那么IO能力也是BT_SMP_IO_KEYBOARD_DISPLAY

3)非no callbacks的情況下,如果定義了passkey_display和passkey_confirm兩個(gè)callbacks且SC, 那么IO能力是BT_SMP_IO_DISPLAY_YESNO

4)非no callbacks的情況下,如果只定義了passkey_entry一個(gè)callback,當(dāng)CONFIG_BT_FIXED_PASSKEY=y且fixed_passkey != BT_PASSKEY_INVALID時(shí),IO能力是BT_SMP_IO_KEYBOARD_DISPLAY,否則,IO能力是BT_SMP_IO_ KEYBOARD _ONLY

注:如果使用fixed passkey,那么相當(dāng)與只有KEYBOARD輸入的設(shè)備,偽裝成了有KEYBOARD輸入和DISPLAY輸出能力的設(shè)備。

5)非no callbacks的情況下,如果只定義了passkey_display一個(gè)callback,IO能力是BT_SMP_IO_DISPLAY_ONLY

注意,最終的配對(duì)方式和行為是本設(shè)備的綜合能力和對(duì)方設(shè)備的綜合能力共同決定的。用戶在設(shè)計(jì)自己應(yīng)用的時(shí)候需要根據(jù)自己設(shè)備實(shí)際的IO能力和設(shè)備角色(central/peripheral)去做配置和編寫相應(yīng)的代碼,同時(shí)也要考慮安全性和兼容性。

如何配置IO能力

定義和實(shí)現(xiàn)好相關(guān)的callback函數(shù)就可以控制IO能力了。IO能力越強(qiáng)的設(shè)備,如果要做好兼容性,代碼的復(fù)雜性會(huì)更高一些。拿從機(jī)來舉例,如果沒有輸入輸出能力,那么只能支持Jusk works(fixed passkey除外),也只需要支持Jusk works;如果只有display的能力,如下圖,它需要兼容Jusk works和 passkey entry(passkey display)

如果有display和Keyboard的能力,如下圖,它需要兼容Jusk works, passkey entry(passkey input,passkey display)和Numeric Comparison

(6)結(jié)構(gòu)體struct bt_conn_auth_cb callback主要函數(shù)的作用

passkey_display callback的作用是從底層向應(yīng)用層提供passkey。Passkey entry配對(duì)過程中,這個(gè)passkey需要通過本機(jī)的顯示接口展示給用戶。用戶再將這個(gè)passkey通過對(duì)端設(shè)備的輸入接口輸入給對(duì)端。正常情況下,用戶只會(huì)給他信任的設(shè)備輸入passkey,passkey起到了身份驗(yàn)證的作用。nrfsamplesbluetoothperipheral_uart例子演示了passkey_display callback的使用方法。

	/** @brief Display a passkey to the user.
	 *
	 *  When called the application is expected to display the given
	 *  passkey to the user, with the expectation that the passkey will
	 *  then be entered on the peer device. The passkey will be in the
	 *  range of 0 - 999999, and is expected to be padded with zeroes so
	 *  that six digits are always shown. E.g. the value 37 should be
	 *  shown as 000037.
	 *
	 *  This callback may be set to NULL, which means that the local
	 *  device lacks the ability do display a passkey. If set
	 *  to non-NULL the cancel callback must also be provided, since
	 *  this is the only way the application can find out that it should
	 *  stop displaying the passkey.
	 *
	 *  @param conn Connection where pairing is currently active.
	 *  @param passkey Passkey to show to the user.
	 */
	void (*passkey_display)(struct bt_conn *conn, unsigned int passkey);

#if defined(CONFIG_BT_PASSKEY_KEYPRESS)
	/** @brief Receive Passkey Keypress Notification during pairing
	 *
	 *  This allows the remote device to use the local device to give users
	 *  feedback on the progress of entering the passkey over there. This is
	 *  useful when the remote device itself has no display suitable for
	 *  showing the progress.
	 *
	 *  The handler of this callback is expected to keep track of the number
	 *  of digits entered and show a password-field-like feedback to the
	 *  user.
	 *
	 *  This callback is only relevant while the local side does Passkey
	 *  Display.
	 *
	 *  The event type is verified to be in range of the enum. No other
	 *  sanitization has been done. The remote could send a large number of
	 *  events of any type in any order.
	 *
	 *  @param conn The related connection.
	 *  @param type Type of event. Verified in range of the enum.
	 */
	void (*passkey_display_keypress)(struct bt_conn *conn,
					 enum bt_conn_auth_keypress type);
#endif

passkey_entry callback的作用是提示用戶輸入passkey。Passkey entry配對(duì)過程中,等待用戶輸入passkey的時(shí)候,這個(gè)callback函數(shù)被調(diào)用。當(dāng)passkey被用戶輸入后,應(yīng)用需要調(diào)用bt_conn_auth_passkey_entry()API,將passkey從應(yīng)用層傳到底層。nrfapplicationsnrf_desktopsrcmodulesble_passkey.c例子演示了passkey_entry callback的使用方法。

	/** @brief Request the user to enter a passkey.
	 *
	 *  When called the user is expected to enter a passkey. The passkey
	 *  must be in the range of 0 - 999999, and should be expected to
	 *  be zero-padded, as that's how the peer device will typically be
	 *  showing it (e.g. 37 would be shown as 000037).
	 *
	 *  Once the user has entered the passkey its value should be given
	 *  to the stack using the bt_conn_auth_passkey_entry() API.
	 *
	 *  This callback may be set to NULL, which means that the local
	 *  device lacks the ability to enter a passkey. If set to non-NULL
	 *  the cancel callback must also be provided, since this is the
	 *  only way the application can find out that it should stop
	 *  requesting the user to enter a passkey.
	 *
	 *  @param conn Connection where pairing is currently active.
	 */
	void (*passkey_entry)(struct bt_conn *conn);

passkey_confirm callback的作用是從底層向應(yīng)用層提供 passkey(user confirm value)并提示用戶是否確認(rèn)。Numeric Comparison方式的配對(duì)過程中,兩邊的設(shè)備都會(huì)計(jì)算出一個(gè)數(shù)字(user confirm value),需要給用戶確認(rèn),確認(rèn)它們是否相同。如果兩邊的數(shù)字相同,說明這兩個(gè)設(shè)備是可以被用戶信任的。用戶確認(rèn)后,配對(duì)才能繼續(xù)。passkey_display提供的passkey實(shí)際上是user confirm value。另外,如果用戶確認(rèn)兩邊的數(shù)字相同,應(yīng)用需要調(diào)用bt_conn_auth_passkey_confirm()API去通知底層確認(rèn)值匹配;如果不同,應(yīng)用需要調(diào)用bt_conn_auth_cancel()API去通知底層確認(rèn)值不匹配。nrfsamplesbluetoothperipheral_uart例子演示了passkey_confirm callback的使用方法。

	/** @brief Request the user to confirm a passkey.
	 *
	 *  When called the user is expected to confirm that the given
	 *  passkey is also shown on the peer device.. The passkey will
	 *  be in the range of 0 - 999999, and should be zero-padded to
	 *  always be six digits (e.g. 37 would be shown as 000037).
	 *
	 *  Once the user has confirmed the passkey to match, the
	 *  bt_conn_auth_passkey_confirm() API should be called. If the
	 *  user concluded that the passkey doesn't match the
	 *  bt_conn_auth_cancel() API should be called.
	 *
	 *  This callback may be set to NULL, which means that the local
	 *  device lacks the ability to confirm a passkey. If set to non-NULL
	 *  the cancel callback must also be provided, since this is the
	 *  only way the application can find out that it should stop
	 *  requesting the user to confirm a passkey.
	 *
	 *  @param conn Connection where pairing is currently active.
	 *  @param passkey Passkey to be confirmed.
	 */
	void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey);

pairing_confirm callback和IO能力沒有關(guān)系,它用來通知應(yīng)用,收到了pairing request請求。這里留出的接口,可以讓用戶做出是否同意配對(duì)的選擇。如果同意進(jìn)行配對(duì),那么應(yīng)用需要調(diào)用bt_conn_auth_pairing_confirm()API表示同意;如果用戶不同意進(jìn)行配對(duì),應(yīng)用可以調(diào)用bt_conn_auth_cancel()取消配對(duì)。當(dāng)使用fixed key或just works配對(duì)方式時(shí),可以定義這個(gè)callback函數(shù),提示用戶是否同意配對(duì),添加用戶的控制權(quán)。nrfsamplesbluetoothperipheral_mds例子演示了pairing_confirm callback的使用方法。

	/** @brief Request confirmation for an incoming pairing.
	 *
	 *  This callback will be called to confirm an incoming pairing
	 *  request where none of the other user callbacks is applicable.
	 *
	 *  If the user decides to accept the pairing the
	 *  bt_conn_auth_pairing_confirm() API should be called. If the
	 *  user decides to reject the pairing the bt_conn_auth_cancel() API
	 *  should be called.
	 *
	 *  This callback may be set to NULL, which means that the local
	 *  device lacks the ability to confirm a pairing request. If set
	 *  to non-NULL the cancel callback must also be provided, since
	 *  this is the only way the application can find out that it should
	 *  stop requesting the user to confirm a pairing request.
	 *
	 *  @param conn Connection where pairing is currently active.
	 */
	void (*pairing_confirm)(struct bt_conn *conn);

oob_data_request callback和IO能力也沒有關(guān)系,它用于OOB配對(duì),通知應(yīng)用,需要提供OOB數(shù)據(jù)了。當(dāng)應(yīng)用層準(zhǔn)備好這些數(shù)據(jù)后,需要調(diào)用bt_le_oob_set_sc_data() API(SC OOB)或bt_le_oob_set_legacy_tk() API(Legacy OOB)將數(shù)據(jù)傳給底層。nrfsamplesbluetoothcentral_nfc_pairing例子演示了oob_data_request callback的使用方法。


	/** @brief Request the user to provide Out of Band (OOB) data.
	 *
	 *  When called the user is expected to provide OOB data. The required
	 *  data are indicated by the information structure.
	 *
	 *  For LE Secure Connections OOB pairing, the user should provide
	 *  local OOB data, remote OOB data or both depending on their
	 *  availability. Their value should be given to the stack using the
	 *  bt_le_oob_set_sc_data() API.
	 *
	 *  This callback must be set to non-NULL in order to support OOB
	 *  pairing.
	 *
	 *  @param conn Connection where pairing is currently active.
	 *  @param info OOB pairing information.
	 */
	void (*oob_data_request)(struct bt_conn *conn,
				 struct bt_conn_oob_info *info);

pairing_accept callback只有在設(shè)置了CONFIG_BT_SMP_APP_PAIRING_ACCEPT=y的情況下,才能使用。pairing_accept和pairing_confirm的功能上有點(diǎn)重合。pairing_confirm收到pairing req會(huì)被調(diào)用;pairing_accept收到pairing req或rsp都會(huì)被調(diào)用。用戶通過它們可以去干預(yù)與和控制配對(duì)過程。nrfapplicationsnrf_desktopsrcmodulesfast_pair.c例子演示了pairing_accept callback的使用方法。

	 *  On any incoming pairing req/rsp this callback will be called for
	 *  the application to decide whether to allow for the pairing to
	 *  continue.
	 *
	 *  The pairing info received from the peer is passed to assist
	 *  making the decision.
	 *
	 *  As this callback is synchronous the application should return
	 *  a response value immediately. Otherwise it may affect the
	 *  timing during pairing. Hence, this information should not be
	 *  conveyed to the user to take action.
	 *
	 *  The remaining callbacks are not affected by this, but do notice
	 *  that other callbacks can be called during the pairing. Eg. if
	 *  pairing_confirm is registered both will be called for Just-Works
	 *  pairings.
	 *
	 *  This callback may be unregistered in which case pairing continues
	 *  as if the Kconfig flag was not set.
	 *
	 *  This callback is not called for BR/EDR Secure Simple Pairing (SSP).
	 *
	 *  @param conn Connection where pairing is initiated.
	 *  @param feat Pairing req/resp info.
	 */
	enum bt_security_err (*pairing_accept)(struct bt_conn *conn,
			      const struct bt_conn_pairing_feat *const feat);

cancel callback通知應(yīng)用,之前的用戶請求(密碼顯示、輸入 或確認(rèn))被取消了。應(yīng)用通過cancel callback函數(shù)可以提示用戶,配對(duì)被取消了。只要定義了

passkey_display、passkey_entry、 passkey_confirm 或 pairing_confirm,那么就必須定義cancel callback。

	/** @brief Cancel the ongoing user request.
	 *
	 *  This callback will be called to notify the application that it
	 *  should cancel any previous user request (passkey display, entry
	 *  or confirmation).
	 *
	 *  This may be set to NULL, but must always be provided whenever the
	 *  passkey_display, passkey_entry passkey_confirm or pairing_confirm
	 *  callback has been provided.
	 *
	 *  @param conn Connection where pairing is currently active.
	 */
	void (*cancel)(struct bt_conn *conn);

應(yīng)用使用bt_conn_auth_cb_register()函數(shù)注冊這些callback。例子片段如下:

//display only
static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = auth_passkey_display,
	.cancel = auth_cancel,
};
//Keyboard only
static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_entry = auth_passkey_entry,
	.cancel = auth_cancel,
};
//display yes no
static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = auth_passkey_display,
	.passkey_confirm = auth_passkey_confirm,
	.cancel = auth_cancel,
};
//Keyboard display
static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = auth_passkey_display,
	.passkey_entry = auth_passkey_entry,
	.passkey_confirm = auth_passkey_confirm,
	.cancel = auth_cancel,
};
err = bt_conn_auth_cb_register(&conn_auth_callbacks);

(7) 結(jié)構(gòu)體struct bt_conn_auth_info_cb用于通知應(yīng)用,配對(duì)結(jié)果(成功或失敗)以及綁定信息刪除結(jié)果。如果應(yīng)用對(duì)這些信息感興趣可以定義相應(yīng)的callback函數(shù)。


/** Authenticated pairing information callback structure */
struct bt_conn_auth_info_cb {
	/** @brief notify that pairing procedure was complete.
	 *
	 *  This callback notifies the application that the pairing procedure
	 *  has been completed.
	 *
	 *  @param conn Connection object.
	 *  @param bonded Bond information has been distributed during the
	 *                pairing procedure.
	 */
	void (*pairing_complete)(struct bt_conn *conn, bool bonded);

	/** @brief notify that pairing process has failed.
	 *
	 *  @param conn Connection object.
	 *  @param reason Pairing failed reason
	 */
	void (*pairing_failed)(struct bt_conn *conn,
			       enum bt_security_err reason);

	/** @brief Notify that bond has been deleted.
	 *
	 *  This callback notifies the application that the bond information
	 *  for the remote peer has been deleted
	 *
	 *  @param id   Which local identity had the bond.
	 *  @param peer Remote address.
	 */
	void (*bond_deleted)(uint8_t id, const bt_addr_le_t *peer);

	/** Internally used field for list handling */
	sys_snode_t node;
};

應(yīng)用使用bt_conn_auth_info_cb_register()函數(shù)注冊這些callback。例子片段如下:

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};
err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);

注:本文中的圖表主要摘自Bluetooth Core Specification,Bluetooth LE Security Study Guide以及Nordic官網(wǎng)資料;代碼摘自nRF Connect SDK 2.6.0。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • NRF
    NRF
    +關(guān)注

    關(guān)注

    0

    文章

    49

    瀏覽量

    38237
  • SDK
    SDK
    +關(guān)注

    關(guān)注

    3

    文章

    1077

    瀏覽量

    49070
  • Bluetooth LE
    +關(guān)注

    關(guān)注

    0

    文章

    323

    瀏覽量

    2498
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    泰凌微電子Bluetooth LE Audio Dongle方案介紹

    藍(lán)牙低功耗音頻(Bluetooth LE Audio)自2020年1月發(fā)布,到2022年7月完成全套規(guī)范的定義。Bluetooth LE Audio是新一代藍(lán)牙音頻技術(shù)標(biāo)準(zhǔn),采用了全新
    的頭像 發(fā)表于 09-27 08:40 ?4373次閱讀
    泰凌微電子<b class='flag-5'>Bluetooth</b> <b class='flag-5'>LE</b> Audio Dongle方案介紹

    Nordic 推出nRF Connect for Cloud 的無線物聯(lián)網(wǎng)設(shè)計(jì)方案

    Nordic Semiconductor宣布推出nRF Connect for Cloud,用于免費(fèi)評(píng)估、測試和驗(yàn)證基于云并且采用Nordic nRF51和nRF52系列多協(xié)議低功耗藍(lán)
    的頭像 發(fā)表于 06-21 15:05 ?9401次閱讀

    nRF Connect SDK(NCS)/Zephyr固件升級(jí)詳解 – 重點(diǎn)講述MCUboot和藍(lán)牙空中升級(jí)

    如何在nRF Connect SDK(NCS)實(shí)現(xiàn)藍(lán)牙空中升級(jí)?MCUboot和B0兩個(gè)Bootloader有什么區(qū)別?MCUboot升級(jí)使用的image格式是怎么樣的?什么是SMP
    的頭像 發(fā)表于 05-09 14:14 ?1783次閱讀
    <b class='flag-5'>nRF</b> <b class='flag-5'>Connect</b> <b class='flag-5'>SDK</b>(NCS)/Zephyr固件升級(jí)詳解 – 重點(diǎn)講述MCUboot和藍(lán)牙空中升級(jí)

    2.4GHz+5GHz雙頻低功耗 Wi-Fi 6協(xié)同IC -nRF7002

    AR/VR設(shè)備的創(chuàng)新浪潮,流暢、低延遲的無線連接是實(shí)現(xiàn)沉浸式體驗(yàn)的關(guān)鍵。nRF7002 Wi-Fi 6協(xié)同IC,憑借Wi-Fi 6+ Bluetooth
    發(fā)表于 02-26 14:54

    Nordic藍(lán)牙開發(fā)不用Keil用VS code了?

    。 nRF Connect SDK 包括來自 Zephyr 的中間件,如 MQTT 或用于安全的 Trusted Firmware-M。除此之外,n
    發(fā)表于 03-05 16:41

    Nordic nRF Connect SDK 官方開發(fā)文檔、學(xué)習(xí)資料下載鏈接

    /14174427.html nRF Connect SDK詳解 https://lgl88911.gitee.io/ 其他博客 https://academy.nordicsemi.com/courses
    發(fā)表于 04-23 13:48

    Bluetooth LE Link Layer數(shù)據(jù)包全解析

    Bluetooth LE有幾種空中包格式? 常見的PDU命令有哪些? PDU和MTU的區(qū)別是什么? DLE又是什么? Bluetooth LE怎么實(shí)現(xiàn)重傳的?
    發(fā)表于 06-03 10:28

    Bluetooth LE Packet格式

    ? Bluetooth LE鏈路層(link layer)只定義了一種packet(空中包)格式,如下所示: ?編輯 而且PDU(protocol data unit,協(xié)議數(shù)據(jù)單元)前兩個(gè)字節(jié)固定
    發(fā)表于 06-03 10:45

    NRF24LE1/NRF24LE1D-F16Q24/NRF24LE1E-F16Q32/NRF24LE1F-F16Q48長期現(xiàn)貨穩(wěn)定配合

    1-O17Q24 nRF24LE1-O17Q32nRF24LE1-O17Q48nRF24LU1P-F16Q32nRF24LU1P-O17Q32 nRF24LU1P-F32Q32以上Nordic系列芯片,現(xiàn)貨形式配合服務(wù),研發(fā)樣
    發(fā)表于 07-08 22:18

    nRF24LE1文數(shù)據(jù)手冊

    nRF24LE1文數(shù)據(jù)手冊
    發(fā)表于 07-17 10:46

    Bluetooth LE模塊的結(jié)構(gòu)是由哪些部分組成的?

    Bluetooth LE LSI的內(nèi)部結(jié)構(gòu)是怎樣構(gòu)成的?Bluetooth LE模塊的結(jié)構(gòu)是由哪些部分組成的?
    發(fā)表于 05-24 07:07

    nRF24LE1文手冊

    nRF24LE1的中文版資料。圖片部分不清晰,可對(duì)照英文版。
    發(fā)表于 04-14 17:05 ?60次下載

    nRF24LE1減少功耗的編程技巧

    關(guān)鍵詞:nRF24LE1 , 功耗 , 編程 無線世界,應(yīng)用無限 nRF24LE1減少功耗的編程技巧1.jpg(48.14 KB, 下載次數(shù): 42) 2012-4-20 17:42:18 上傳
    發(fā)表于 02-24 18:34 ?1029次閱讀
    <b class='flag-5'>nRF24LE</b>1減少功耗的編程技巧

    nRF24LE1功耗測試與計(jì)算

    關(guān)鍵詞:nRF24LE1 無線世界,應(yīng)用無限 nRF24LE1功耗測試與計(jì)算.jpg(91.86 KB, 下載次數(shù): 52) 2012-4-19 16:11:08 上傳 下載次數(shù): 52
    發(fā)表于 02-27 14:09 ?604次閱讀

    nRF24LE1的喚醒源

    關(guān)鍵詞:nRF24LE1 無線世界,應(yīng)用無限 nRF24LE1的喚醒源.jpg(87.94 KB, 下載次數(shù): 66) 2012-4-18 15:44:11 上傳 下載次數(shù): 66
    發(fā)表于 02-27 14:12 ?600次閱讀
    <b class='flag-5'>nRF24LE</b>1的喚醒源