蓝牙**(安全管理协议,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_ent
、delayed_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 生成 dB 和 QB =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 密钥交换的基础。