重启时恢复

在 Android 11 中,可以使用A/B 更新虚拟 A/B 更新机制,结合RecoverySystem类方法来应用 OTA 更新。在设备重新启动以应用 OTA 更新后,Resume-on-Reboot (RoR) 会解锁设备凭据加密 (CE) 存储

尽管合作伙伴可以将此过程与 OTA 系统功能配对,当设备在 Android 11 中预计空闲时应用更新,但在 Android 12 中,合作伙伴不需要额外的 OTA 系统功能。 RoR 流程为用户提供了额外的安全性和便利性,因为可以在设备空闲时间进行更新,而 Android 12 多客户端和基于服务器的更新功能共同提供了设备硬件级别的类型安全性。

尽管您必须为android.hardware.reboot_escrow功能提供设备权限以支持 Android 11 中的 RoR,但您无需这样做即可在 Android 12 及更高版本中启用基于服务器的 RoR,因为它们不使用 HAL。

android.hardware.reboot_escrow功能提供设备权限。您无需执行任何操作即可在 Android 12 中启用基于服务器的 RoR,因为 Android 12 及更高版本不使用 HAL。

背景

从 Android 7 开始,Android 支持Direct Boot ,这使设备上的应用程序能够在用户解锁 CE 存储之前启动。直接启动支持的实施为用户在启动后需要输入锁屏知识因子 (LSKF) 之前提供了更好的体验。

RoR 允许在 OTA 更新后启动重新启动时解锁设备上所有应用程序的 CE 存储,包括那些不支持直接启动的应用程序。此功能使用户能够在重新启动后接收来自所有已安装应用程序的通知。

威胁模型

RoR 的实现必须确保当设备落入攻击者手中时,攻击者很难恢复用户的 CE 加密数据,即使设备上电,CE 存储被解锁,设备被收到OTA更新后的用户。即使攻击者获得了广播加密签名密钥的访问权限,内部攻击抵抗也必须有效。

具体来说,CE 存储不能被物理上拥有设备的攻击者读取,并且具有以下功能和限制:

能力

  • 可以使用任何供应商或公司的签名密钥对任意消息进行签名。
  • 可能导致设备接收 OTA 更新。
  • 可以修改任何硬件(例如应用处理器或闪存)的操作 - 除非下面的限制中详细说明。 (但是,这种修改涉及至少一小时的延迟,以及破坏 RAM 内容的电源循环。)

限制

  • 无法修改防篡改硬件(例如 Titan M)的操作。
  • 无法读取活动设备的 RAM。
  • 无法猜测用户的凭据(PIN、图案、密码)或以其他方式导致它们被输入。

解决方案

Android 12 RoR 更新系统可针对非常老练的攻击者提供安全保护,并且在设备上的密码和 PIN 保留在设备上的同时,它们不会发送到或存储在 Google 服务器上。这是确保提供的安全级别类似于基于硬件的设备级 RoR 系统的过程概述:

  • Android 对存储在设备上的数据应用加密保护。
  • 所有数据都由存储在可信执行环境(TEE) 中的密钥保护。
  • TEE 仅在运行的操作系统通过密码验证(验证启动)时才释放密钥。
  • 在 Google 服务器上运行的 RoR 服务通过存储只能在有限时间内检索的秘密来保护 CE 数据。这适用于整个 Android 生态系统。
  • 受用户 PIN 保护的加密密钥用于解锁设备和解密 CE 存储。
    • 当安排夜间重启时,Android 会提示用户输入他们的 PIN,然后计算合成密码 (SP)。
    • 然后它对 SP 进行两次加密:一次使用存储在 RAM 中的密钥K_s ,另一次使用存储在 TEE 中的密钥K_k
    • 双重加密的 SP 存储在磁盘上,并且 SP 从 RAM 中擦除。这两个密钥都是新生成的,仅用于一次重新启动
  • 当需要重新启动时,Android 将K_s委托给服务器。带有K_k的收据在存储到磁盘之前会被加密。
  • 重启后,Android 使用K_k解密收据,然后将其发送到服务器以检索K_s
    • K_kK_s用于解密存储在磁盘上的 SP。
    • Android 使用 SP 解锁 CE 存储并允许正常的应用启动。
    • K_kK_s被丢弃。

确保手机安全的更新可以在您方便的时候进行:在您睡觉时。

SIM-PIN 重播

在某些情况下,SIM 卡的 PIN 码会从缓存中得到验证,这一过程称为 SIM-PIN 重放。

启用 PIN 的 SIM 卡还必须在无人值守重启后进行无缝 PIN 码验证(SIM-PIN 重放)以恢复蜂窝连接(电话、短信和数据服务需要)。 SIM PIN 及其匹配的 SIM 卡信息(ICCID 和 SIM 插槽号)被安全地存储在一起。只有在无人值守重启成功后,才能检索存储的 PIN 并将其用于验证。如果设备受到保护,SIM PIN 将与受 LSKF 保护的密钥一起存储。如果 SIM 卡启用了 PIN,则与 RoR 服务器的交互需要WiFi 连接以进行 OTA 更新和基于服务器的 RoR,从而确保重启后的基本功能(通过蜂窝连接)。

每次用户成功启用、验证或修改 SIM PIN 时,都会重新加密和存储 SIM PIN。如果发生以下任何一种情况,SIM PIN 将被丢弃:

  • SIM 被移除或重置。
  • 用户禁用 PIN。
  • 发生了非 RoR 启动的重新启动。

存储的 SIM PIN 只能在 RoR 启动的重新启动后使用一次,并且只能在很短的持续时间(20 秒)内使用 -如果SIM 卡的详细信息匹配。存储的 SIM PIN 永远不会离开 TelephonyManager 应用程序,并且无法由外部模块检索。

实施指南

在 Android 12 中,多客户端和基于服务器的 RoR 功能为合作伙伴推送 OTA 更新时提供了更轻的负载。必要的更新可以在设备方便的停机时间内进行,例如在指定的睡眠时间。

为确保此类时间段内的 OTA 更新不会中断用户,请使用暗模式来减少光发射。为此,请让设备引导加载程序搜索字符串 reason unattended 。如果unattendedtrue ,则将设备置于暗模式。请注意,减少声光发射是每个 OEM 的责任。

如果您要升级到 Android 12 或启动 Android 12 设备,则无需执行任何操作即可实现新的 RoR 功能。

多客户端流程中有一个新调用isPreparedForUnattendedUpdate ,如下所示:

@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
            android.Manifest.permission.REBOOT})
public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)

您不需要实现这一点,因为 HAL 自 Android 12 起已弃用。

电话经理

OTA 客户端在 Android 12 中即将重启时调用TelephonyManager系统 API。此 API 将所有缓存的 PIN 码从AVAILABLE状态移动到REBOOT_READY状态。 TelephonyManager系统 API 受现有REBOOT Manifest 权限的保护。

 /**
    * 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 以 root ( adb root ) 运行时有效。

仅限安卓 11

本页的其余部分适用于 Android 11。

截至 2020 年 7 月,RoR HAL 的实现分为两类:

  1. 如果 SoC 硬件在重启后支持 RAM 持久性,OEM 可以使用 AOSP 中的默认实现(默认 RAM Escrow )。
  2. 如果设备硬件或 SoC 支持安全硬件飞地(具有自己的 RAM 和 ROM 的离散安全协处理器),它还必须执行以下操作:
    • 能够检测到主 CPU 重启。
    • 有一个在重新启动后仍然存在的硬件计时器源。即,飞地必须能够检测到重新启动并且使在重新启动之前设置的计时器到期。
    • 支持将托管密钥存储在 enclave RAM/ROM 中,使其无法通过离线攻击恢复。它必须以某种方式存储 RoR 密钥,使内部人员或攻击者无法恢复它。

默认 RAM 托管

AOSP 使用 RAM 持久性实现了 RoR HAL。为此,OEM 必须确保其 SoC 支持跨重启的 RAM 持久性。某些 SoC 无法在重新启动后保留 RAM 内容,因此建议 OEM 在启用此默认 HAL 之前咨询其 SoC 合作伙伴。下一节中对此的规范参考。

使用 RoR 的 OTA 更新流程

手机上的OTA客户端app必须拥有Manifest.permission.REBOOTManifest.permission.RECOVERY权限,才能调用必要的方法来实现RoR。有了这个先决条件,更新流程遵循以下步骤:

  1. OTA 客户端应用程序下载更新。
  2. OTA 客户端应用程序调用RecoverySystem#prepareForUnattendedUpdate ,这会触发用户在下次解锁期间在锁定屏幕上被提示输入其 PIN 码、图案或密码。
  3. 用户在锁定屏幕上解锁设备,并且设备已准备好应用更新。
  4. OTA 客户端应用程序调用RecoverySystem#rebootAndApply ,这会立即触发重启。

在此流程结束时,设备重新启动并且 RoR 机制解锁凭证加密 (CE) 存储。对于应用程序来说,这显示为普通用户解锁,因此他们会收到所有信号,例如他们通常会收到的ACTION_LOCKED_BOOT_COMPLETEDACTION_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的新设备(例如pmem1pmem2 )。

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