セキュリティで保護された MOR 実装

まとめ

  • MorLock、リビジョン2の動作

最終更新日

  • 2020 年 8 月

適用対象

  • Windows 10

  • Windows 10のCredential Guard機能をサポートするOEMおよびBIOSベンダー。

公式の仕様

概要

このトピックでは MemoryOverwriteRequestControlLock UEFI変数、リビジョン2の動作と使用状況について説明します。

高度なメモリ攻撃を防ぐために、既存のシステム BIOS セキュリティ緩和策 MemoryOverwriteRequestControl は、新たな脅威を防御するためのロックをサポートするように改良されている。 脅威モデルは、敵対者としてホストOSカーネルを含むように拡張されているため、カーネル特権レベルで実行されているACPIおよびUEFIランタイムサービスは信頼されていません。 セキュアブートの実装と同様に、ホストOSカーネル(たとえば、System Management Mode、TrustZone、BMCなど)によって改ざんできない特権ファームウェア実行コンテキストでMorLockを実装する必要があります。 インターフェイスは、 「変数サービス」 という名前のUEFI仕様バージョン2.5、セクション7.2で説明されているUEFI変数サービスに基づいて構築されています。

MorLockと呼ばれるこの軽減策は、すべての新しいシステムに実装する必要があり、トラステッドプラットフォームモジュールを搭載したシステムに限定されません。 リビジョン2では、特に大規模なメモリシステムでのブートパフォーマンスの問題を軽減するために、新しい機能 ロック解除、が追加されています。

Regarding the ACPI _DSM control method for setting the MOR bit state (as described in Section 6 of PC クライアント・ワークグループ・プラットフォーム・リセット攻撃緩和仕様書(バージョン 1.10 (PDF download)), 最近のBIOS実装では、この_DSMメソッドを削除することを推奨する。

ただし、BIOSがこの_DSMメソッドを実装している場合は、MorLockの状態を尊重する必要があります。 MorLockがロックされている場合、キーの有無にかかわらず、この_DSMメソッドは、MORの変更に失敗し、"一般的なエラー"に対応する1の値を返す必要があります。 MorLockリビジョン2のロックを解除するためのACPIメカニズムは定義されていません。

Windowsは、Windows 7以降、この_DSMメソッドを直接呼び出しておらず、非推奨と見なされていることに注意してください。 一部のBIOS indirectly のセクション2.3で説明されているように)、WindowsがクリーンシャットダウンのMOR自動検出の実装としてACPI _PTSを呼び出すときに、この_DSMメソッドを呼び出します PC クライアント・ワークグループ・プラットフォーム・リセット攻撃緩和仕様書バージョン1.10(PDFダウンロード)).

このACPI_PTSのMOR自動検出の実装はセキュリティが不足しているため、使用しないでください。

MemoryOverwriteRequestControlLock

改善された軽減策を含むBIOSは、初期ブート中にこのUEFI変数を作成します。

VendorGuid:{BB983CCF-151D-40E1-A07B-4A17BE168292}

名前:MemoryOverwriteRequestControlLock

属性: NV+BS+RT

GetVariable value in Data パラメータ:0x0(アンロック)、0x1(キーなしでロック)、0x2(キーでロック)

データ パラメータの SetVariable 値: 0x0 (ロック解除);0x1 (ロック)

SetVariableによるロック

ブートするたびに、BIOSは次のように初期化する MemoryOverwriteRequestControlLock を半角の0x00に変換する unlocked) DRIVER##, SYSPREP##, BOOT##, *RECOVERY*, ...)の前に、ブートデバイス選択(BDS)フェーズを実行します。 MemoryOverwriteRequestControlLock (および MemoryOverwriteRequestControl) の場合、BIOSは変数の削除を防止し、属性はNV+BS+RTに固定する必要があります。

いつ SetVariable にとって MemoryOverwriteRequestControlLock に有効なゼロ以外の値を渡して呼び出される データ, の両方のアクセス・モード MemoryOverwriteRequestControlLock そして MemoryOverwriteRequestControl が読み取り専用に変更され、ロックされていることを示す。

リビジョン1の実装では MemoryOverwriteRequestControlLockに対して0x00または0x01の1バイトのみを受け入れます。

リビジョン2はさらに、共有秘密キーを表す8バイトの値を受け入れます。 SetVariableでその他の値が指定されている場合、呼び出しは状態EFI_無効な_パラメーターで失敗します。 そのキーを生成するには、トラステッドプラットフォームモジュールやハードウェア乱数ジェネレーターなどの高品質のエントロピソースを使用します。

キーを設定した後、呼び出し元とファームウェアの両方が、IA32/X64または保護された記憶域を持つサービスプロセッサのSMRAMなど、機密保護された場所にこのキーのコピーを保存する必要があります。

システムの状態を取得します。

リビジョン2では MemoryOverwriteRequestControlLockMemoryOverwriteRequestControl 変数がロックされている場合 SetVariable (これらの変数) の呼び出しは、一定時間アルゴリズムを使用して、登録されているキーに対して最初にチェックされます。 両方のキーが存在し、一致する場合、変数はロック解除された状態に戻ります。 この最初の試行の後、またはキーが登録されていない場合、ブルートフォース攻撃を防ぐために、それ以降この変数を設定しようとすると、EFI_ACCESS_DENIEDで失敗する。 その場合、システムの再起動は、変数のロックを解除する唯一の方法である必要があります。

オペレーティングシステムは GetVariableを呼び出すことによって MemoryOverwriteRequestControlLock の存在とその状態を検出します。 システムは MemoryOverwriteRequestControlLock 値を0x1に設定することによって MemoryOverwriteRequestControl の現在の値をロックできます。 または、シークレットデータがメモリから安全に削除された後に、今後のロック解除を有効にするキーを指定することもできます。

呼び出し GetVariable for MemoryOverwriteRequestControlLock は0x0、0x1、または0x2を返し、アンロック、キーなしロック、キーありロックの状態を示す。

セッティング MemoryOverwriteRequestControlLock はフラッシュにコミットしない(内部ロックの状態を変更するだけ)。 変数を取得すると、内部状態が返され、キーは公開されません。

オペレーティングシステムによる使用例:

if (gSecretsInMemory)
{
    char data = 0x11;
    SetVariable(MemoryOverwriteRequestControl, sizeof(data), &data);
}

// check presence
status = GetVariable(MemoryOverwriteRequestControlLock, &value);  

if (SUCCESS(status))
{
    // first attempt to lock and establish a key
    // note both MOR and MorLock are locked if successful

    GetRNG(8, keyPtr);
    status = SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

    if (status != EFI_SUCCESS)
    {
        // fallback to revision 1 behavior
        char data = 0x01;
        status = SetVariable(MemoryOverwriteRequestControlLock, 1, &data);
        if (status != EFI_SUCCESS) { // log error, warn user }
    }
}
else
{
    // warn user about potentially unsafe system
}

// put secrets in memory

// … time passes …

// remove secrets from memory, flush caches

SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

MorLock実装フロー

これらのフローチャートは、実装の予期される動作を示しています。

初期化

morlock initialization.

SetVariableフロー

morlock programming flow.

SetVariableのロック解除された状態フロー

morlock unlocked flow.

SetVariableのロックされた状態フロー

morlock locked flow.

GetVariableのフロー

morlock getvariable.

関連項目

SoC プラットフォーム上のすべての Windows エディションに適用される UEFI 要件

PC Client Work Group Platform Reset Attack Mitigation Specification, Version 1.10 (PDFダウンロード)

コールド攻撃 (およびその他の脅威) からBitLockerを保護します

EDKIIでのUEFI TPM2サポートによるBIOSを超えたツアー

Credential Guard によるドメインの派生資格情報の保護

UEFI の仕様