Android 7.0 は、デバイスのロックを解除していない状態でユーザーがデバイスの電源を入れた場合、セキュアなダイレクト ブート モードで動作します。この機能をサポートするため、システムは次の 2 つのデータ保存先を備えています。
- 認証情報暗号化ストレージ。これはデフォルトの保存先で、ユーザーがデバイスのロックを解除した後にだけ使用できます。
- デバイス暗号化ストレージ。この保存先は、ダイレクト ブート モード中とユーザーがデバイスのロックを解除した後の両方で使用できます。
デフォルトでは、ダイレクト ブート モード中はアプリは稼働しません。ダイレクト ブート モード中にアプリの稼働が必要となる場合は、このモード中でも実行を許可するアプリ コンポーネントを登録します。ダイレクト ブート モード中に実行する必要がある主なアプリは次のとおりです。
- アラーム クロック アプリなど、通知がスケジュールされているアプリ。
- SMS アプリなど、重要なユーザー通知を表示するアプリ。
- Talkback など、ユーザー補助機能サービスを提供するアプリ。
ダイレクト ブート モードで実行中にアプリがデータにアクセスする必要がある場合は、デバイス暗号化ストレージを使用します。デバイス暗号化ストレージにはキーで暗号化されたデータが保存され、このキーは、デバイスがセキュアブートに成功した後であれば利用可能になります。
ユーザー認証情報(PIN やパスワードなど)に関連付けられたキーによる暗号化が必要なデータには、認証情報暗号化ストレージを使用します。認証情報暗号化ストレージは、ユーザーがデバイスのロック解除に成功した後に限り利用可能になり、ユーザーがデバイスを再起動するまでアクセスできます。ユーザーがデバイスをロック解除した後にロック画面を有効にしても、認証情報暗号化ストレージはロックされません。
ダイレクト ブート中に実行するためのアクセスを要求する
ダイレクト ブート モード中にアプリを実行したり、デバイス暗号化ストレージにアクセスしたりするには、アプリ コンポーネントの登録が必要です。アプリをシステムに登録するには、コンポーネントを「暗号化対応」としてマーキングします。コンポーネントを暗号化対応としてマーキングするには、マニフェスト内で android:directBootAware
属性を true に設定します。
暗号化対応コンポーネントを登録しておくと、デバイスを再起動したときにシステムから ACTION_LOCKED_BOOT_COMPLETED
ブロードキャスト メッセージを受信できます。この時点でデバイス暗号化ストレージを利用できるようになり、ダイレクト ブート モード中に実行する必要があるタスク(スケジュール設定したアラームのトリガーなど)をコンポーネントが実行できるようになります。
アプリ マニフェスト内で BroadcastReceiver
を暗号化対応として登録し、ACTION_LOCKED_BOOT_COMPLETED
用のインテント フィルタを追加する方法の例を以下のコード スニペットに示します。
<receiver android:directBootAware="true" > ... <intent-filter> <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /> </intent-filter> </receiver>
ユーザーがデバイスのロックを解除すると、すべてのコンポーネントが、デバイス暗号化ストレージと認証情報暗号化ストレージの両方にアクセスできるようになります。
デバイス暗号化ストレージにアクセスする
デバイス暗号化ストレージにアクセスするには、Context.createDeviceProtectedStorageContext()
を呼び出すことで、2 つ目の Context
インスタンスを作成します。このコンテキストを使用して実行されたストレージ API 呼び出しはすべて、デバイス暗号化ストレージにアクセスします。次の例では、デバイス暗号化ストレージにアクセスして既存のアプリのデータファイルを開きます。
Kotlin
val directBootContext: Context = appContext.createDeviceProtectedStorageContext() // Access appDataFilename that lives in device encrypted storage val inStream: InputStream = directBootContext.openFileInput(appDataFilename) // Use inStream to read content...
Java
Context directBootContext = appContext.createDeviceProtectedStorageContext(); // Access appDataFilename that lives in device encrypted storage FileInputStream inStream = directBootContext.openFileInput(appDataFilename); // Use inStream to read content...
デバイス暗号化ストレージを使用するのは、ダイレクト ブート モード中にアクセスが必要な情報だけに限るようにしてください。デバイス暗号化ストレージを汎用的な暗号化保存場所として使用しないでください。ユーザーの個人情報や、ダイレクト ブート モード中に必要ではない暗号化データに対しては、認証情報暗号化ストレージを使用してください。
ユーザーによるデバイスのロック解除の通知を受信する
再起動後にユーザーがデバイスのロックを解除すると、アプリは、認証情報暗号化ストレージにアクセスするよう切り替えて、ユーザー認証情報が必要な通常のシステム サービスを使用するようになります。
再起動後、ユーザーがデバイスのロックを解除したときに通知を受信するには、実行中のコンポーネントを対象とする BroadcastReceiver
を登録して、ロック解除の通知メッセージをリッスンするようにします。デバイスの起動後、ユーザーがデバイスのロックを解除した場合の動作は次のとおりです。
- 即時通知を必要とするフォアグラウンド プロセスをアプリが使用している場合は、
ACTION_USER_UNLOCKED
メッセージをリッスンします。 - アプリが使用するプロセスが、遅延通知で対応できるバックグラウンド プロセスだけの場合は、
ACTION_BOOT_COMPLETED
メッセージをリッスンします。
ユーザーがデバイスのロックを解除しているかどうかを確認するには、UserManager.isUserUnlocked()
を呼び出します。
既存のデータを移行する
ユーザーがデバイスをアップデートしてダイレクト ブート モードを使用できるようにした場合、既存のデータをデバイス暗号化ストレージに移行することが必要になる場合があります。Context.moveSharedPreferencesFrom()
や Context.moveDatabaseFrom()
を使用すると、設定やデータベースのデータを、認証情報暗号化ストレージとデバイス暗号化ストレージとの間で移行できます。
どのデータを認証情報暗号化ストレージからデバイス暗号化ストレージに移行するかは、慎重に判断してください。パスワードや承認トークンなどのユーザーの個人情報は、デバイス暗号化ストレージに移行しないでください。場合によっては、この 2 つの暗号化された保存先に、データセットを振り分けて管理する必要があります。
暗号化対応アプリをテストする
ダイレクト ブート モードを有効にして、暗号化対応アプリをテストします。ダイレクト ブートを有効にする方法は 2 つあります。
注意: ダイレクト ブートを有効にすると、デバイス上のすべてのユーザーデータが消去されます。
Android 7.0 がインストールされたサポート対象デバイスでは、次のいずれかの方法を使用してダイレクト ブートを有効にします。
- デバイスで [開発者向けオプション] がまだ有効になっていない場合は、次の手順で有効にします。[設定] > [デバイス情報] を選択して [ビルド番号] を 7 回タップします。[開発者向けオプション] 画面が表示されたら、[設定] > [開発者向けオプション] で、[ファイル暗号化に変換する] を選択します。
- 次の adb shell コマンドを使用して、ダイレクト ブート モードを有効にします。
$ adb reboot-bootloader $ fastboot --wipe-and-use-fbe
テストデバイスでモードの切り替えが必要な場合、エミュレートされたダイレクト ブート モードも使用できます。ただし、データが失われる可能性があるため、エミュレーション モードは開発中にのみ使用してください。エミュレートされたダイレクト ブート モードを有効にするには、デバイスでロックパターンを設定します。ロックパターンの設定時に [安全な起動] 画面が表示された場合は、[スキップ] を選択します。次に、以下の adb shell コマンドを実行します。
$ adb shell sm set-emulate-fbe true
エミュレートされたダイレクト ブート モードを無効にするには、次のコマンドを使用します。
$ adb shell sm set-emulate-fbe false
このコマンドを実行すると、デバイスが再起動します。
デバイス ポリシーの暗号化ステータスをチェックする
デバイス管理アプリは、DevicePolicyManager.getStorageEncryptionStatus()
を使用すると、デバイスの現在の暗号化ステータスをチェックできます。アプリが API レベル 24.0(Android 7.0)以前をターゲットとしている場合、デバイスがフルディスク暗号化を使用しているか、ダイレクト ブート モード時にファイルベース暗号化を使用していれば、getStorageEncryptionStatus()
は ENCRYPTION_STATUS_ACTIVE
を返します。どちらの状況においても、データは常に暗号化されて安全に保存されます。アプリが API レベル 24.0 以降をターゲットとしている場合、デバイスがフルディスク暗号化を使用していれば、getStorageEncryptionStatus()
は ENCRYPTION_STATUS_ACTIVE
を返します。デバイスがダイレクト ブート モード時にファイルベース暗号化を使用しているのであれば、ENCRYPTION_STATUS_ACTIVE_PER_USER
が返されます。
Android 7.0 をターゲットとするデバイス管理アプリを作成する場合は、ENCRYPTION_STATUS_ACTIVE
と ENCRYPTION_STATUS_ACTIVE_PER_USER
の両方をチェックして、デバイスが暗号化されているか判定するようにしてください。
他のサンプルコード
このページで説明した API の使用方法の他の例については、DirectBoot サンプルをご覧ください。