Resume-on-Reboot

Android 11 では、A/B アップデートまたは仮想 A/B アップデートのメカニズムを RecoverySystem クラスメソッドと組み合わせて使用することで、OTA アップデートを適用できます。OTA アップデートを適用するためにデバイスが再起動すると、Resume-on-Reboot(RoR)によってデバイスの認証情報暗号化(CE)ストレージがロック解除されます。

Android 11 では、パートナーはこのプロセスを、デバイスがアイドル状態にあると予想されるときにアップデートを適用する OTA システム機能と組み合わせることができますが、Android 12 では、パートナーは追加の OTA システム機能を必要としません。デバイスがアイドル状態のときにアップデートを行うことができるため、RoR プロセスはユーザーにとってのセキュリティと利便性を高めます。一方、Android 12 のマルチクライアントかつサーバーベースのアップデート機能は、連携してデバイスのハードウェア レベルのタイプ セキュリティを提供します。

Android 11 で RoR をサポートするには android.hardware.reboot_escrow 機能のデバイス権限を提供する必要がありますが、Android 12 以降では HAL が使用されないため、サーバーベースの RoR を有効にするために権限を提供する必要はありません。

背景

Android 7 以降、Android はダイレクト ブートをサポートしています。これは、CE ストレージがユーザーによってロック解除される前に、デバイス上のアプリを起動できるようにするものです。ダイレクト ブートのサポートを実装することにより、起動してからロック画面ナレッジ ファクタ(LSKF)の入力が必要になるまでのユーザー エクスペリエンスが向上しました。

RoR を使用すると、OTA アップデート後に再起動が開始されたときに、デバイス上のすべてのアプリ(ダイレクト ブートをサポートしていないものを含む)の CE ストレージをロック解除できます。この機能により、ユーザーは再起動後にすべてのインストール済みアプリから通知を受け取ることができます。

脅威モデル

RoR の実装は、デバイスが攻撃者の手に渡ったときに、攻撃者がユーザーの CE 暗号化データを復元することが極めて困難であるという状況を保証する必要があります。これは、デバイスの電源がオンで CE ストレージがロック解除されており、OTA アップデートの受信後にユーザーがデバイスをロック解除した場合であっても同様です。インサイダー攻撃への耐性は、攻撃者がブロードキャスト暗号署名鍵へのアクセスを取得した場合でも、有効でなければなりません。

具体的には、攻撃者がデバイスを物理的に所持していて以下の能力と制限がある場合に、CE ストレージが読み取られないようにする必要があります

能力

  • なんらかのベンダーまたは企業の署名鍵を使用して、任意のメッセージに署名できる。
  • デバイスに OTA アップデートを受信させることができる。
  • 任意のハードウェア(アプリケーション プロセッサやフラッシュ メモリなど)のオペレーションを変更できる。ただし、下記の制限で詳述されている場合を除く(そのような変更には、1 時間以上の遅延と、電源をオフにして再度オンにする動作による RAM の内容の破棄の両方が含まれます)。

制限

  • 耐タンパー性を備えたハードウェア(Titan M など)のオペレーションを変更できない。
  • ライブデバイスの RAM を読み取れない。
  • ユーザーの認証情報(PIN、パターン、パスワード)を推測できず、また、それらをユーザーに入力させることができない。

ソリューション

Android 12 の RoR アップデート システムは、狡知に長けた攻撃者に対するセキュリティを提供します。デバイス上のパスワードと PIN がデバイスに残っている間はそうしたセキュリティが提供され、それらが Google サーバーに送信または保存されることは決してありません。ここでは、指定されたセキュリティ レベルが、ハードウェアに基づくデバイスレベルの RoR システムと同様であるプロセスの概要について説明します。

  • Android は、デバイスに保存されているデータに対する暗号保護を適用します。
  • すべてのデータは、高信頼実行環境(TEE)に保存される鍵によって保護されます。
  • TEE は、実行中のオペレーティング システムが暗号認証(確認付きブート)に合格した場合にのみ、鍵を解放します。
  • Google サーバーで実行される RoR サービスは、期間限定で取得できるシークレットを保存することにより、CE データを保護します。これは、Android エコシステム全体で機能します。
  • ユーザーの PIN によって保護される暗号鍵は、デバイスのロック解除と CE ストレージの復号に使用されます。
    • 夜間の再起動がスケジュールされている場合、Android はユーザーに PIN の入力を求めた後、合成パスワード(SP)を計算します。
    • 次に、SP を 2 回暗号化します。1 回目は RAM に保存される鍵 K_s、2 回目は 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 リプレイ)を行い、(通話、SMS メッセージ、データサービスに必要な)モバイル接続を復元する必要があります。SIM PIN とそれに対応する SIM カード情報(ICCID と SIM スロット番号)は、一緒に安全に保存されます。保存された PIN は、無人再起動の成功後にのみ、取得して検証に使用できます。デバイスが保護されている場合、SIM PIN は LSKF によって保護される鍵で保存されます。SIM で PIN が有効になっている場合、RoR サーバーとのやり取りには、OTA アップデートとサーバーベースの RoR のための Wi-Fi 接続が必要です。これにより、再起動後の(モバイル接続による)基本機能が保証されます。

SIM PIN は、ユーザーがその有効化、検証、または変更に成功するたびに、再暗号化されて保存されます。次のいずれかが発生すると、SIM PIN は破棄されます。

  • SIM が取り外されるか、リセットされた。
  • ユーザーが PIN を無効にした。
  • RoR 以外で開始される再起動が発生した。

保存された SIM PIN を使用できるのは、SIM カードの詳細が一致する場合、RoR で開始される再起動後 1 回のみであり、非常に短い期間(20 秒)に限られます。保存された SIM PIN は TelephonyManager アプリの外に出ることはなく、外部モジュールが取得することはできません。

実装ガイドライン

Android 12 では、マルチクライアントかつサーバーベースの RoR 機能により、パートナーが OTA アップデートをプッシュする際の負荷が軽減されます。指定された就寝時間中など、ユーザーにとって都合の良いデバイスのダウンタイム中に必要なアップデートを行うことができます。

その時間に OTA アップデートがユーザーの邪魔をしないようにするには、ダークモードを使用して発光を抑制します。そのためには、デバイスのブートローダーが理由文字列 unattended を検索するようにします。unattendedtrue の場合は、デバイスをダークモードにします。音と発光を抑制するのは各 OEM の役割です。

Android 12 にアップグレードする場合または Android 12 デバイスを起動する場合、新しい RoR 機能を実装するために何もする必要はありません。

次に示すように、マルチクライアント フロー isPreparedForUnattendedUpdate には新しい呼び出しが 1 つあります。

@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

このコマンドは、シェルが root(adb root)として実行されている場合にのみ機能します。

Android 11 のみ

このページの残りの部分は Android 11 を対象としています。

2020 年 7 月現在、RoR HAL の実装は 2 つのカテゴリに分類されています。

  1. SoC ハードウェアが再起動後も RAM の永続性をサポートする場合、OEM は AOSP のデフォルト実装(デフォルトの RAM エスクロー)を使用できます。
  2. デバイス ハードウェアまたは SoC が安全なハードウェア エンクレーブ(独自の RAM と ROM を持つ個別のセキュリティ コプロセッサ)をサポートする場合は、以下の要件を満たす必要があります。
    • メイン CPU の再起動を検出できる。
    • 再起動後も持続するハードウェア タイマーのソースがある。つまり、エンクレーブが再起動を検出し、再起動前に設定されたタイマーを期限切れにすることができる。
    • エスクローされた鍵をエンクレーブの RAM / ROM に保存して、オフライン攻撃で復元できないようにする。インサイダーまたは攻撃者が復元できない方法で RoR 鍵を保存する必要があります。

デフォルトの RAM エスクロー

AOSP には、RAM の永続性を使用した RoR HAL の実装があります。これが機能するためには、再起動後も OEM の SoC が RAM の永続性をサポートすることを OEM が保証する必要があります。一部の SoC は再起動後に RAM の内容を保持できないので、OEM はこのデフォルトの HAL を有効にする前に SoC パートナーに相談することが推奨されます。この場合の正規参照については、次のセクションで説明します。

RoR を使用した OTA アップデートのフロー

スマートフォンで動作する OTA クライアント アプリには、RoR を実装するのに必要なメソッドを呼び出すための Manifest.permission.REBOOT 権限と Manifest.permission.RECOVERY 権限が必要です。この前提条件が適用される場合、アップデートのフローは次のステップに従って進みます。

  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 の実装

デフォルトの実装を使用するには、65,536(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