Android では、次のコンポーネントを必要とするユーザー認証依存型の暗号鍵の概念が使用されます。
- 暗号鍵ストレージとサービス プロバイダ。暗号鍵を格納し、それらの鍵に加えて標準の暗号ルーティンを提供します。Android は、高信頼実行環境(TEE)やセキュア エレメント(SE)を含む、鍵を保管するハードウェア格納型暗号などの暗号サービス用に、ハードウェア格納型キーストアと Keymaster(Strongbox など)をサポートしています。
- ユーザー認証システム。ユーザーの存在や認証の成功を証明します。Android は、PIN、パターン、パスワード認証用にゲートキーパー、指紋認証用に指紋に対応しています。Android 9 以降を搭載したデバイスでは、指紋認証と他の生体認証システムの単一統合ポイントとして、
BiometricPrompt
を使用できます。これらのコンポーネントは、認証済みのチャネルを通じてキーストア サービスと認証状態をやり取りします (フレームワーク レベルの Android Keystore システムも、キーストア サービスによってサポートされています)。
ゲートキーパー、指紋認証、生体認証コンポーネントはキーストアなどのコンポーネントと連携して、ハードウェア格納型認証トークン(AuthToken)の使用をサポートします。
登録
デバイスを出荷時設定にリセットした後の最初の起動時に、すべての認証システムでユーザーによる認証情報の登録準備が行われます。ユーザーは、最初にゲートキーパーに PIN、パターン、パスワードを登録する必要があります。この初期登録では、ユーザーの識別子として、またユーザーの暗号マテリアルのバインディング トークンとして機能する、ランダムに生成された 64 ビットのユーザー セキュア識別子(SID)が作成されます。このユーザー SID は暗号でユーザーのパスワードにバインドされます。ゲートキーパーに対する認証が成功すると、そのパスワードのユーザー SID を含む AuthToken が生成されます。
認証情報を変更する場合は、既存の認証情報を提示する必要があります。 既存の認証情報が正常に検証されると、既存の認証情報に関連付けられたユーザー SID が新しい認証情報に転送されるため、ユーザーは認証情報の変更後も鍵へのアクセスを保持できます。ユーザーが既存の認証情報を提示しない場合、新しい認証情報は完全にランダムなユーザー SID で登録されます。ユーザーはデバイスにアクセスできますが、古いユーザー SID で作成された鍵は完全に失われます。これは、信頼できない登録と呼ばれます。
通常、Android フレームワークは信頼できない登録を許可しないため、ほとんどのユーザーはこの操作性に触れることがありません。ただし、デバイスの管理者や攻撃者によって強制的にパスワードが再設定されると、この状況が発生する場合があります。
認証
ユーザーは認証情報を設定してユーザー SID を受け取ったら、PIN、パターン、パスワード、または指紋を提示して認証を開始できます。すべての TEE コンポーネントは、互いのメッセージの認証に使用する秘密鍵を共有します。
- ユーザーが認証方法を指定し、関連するサービスが関連デーモンにリクエストを送信します。
- PIN、パターン、パスワードの場合、
LockSettingsService
はリクエストをgatekeeperd
に送信します。 - 生体認証ベースの認証フローは、Android のバージョンによって異なります。
Android 8.x 以前を搭載したデバイスの場合、
FingerprintService
はリクエストをfingerprintd
に送信します。Android 9 以降を搭載したデバイスの場合、BiometricPrompt
は適切なBiometricManager
クラス(FingerprintManager
やFaceManager
など)を使用して、該当する生体認証デーモン(たとえば、指紋認証はfingerprintd
、顔認証はfaced
)にリクエストを送信します。バージョンに関係なく、生体認証はリクエストの送信後に非同期で行われます。
- PIN、パターン、パスワードの場合、
- デーモンが対応するコンポーネントにデータを送信すると、AuthToken が生成されます。
- PIN 認証、パターン認証、パスワード認証の場合、
gatekeeperd
は PIN、パターン、またはパスワード ハッシュを TEE のゲートキーパーに送信します。TEE での認証が成功した場合、TEE のゲートキーパーは、対応するユーザー SID を含む AuthToken を(AuthToken HMAC 鍵で署名して)Android OS の対応するコンポーネントに送信します。 - 指紋認証の場合、
fingerprintd
は指紋イベントをリッスンし、TEE の指紋認証コンポーネントにデータを送信します。TEE での認証が成功した場合、TEE の指紋認証コンポーネントは AuthToken HMAC 鍵で署名された AuthToken を Android OS の対応するコンポーネントに送信します。 - 他の生体認証の場合、該当する生体認証デーモンが生体認証イベントをリッスンし、適切な生体認証 TEE コンポーネントに送信します。
- PIN 認証、パターン認証、パスワード認証の場合、
- デーモンは署名された AuthToken を受け取り、キーストア サービスのバインダー インターフェースの拡張機能を介してキーストア サービスに渡します(
gatekeeperd
は、デバイスが再ロックされた場合とデバイスのパスワードが変更された場合もキーストア サービスに通知します)。 - キーストア サービスは AuthToken を Keymaster に渡し、ゲートキーパーおよびサポートされている生体認証 TEE コンポーネントと共有している鍵を使用して AuthToken を検証します。Keymaster は、最後の認証時刻としてトークンのタイムスタンプを信頼し、タイムスタンプに基づいて鍵を解放する(アプリによる鍵の使用を許可する)かどうか決定します。
AuthToken の形式
言語とコンポーネントの間でトークンの共有と互換性を実現するために、hw_auth_token.h
で AuthToken の形式を記述します。
形式は、固定サイズの項目を持つ単純なシリアル化プロトコルです。
項目 | 型 | 必須 | 説明 |
---|---|---|---|
AuthToken バージョン | 1 バイト | ○ | 以下のすべての項目のグループタグ。 |
チャレンジ | 64 ビット符号なし整数 | × | リプレイ攻撃を防ぐためのランダムな整数。通常は、リクエストされた暗号処理の ID です。トランザクション指紋認証で現在使用されています。この項目が存在する場合、AuthToken は同じチャレンジを含む暗号処理に対してのみ有効です。 |
ユーザー SID | 64 ビット符号なし整数 | ○ | デバイス認証に関連付けられたすべての鍵に暗号的に関連付けられる非反復ユーザー識別子。詳しくは、ゲートキーパーをご覧ください。 |
認証システム ID(ASID) | ネットワーク バイト オーダーの 64 ビット符号なし整数 | × | 特定の認証システム ポリシーにバインドするために使用される識別子。すべての認証システムに独自の ASID 値があり、独自の要件に従って変更できます。 |
認証システムの種類 | ネットワーク バイト オーダーの 32 ビット符号なし整数 | ○ |
|
タイムスタンプ | ネットワーク バイト オーダーの 64 ビット符号なし整数 | ○ | システムが最後に起動してからの時間(ミリ秒)。 |
AuthToken HMAC(SHA-256) | 256 ビット blob | ○ | HMAC 項目を除くすべての項目の鍵付き SHA-256 MAC。 |
デバイスの起動フロー
デバイスが起動するたびに AuthToken HMAC 鍵が生成され、すべての TEE コンポーネント(ゲートキーパー、Keymaster、サポートされる生体認証システムの Trustlet)で共有される必要があります。したがって、リプレイ攻撃に対する保護を強化するためには、デバイスが再起動するたびに HMAC 鍵をランダムに生成する必要があります。
この HMAC 鍵をすべてのコンポーネントで共有するためのプロトコルは、プラットフォーム依存の実装機能です。鍵は、TEE の外部で絶対に利用できないようにする必要があります。TEE OS に内部プロセス間通信(IPC)メカニズムがなく、信頼できない OS を介してデータを転送する必要がある場合は、安全な鍵交換プロトコルを使用して転送してください。
TEE の一例として、Android と並んで実行される Trusty オペレーティング システムがありますが、他の TEE を使用することもできます。Trusty では、Keymaster とゲートキーパーまたは該当する生体認証システム Trustlet の間の直接通信に内部 IPC システムが使用されます。HMAC 鍵は Keymaster にのみ保持されます。指紋認証システムとゲートキーパーは使用のたびに鍵を Keymaster にリクエストし、値を保持したりキャッシュしたりすることはありません。
一部の TEE には IPC インフラストラクチャがないため、TEE のアプレット間で通信は行われません。また、キーストア サービスはシステムの認証テーブルを把握しており、失敗することになるリクエストをすばやく拒否できるため、TEE でコストのかかる可能性がある IPC を省くこともできます。