FIPS 140-3 認証が可能な GKI 暗号化モジュール

GKI カーネルには、暗号ソフトウェア モジュールの FIPS 140-3 要件を遵守している fips140.ko という Linux カーネル モジュールが含まれています。このモジュールは、GKI カーネルを実行している製品で必要な場合、FIPS 認証のために送信できます。

暗号ルーティンを使用するには、特に次の FIPS 140-3 要件を満たす必要があります。

  • モジュールは、暗号アルゴリズムを使用可能にする前に、自身の整合性をチェックする必要があります。
  • モジュールは、承認された暗号アルゴリズムを使用可能にする前に、既知の回答のセルフテストを使用してこのアルゴリズムを実施、検証する必要があります。

個別のカーネル モジュールを使用する理由

FIPS 140-3 の検証は、ソフトウェアまたはハードウェア ベースのモジュールが認証された後は、そのモジュールが変更されることはないという考えに基づいています。変更された場合は、再度認証を受ける必要があります。これは、現在使用されているソフトウェア開発プロセスと容易には一致しません。この要件により、FIPS ソフトウェア モジュールは通常、暗号コンポーネントのみに可能な限り絞って設計され、暗号に関連のない変更は、暗号の再評価を必要としないようになっています。

GKI カーネルは、サポートされている期間全体にわたって定期的に更新されることが想定されています。これにより、カーネル全体が FIPS モジュールの境界内に収まることは不可能になります。このようなモジュールは、カーネルが更新されるたびに再認証される必要があるためです。「FIPS モジュール」をカーネル・イメージのサブセットとして定義すれば、この問題を軽減できますが、「FIPS モジュール」のバイナリ・コンテンツが必要以上に頻繁に変更されるため、解決にはなりません。

カーネル・バージョン 6.1 以前では、GKI は重要なセキュリティ機能である制御フローの整合性の前提条件となる LTO(リンク時最適化)を有効にしてコンパイルされていました。

したがって、FIPS 140-3 要件の対象となるすべてのコードは、ビルド元の GKI カーネルソースによって公開される安定したインターフェースのみに依存する、別のカーネル モジュール fips140.ko にパッケージ化されます。これにより、このモジュールは同じ世代の異なる GKI リリースで使用できることと、モジュール自体によって提供されるコードで問題が修正された場合にのみ、モジュールを更新して認証のために再送信する必要があることが保証されます。

モジュールを使用する場面

GKI カーネル自体には、FIPS 140-3 カーネル モジュールにもパッケージ化されている暗号ルーティンに依存するコードが含まれています。したがって、組み込みの暗号ルーティンは実際には GKI カーネルから移動されず、モジュールにコピーされます。モジュールが読み込まれると、組み込みの暗号ルーティンは Linux CryptoAPI から登録解除され、モジュールで提供される暗号ルーティンが優先されます。

つまり、fips140.ko モジュールは省略可能であり、FIPS 140-3 認証が要件である場合にのみデプロイする必要があります。このモジュールはそれ以上の機能は提供しません。モジュールを不必要に読み込むと、起動時間に影響を与えるだけでメリットはありません。

モジュールをデプロイする方法

このモジュールは、次の手順で Android ビルドに組み込むことができます。

  • モジュール名を BOARD_VENDOR_RAMDISK_KERNEL_MODULES に追加します。これにより、モジュールがベンダー RAM ディスクにコピーされます。
  • モジュール名を BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD に追加します。これにより、モジュール名がターゲットの modules.load に追加されます。modules.load は、デバイスの起動時に init によって読み込まれるモジュールのリストを保持します。

整合性のセルフチェック

FIPS 140-3 カーネル モジュールは、モジュール読み込み時に独自の .code セクションと .rodata セクションの HMAC-SHA256 ダイジェストを取得し、モジュールに記録されたダイジェストと比較します。これは、Linux モジュール ローダーが、ELF の再配置処理や、それらのセクションに対する CPU の誤りの代替パッチなどの通常の変更をすでに行った後に行われます。ダイジェストを正しく再現できるようにするため、次の追加手順が行われます。

  • ELF の再配置は、HMAC の入力と逆方向に適用できるようにモジュール内に保持されます。
  • 静的キー、トレースポイント、ベンダーフックなど、他のすべてのコードパッチはモジュールに対して無効になっています。

既知の回答のセルフテスト

FIPS 140-3 要件の対象となる実装されたアルゴリズムは、使用する前に既知の回答のセルフテストを行う必要があります。FIPS 140-3 実装ガイダンス 10.3.A によると、暗号化と復号の両方がテストされる場合に限り、サポートされている鍵長のいずれかを使用するアルゴリズムごとのテストベクターは暗号では 1 つで十分です。

Linux CryptoAPI にはアルゴリズムの優先順位の概念があり、同じアルゴリズムの複数の実装(特殊な暗号命令を使用する実装や、そのような命令を実装しない CPU のフォールバックなど)が共存する場合があります。したがって、同じアルゴリズムの実装をすべてテストする必要があります。その必要があるのは、Linux CryptoAPI が、優先度ベースの選択を回避して、代わりに優先度の低いアルゴリズムを選択できるようにするためです。

モジュールに含まれるアルゴリズム

FIPS 140-3 モジュールに含まれるすべてのアルゴリズムを以下に示します。これはandroid12-5.10android13-5.10android13-5.15android14-5.15android14-6.1 カーネル・ブランチに適用されますが、カーネル・バージョン間の違いが必要に応じて記載されています。

アルゴリズム 実装 承認可能 定義
aes aes-genericaes-arm64aes-ce、AES ライブラリ オペレーション モードのないプレーン AES ブロック暗号: すべての鍵サイズ(128 ビット、192 ビット、256 ビット)がサポートされています。ライブラリ実装以外のすべての実装は、テンプレートを介したオペレーション モードで作成できます。
cmac(aes) cmac(テンプレート)、cmac-aes-neoncmac-aes-ce AES-CMAC: すべての AES 鍵サイズがサポートされています。cmac テンプレートは、cmac(<aes-impl>) を使用して aes の任意の実装で作成できます。他の実装はスタンドアロンです。
ecb(aes) ecb(テンプレート)、ecb-aes-neonecb-aes-neonbsecb-aes-ce AES-ECB: すべての AES 鍵サイズがサポートされています。ecb テンプレートは、ecb(<aes-impl>) を使用して aes の任意の実装で作成できます。他の実装はスタンドアロンです。
cbc(aes) cbc(テンプレート)、cbc-aes-neoncbc-aes-neonbscbc-aes-ce AES-CBC: すべての AES 鍵サイズがサポートされています。cbc テンプレートは、ctr(<aes-impl>) を使用して aes の任意の実装で作成できます。他の実装はスタンドアロンです。
cts(cbc(aes)) cts(テンプレート)、cts-cbc-aes-neoncts-cbc-aes-ce ciphertext stealing を備えた AES-CBC-CTS または AES-CBC: 使用される慣例は CS3 です。最後の 2 つの暗号テキスト ブロックは無条件にスワップされます。すべての AES 鍵サイズがサポートされています。cts テンプレートは、cts(<cbc(aes)-impl>) を使用して cbc の任意の実装で作成できます。他の実装はスタンドアロンです。
ctr(aes) ctr(テンプレート)、ctr-aes-neonctr-aes-neonbsctr-aes-ce AES-CTR: すべての AES 鍵サイズがサポートされています。ctr テンプレートは、ctr(<aes-impl>) を使用して aes の任意の実装で作成できます。他の実装はスタンドアロンです。
xts(aes) xts(テンプレート)、xts-aes-neonxts-aes-neonbsxts-aes-ce AES-XTS: すべての AES 鍵サイズがサポートされています。xts テンプレートは、xts(<ecb(aes)-impl>) を使用して ecb(aes) の任意の実装で作成できます。他の実装はスタンドアロンです。すべての実装は、FIPS で必要とされる弱鍵チェックを実装します。つまり、前半と後半が等しい XTS 鍵は拒否されます。
gcm(aes) gcm(テンプレート)、gcm-aes-ce ×1 AES-GCM: すべての AES 鍵サイズがサポートされています。96 ビットの IV のみがサポートされます。このモジュールの他の AES モードと同様に、呼び出し元は IV を提供する必要があります。gcm テンプレートは、gcm_base(<ctr(aes)-impl>,<ghash-impl>) を使用して ctr(aes)ghash の任意の実装で作成できます。他の実装はスタンドアロンです。
sha1 sha1-genericsha1-ce SHA-1 暗号学的ハッシュ関数
sha224 sha224-genericsha224-arm64sha224-ce SHA-224 暗号学的ハッシュ関数: コードは SHA-256 と共有されます。
sha256 sha256-genericsha256-arm64sha256-ce、SHA-256 ライブラリ SHA-256 暗号学的ハッシュ関数: 従来の CryptoAPI インターフェースに加えて、ライブラリ インターフェースも SHA-256 に提供されます。このライブラリ インターフェースは別の実装を使用します。
sha384 sha384-genericsha384-arm64sha384-ce SHA-384 暗号学的ハッシュ関数: コードは SHA-512 と共有されます。
sha512 sha512-genericsha512-arm64sha512-ce SHA-512 暗号学的ハッシュ関数
hmac hmac(テンプレート) HMAC(キー付きのハッシュ メッセージ認証コード): hmac テンプレートは、hmac(<sha-alg>) または hmac(<sha-impl>) を使用して任意の SHA アルゴリズムまたは実装で作成できます。
stdrng drbg_pr_hmac_sha1drbg_pr_hmac_sha256drbg_pr_hmac_sha384drbg_pr_hmac_sha512 名前付きハッシュ関数と予測耐性を有効にしてインスタンス化された HMAC_DRBG: ヘルスチェックが含まれています。このインターフェースのユーザーは、独自の DRBG インスタンスを取得します。
stdrng drbg_nopr_hmac_sha1drbg_nopr_hmac_sha256drbg_nopr_hmac_sha384drbg_nopr_hmac_sha512 drbg_pr_* アルゴリズムと同じですが、予測耐性が無効になっています。コードは、予測耐性のあるバリアントと共有されます。カーネル バージョン 5.10 で優先度が最も高い DRBG は drbg_nopr_hmac_sha256 です。カーネル バージョン 5.15 以降では drbg_pr_hmac_sha512 です。
jitterentropy_rng jitterentropy_rng × Jitter RNG のバージョン 2.2.0: このインターフェースのユーザーは、独自の Jitter RNG インスタンスを取得します。DRBG が使用するインスタンスは再利用しません。
xcbc(aes) xcbc-aes-neonxcbc-aes-ce ×
xctr(aes) xctr-aes-neonxctr-aes-ce × カーネル バージョン 5.15 以降にのみ存在します。
cbcmac(aes) cbcmac-aes-neoncbcmac-aes-ce ×
essiv(cbc(aes),sha256) essiv-cbc-aes-sha256-neonessiv-cbc-aes-sha256-ce ×

ソースからモジュールをビルドする

Android 14 以降(android-mainline を含む)の場合は、以下のコマンドを使用してソースから fips140.ko モジュールをビルドします。

  • Bazel を使用したビルド:

    tools/bazel run //common:fips140_dist
    
  • build.sh を使用したビルド(レガシー):

    BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
    

これらのコマンドにより、カーネルと fips140.ko モジュールが含まれるフルビルドが行われ、その内容の HMAC-SHA256 ダイジェストが埋め込まれます。

エンドユーザー向けガイダンス

暗号管理者向けガイダンス

カーネル モジュールを操作するには、オペレーティング システムをシングル オペレーターのオペレーション モードに制限する必要があります。これは、プロセッサ内のメモリ管理ハードウェアを使用して Android によって自動的に処理されます。

カーネル モジュールを個別にインストールすることはできません。カーネル モジュールはデバイスのファームウェアの一部として含まれており、起動時に自動的に読み込まれます。承認済みのオペレーション モードでのみ動作します。

暗号管理者は、デバイスを再起動することで、いつでもセルフテストを実行できます。

ユーザー向けガイダンス

カーネル モジュールのユーザーは、暗号アルゴリズムを使用する必要がある他のカーネル コンポーネントです。カーネル モジュールは、アルゴリズムの使用において追加のロジックを提供せず、暗号オペレーションを実行するのに必要な時間を超えてパラメータを格納しません。

FIPS の遵守を目的としたアルゴリズムの使用は、承認されたアルゴリズムに限定されています。FIPS 140-3「サービス インジケーター」の要件を満たすために、モジュールにはアルゴリズムが承認されているかどうかを示す関数 fips140_is_approved_service が用意されています。

セルフテストのエラー

セルフテストが失敗した場合、カーネル モジュールによってカーネルがパニック状態になり、デバイスは起動を継続しません。デバイスを再起動しても問題が解決しない場合は、デバイスをリカバリモードで起動し、デバイスを再フラッシュして問題を解決する必要があります。


  1. モジュールの AES-GCM 実装は「アルゴリズム承認済み」にできますが、「モジュール承認済み」にはできないことが想定されています。それらを検証することはできますが、FIPS モジュールの観点から、AES-GCM を承認されたアルゴリズムと見なすことはできません。これは、GCM の FIPS モジュール要件が、独自の IV を生成しない GCM 実装と互換性がないためです。