android - Android BLE 配对和 BREDR 密钥分配
问题描述
我是一名使用 Qualcomm SoC 进行蓝牙和音频处理的蓝牙耳机产品的开发人员。我们的产品将 BREDR 蓝牙用于“经典”配置文件 (HFP/AVRCP/A2DP),将 LE 用于移动应用程序和 OTAU。
我们期望用户执行的典型流程是:
- 使用智能手机的蓝牙设置进行 BREDR 配对。这使用产生 P192 加密密钥的传统 BREDR“简单配对”方法。
- 用户打开我们的应用程序,这将在应用程序尝试访问我们的自定义 GATT 服务时触发 LE 配对。
由于兼容性问题,我们的耳机不支持基于 BREDR 的安全连接,但它支持 LE 安全连接。因此,通常会在 LE 配对完成后,根据 LE 长期密钥重新计算 BREDR 链接密钥,这使其具有 P256 加密能力。例如,在 BREDR 配对后,我的耳机永久存储中的链接密钥如下所示:
Device #0: addr_type=PUBLIC
BDADDR = xxxx xx xxxxxx
BREDR key: bbb...b (AUTHENTICATED P192)
在 LE 配对之后:
Device #0: addr_type=PUBLIC
BDADDR = xxxx xx xxxxxx
BREDR key: aaa...a (AUTHENTICATED P256)
LE CENTRAL Key : 0000 (EVID) 0000000000000000 (RAND) bbb...b (LTK)
LE IRK: ccc...c
现在,这对于大多数平台来说都不是问题,但最近我开始看到某些运行 Android 10/11 的 Android 设备和一些运行 Android 9 并带有最新安全补丁的设备存在问题。基本上,在 LE 配对之后,我无法创建任何新的 BREDR ACL。连接总是在 LMP_rand_au -> sres 响应阶段失败 - 本质上,移动设备在 LE 配对后没有重新计算其 BREDR 链接密钥,现在设备不再同意 LTK。我在我的耳机设备中明确禁用了交叉传输密钥派生,但在 LE 密钥分发后 BREDR 密钥仍会更改。这在 iOS 设备上似乎根本不是问题。有没有其他人遇到过这个问题?关于如何进行的任何建议?到目前为止,我已经尝试过:
- 禁用 LE 链接密钥分发:这可以防止重新计算 BREDR 密钥,因为没有 LE LTK/IRK。然而,一旦手机更改其随机 LE 地址,用户将被迫重新配对。这也会导致我在耳机设备上的受信任设备列表膨胀,而且非常有限
- 在 LE 安全性完成后强制 LTK 更改 - 有一个 HCI 命令明确用于重新派生 LTK。然而,尝试这样做会导致各种令人讨厌的奇怪行为。也许我的耳机 SoC 不完全支持它
- 在 LE 配对之前保存 BREDR LTK 并在 LE 配对之后将其重置。这允许 BREDR 连接,这让我怀疑问题出在移动设备上。但是,这当然会阻止用户访问移动应用程序。
解决方案
好的,我实际上设法从高通那里获得了一些关于这个问题的技术支持。问题出在 Android 设备中,因此解决方案是强制禁用耳机中的 CTKD,即使 BREDR 安全连接被禁用。这对于高通的 API 是不可能的,我被迫更改了高通在 ADK 中提供的开源连接库中的一些文件。
推荐阅读
- java - Java:类 org.apache.poi.openxml4j.util.ZipSecureFile$ThresholdInputStream 不能转换为类 java.util.zip.ZipFile$ZipFileInputStream
- sql - 如何将 NOT NULL 列添加到 SQL 表但现有条目具有 NULL 值?
- javascript - 为什么 React 在这两种情况下表现不同?
- javascript - 如何让 React Router NavLink 等待状态变化?
- javascript - ** setInterval() 调用的函数在封闭函数返回后如何访问封闭函数的变量?
- php - PHP - 在电子邮件中显示复选框标签而不是其值
- laravel - 为什么 Laravel 集合不支持所有 PHP 运算符?
- javascript - 如何防止浏览器在控制台中写入日志?
- javascript - 如何在 Meteor 中重置用户每月使用量?
- ssl - Heroku 子域的自动证书管理?