当前位置: 首页 > news >正文

【Bluedroid】蓝牙启动之 btif_init_ok 流程源码解析

本文深入分析 Android 蓝牙协议栈(Bluedroid)中 BLE 本地密钥的加载机制。重点剖析 btif_dm_load_ble_local_keys函数的实现逻辑,解读加密根密钥(ER)和标识密钥组(IR/IRK/DHK)的协同加载策略,揭示了密钥存储与加载的解耦设计。

一、概述

BLE 设备的本地密钥(如 ER、IR、IRK、DHK)是确保蓝牙通信安全的核心数据。在 Android 蓝牙协议栈的btif(蓝牙接口框架)模块中,密钥的存储与加载涉及三个关键组件:

  • btif_core:作为初始化入口,通过btif_init_ok触发密钥加载流程;

  • btif_dm:负责密钥加载的核心逻辑,通过调用存储接口读取密钥并更新全局状态;

  • btif_storage:提供存储映射规则(通过BTIF_STORAGE_LOCAL_LE_KEYS数组)和密钥读取接口(btif_storage_get_ble_local_key),实现上层模块与存储系统的解耦。

本文从代码实现出发,详细解析密钥从存储系统到内存的完整加载流程。

二、源码解析

btif_init_ok

packages/modules/Bluetooth/system/btif/src/btif_core.cc
void btif_init_ok() {btif_dm_load_ble_local_keys();
}

btif_dm_load_ble_local_keys

packages/modules/Bluetooth/system/btif/src/btif_dm.ccusing Octet16 = bluetooth::hci::Octet16;
constexpr int kOctet16Length = 16;
using Octet16 = std::array<uint8_t, kOctet16Length>;// 存储 BLE 设备的本地标识密钥组
// btif_dm_local_key_id_t == tBTM_BLE_LOCAL_ID_KEYS == tBTA_BLE_LOCAL_ID_KEYS
typedef struct {Octet16 ir;   // 身份解析密钥(Identity Resolving Key, IRK)的关联数据Octet16 irk;  // 身份解析密钥(IRK)Octet16 dhk;  // Diffie-Hellman 密钥(DHK)
} btif_dm_local_key_id_t;// 记录本地密钥的加载状态和实际数据
typedef struct {bool is_er_rcvd;       // ER密钥是否加载成功Octet16 er;            // 加密根密钥(Encryption Root Key, ER)bool is_id_keys_rcvd;  // 标识密钥组(ir/irk/dhk)是否全部加载成功btif_dm_local_key_id_t id_keys;  // 存储标识密钥组的具体值
} btif_dm_local_key_cb_t;// 静态全局变量,在模块内共享当前加载的本地密钥状态和数据
static btif_dm_local_key_cb_t ble_local_key_cb;#define BTIF_DM_LE_LOCAL_KEY_IR (1 << 0)
#define BTIF_DM_LE_LOCAL_KEY_IRK (1 << 1)
#define BTIF_DM_LE_LOCAL_KEY_DHK (1 << 2)
#define BTIF_DM_LE_LOCAL_KEY_ER (1 << 3)void btif_dm_load_ble_local_keys(void) {memset(&ble_local_key_cb, 0, sizeof(btif_dm_local_key_cb_t));// 加载 ER 密钥if (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_ER, &ble_local_key_cb.er) == BT_STATUS_SUCCESS) {ble_local_key_cb.is_er_rcvd = true;log::verbose("BLE ER key loaded");}// 加载标识密钥组(ir/irk/dhk)if ((btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IR,&ble_local_key_cb.id_keys.ir) ==BT_STATUS_SUCCESS) &&(btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IRK,&ble_local_key_cb.id_keys.irk) ==BT_STATUS_SUCCESS) &&(btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_DHK,&ble_local_key_cb.id_keys.dhk) ==BT_STATUS_SUCCESS)) {ble_local_key_cb.is_id_keys_rcvd = true;log::verbose("BLE ID keys loaded");}
}

从存储模块加载BLE 的本地密钥(ER 和标识密钥组),并更新全局变量ble_local_key_cb的状态。

必须同时加载 IR、IRK、DHK 三个密钥(通过&&逻辑与判断),只有全部加载成功时,才标记is_id_keys_rcvdtrue。说明标识密钥组需要完整加载才有效,任意一个密钥缺失都会导致整个密钥组不可用。

btif_storage_get_ble_local_key

packages/modules/Bluetooth/system/btif/src/btif_storage.cc
// 存储键的元信息
struct BtifStorageKey {uint8_t type;          // 密钥类型(与上层模块定义的枚举值绑定)const std::string& name;  // 密钥在存储系统中的键名(字符串引用)uint8_t size;          // 密钥数据的长度(字节)
};// 定义了  BLE 本地密钥的类型、存储键名、数据长度的映射关系
static const BtifStorageKey BTIF_STORAGE_LOCAL_LE_KEYS[] = {{BTIF_DM_LE_LOCAL_KEY_IR, BTIF_STORAGE_KEY_LE_LOCAL_KEY_IR,sizeof(Octet16)},{BTIF_DM_LE_LOCAL_KEY_IRK, BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK,sizeof(Octet16)},{BTIF_DM_LE_LOCAL_KEY_DHK, BTIF_STORAGE_KEY_LE_LOCAL_KEY_DHK,sizeof(Octet16)},{BTIF_DM_LE_LOCAL_KEY_ER, BTIF_STORAGE_KEY_LE_LOCAL_KEY_ER,sizeof(Octet16)},
};/** Stores local key of |key_type| into |key_value|* Returns BT_STATUS_SUCCESS if the fetch was successful, BT_STATUS_FAIL* otherwise*/
bt_status_t btif_storage_get_ble_local_key(uint8_t key_type, Octet16* key_value) {// 遍历存储映射数组,查找匹配的密钥类型for (size_t i = 0; i < std::size(BTIF_STORAGE_LOCAL_LE_KEYS); i++) {auto key = BTIF_STORAGE_LOCAL_LE_KEYS[i];if (key.type == key_type) {  // 匹配密钥类型// 获取Octet16的长度(固定16字节)size_t length = key_value->size();// 从存储系统读取二进制数据bool ret = btif_config_get_bin(BTIF_STORAGE_SECTION_ADAPTER,  // 存储段(属于“适配器”相关分区)key.name,                      // 存储键名(如BTIF_STORAGE_KEY_LE_LOCAL_KEY_IRK)key_value->data(),             // 数据缓冲区(Octet16的底层字节数组)&length                        // 传入/传出参数:期望长度和实际读取长度);// 根据读取结果返回状态return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;}}// 未找到匹配的密钥类型时记录警告并返回失败log::warn("Unknown LE key type: {}", key_type);return BT_STATUS_FAIL;
}

定义了BLE本地密钥的存储映射关系,并提供了从存储中读取密钥的接口函数。解耦蓝牙上层模块与存储系统,确保密钥数据的存储位置、格式和读取逻辑被统一管理,提高了代码的可维护性和可靠性。

btif_config_get_bin分析见【Bluedroid】蓝牙配对设备管理的源码研究:从NVRAM加载到安全机制实现-CSDN博客

数组作用

  • 解耦上层与存储系统:上层模块(如btif_dm)只需通过密钥类型(type)即可查询到存储系统中的键名(name)和数据长度(size),无需直接关心存储系统的具体实现。

  • 标准化存储规则:所有 BLE 本地密钥的存储键名和数据长度通过该数组统一管理,避免因分散定义导致的键名冲突或长度错误。

三、总结

BLE 本地密钥的存储与加载机制是蓝牙安全通信的基础支撑,其核心设计思想可归纳为以下三点:

  1. 解耦设计:通过BTIF_STORAGE_LOCAL_LE_KEYS存储映射数组,将上层模块(如btif_dm)与存储系统解耦,上层只需关注密钥类型,无需感知存储键名或数据格式;

  2. 状态标准化:通过ble_local_key_cb全局变量记录密钥加载状态(is_er_rcvdis_id_keys_rcvd),确保其他模块可快速判断密钥是否可用;

  3. 可靠性保障:标识密钥组(IR/IRK/DHK)需全部加载成功才标记有效,避免因部分密钥缺失导致的通信安全风险。

该机制通过标准化、模块化的设计,有效提升了蓝牙密钥管理的可维护性和可靠性,为 BLE 设备的安全通信提供了关键支撑。

四、流程图

五、时序图


相关文章:

  • 小智AI玩具市场爆发:四大品牌领跑情感交互新赛道
  • 3DTiles三维模型
  • Linux 核心知识点整理(高频考点版)
  • Mac电脑 Office 2024 LTSC 长期支持版(Excel、Word、PPT)
  • 《超级处理器》怎么安装到WPS/excel(最后有下载地址)
  • 李宏毅《生成式人工智能导论》| 第1讲:什么是生成式人工智能
  • 一体机主板步入大存储时代,存储突围到性能质变
  • OpenAI 公布《走向理解与预防失准泛化:由“角色特征”驱动的突现性失准》研究总结
  • MySql升级安装、socket 及密码重置
  • 3.1 Hector_mapping初体验
  • langchain框架中各种Agent(LLMSingleAgent ReactAgent Plan-and-Execute Agent)原理方式对比
  • Spring Boot 虚拟线程 vs WebFlux:谁更胜一筹?
  • Ascend上如何进行带宽测试
  • Spring Boot + MyBatis + Vue:构建高效全栈应用的实战指南
  • px4仿真使用fastlio的定位数据飞行
  • 用流行民族戏腔三种方式打开国风爆款《闲人填梦》,邓超予的跨界演绎引领文化传播新高度!
  • QSqlDatabase: QSQLITE driver not loaded
  • 小孙学变频学习笔记(三)变频器的逆变器件—IGBT管(上)
  • 16.大数据监控
  • Kafka Broker处理消费者请求源码深度解析:从请求接收到数据返回
  • 网站版面设计/发布软文的平台
  • 网站的友情链接做多少个比较合适/地推是什么
  • 网站怎么做页游/如何在百度上推广业务
  • 教师招聘网站长城建设集团/热门推广平台
  • 龙岩做网站设计公司/专业的seo搜索引擎优化培训
  • 万网网站建设步骤/湖南正规关键词优化首选