【Bluedroid】蓝牙启动之 SMP_Init 源码解析

蓝牙**(安全管理协议,Security Management Protocol)** 是蓝牙设备安全通信的核心协议,负责配对、密钥协商和安全等级管理。本文围绕 Bluedroid SMP 协议的初始化流程展开,系统解析其核心控制块(tSMP_CB)的状态管理、与 L2CAP 层的接口注册,以及 P-256 椭圆曲线参数的初始化逻辑。通过分析SMP_Init函数的调用链,揭示tsmp_CB如何重置状态、初始化定时器与测试参数,smp_l2cap_if_init如何建立与 L2CAP 的通信接口,以及p_256_init_curve如何为安全连接(SC)提供密码学基础。这些步骤共同确保 SMP 协议栈的可靠启动与安全通信能力。

一、概述

蓝牙设备的安全通信依赖 SMP实现配对、密钥交换和安全策略协商。SMP 的初始化是协议栈启动的关键环节,涉及状态管理、资源初始化、底层接口绑定及密码学参数配置。本文聚焦以下核心内容:

1.1 核心控制块: tSMP_CB 的状态管理

tSMP_CB是 SMP 协议的 "状态仓库",存储协议运行中的关键数据:

  • 状态与配置:记录当前协议状态(如配对阶段)、本地与对端的安全策略(如 IO 能力、是否强制安全连接)。

  • 临时数据与密钥:缓存配对过程中的随机数、确认值,以及协商生成的密钥(如临时密钥 TK、长期密钥 LTK)。

  • 异步事件管理:关联定时器(如响应超时、延迟认证)和回调函数(通知上层事件)。

1.2 初始化流程:从 SMP_Init 到资源配置

SMP_Init作为入口函数,调用tsmp_CB::init完成核心初始化:

  • 状态重置 :通过*this = {}清空历史数据,确保初始状态干净。

  • 资源初始化 :创建定时器(smp_rsp_timer_entdelayed_auth_timer_ent)处理异步事件;调用smp_l2cap_if_init注册 L2CAP 接口,建立与底层数据传输层的通信。

  • 测试支持:配置 PTS(协议一致性测试)失败案例,满足认证需求。

1.3 L2CAP 接口绑定:smp_l2cap_if_init的作用

L2CAP是 SMP 的底层传输载体。smp_l2cap_if_init通过注册固定通道回调(连接、数据接收、发送完成),将 SMP 与 L2CAP 绑定:

  • BLE 场景 :注册L2CAP_SMP_CID通道,处理低功耗蓝牙的 SMP 数据。

  • BR/EDR 场景 :注册L2CAP_SMP_BR_CID通道,支持传统蓝牙的安全管理。

1.4 密码学基础:P-256 椭圆曲线参数初始化

蓝牙安全连接(SC)基于 ECDH(椭圆曲线 Diffie-Hellman)密钥交换,依赖 P-256 椭圆曲线的标准参数。p_256_init_curve函数初始化曲线参数(模数p、系数a/b、基点G),为 ECDH 提供数学基础,确保设备间基于相同参数生成共享密钥。

二、源码分析

SMP_Init

cpp 复制代码
packages/modules/Bluetooth/system/stack/smp/smp_api.cc
tSMP_CB smp_cb;

/*******************************************************************************
 *
 * Function         SMP_Init
 *
 * Description      This function initializes the SMP unit.
 *
 * Returns          void
 *
 ******************************************************************************/
void SMP_Init(uint8_t init_security_mode) { smp_cb.init(init_security_mode); }

初始化 SMP 单元。

tSMP_CB smp_cb

cpp 复制代码
packages/modules/Bluetooth/system/stack/smp/smp_int.h
/* SMP control block */
class tSMP_CB {
 public:
  void init(uint8_t security_mode);
  void reset();

 public:
  //初始化时设置的安全模式(由 SMP_Init 传入),决定配对的安全等级(如无认证、单向认证、双向认证等)
  uint8_t init_security_mode{0};
  // SMP 事件回调函数指针(用于通知上层协议(如 L2CAP)或应用层配对结果、错误等)
  tSMP_CALLBACK* p_callback;
  // SMP 响应超时定时器(若对端未在规定时间内响应,触发超时处理)
  alarm_t* smp_rsp_timer_ent;
  RawAddress pairing_bda;
  tSMP_STATE state;
  bool derive_lk;
  bool id_addr_rcvd;
  tBLE_ADDR_TYPE id_addr_type;
  RawAddress id_addr;
  bool smp_over_br;
  tSMP_BR_STATE br_state; /* if SMP over BR/ERD has priority over SMP */
  uint8_t failure;
  tSMP_STATUS status;
  tHCI_ROLE role;
  uint16_t flags;
  tSMP_EVT cb_evt;
  tSMP_SEC_LEVEL sec_level; // 最终协商的安全等级(如无加密、加密、加密且认证)
  bool connect_initialized;
  // 本地与对端的确认值(用于配对认证,如数值比较或 OOB 验证)
  Octet16 confirm;
  Octet16 rconfirm;
  // 本地与对端的随机数(用于生成确认值或密钥)
  Octet16 rrand; /* for SC this is peer nonce */
  Octet16 rand;  /* for SC this is local nonce */
  // 本地私钥和 DH(Diffie-Hellman)共享密钥(用于安全连接的椭圆曲线密钥交换)
  BT_OCTET32 private_key;
  BT_OCTET32 dhkey;
  
  Octet16 commitment;
  Octet16 remote_commitment;
  Octet16 local_random; /* local randomizer - passkey or OOB randomizer */
  Octet16 peer_random;  /* peer randomizer - passkey or OOB randomizer */
  Octet16 dhkey_check;
  Octet16 remote_dhkey_check;
  // 本地与对端的公钥(椭圆曲线公钥,用于 DH 交换)
  tSMP_PUBLIC_KEY loc_publ_key;
  tSMP_PUBLIC_KEY peer_publ_key;
  
  tSMP_OOB_DATA_TYPE req_oob_type;
  tSMP_SC_OOB_DATA sc_oob_data;
  tSMP_IO_CAP peer_io_caps;
  tSMP_IO_CAP local_io_capability;
  tSMP_OOB_FLAG peer_oob_flag;
  tSMP_OOB_FLAG loc_oob_flag;
  tSMP_AUTH_REQ peer_auth_req;
  tSMP_AUTH_REQ loc_auth_req;

  // 本地是否强制仅使用安全连接(Secure Connections,SC)模式(基于椭圆曲线加密)
  bool sc_only_mode_locally_required; /* true if sc_only required required
                                         locally */
  // 对端是否强制要求安全连接模式
  bool sc_mode_required_by_peer;      /* true if peer requires sc in pair_req or
                                         pair_rsp */

  /* either in Secure Connections mode or not at all */
  tSMP_ASSO_MODEL selected_association_model;
  bool key_derivation_h7_used;
  bool le_sc_kp_notif_is_used;
  tSMP_SC_KEY_TYPE local_keypress_notification;
  tSMP_SC_KEY_TYPE peer_keypress_notification;
  // 认证阶段轮次(如基于 PIN 码的配对可能分多轮交互)
  uint8_t round; /* authentication stage 1 round for passkey association model */
  // 需要显示的配对码(如 6 位数字,用于用户确认是否一致)
  uint32_t number_to_display;
  Octet16 mac_key;
  uint8_t peer_enc_size;
  uint8_t loc_enc_size;
  uint8_t peer_i_key;
  uint8_t peer_r_key;
  uint8_t local_i_key;
  uint8_t local_r_key;

  // 临时密钥(Temporary Key),配对过程中生成的关键临时密钥,用于推导其他密钥(如 LTK)
  Octet16 tk; 
  // 长期密钥(Long Term Key),用于后续连接的加密和认证
  Octet16 ltk;
  uint16_t div;
  // 加密同步根密钥(Connection Signature Resolving Key),用于数据签名防篡改
  Octet16 csrk; /* storage for local CSRK */
  uint16_t ediv;
  BT_OCTET8 enc_rand;
  tBLE_ADDR_TYPE addr_type;
  RawAddress local_bda;
  bool is_pair_cancel;
  bool discard_sec_req;
  uint8_t rcvd_cmd_code;
  uint8_t rcvd_cmd_len;
  uint16_t total_tx_unacked;
  bool wait_for_authorization_complete;
  tSMP_STATUS cert_failure; /*failure case for certification */
  // 延迟认证定时器(用于异步授权场景)
  alarm_t* delayed_auth_timer_ent;
  tBLE_BD_ADDR pairing_ble_bd_addr;
};

tSMP_CB 类是SMP的核心控制块(Control Block),用于存储 SMP 协议运行过程中的状态、配置参数、临时数据、密钥材料 等关键信息。它是 SMP 协议栈实现的核心数据结构,贯穿配对(Pairing)、密钥生成(Key Generation)、安全等级协商等全流程。

通过成员变量和方法(init/reset)实现以下核心能力:

  • 状态管理:记录 SMP 协议当前运行阶段(如配对初始化、密钥交换、认证等)。

  • 配置参数存储:保存本地与对端设备的安全策略(如是否强制安全连接、IO 能力、认证需求等)。

  • 临时数据缓存:存储配对过程中生成的临时值(如随机数、确认值、DH 密钥等)。

  • 密钥材料管理:保存协商或生成的密钥(如临时密钥 TK、长期密钥 LTK、CSRK 等)。

  • 回调与定时器:关联协议事件回调和超时定时器,处理异步事件(如响应超时)。

tSMP_CB::init

cpp 复制代码
packages/modules/Bluetooth/system/stack/smp/smp_utils.cc
void tSMP_CB::init(uint8_t security_mode) {
  *this = {}; // 重置控制块状态

  init_security_mode = security_mode; // 设置初始安全模式
  smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
  smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");

  log::verbose("init_security_mode:{}", init_security_mode);

  // 初始化 SMP 与 L2CAP的接口
  smp_l2cap_if_init();
  // 初始化椭圆曲线参数
  /* initialization of P-256 parameters */
  p_256_init_curve();

  // 配置认证测试失败案例
  /* Initialize failure case for certification */
  smp_cb.cert_failure = static_cast<tSMP_STATUS>(
      stack_config_get_interface()->get_pts_smp_failure_case());
  if (smp_cb.cert_failure)
    log::error("PTS FAILURE MODE IN EFFECT (CASE {})", smp_cb.cert_failure);
}

为 SMP 协议运行准备干净的初始状态,包括重置控制块、初始化关键资源(定时器、L2CAP 接口、椭圆曲线参数),并处理测试相关的失败案例配置。

蓝牙**安全连接(Secure Connections,SC)基于椭圆曲线 Diffie-Hellman(ECDH)**密钥交换,P-256 是 SC 强制支持的椭圆曲线。

smp_l2cap_if_init

cpp 复制代码
packages/modules/Bluetooth/system/stack/smp/smp_l2c.cc
/*******************************************************************************
 *
 * Function         smp_l2cap_if_init
 *
 * Description      This function is called during the SMP task startup
 *                  to register interface functions with L2CAP.
 *
 ******************************************************************************/
void smp_l2cap_if_init(void) {
  // 1. 定义 L2CAP 固定通道注册结构体
  // 用于配置 L2CAP 通道的回调函数和参数。其成员变量对应 L2CAP 与上层协议(如 SMP)交互的关键接口
  tL2CAP_FIXED_CHNL_REG fixed_reg; 
  log::verbose("SMDBG l2c");

  // 2. 配置 SMP 通道的回调函数(BLE 场景)
  fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback; // 连接回调
  fixed_reg.pL2CA_FixedData_Cb = smp_data_received; // 数据接收回调
  fixed_reg.pL2CA_FixedTxComplete_Cb = smp_tx_complete_callback; // 发送完成回调

  // 3. 配置通道可选参数
  fixed_reg.pL2CA_FixedCong_Cb =
      NULL; /* do not handle congestion on this channel */
  fixed_reg.default_idle_tout =
      60; /* set 60 seconds timeout, 0xffff default idle timeout */

  // 4. 注册 BLE SMP 固定通道
  L2CA_RegisterFixedChannel(L2CAP_SMP_CID, &fixed_reg);

  // 5. 配置并注册 BR/EDR SMP 通道(传统蓝牙场景)
  fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
  fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
  L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, &fixed_reg);
}

通过向 L2CAP 注册 SMP 的连接管理、数据接收、发送完成等回调函数,使 L2CAP 能够将 SMP 通道的事件(如数据到达、连接状态变化)传递给 SMP 协议栈处理,最终实现 SMP 协议在蓝牙链路上的正常运行。

p_256_init_curve

cpp 复制代码
packages/modules/Bluetooth/system/stack/smp/p_256_curvepara.cc
#define KEY_LENGTH_DWORDS_P256 8

// 表示椭圆曲线上的点
typedef struct {
  uint32_t x[KEY_LENGTH_DWORDS_P256];
  uint32_t y[KEY_LENGTH_DWORDS_P256];
  uint32_t z[KEY_LENGTH_DWORDS_P256];
} Point;

// 存储椭圆曲线的全局参数
typedef struct {
  // curve's coefficients
  uint32_t a[KEY_LENGTH_DWORDS_P256];
  uint32_t b[KEY_LENGTH_DWORDS_P256];

  // whether a is -3
  int a_minus3;

  // prime modulus
  uint32_t p[KEY_LENGTH_DWORDS_P256];

  // Omega, p = 2^m -omega
  uint32_t omega[KEY_LENGTH_DWORDS_P256];

  // base point, a point on E of order r
  Point G;

} elliptic_curve_t;

// 初始化 P-256 曲线参数
void p_256_init_curve() {
  elliptic_curve_t* ec = &curve_p256;

  // 1. 有限域模数 p
  // 组合后 p=0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF(256 位素数)
  ec->p[7] = 0xFFFFFFFF;
  ec->p[6] = 0x00000001;
  ec->p[5] = 0x0;
  ec->p[4] = 0x0;
  ec->p[3] = 0x0;
  ec->p[2] = 0xFFFFFFFF;
  ec->p[1] = 0xFFFFFFFF;
  ec->p[0] = 0xFFFFFFFF;

 // 2. 曲线系数 a 和 b
  memset(ec->omega, 0, KEY_LENGTH_DWORDS_P256);
  memset(ec->a, 0, KEY_LENGTH_DWORDS_P256);

  ec->a_minus3 = true;

  // b
  // b 的值:0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
  ec->b[7] = 0x5ac635d8;
  ec->b[6] = 0xaa3a93e7;
  ec->b[5] = 0xb3ebbd55;
  ec->b[4] = 0x769886bc;
  ec->b[3] = 0x651d06b0;
  ec->b[2] = 0xcc53b0f6;
  ec->b[1] = 0x3bce3c3e;
  ec->b[0] = 0x27d2604b;

  // 3. 基点 G
  // base point
  // 基点 G 的 X 坐标:0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
  ec->G.x[7] = 0x6b17d1f2;
  ec->G.x[6] = 0xe12c4247;
  ec->G.x[5] = 0xf8bce6e5;
  ec->G.x[4] = 0x63a440f2;
  ec->G.x[3] = 0x77037d81;
  ec->G.x[2] = 0x2deb33a0;
  ec->G.x[1] = 0xf4a13945;
  ec->G.x[0] = 0xd898c296;

  // 基点 G 的 Y 坐标:0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
  ec->G.y[7] = 0x4fe342e2;
  ec->G.y[6] = 0xfe1a7f9b;
  ec->G.y[5] = 0x8ee7eb4a;
  ec->G.y[4] = 0x7c0f9e16;
  ec->G.y[3] = 0x2bce3357;
  ec->G.y[2] = 0x6b315ece;
  ec->G.y[1] = 0xcbb64068;
  ec->G.y[0] = 0x37bf51f5;
}

P-256 椭圆曲线是蓝牙安全连接(Secure Connections,SC) 的强制支持曲线,用于实现 ECDH(椭圆曲线 Diffie-Hellman)密钥 交换。p_256_init_curve 函数的初始化操作是 ECDH 的基础:

  • 密钥交换流程 :设备 A 生成私钥 dA 和公钥 QA =dAG ,设备 B 生成 dBQB =dBG ,双方通过交换公钥计算共享密钥 K =dAQB =dBQA(基于椭圆曲线的离散对数难题保证安全性)。

  • 参数一致性 :所有支持蓝牙 SC 的设备必须使用相同的 P-256 参数(p ,a ,b ,G),否则无法正确计算共享密钥。

通过初始化 P-256 椭圆曲线的标准参数,为蓝牙安全连接中的 ECDH 密钥交换提供了数学基础。其核心是将 P-256 的曲线方程、有限域模数和生成元(基点)写入内存,确保设备间能基于相同的密码学参数完成安全密钥协商,最终实现蓝牙设备的安全配对与通信。

椭圆曲线由方程 y 2=x 3+ax +b 定义(在有限域 GF(p) 上),结构体存储了该方程的系数、模数及生成元(基点)。

  • 系数 a :标准 P-256 曲线的 a =−3,代码中通过 a_minus3 = true 显式标记,避免存储全 0 的 a (实际运算时直接使用 a=−3 以优化计算)。

  • 系数 b :存储 P-256 的标准 b 值(十六进制),是椭圆曲线方程的关键参数,决定曲线形状。

  • G 是椭圆曲线群的生成元,其阶 r 是一个大素数(r =0xFFFFFFFF 00000000FFFFFFFFFFFFFFFFBCE 6FAADA 7179E 84F 3B 9CAC 2FC 632551)。所有椭圆曲线密钥对(如 ECDH 中的公私钥)均通过 dG (标量乘法)生成(d 是私钥,dG 是公钥)

  • omega 用于优化模数运算(如 p =2m −omega 时,模运算可转换为减法)。P-256 的 p 接近 2256,此处初始化为全 0,可能表示未启用该优化或预留扩展

三、流程图

四、时序图

五、总结

SMP 协议的初始化是蓝牙安全通信的起点,通过tSMP_CB控制块的状态管理、L2CAP 接口的绑定,以及 P-256 曲线参数的配置,实现了协议栈的可靠启动与安全能力。其中:

  • tSMP_CB作为核心数据结构,贯穿配对、密钥交换全流程,确保状态与数据的一致性。

  • L2CAP 接口的注册建立了 SMP 与底层传输的桥梁,支撑协议消息的收发。

  • P-256 曲线参数的初始化则为安全连接(SC)提供了密码学保障,是 ECDH 密钥交换的基础。


相关推荐
casual_clover3 分钟前
Android Studio 解决首次安装时下载 Gradle 慢问题
android·ide·android studio
Dovis(誓平步青云)19 分钟前
探索C++标准模板库(STL):String接口的底层实现(下篇)
开发语言·c++·stl·string
天天爱吃肉821826 分钟前
新能源汽车热管理核心技术解析:冬季续航提升40%的行业方案
android·python·嵌入式硬件·汽车
KyollBM1 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
快乐觉主吖1 小时前
Unity的日志管理类
android·unity·游戏引擎
明月看潮生1 小时前
青少年编程与数学 01-011 系统软件简介 06 Android操作系统
android·青少年编程·操作系统·系统软件·编程与数学
feiyangqingyun1 小时前
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
c++·qt·udp·gb28181
snetlogon201 小时前
JDK17 Http Request 异步处理 源码刨析
android·网络协议·http
CV点灯大师1 小时前
C++算法训练营 Day10 栈与队列(1)
c++·redis·算法
消失的旧时光-19432 小时前
Android USB 通信开发
android·java