NRF52832學習筆記(11)——藍牙MAC地址

一、背景

一個 BLE 設備,可以使用兩種類型的地址(一個 BLE 設備可同時具備兩種地址):

  • Public Device Address(公共設備地址)
  • Random Device Address(隨機設備地址)可分爲兩類:
    • Static Device Address(靜態設備地址)
    • Private Device Address(私密設備地址)又可分爲兩類:
      • Non-resolvable Private Address(不可解析私密地址)
      • Resolvable Private Address(可解析私密地址)

1.1 公共設備地址 Public Device Address

在通信系統中,設備地址是用來唯一識別一個物理設備的,如TCP/IP網絡中的MAC地址、傳統藍牙中藍牙地址等。對設備地址而言,一個重要的特性,就是唯一性。

對於經典藍牙(BR/EDR)來說,其設備地址是一個 48bits 的數字,稱作“48-bit universal LAN MAC address”。正常情況下,該地址需要向 IEEE 申請,具有唯一性。

這種地址分配方式在 BLE 中也保留了下來,就是公共設備地址(Public Device Address)。由 24-bit 的 company_id 和 24-bit 的 company_assigned 組成。

高 24 位是公司標識,低 24 位公司內部自己賦值。

1.2 隨機設備地址 Random Device Address

但是,在 BLE 時代,只有公共設備地址明顯不夠用了,有如下原因:

  1. 公共設備地址需要向 IEEE 購買,需要一筆開銷。
  2. 公共設備地址的申請與管理相對繁瑣、複雜,再加上 BLE 設備的數量衆多(和傳統藍牙設備不是一個數量級的),導致維護成本增大。
  3. 安全因素。BLE 很大一部分的應用場景是廣播通信,這意味着只要知道設備的地址,就可以獲取所有的信息,這是很不安全的。因此固定的設備地址,加大了信息泄露的風險。

爲了解決上述問題,BLE 協議新增了一種地址:隨機設備地址,即設備地址不是固定分配的,而是在設備啓動後隨機生成的。根據不同的目的,隨機設備地址分爲靜態設備地址和私密設備地址。

1.2.1 靜態設備地址 Static Device Address

靜態設備地址是設備在上電時隨機生成的地址,NRF52832 官方工程默認都是使用靜態地址,其格式如下:

靜態設備地址的特徵可總結爲:

  1. 最高兩個 bit 爲 “11”。
  2. 剩餘的 46bits 是一個隨機數,不能全部爲0,也不能全部爲1。
  3. 在一個上電週期內保持不變。
  4. 下一次上電的時候可以改變。但不是強制的,因此也可以保持不變。如果改變,上次保存的連接等信息,將不再有效。

靜態設備地址的使用場景可總結爲:

  1. 46bits 的隨機數,可以很好地解決“設備地址唯一性”的問題,因爲兩個地址相同的概率很小。
  2. 地址隨機生成,可以解決公共設備地址申請所帶來的費用和維護問題。

1.2.2 私密設備地址 Private Device Address

靜態設備地址通過地址隨機生成的方式,解決了部分問題。私密設備地址則更進一步,通過定時更新和地址加密兩種方式,提高藍牙地址的可靠性和安全性。根據設備地址是否加密,又分爲兩類:
① 不可解析私密地址 Non-resolvable Private Address
不可解析私密地址和靜態設備地址類似,不同之處在於不可解析私密地址會定時更新。更新的週期是由 GAP 規定的,稱作 T_GAP(private_addr_int),建議值是 15 分鐘。其格式如下:

不可解析私密地址的特徵可總結爲:

  1. 最高兩個 bit 爲 “00”。
  2. 剩餘的 46bits 是一個隨機數,不能全部爲0,也不能全部爲1。
  3. 以 T_GAP(private_addr_int) 爲週期,定時更新。

② 可解析私密地址 Resolvable Private Address
可解析私密地址比較有用,它通過一個隨機數和一個稱作 identity resolving key(IRK) 的密碼生成,因此只能被擁有相同 IRK 的設備掃描到,可以防止被未知設備掃描和追蹤。其格式如下:

可解析私密地址的特徵可總結爲:

  1. 高位 24bits 是隨機數部分,其中最高兩個 bit 爲“10”,用於標識地址類型;低位 24bits 是隨機數和 IRK 經過 hash 運算得到的 hash值,運算公式爲 hash = ah(IRK, prand)。
  2. 當主端 BLE 設備掃描到該類型的藍牙地址後,會使用保存在本機的 IRK,和該地址中的 prand,進行同樣的 hash 運算,並將運算結果和地址中的 hash 字段比較,相同的時候,才進行後續的操作。這個過程稱作 resolve(解析),如果不同則繼續用下一個 IRK 做上面的過程,直到找到一個關聯 IRK 或者一個也沒找到。
  3. 以T_GAP(private_addr_int) 爲週期,定時更新。哪怕在廣播、掃描、已連接等過程中,也可能改變。
  4. Resolvable Private Address 不能單獨使用,因此需要使用該類型的地址的話,設備要同時具備 Public Device Address 或者 Static Device Address 中的一種。

二、分析廣播包中藍牙MAC地址

使用抓包工具抓取類似如下數據包:

其中數據包第 6 部分:

其中 TxAdd 表示發送方的地址類型(0 爲 public,1爲 random)。
RxAdd 表示接收方的地址類型。
對於普通廣播來說,只有 TxAdd 的指示是有效的,表示廣播發送者的第一類型。而對於定向廣播來說,TxAdd 和 RxAdd 都是有效的。

其中數據包第 7 部分:

如果是隨機設備地址,則查看地址的最高兩位。

  • 如果是 “11” 就是靜態隨機地址。
  • 如果是 “00” 就是不可解析私密地址。
  • 如果是 “01” 就是可解析私密地址,並執行上面說過的 ah 方法進行解析。

三、讀取MAC地址

  1. 包含頭文件
#include "ble_gap.h"
  1. 定義結構體變量
ble_gap_addr_t bleAddr;

BLE 的地址由 ble_gap_addr_t 進行管理:

/**@brief Bluetooth Low Energy address. */
typedef struct
{
  uint8_t addr_id_peer : 1;       /**< Only valid for peer addresses.
                                       This bit is set by the SoftDevice to indicate whether the address has been resolved from
                                       a Resolvable Private Address (when the peer is using privacy).
                                       If set to 1, @ref addr and @ref addr_type refer to the identity address of the resolved address.

                                       This bit is ignored when a variable of type @ref ble_gap_addr_t is used as input to API functions. */
  uint8_t addr_type    : 7;       /**< See @ref BLE_GAP_ADDR_TYPES. */
  uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format.
                                       @ref addr is not used if @ref addr_type is @ref BLE_GAP_ADDR_TYPE_ANONYMOUS. */
} ble_gap_addr_t;
  • addr_id_peer:僅對匹配地址有效。此位由軟件設置,以指示該地址是否已從可解析私密地址中解析(當匹配加密時)
  • addr_type:地址類型,作爲傳入參數時可忽略
  • addr:48-bit 的MAC地址數組,低字節在前,所以與我們實際看到的地址順序相反
  1. 調用獲取地址函數
    uint32_t sd_ble_gap_addr_get(ble_gap_addr_t *p_addr)
sd_ble_gap_addr_get(&bleAddr);
  1. 將地址逆序並打印出來
#include "nrf_log.h"

uint8 address[6];
uint8 i;
for(i = 0; i < 6; i++)
{
  address[i] = bleAddr.addr[5 - i];    // 逆序
}

NRF_LOG_INFO("address:%02x", address[0]);
NRF_LOG_INFO("address:%02x", address[1]);
NRF_LOG_INFO("address:%02x", address[2]);
NRF_LOG_INFO("address:%02x", address[3]);
NRF_LOG_INFO("address:%02x", address[4]);
NRF_LOG_INFO("address:%02x", address[5]);

這樣打印出來的地址就跟我們實際掃描到的地址順序相同。

四、修改MAC地址

首先採用 sd_ble_gap_addr_get 讀取官方默認的 MAC 地址,然後再默認地址+1,再用 sd_ble_gap_addr_set 寫入到設備中。

void mac_set(void)
{
  ble_gap_addr_t addr;
  uint32_t err_code = sd_ble_gap_addr_get(&addr);
  APP_ERROR_CHECK(err_code);

  // Increase the BLE address by one when advertising openly.
  addr.addr[0] += 1;

  err_code = sd_ble_gap_addr_set(&addr);
  APP_ERROR_CHECK(err_code);
}

主函數中進行調用,注意,一定要在廣播開始前設置,下次廣播後新的 MAC 地址就設置成功。

/**@brief Application main function.
 */
int main(void)
{
    bool erase_bonds;

    // Initialize.
    uart_init();
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
    gap_params_init();
	  mac_set();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    // Start execution.
    advertising_start();

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

新的 MAC 地址加1,設置成功。


• 由 Leung 寫於 2020 年 2 月 19 日

• 參考:青風電子社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章