在 Android 11 中,可以使用 A/B 更新或虚拟 A/B 更新机制,同时结合 RecoverySystem 类方法,从而应用 OTA 更新。设备重新启动以应用 OTA 更新后,重新启动时恢复 (RoR) 会解锁设备凭据加密 (CE) 存储空间。
虽然在 Android 11 中,合作伙伴可以将此过程与在设备预计空闲时应用更新的 OTA 系统功能相结合,但在 Android 12 中,合作伙伴不需要使用其他 OTA 系统功能。RoR 流程可为用户提供更高的安全性和便利性,因为更新可在设备空闲时进行,而 Android 12 多客户端和基于服务器的更新功能可同时提供设备硬件级的类型安全。
虽然您必须为 android.hardware.reboot_escrow
功能提供设备权限以在 Android 11 中支持 RoR,但您无需执行此操作即可在 Android 12 及更高版本中启用基于服务器的 RoR,因为它们不使用 HAL。
背景
从 Android 7 开始,Android 支持直接启动,这使得设备上的应用可在用户解锁 CE 存储空间之前启动。直接启动支持的实现可让用户在启动后需要输入锁定屏幕验证凭据 (LSKF) 之前获得更好的体验。
当 OTA 更新后发起重新启动时,RoR 可允许解锁设备上所有应用的 CE 存储空间,包括不支持直接启动的应用。此功能使用户可以在重新启动设备后接收来自所有已安装应用的通知。
威胁模型
RoR 的实现必须确保当设备落入攻击者手中时,攻击者极难恢复用户的 CE 加密数据,即使设备已开机、CE 存储空间已解锁也是如此,并且在收到 OTA 更新后用户可以解锁设备。即使攻击者获得了对广播加密签名密钥的访问权限,内部攻击防御措施也必须有效。
具体来说,CE 存储空间不得被实际拥有设备的攻击者读取,并且具有以下功能和限制:
功能
- 可以使用任何供应商或公司的签名密钥对任意消息进行签名。
- 可以使设备接收 OTA 更新。
- 可以修改任何硬件(例如应用处理器或闪存)的操作,下文的限制中另有详细说明的除外。 (然而,此类修改至少会延迟一个小时并造成破坏 RAM 内容的重启。)
限制
- 无法修改防篡改硬件(例如 Titan M)的操作。
- 无法读取活动设备的 RAM。
- 无法猜测用户的凭据(PIN 码、图案和密码),或以其他方式输入此类凭据。
解决方案
Android 12 RoR 更新系统可针对非常复杂的攻击者提供安全保护,而设备端密码和 PIN 码会保留在设备上,且绝不会发送到 Google 服务器或存储在 Google 服务器上。下文概述了此过程,其旨在确保所提供的安全级别与基于硬件的设备级 RoR 系统类似:
- Android 对设备上存储的数据应用加密保护。
- 所有数据均受可信执行环境 (TEE) 中存储的密钥保护。
- 仅当正在运行的操作系统通过加密身份验证(启动时验证)时,TEE 才会释放密钥。
- 在 Google 服务器上运行的 RoR 服务通过存储仅在有限时间内可以检索的 Secret 来保护 CE 数据。 这适用于整个 Android 生态系统。
- 用于解锁设备并对 CE 存储空间进行解密的加密密钥受用户的 PIN 码保护。
- 如果安排在夜间重新启动 Android 设备,Android 会提示用户输入 PIN 码,然后计算合成密码 (SP)。
- 然后,它会对 SP 进行两次加密:一次是使用存储在 RAM 中的密钥
K_s
,另一次是使用存储在 TEE 中的密钥K_k
。 - 双重加密的 SP 存储在磁盘上,并且 SP 会从 RAM 中擦除。这两个密钥都是即时生成的,仅用于一次重新启动。
- 当需要重新启动时,Android 会将
K_s
委托给服务器。收到的K_k
会在存储在磁盘上之前获得加密。 - 重新启动后,Android 会使用
K_k
解密收到的密钥,然后将其发送到服务器以检索K_s
。K_k
和K_s
用于解密存储在磁盘上的 SP。- Android 使用 SP 解锁 CE 存储空间并允许正常启动应用。
- 已舍弃
K_k
和K_s
。
用于保护手机安全的更新可能在您方便时(在您睡觉时)进行。
SIM 卡 PIN 码回顾
在特定情况下,系统会从缓存中验证 SIM 卡的 PIN 码,此过程称为 SIM 卡 PIN 码回顾。
已启用 PIN 码的 SIM 卡还必须在无人值守的重新启动后进行无缝 PIN 码验证(SIM 卡 PIN 码回顾),以恢复移动网络连接(电话通话、短信和数据服务需要此连接)。SIM 卡 PIN 码及其匹配的 SIM 卡信息(ICCID 和 SIM 卡插槽编号)会安全地存储在一起。只有在成功完成无人值守的重新启动后,系统才能检索存储的 PIN 码并用其进行验证。如果设备受保护,系统会使用受 LSKF 保护的密钥存储 SIM 卡 PIN 码。如果 SIM 卡已启用 PIN 码,则与 RoR 服务器进行交互时需要 WiFi 连接以进行 OTA 更新和基于服务器的 RoR,从而确保重新启动后的基本功能(使用移动网络连接)。
每次用户成功启用、验证或修改 SIM 卡 PIN 码时,系统都会重新加密并存储 SIM 卡 PIN 码。如果出现以下任一情况,系统会舍弃 SIM 卡 PIN 码:
- 已移除或重置 SIM 卡。
- 用户停用 PIN 码。
- 发生了非 RoR 发起的重新启动。
存储的 SIM 卡 PIN 码只能在 SIM 卡的详细信息匹配的情况下使用,并且只能在 RoR 发起的重新启动后使用一次,而且只能在极短的时间期限(20 秒)内使用。存储的 SIM 卡 PIN 码绝不会离开 TelephonyManager 应用,并且外部模块无法检索到该 PIN 码。
实现准则
在 Android 12 中,多客户端和基于服务器的 RoR 功能在合作伙伴推送 OTA 更新时,可减轻其负担。 必要的更新可以在方便的设备停机时间内进行,例如在指定的睡觉时段期间。
为了确保在此类时间段内的 OTA 更新不会干扰用户,请采用深色模式,以减少光发射。为此,请让设备引导加载程序搜索原因字符串 unattended
。如果 unattended
为 true
,请将设备置于深色模式。请注意,每个原始设备制造商 (OEM) 都有责任减少发出的声音和光亮。
如果您要升级到 Android 12 或正在启动 Android 12 设备,无需执行任何操作即可实现新的 RoR 功能。
多客户端流程中有一个新的调用,即 isPreparedForUnattendedUpdate
,如下所示:
@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
android.Manifest.permission.REBOOT})
public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)
您无需实现此方法,因为从 Android 12 开始,HAL 已被弃用。
TelephonyManager
当 Android 12 中即将重新启动时,OTA 客户端会调用 TelephonyManager
系统 API。此 API 会将所有缓存的 PIN 码从 AVAILABLE
状态更改为 REBOOT_READY
状态。TelephonyManager
系统 API 受现有的 REBOOT
清单权限保护。
/**
* The unattended reboot was prepared successfully.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_SUCCESS = 0;
/**
* The unattended reboot was prepared, but the user will need to manually
* enter the PIN code of at least one SIM card present in the device.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1;
/**
* The unattended reboot was not prepared due to generic error.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_ERROR = 2;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"PREPARE_UNATTENDED_REBOOT_"},
value = {
PREPARE_UNATTENDED_REBOOT_SUCCESS,
PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED,
PREPARE_UNATTENDED_REBOOT_ERROR
})
public @interface PrepareUnattendedRebootResult {}
/**
* Prepare TelephonyManager for an unattended reboot. The reboot is
* required to be done shortly after the API is invoked.
*
* Requires system privileges.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#REBOOT}
*
* @return {@link #PREPARE_UNATTENDED_REBOOT_SUCCESS} in case of success.
* {@link #PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED} if the device contains
* at least one SIM card for which the user needs to manually enter the PIN
* code after the reboot. {@link #PREPARE_UNATTENDED_REBOOT_ERROR} in case
* of error.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.REBOOT)
@PrepareUnattendedRebootResult
public int prepareForUnattendedReboot()
TelephonyManager 系统 API 供特权 APK 使用。
测试
如需测试新的 API,请执行以下命令:
adb shell cmd phone unattended-reboot
此命令仅在 shell 作为根 (adb root
) 运行时有效。
仅限 Android 11
本页的其余内容适用于 Android 11。
自 2020 年 7 月起,RoR HAL 的实现分为两类:
- 如果 SoC 硬件支持重新启动中的 RAM 持久化,OEM 可以使用 AOSP 中的默认实现(默认 RAM 托管)。
- 如果设备硬件或 SoC 支持安全的硬件隔离(具有自己的 RAM 和 ROM 的离散安全协处理器),则它必须执行以下操作:
- 能够检测主要 CPU 重新启动。
- 具有可在重新启动后持久保留的硬件计时器来源;也就是说,此隔离机制必须能够检测到重新启动,并在重新启动之前使设置的计时器失效。
- 支持在此隔离 RAM/ROM 中存储托管密钥,确保无法通过离线攻击恢复此密钥。必须以一种内部人员或攻击者无法恢复的方式存储 RoR 密钥。
默认 RAM 托管
AOSP 具有使用 RAM 持久化的 RoR HAL 实现。为此,OEM 必须确保其 SoC 支持在重新启动中的 RAM 持久化。某些 SoC 无法在重新启动后保留 RAM 内容,因此建议 OEM 先咨询 SoC 合作伙伴,然后再启用此默认 HAL。下一节介绍了此方面的规范引用。
使用 RoR 进行 OTA 更新的流程
手机上的 OTA 客户端应用必须具有 Manifest.permission.REBOOT 和 Manifest.permission.RECOVERY
权限才能调用必要的方法来实现 RoR。满足这些前提条件后,更新流程将遵循以下步骤:
- OTA 客户端应用下载更新。
- OTA 客户端应用调用
RecoverySystem#prepareForUnattendedUpdate
,以触发在下一次用户解锁设备时在锁定屏幕上提示用户输入 PIN 码、图案或密码。 - 用户在锁定屏幕上解锁设备,设备将准备好应用更新。
- OTA 客户端应用调用
RecoverySystem#rebootAndApply
,这会立即触发重新启动操作。
在此流程结束时,设备会重新启动,并且 RoR 机制会解锁凭据加密 (CE) 存储空间。对于应用,这会显示为正常的用户解锁,因此它们会收到所有信号,例如与往常一样的 ACTION_LOCKED_BOOT_COMPLETED 和 ACTION_BOOT_COMPLETED。
修改产品配置
在 Android 11 中标记为支持 RoR 功能的产品必须包含 RebootEscrow HAL 的实现,并包含相应功能标记 XML 文件。默认实现适用于使用热重新启动的设备(当重新启动期间 DRAM 的电源保持开启状态时)。
重新启动托管功能标记
此外,还必须提供以下特征标记:
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.reboot_escrow.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.reboot_escrow.xml
默认重新启动托管 HAL 实现
如需使用默认实现,您必须预留 65536 (0x10000) 字节。切勿将这些字节写入非易失性存储空间,以确保安全属性的持久性。
Linux 内核设备树更改
在 Linux 内核的设备树中,必须为 pmem
区域预留内存。以下示例展示了预留的 0x50000000
:
reserved-memory {
my_reservation@0x50000000 {
no-map;
reg = <0x50000000 0x10000>;
}
}
reboot_escrow@0 {
compatible = "pmem-region";
reg = <0x50000000 0x10000>;
};
验证您是否在块目录中有名称类似于 /dev/block/pmem0
(例如 pmem1
或 pmem2
)的新设备。
Device.mk 更改
假设上一步中的新设备名称为 pmem0
,您必须确保将以下新条目添加到 vendor/<oem>/<product>/device.mk
:
# Resume on Reboot support
PRODUCT_PROPERTY_OVERRIDES += \
ro.rebootescrow.device=/dev/block/pmem0
PRODUCT_PACKAGES += \
android.hardware.rebootescrow-service.default
SELinux 规则
将这些新条目添加到设备的 file_contexts
:
/dev/block/pmem0 u:object_r:rebootescrow_device:s0
/vendor/bin/hw/android\.hardware\.rebootescrow-service\.default u:object_r:hal_rebootescrow_default_exec:s0