ブートの確認

確認付きブートでは、起動する Android バージョンの一部であるすべての実行可能なコードとデータを、使用前に暗号的に確認する必要があります。これには、カーネル(boot パーティションから読み込み)、デバイスツリー(dtbo パーティションから読み込み)、system パーティション、vendor パーティションなどがあります。

bootdtbo などの、1 回しか読み込まれない小さなパーティションの確認では、通常は内容全体をメモリに読み込んでハッシュを計算します。この計算されたハッシュ値は、「予想ハッシュ値」と比較されます。値が一致しない場合、Android は読み込まれません。 詳細については、起動フローをご覧ください。

メモリに収まらない大きなパーティション(ファイルシステムなど)ではハッシュツリーを使用する場合があります。この場合、確認処理は、データがメモリに読み込まれると発生する連続した処理となります。このような場合は、ハッシュツリーのルートハッシュは実行時に計算され、「予想ルートハッシュ値」と照合されます。 Android には dm-verity ドライバがあり、大きなパーティションを確認できます。計算されたルートハッシュが「予想ルートハッシュ値」と一致しない場合、データは使用されず、Android はエラー状態になります。詳細については、dm-verity の破損をご覧ください。

「予想ハッシュ」は通常、確認済みの各パーティションの末尾または先頭、または専用のパーティション、またはその両方に格納されます。重要なのは、これらのハッシュがルート オブ トラストにより(直接的または間接的に)署名されることです。例として、AVB 実装はどちらの方法もサポートしています。Android の確認付きブートをご覧ください。

ロールバック保護

アップデート プロセスが完全に安全であっても、永続的な Android カーネルを悪用して、古くて脆弱な Android バージョンを手動でインストールし、その Android バージョンで再起動して永続的な弱点を作ることができます。そこから、攻撃者はデバイスを恒久的に所有し、アップデートを無効にするなど、何でもできるようになります。

このような攻撃からの保護は「ロールバック保護」と呼ばれます。ロールバック保護では、通常、改ざん検出可能なストレージを使用して Android の最新バージョンを記録し、起動に使用する Android のバージョンが記録されているバージョンより低ければ起動を拒否します。通常、バージョンはパーティションごとに追跡されます。

AVB がロールバック保護を処理する方法の詳細については、AVB README を参照してください。

検証エラーの処理

検証は起動時(boot パーティションで計算されたハッシュが予想ハッシュと一致しない場合など)や実行時(system パーティションで dm-verity の検証エラーが発生した場合など)に失敗することがあります。起動時に検証が失敗すると、デバイスは起動できず、エンドユーザーはデバイスの復旧処理を行う必要があります。

検証が実行時に失敗した場合、フローはもう少し複雑になります。デバイスが dm-verity を使用している場合は、restart モードで設定する必要があります。restart モードでは、検証エラーが発生した場合、デバイスは直ちに再起動され、その理由を示す特定のフラグが設定されます。ブートローダーはこのフラグを認識し、dm-verity が入出力エラー(eio)モードを使用するよう切り替えます。新しいアップデートがインストールされるまでこのモードは維持されます。

eio モードで起動する場合、デバイスにはエラー画面が表示され、破損が検出されたことと、デバイスが正常に機能しない可能性があることをユーザーに通知します。この画面はユーザーが閉じるまで表示されます。eio モードでは、検証エラーが発生した場合 dm-verity ドライバはデバイスを再起動しません。代わりに EIO エラーが返され、アプリケーションはこのエラーを処理する必要があります。

これは、システム アップデートが実行される(新しい OS のインストール時に破損エラーが発生しない)ようにするため、あるいはユーザーがデバイスから可能な限り多くのデータを得られるようにするためです。新しい OS がインストールされると、ブートローダーは新しくインストールされた OS を認識し、restart モードに戻ります。