ファイルベースの暗号化

Android 7.0 以降では、ファイルベースの暗号化(FBE)がサポートされています。ファイルベースの暗号化を使用すると、さまざまなファイルを異なる鍵で暗号化して、個別にロック解除できます。

この記事では、新しいデバイスでファイルベースの暗号化を有効にする方法と、システムアプリが Direct Boot API を使用して、可能な限り安全性の高い最適な操作性をユーザーに提供する仕組みについて説明します。

Android 10 以降を搭載するデバイスはすべて、ファイルベースの暗号化を使用する必要があります。

ダイレクト ブート

ファイルベースの暗号化により、Android 7.0 で導入されたダイレクト ブートという新機能を有効利用できるようになります。ダイレクト ブートでは、暗号化されたデバイスをロック画面に直接起動できます。これまで、フルディスク暗号化(FDE)を使用して暗号化されたデバイスでは、認証情報を提供しないとデータに一切アクセスできず、ごく基本的な操作を除いて、スマートフォンでほとんどの操作を行えませんでした。たとえば、アラームを操作することも、ユーザー補助サービスを利用することもできず、緊急通報操作を除いてスマートフォンで通話を受信することもできません。

ファイルベースの暗号化(FBE)と、アプリが暗号化を認識できるようにする新しい API の導入により、限られたコンテキスト内でアプリが動作できるようになりました。ユーザーが認証情報を提供する前に、個人情報を保護したままでこの動作が実現します。

FBE 対応デバイスでは、デバイスの各ユーザーが 2 つの保存場所をアプリで使用できます。

  • デフォルトの保存先であり、ユーザーがデバイスのロックを解除した後にだけ使用できる、認証情報暗号化(CE)ストレージ。
  • ダイレクト ブート モード中とユーザーがデバイスのロックを解除した後の両方で保存先として使用できる、デバイス暗号化(DE)ストレージ。

暗号化が起動時のパスワードのみに基づくものではなくなり、この分離によって複数のユーザーを一度に保護できるため、仕事用プロファイルの安全性が高まります。

Direct Boot API を使用すると、暗号化対応のアプリがこれらの領域にアクセスできます。ロック画面に認証情報が最初に入力された際の応答として、または仕事用プロファイルでワーク チャレンジが提供された場合に、ユーザーの CE ストレージがロック解除されたことをアプリに通知できるようにアプリのライフサイクルが変更されています。Android 7.0 搭載デバイスは、FBE を実装しているかどうかにかかわらず、新しい API とライフサイクルをサポートする必要があります。ただし、FBE が実装されていない場合は、DE ストレージと CE ストレージが常にロック解除状態になります。

Android オープンソース プロジェクト(AOSP)で提供されている、Ext4 と F2FS のファイルシステムに対するファイルベースの暗号化の完全な実装は、要件を満たすデバイスでのみ有効です。FBE の使用を選択したメーカーは、使用するシステム オン チップ(SoC)に基づいて機能を最適化する方法を検討できます。

AOSP 内で対応の必要なパッケージはすべて、ダイレクトブート対応に更新されています。ただし、デバイス メーカーがこれらのアプリのカスタマイズ版を使用する場合、次のサービスを提供するダイレクトブート対応パッケージが最低限必要になります。

  • 電話サービスと電話アプリ
  • ロック画面にパスワードを入力するための入力方法

例とソース

Android にはファイルベースの暗号化のリファレンス実装が用意されており、vold(system/vold)によって Android のストレージ デバイスとボリュームを管理する機能が提供されます。FBE を追加すると、複数のユーザーの CE 鍵と DE 鍵の管理に対応したいくつかの新しいコマンドが vold に提供されます。カーネルでファイルベースの暗号化機能を使用するための主な変更に加え、ロック画面と SystemUI を含む多くのシステム パッケージが、FBE とダイレクト ブート機能をサポートするように変更されました。これには以下が含まれます。

  • AOSP 電話アプリ(packages/apps/Dialer)
  • 時計(packages/apps/DeskClock)
  • LatinIME(packages/inputmethods/LatinIME)*
  • 設定アプリ(packages/apps/Settings)*
  • SystemUI(frameworks/base/packages/SystemUI)*

* defaultToDeviceProtectedStorage マニフェスト属性を使用するシステムアプリ

暗号化に対応しているアプリとサービスのその他の例は、AOSP ソースツリーのフレームワークまたはパッケージ ディレクトリでコマンド mangrep directBootAware を実行することで確認できます。

依存関係

FBE の AOSP 実装を安全に使用するには、デバイスが次の依存関係を満たしている必要があります。

  • Ext4 暗号化または F2FS 暗号化のカーネル サポート
  • HAL バージョン 1.0 以降の Keymaster サポート。Keymaster 0.3 は、必要な機能を提供していなかったり、暗号鍵の保護が不十分であったりするため、サポートされていません。
  • Keymaster またはキーストアとゲートキーパー高信頼実行環境(TEE)に実装して DE 鍵を保護し、未承認の OS(デバイスに書き込まれたカスタム OS)が簡単に DE 鍵を要求できないようにする必要があります。
  • 未承認のオペレーティング システム DE 鍵にアクセスできないようにするには、Keymaster の初期化にバインドされたハードウェア ルート オブ トラスト確認付きブートが必要です。

実装

まずは、ダイレクト ブートのデベロッパー向けドキュメントに基づいて、アラーム時計、電話、ユーザー補助機能などのアプリを android:directBootAware にする必要があります。

カーネル サポート

Ext4 と F2FS の暗号化向けのカーネル サポートは、Android 共通カーネルのバージョン 3.18 以降で利用できます。バージョン 5.1 以降のカーネルでこのカーネル サポートを有効にする場合は、以下を使用します。

CONFIG_FS_ENCRYPTION=y

古いカーネルの場合、デバイスの userdata ファイル システムが Ext4 であれば CONFIG_EXT4_ENCRYPTION=y を使用し、デバイスの userdata ファイル システムが F2FS であれば CONFIG_F2FS_FS_ENCRYPTION=y を使用します。

デバイスが Adoptable Storage をサポートする場合や、内部ストレージのメタデータ暗号化を使用する場合は、メタデータ暗号化に必要なカーネル構成オプションも有効にします。詳細については、メタデータ暗号化に関するドキュメントをご覧ください。

ファイルベース暗号化を高速化し、ユーザー エクスペリエンスを高めるため、デバイス メーカーは、Ext4 / F2FS 暗号化の機能サポートに加えて暗号アクセラレーションも有効にする必要があります。たとえば ARM64 ベースのデバイスでは、次のカーネル構成オプションを設定することによって ARMv8 CE(暗号拡張機能)のアクセラレーションを有効にできます。

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

デバイス メーカーは、さらなるパフォーマンスの向上と電力消費量の削減のために、ストレージ デバイスとの間でデータを伝送する際にデータの暗号化と復号を行う「インライン暗号化ハードウェア」の実装を検討することもできます。Android 共通カーネル(バージョン 4.14 以降)には、ハードウェアとベンダー ドライバのサポートが利用可能な場合にインライン暗号化を使用できるようにするフレームワークが搭載されています。インライン暗号化フレームワークを有効にするには、以下のカーネル構成オプションを設定します。

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

デバイスで UFS ベースのストレージを使用する場合は、次のオプションも有効にします。

CONFIG_SCSI_UFS_CRYPTO=y

デバイスで eMMC ベースのストレージを使用する場合は、次のオプションも有効にします。

CONFIG_MMC_CRYPTO=y

ファイルベースの暗号化の有効化

デバイスで FBE を有効にする場合、内部ストレージ(userdata)で有効にする必要があります。これにより、Adoptable Storage でも FBE が自動的に有効化されます。ただし、Adoptable Storage での暗号化形式は、必要に応じてオーバーライドされることがあります。

内部ストレージ

FBE を有効にするには、userdatafstab 行の fs_mgr_flags 列にオプション fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] を追加します。このオプションでは、内部ストレージでの暗号化形式を定義します。オプションには最大 3 つのパラメータを含めることができます(コロンで区切って指定)。

  • contents_encryption_mode パラメータでは、ファイルの内容の暗号化に使用される暗号アルゴリズムを定義します。aes-256-xts または adiantum のいずれかを指定できます。Android 11 以降の場合は、空のままにしてデフォルトのアルゴリズム(aes-256-xts)を指定することもできます。
  • filenames_encryption_mode パラメータでは、ファイル名の暗号化に使用される暗号アルゴリズムを定義します。aes-256-ctsaes-256-hehadiantumaes-256-hctr2 のいずれかを指定できます。指定しない場合のデフォルトは、contents_encryption_modeaes-256-xts の場合は aes-256-ctscontents_encryption_modeadiantum の場合は adiantum です。
  • Android 11 で新たに導入された flags パラメータでは、フラグのリストを指定します(+ 記号で区切って指定)。次のフラグがサポートされています。
    • v1 フラグを指定するとバージョン 1 の暗号化ポリシーが、v2 フラグを指定するとバージョン 2 の暗号化ポリシーが選択されます。バージョン 2 の暗号化ポリシーでは、安全性と柔軟性に優れた鍵導出関数が使用されます。デフォルトは、Android 11 以降を搭載して出荷されたデバイス(ro.product.first_api_level によって特定される)の場合は v2、Android 10 以前を搭載して出荷されたデバイスの場合は v1 です。
    • inlinecrypt_optimized フラグを指定すると、多数の鍵を効率的に処理できないインライン暗号化ハードウェア向けに最適化された暗号化形式が選択されます。これは、ファイルの内容の暗号化に使用する鍵を、ファイルごとに 1 つではなく CE 鍵または DE 鍵ごとに 1 つだけ派生させることによって行われます。IV(初期化ベクトル)の生成は適宜調整されます。
    • emmc_optimized フラグは inlinecrypt_optimized と同様ですが、IV を 32 ビットに制限する IV 生成メソッドも選択することになります。このフラグは、JEDEC eMMC v5.2 仕様に従って 32 ビットの IV のみサポートするインライン暗号化ハードウェアでのみ使用してください。他のインライン暗号化ハードウェアでは、代わりに inlinecrypt_optimized を使用します。このフラグは UFS ベースのストレージでは使用できません。UFS 仕様では、64 ビットの IV を使用できます。
    • ハードウェアでラップされた鍵をサポートしているデバイスでは、wrappedkey_v0 フラグを指定すると、ハードウェアでラップされた鍵を FBE に使用できるようになります。これは、inlinecrypt マウント オプションと、inlinecrypt_optimized フラグまたは emmc_optimized フラグのいずれかと組み合わせた場合にのみ使用できます。
    • dusize_4k フラグは、ファイルシステムのブロック サイズが 4,096 バイトではない場合でも、暗号化データのユニット サイズを強制的に 4,096 バイトにします。暗号化データのユニット サイズは、ファイルの内容の暗号化の粒度です。このフラグは Android 15(AOSP 試験運用版)以降で使用できます。このフラグは、f2fs ファイルシステムと 4,096 バイトを越えるページサイズを使用するデバイス上で、4,096 バイト未満のデータ ユニットをサポートしていないインライン暗号化ハードウェアの使用を可能にする目的でのみ使用してください。

インライン暗号化ハードウェアを使用していない場合、ほとんどのデバイスでは、fileencryption=aes-256-xts を設定することをおすすめします。インライン暗号化ハードウェアを使用している場合、ほとんどのデバイスでは fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized(または同等の fileencryption=::inlinecrypt_optimized)を設定することをおすすめします。どの形式の AES アクセラレーションも使用していないデバイスでは、fileencryption=adiantum を設定することで、AES の代わりに Adiantum を使用できます。

Android 14 以降では、高速な暗号化方式に対応したデバイス用のファイル名の暗号化モードとして AES-HCTR2 が推奨されています。ただし、AES-HCTR2 をサポートするのは新しい Android カーネルのみです。今後の Android リリースでは、これがファイル名の暗号化モードのデフォルトになる予定です。AES-HCTR2 がサポートされているカーネルでは、filenames_encryption_modeaes-256-hctr2 に設定することで、ファイル名の暗号化を有効にできます。最も単純なケースでは fileencryption=aes-256-xts:aes-256-hctr2 のようになります。

Android 10 以前を搭載して出荷されたデバイスでは、fileencryption=ice を指定することで、ファイルの内容の暗号化モードとして FSCRYPT_MODE_PRIVATE を使用することもできます。このモードは Android 共通カーネルでは実装されませんが、ベンダーがカスタムのカーネルパッチを使用して実装している場合があります。このモードで生成されるディスク上の暗号化形式はベンダー固有でした。Android 11 以降を搭載して出荷されるデバイスでは、このモードは使用できなくなりました。代わりに、標準の暗号化形式を使用する必要があります。

デフォルトでは、ファイルの内容の暗号化は Linux カーネルの暗号 API を使用して行われます。インライン暗号化ハードウェアを使用する場合も、inlinecrypt マウント オプションを追加します。たとえば、完全な fstab 行は次のようになります。

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

Adoptable Storage

Android 9 以降では、FBE と Adoptable Storage を組み合わせて使用できます。

また、userdata に対して fileencryption fstab オプションを指定すると、Adoptable Storage で FBE とメタデータ暗号化の両方が自動的に有効化されます。ただし Adoptable Storage では、PRODUCT_PROPERTY_OVERRIDES のプロパティを設定することで、FBE またはメタデータ暗号化(あるいはその両方)の形式をオーバーライドできます。

Android 11 以降を搭載して出荷されたデバイスでは、次のプロパティを使用します。

  • ro.crypto.volume.options(Android 11 で新たに導入されたプロパティ): Adoptable Storage で FBE 暗号化形式を選択します。このプロパティは、fileencryption fstab オプションに対する引数と構文が同じであるため、同じデフォルトを使用します。このプロパティで使用する内容については、上記の fileencryption に関する推奨事項をご覧ください。
  • ro.crypto.volume.metadata.encryption: Adoptable Storage のメタデータ暗号化形式を選択します。詳細については、メタデータ暗号化をご覧ください。

Android 10 以前を搭載して出荷されたデバイスの場合、以下のプロパティを使用します。

  • ro.crypto.volume.contents_mode: ファイルの内容の暗号化モードを選択します。これは、ro.crypto.volume.options の最初のコロン区切りのフィールドと同じです。
  • ro.crypto.volume.filenames_mode: ファイル名の暗号化モードを選択します。これは、Android 10 以前を搭載して出荷されたデバイスのデフォルトが aes-256-heh であることを除き、ro.crypto.volume.options の 2 番目のコロン区切りのフィールドと同じです。ほとんどのデバイスでは、このデフォルトを明示的にオーバーライドして aes-256-cts にする必要があります。
  • ro.crypto.fde_algorithmro.crypto.fde_sector_size: Adoptable Storage のメタデータ暗号化形式を選択します。詳細については、メタデータ暗号化をご覧ください。

Keymaster との統合

Keymaster HAL は、early_hal クラスの一部として起動する必要があります。これは、FBE では、post-fs-data の起動フェーズ(vold が最初の鍵をセットアップする際)に Keymaster がリクエストを処理する準備ができている必要があるためです。

ディレクトリの除外

init は、システムの DE 鍵/data のすべての最上位ディレクトリに適用します。ただし、暗号化されていない必要があるディレクトリ、つまり、システムの DE 鍵そのものが含まれているディレクトリとユーザーの CE または DE ディレクトリが含まれているディレクトリは、除外されます。暗号鍵は再帰的に適用され、サブディレクトリでオーバーライドすることはできません。

Android 11 以降では、init がディレクトリに適用する鍵は、init スクリプト内の mkdir コマンドの encryption=<action> 引数で制御できます。<action> の有効な値については、Android init 言語の README をご覧ください。

Android 10 では、init の暗号化アクションは次の場所にハードコードされていました。

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

Android 9 以前では、次の場所にハードコードされていました。

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

例外を追加して、特定のディレクトリが暗号化されないようにすることもできます。このような変更を行う場合、デバイス メーカーは、暗号化されていないディレクトリを使用するアプリにのみアクセスを許可する SELinux ポリシーを含める必要があります。これにより、信頼できないアプリがすべて除外されます。

なお、従来の OTA 機能のサポートに含まれるのは既知の利用可能なユースケースのみです。

システムアプリでのダイレクト ブートのサポート

アプリをダイレクト ブート対応にする

システムアプリの迅速な移行を実現するために、アプリレベルで設定できる新しい属性が 2 つあります。defaultToDeviceProtectedStorage 属性はシステムアプリでのみ使用できます。directBootAware 属性はすべてのアプリに使用できます。

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

アプリレベルの directBootAware 属性は、簡単にアプリ内のすべてのコンポーネントを暗号化対応にする方法です。

defaultToDeviceProtectedStorage 属性は、CE ストレージではなく DE ストレージを指すように、デフォルトのアプリの保存場所をリダイレクトします。 このフラグを使用するシステムアプリは、デフォルトの場所に保存されたすべてのデータを慎重に監査し、CE ストレージを使用するように機密データのパスを変更する必要があります。この方法を使用するデバイス メーカーは、保存するデータを慎重に調べて、個人情報が含まれていないことを確認する必要があります。

このモードを実行する場合は、次のシステム API を使用して、必要に応じて CE ストレージに保持されたコンテキストを明示的に管理できます。これは、デバイス保護ストレージに相当します。

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

複数のユーザーをサポートする

マルチユーザー環境の各ユーザーは個別の暗号鍵を取得します。すべてのユーザーが DE と CE の 2 つの鍵を取得します。ユーザー 0 は特別なユーザーであるため、最初にデバイスにログインする必要があります。これは、デバイス管理の使用に関係します。

暗号化対応アプリは、INTERACT_ACROSS_USERSINTERACT_ACROSS_USERS_FULL(アプリがデバイス上のすべてのユーザー間で動作できるようにする)によってユーザー間で動作します。ただしこれらのアプリがアクセスできるのは、すでにロック解除されているユーザーの CE で暗号化されたディレクトリのみです。

アプリは DE エリア間で自由に動作できますが、1 人のユーザーがロック解除されていても、デバイス上のすべてのユーザーがロック解除されているわけではありません。アプリはこのステータスを確認してから、これらの領域にアクセスする必要があります。

仕事用プロファイルの各ユーザー ID にも、DE と CE の 2 つの鍵があります。ワーク チャレンジが満たされると、プロファイルのユーザーがロック解除され、TEE 内の Keymaster によりプロファイルの TEE 鍵が提供されます。

アップデートの処理

リカバリ パーティションは、userdata パーティションの DE で保護されたストレージにアクセスできません。FBE を実装するデバイスでは、A/B システムアップデートを使用した OTA をサポートすることを強くおすすめします。通常の動作中に OTA を適用できるため、暗号化されたドライブ上のデータにリカバリがアクセスする必要はありません。

以前の OTA ソリューションを使用している場合は、リカバリが userdata パーティション上の OTA ファイルにアクセスする必要があります。

  1. userdata パーティションに最上位ディレクトリ(misc_ne など)を作成します。
  2. この最上位ディレクトリを暗号化されないように設定します(「ディレクトリの除外」をご覧ください)。
  3. OTA パッケージを格納するディレクトリを最上位ディレクトリ内に作成します。
  4. SELinux ルールとファイル コンテキストを追加して、このディレクトリとそのコンテンツへのアクセスを制御します。OTA アップデートを受信するプロセスまたはアプリのみが、このディレクトリの読み取りと書き込みを行える必要があります。他のアプリやプロセスがこのディレクトリにアクセスできないようにしてください。

検証

機能の実装バージョンが意図したとおりに動作することを確認するには、多数の CTS 暗号化テスト(DirectBootHostTestEncryptionTest など)を使用します。

Android 11 以降が搭載されているデバイスの場合は、vts_kernel_encryption_test も使用します。

atest vts_kernel_encryption_test

または

vts-tradefed run vts -m vts_kernel_encryption_test

デバイス メーカーは次の手動テストを実施することもできます。FBE が有効になっているデバイスで以下を実施します。

  • ro.crypto.state をチェックします
    • ro.crypto.state が暗号化されていることを確認します
  • ro.crypto.type をチェックします
    • ro.crypto.typefile に設定されていることを確認します

さらに、テスターはデバイスが起動してから初めてロック解除される前に、CE ストレージがロックされていることを確認できます。そのためには、userdebug または eng ビルドを使用し、メインユーザーの PIN、パターン、またはパスワードを設定して、デバイスを再起動します。デバイスをロック解除する前に、以下のコマンドを実行してメインユーザーの CE ストレージをチェックします。ヘッドレス システム ユーザー モードを使用しているデバイスの場合(ほとんどの Automotive デバイス)、メインユーザーは user 10 であるため、以下を実行します。

adb root; adb shell ls /data/user/10

他のデバイスの場合(Automotive 以外のほとんどのデバイス)、メインユーザーは user 0 であるため、以下を実行します。

adb root; adb shell ls /data/user/0

リストされたファイル名が Base64 エンコードされている(ファイル名が暗号化されており、複合するための鍵はまだ利用できない)ことを確認します。ファイル名が平文でリストされている場合、なんらかの問題が発生しています。

また、デバイス メーカーは、自社のデバイスまたはカーネルで Linux の fscrypt 用アップストリーム テストを実行することをおすすめします。このテストは、xfstests ファイルシステムのテストスイートの一部です。ただし、上記アップストリーム テストは Android では公式にはサポートされていません。

AOSP 実装の詳細

このセクションでは、AOSP 実装の詳細とファイルベースの暗号化の仕組みについて説明します。デバイス メーカーが自社のデバイスで FBE とダイレクト ブートを使用するために、変更を加える必要はありません。

fscrypt 暗号化

AOSP 実装では、カーネルで「fscrypt」暗号化(ext4 と f2fs でサポートされている)が使用されます。これは通常、次のように設定されています。

  • XTS モードの AES-256 でファイルの内容を暗号化します
  • CBC-CTS モードの AES-256 でファイル名を暗号化します

Adiantum 暗号化もサポートされています。Adiantum 暗号化が有効になっている場合、ファイルの内容とファイル名はどちらも Adiantum で暗号化されます。

fscrypt は暗号化ポリシーのバージョン 1 とバージョン 2 の 2 つのバージョンをサポートしています。バージョン 1 は非推奨です。Android 11 以降を搭載したデバイスの CDD 要件はバージョン 2 とのみ互換性があります。バージョン 2 の暗号化ポリシーは、HKDF-SHA512 を使用して、ユーザー空間で指定された鍵から実際の暗号鍵を導出します。

fscrypt について詳しくは、アップストリーム カーネルのドキュメントをご覧ください。

ストレージ クラス

次の表に、FBE 鍵とそれらの鍵が保護するディレクトリを詳しく示します。

ストレージ クラス 説明 ディレクトリ
暗号化なし FBE で保護できない、または保護する必要がない /data のディレクトリ。メタデータ暗号化 を使用するデバイスの場合、これらのディレクトリは実際には暗号化されておらず、システムの DE と同等のメタデータ暗号鍵によって保護されます。
  • /data/apex(システムの DE である /data/apex/decompressed および /data/apex/ota_reserved を除く)
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • サブディレクトリで別の FBE 鍵を使用しているすべてのディレクトリ。例: それぞれの /data/user/${user_id} ディレクトリでユーザー別の鍵を使用しているため、/data/user 自体では鍵を使用していない。
システムの DE 特定のユーザーに結び付けられていないデバイス暗号化データ
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • この表で別のクラスを持っていると示されていない /data のその他すべてのサブディレクトリ
起動ごと 再起動後は維持する必要のないエフェメラル システム ファイル /data/per_boot
ユーザーの CE(内部) 内部ストレージに保存された、ユーザーごとの認証情報暗号化データ
  • /data/data/data/user/0 の別名)
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
ユーザーの DE(内部) 内部ストレージに保存された、ユーザーごとのデバイス暗号化データ
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
ユーザーの CE(Adoptable) Adoptable Storage に保存された、ユーザーごとの認証情報暗号化データ
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
ユーザーの DE(Adoptable) Adoptable Storage に保存された、ユーザーごとのデバイス暗号化データ
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

鍵の保管と保護

FBE 鍵はすべて vold で管理され、まったく保存されない起動ごとの鍵を除き、ディスクに保存されて暗号化されます。次の表に、さまざまな FBE 鍵の保存場所を示します。

鍵の種類 鍵の場所 鍵の場所のストレージ クラス
システムの DE 鍵 /data/unencrypted 暗号化なし
ユーザーの CE(内部)鍵 /data/misc/vold/user_keys/ce/${user_id} システムの DE
ユーザーの DE(内部)鍵 /data/misc/vold/user_keys/de/${user_id} システムの DE
ユーザーの CE(Adoptable)鍵 /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} ユーザーの CE(内部)
ユーザーの DE(Adoptable)鍵 /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} ユーザーの DE(内部)

上の表に示すように、ほとんどの FBE 鍵は、別の FBE 鍵で暗号化されたディレクトリに保存されます。鍵が含まれているストレージ クラスのロックが解除されるまで、鍵のロックを解除することはできません。

vold はすべての FBE 鍵に暗号化のレイヤを適用します。内部ストレージの CE 鍵に加え、どの鍵も、TEE 外に公開されない独自の Keystore 鍵を使用して AES-256-GCM で暗号化されます。このため、確認付きブートで適用される、信頼できるオペレーティング システムの起動が行われない限り、FBE 鍵のロックを解除することはできません。Keystore 鍵にはロールバック耐性も必要です。これにより、Keymaster がロールバック耐性をサポートしているデバイスで、FBE 鍵を安全に削除できます。ロールバック耐性を利用できない場合のベストエフォートの代替として、鍵とともに保存されている secdiscardable ファイルに保存された 16384 ランダムバイトの SHA-512 ハッシュが Keystore 鍵のアプリケーション ID タグとして使用されます。FBE 鍵を復元するには、これらのバイトをすべて復元する必要があります。

内部ストレージの CE 鍵の保護はより強力で、ユーザーのロック画面ナレッジ ファクタ(LSKF)(PIN、パターン、パスワード)、セキュアなパスコード リセット トークン、または Resume-on-Reboot オペレーション用のクライアントサイドとサーバーサイドの両方の鍵がないと、ロックを解除できません。パスコード リセット トークンの作成ができるのは、仕事用プロファイル管理対象デバイスの場合のみです。

このために vold は、ユーザーの合成パスワードから導出された AES-256-GCM 鍵を使用して内部ストレージの各 CE 鍵を暗号化します。合成パスワードは、ユーザーごとにランダムに生成される、不変の高エントロピー暗号シークレットです。system_serverLockSettingsService が合成パスワードとその保護方法を管理します。

LSKF で合成パスワードを保護するため、LockSettingsService は、時間約 25 ms、メモリ使用量約 2 MiB をターゲットに設定して、まず scrypt に渡すことで LSKF を伸ばします。通常、LSKF は短いため、このステップではセキュリティは強化されません。セキュリティのメインレイヤは、セキュア エレメント(SE)、つまり下記の TEE 適用レート制限です。

デバイスにセキュア エレメント(SE)がある場合、LockSettingsService は伸ばされた LSKF を、Weaver HAL を使用して SE に保存されている高エントロピー ランダム シークレットにマッピングします。その後、LockSettingsService は合成パスワードを 2 回暗号化します。1 回目には、伸ばされた LSKF から導出されたソフトウェア鍵と Weaver シークレットを使用し、2 回目には、認証にバインドされていない Keystore 鍵を使用します。これにより、LSKF 推測の SE 適用レート制限が提供されます。

デバイスに SE がない場合、LockSettingsService は代わりに伸ばされた LSKF をゲートキーパーのパスワードとして使用します。その後、LockSettingsService は合成パスワードを 2 回暗号化します。1 回目には、伸ばされた LSKF から導出されたソフトウェア鍵と secdiscardable ファイルのハッシュを使用し、2 回目には、ゲートキーパー登録の認証にバインドされた Keystore 鍵を使用します。これにより、LSKF 推測の TEE 適用レート制限が提供されます。

LSKF が変更されると、LockSettingsService は、古い LSKF と合成パスワードのバインディングに関連付けられたすべての情報を削除します。Weaver やロールバック耐性のある Keystore 鍵をサポートするデバイスでは、これにより、古いバインディングの安全な削除が保証されます。このため、ユーザーに LSKF がない場合でも、ここに記載されている保護が適用されます。