次の方法で共有


D3D11 ビデオを使用したコンテンツ保護の GPU-Based

このトピックでは、グラフィックス ドライバーが提供できるビデオ コンテンツ保護機能について説明します。

はじめに

次の図は、保護されたビデオ コンテンツがパイプラインを通過してレンダリングされる方法の簡略化されたビューを示しています。

保護されたビデオ コンテンツを示す図。

注意

この図では、 保護されたメディア パス (PMP) は示されていません。 ここに示すデータ フローは、PMP プロセス内またはアプリケーション プロセス内で発生する可能性があります。

 

デコーダーは、暗号化された圧縮されたビデオ データを外部ソースから受信します。 また、デコーダーは、このデータを復号化するための暗号化キーも受け取ると想定されます。 このトピックでは、ビデオ ソースとデコーダーの間のキー交換については説明しませんが、PMP では 1 つの可能なメカニズムが定義されています。 この段階では GPU は関与しません。

ハードウェア アクセラレータによるデコードの場合、ソフトウェア デコーダーは圧縮されたビデオ コンテンツを GPU に渡します。 このコンテンツを保護するために、デコーダーはデータをハードウェア アクセラレータに渡す前に、通常は AES-CTR を使用して再暗号化します。 キー交換メカニズムは、デコーダーとグラフィックス ドライバーの間で定義されます。

デコードされたビデオ フレームは、一般にクリアにビデオ メモリに格納されます。 この時点で、フレームが処理され、表示されます。 プレゼンテーションには 2 つのメインオプションがあります。

  • D3D9 API を使用する場合は、ハードウェア オーバーレイを使用してフレームを表示できます。 ハードウェアは D3D11 では過度にサポートされていません。 詳細については、「 ハードウェア オーバーレイのサポート」を参照してください。
  • フレームは、共有サーフェスを使用してデスクトップ ウィンドウ管理 (DWM) によって表示できます。

最後の手順では、フレームをモニターに表示します。これは、グラフィックス カードとディスプレイ デバイス間のリンク保護が必要になる場合があります。 リンク保護の例として、High-Bandwidth Digital Content Protection (HDCP) があります。 リンク保護は、 Output Protection Manager (OPM) を使用して構成されます。 このトピックでは、OPM について説明しません。詳細については、「 Output Protection Manager の使用」を参照してください。

デコード プロセスの概要

ハードウェアアクセラレーションデコード中に、ソフトウェアデコーダーは圧縮されたビデオデータをグラフィックスカードに渡す必要があります。 Premium コンテンツの場合、このデータは通常、GPU に送信される前に対称キー暗号化を使用して暗号化する必要があります。

デコード用のビデオを暗号化するために、ソフトウェア デコーダーは次のインターフェイスを使用します。

  • ID3D11VideoDecoder。 デコーダー デバイス (アクセラレータとも呼ばれます) を表します。
  • ID3D11CryptoSession。 暗号化キーを提供する暗号化セッションを表します。
  • ID3D11AuthenticatedChannel。 認証されたチャネルを表します。これにより、ソフトウェア デコーダーは暗号化セッションをデコーダーに関連付けることができます。

direct3d9 デコード インターフェイスを示す図。

これらのインターフェイスはすべて、次のように Direct3D11 デバイスから取得されます。

インターフェイス 作成
ID3D11VideoDecoder ID3D11VideoDevice::CreateVideoDecoder を呼び出します。 デコーダーの種類は、プロファイル GUID によって識別されます。
ID3D11CryptoSession ID3D11VideoDevice::CreateCryptoSession を呼び出します。
ID3D11AuthenticatedChannel ID3D11VideoDevice::CreateAuthenticatedChannel を呼び出します。

 

Note

ID3D11VideoDevice インターフェイスへのポインターを取得するには、ID3D11Device インターフェイスで QueryInterface を呼び出します。

 

認証されたチャネルは、ソフトウェア デコーダーとドライバーの間の信頼された通信チャネルを提供します。 通信チャネルは次のように機能します。

  • ドライバーは、ルート証明書が Microsoft によって署名された X.509 証明書チェーンを提供します。
  • 証明書には、ドライバーの RSA 公開キーが含まれています。
  • ソフトウェア デコーダーは公開キーを使用して、ドライバーに 128 ビット AES セッション キーを送信します。
  • ソフトウェア デコーダーは、認証されたチャネルにクエリとコマンドを送信します。
  • セッション キーは、クエリとコマンドのメッセージ認証コード (MAC) を計算するために使用されます。 ドライバーは MAC を使用してクエリ/コマンド データの整合性を検証し、ソフトウェア デコーダーはそれらを使用してドライバーからの応答データの整合性を検証します。

デコーダーの圧縮されたビデオ バッファーの暗号化

暗号化とデコードプロセスの概要を次に示します。

  1. ソフトウェア デコーダーは、ビデオ ソースから暗号化されたデータのストリームを受信します。 デコーダーは、このストリームの暗号化を解除します。

  2. ソフトウェア デコーダーは、暗号化セッションとセッション キーをネゴシエートします。

  3. ソフトウェア デコーダーは、認証されたチャネルを使用して、暗号化セッションをデコーダー デバイスに関連付けます。

  4. ソフトウェア デコーダーは、デコーダー デバイス (アクセラレータ) から取得したバッファーに圧縮データを格納します。 保護されたコンテンツの場合、ソフトウェア エンコーダーは、暗号化にセッション キーを使用して、バッファーに格納されたデータを暗号化します。

    注意

    一部のドライバーは、暗号化のためにセッション キーではなくコンテンツ キーを使用します。 コンテンツ キーは、あるフレームから次のフレームに変更される可能性があります。

     

  5. デコーダーは、暗号化された圧縮バッファーをアクセラレータに送信します。 AES-CTR の場合、デコーダーは初期化ベクトルも渡します。 コンテンツ キーが使用されている場合、デコーダーはセッション キーを使用して暗号化されたコンテンツ キーを渡します。

Direct3D11 では、128 ビット AES-CTR の標準サポートがありますが、追加の暗号化の種類まで拡張するように設計されています。

次の 5 つのセクションでは、より詳細な手順について説明します。

1. ドライバーのコンテンツ保護機能のクエリを実行する

暗号化を適用する前に、ドライバーのコンテンツ保護機能を取得します。

  1. ID3D11Device インターフェイスへのポインターを取得します。
  2. ID3D11VideoDevice インターフェイスの QueryInterface を呼び出します。
  3. ID3D11VideoDevice::GetContentProtectionCaps を呼び出します。 このメソッドは、ドライバーのコンテンツ保護機能を D3D11_VIDEO_CONTENT_PROTECTION_CAPS 構造体に入力します。

特に、次の機能を探します。

  • Caps メンバーに D3D11_CONTENT_PROTECTION_CAPS_SOFTWARE または D3D11_CONTENT_PROTECTION_CAPS_HARDWARE フラグが含まれている場合、ドライバーは暗号化を実行できます。
  • Caps メンバーに D3D11_CONTENT_PROTECTION_CAPS_CONTENT_KEY フラグが含まれている場合、ドライバーは暗号化解除に別のコンテンツ キーを使用します。
  • ID3D11VideoDevice::CheckCryptoKeyExchange を呼び出して、ドライバーがセッション キーを生成するためにサポートするキー交換の種類を決定します。

その他の機能は Caps メンバーに示されています。

2. 認証済みチャネルを構成する

次の手順では、認証されたチャネルを構成します。

  1. ID3D11VideoDevice::CreateAuthenticatedChannel を呼び出して、認証されたチャネルを作成します。 ChannelType パラメーターには、ドライバーの機能に一致するチャネルの種類を指定します。

    • D3D11_AUTHENTICATED_CHANNEL_DRIVER_SOFTWARE チャネルの種類は、D3D11_CONTENT_PROTECTION_CAPS_SOFTWAREに対応します。
    • D3D11_AUTHENTICATED_CHANNEL_DRIVER_HARDWARE チャネルの種類は、D3D11_CONTENT_PROTECTION_CAPS_HARDWAREに対応します。

    CreateAuthenticatedChannel メソッドは、ID3D11AuthenticatedChannel インターフェイスへのポインターを返します。

  2. ID3D11AuthenticatedChannel::GetCertificateSize を呼び出して、ドライバーの X.509 証明書のサイズを取得します。 必要なサイズのバッファーを割り当てます。

  3. ID3D11AuthenticatedChannel::GetCertificate を呼び出して証明書を取得します。 メソッドは、前の手順で割り当てられたバッファーに証明書をコピーします。

  4. ドライバーの証明書が Microsoft によって署名され、取り消されていないことを確認します。

  5. 証明書から公開キーを取得します。

  6. ランダムな RSA セッション キーを生成します。 このセッション キーは、認証されたチャネルに送信されるデータに署名するために使用されます。 ドライバーの公開キーを使用してセッション キーを暗号化します。

  7. ID3D11VideoContext::NegotiateAuthenticatedChannelKeyExchange を呼び出して、暗号化されたセッション キーをドライバーに送信します。

  8. セキュリティで保護されたチャネルを次のように初期化します。

    1. ドキュメントの説明に従って 、D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE_INPUT 構造体を入力します。
    2. 「認証済 チャネル コマンドの送信」セクションの説明に従って 、ID3D11VideoContext::ConfigureAuthenticatedChannel を呼び出して、D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE_INPUT コマンドを送信します。 このコマンドには、認証されたチャネルに送信されるコマンドとクエリの開始シーケンス番号が含まれています。
  9. 「認証済みチャネル クエリの送信」セクションで説明されているように、認証されたチャネルに D3D11_AUTHENTICATED_QUERY_CHANNEL_TYPEクエリを送信して、チャネルの種類を確認します。 チャネルの種類が 、CreateAuthenticatedChannel メソッドで指定した内容と一致していることを確認します。

3. 暗号化セッションを構成する

次に、暗号化セッションを構成し、セッション キーを確立します。

  1. ID3D11VideoDevice::CreateCryptoSession を呼び出して暗号化セッションを作成します。 このメソッドは 、ID3D11CryptoSession インターフェイスへのポインターを返します。
  2. ID3D11CryptoSession::GetCertificateSize を呼び出して、ドライバーの X.509 証明書のサイズを取得します。 必要なサイズのバッファーを割り当てます。
  3. ID3D11CryptoSession::GetCertificate を呼び出して証明書を取得します。 メソッドは、前の手順で割り当てられたバッファーに証明書をコピーします。
  4. ドライバーの証明書が Microsoft によって署名され、取り消されていないことを確認します。
  5. 証明書から公開キーを取得します。
  6. ランダムな RSA セッション キーを生成します。 これは、認証されたチャネル セッション キーとは別のセッション キーです。 ドライバーの公開キーを使用してセッション キーを暗号化します。
  7. ID3D11VideoContext::NegotiateCryptoSessionKeyExchange を呼び出して、暗号化されたセッション キーをドライバーに送信します。
  8. コンテンツ保護機能に 3D11_CONTENT_PROTECTION_CAPS_CONTENT_KEYが含まれている場合は、ランダムな RSA コンテンツ キーを作成します。 これは、デコード プロセスの後半で使用されます。

4. デコーダーを暗号化セッションに関連付ける

次に、次のように、デコーダー デバイスを Direct3D11 デバイスと暗号化セッションに関連付けます。

  1. 認証されたチャネルに D3D11_AUTHENTICATED_QUERY_DEVICE_HANDLE クエリを送信して、Direct3D11 デバイスへのハンドルを取得します。
  2. 次の情報を D3D11_AUTHENTICATED_CONFIGURE_CRYPTO_SESSION_INPUT 構造体に入力します。
  3. ID3D11VideoContext::ConfigureAuthenticatedChannel を呼び出して、認証されたチャネルにD3D11_AUTHENTICATED_CONFIGURE_CRYPTO_SESSION コマンドを送信します。

次の図は、ハンドルの交換を示しています。

dxva デコーダーが暗号化セッションにどのように関連付けられているかを示す図。

ソフトウェア デコーダーは、暗号化セッション キーを使用して、圧縮されたビデオ バッファーを暗号化できるようになりました。 各圧縮バッファーには、D3D11_VIDEO_DECODER_BUFFER_DESC構造体の pIV メンバーで指定された独自の初期化ベクトル (IV) があります。

認証済みチャネル コマンドの送信

認証されたチャネルを構成し、さまざまなコンテンツ保護を設定するために、一連のコマンドが定義されています。 コマンドの一覧については、「 コンテンツ保護コマンド」を参照してください。

認証されたチャネルにコマンドを送信するには、次の手順を実行します。

  1. 入力データ構造を入力します。 このデータ構造は、常に D3D11_AUTHENTICATED_CONFIGURE_INPUT 構造の後に追加のフィールドが続きます。 次の表に示すように 、D3D11_AUTHENTICATED_CONFIGURE_INPUT 構造体を入力します。
メンバー 説明
omac ここでは、このフィールドをスキップします。
ConfigureType コマンドを識別する GUID。 コマンドの一覧については、「 コンテンツ保護コマンド」を参照してください。
hChannel 認証済みチャネルへのハンドル。
SequenceNumber シーケンス番号。 最初のシーケンス番号は、 D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE コマンドを送信することによって指定されます。 別のコマンドを送信するたびに、この数値を 1 ずつ増やします。 シーケンス番号は、リプレイ攻撃から保護されます。 メモ: 2 つの個別のシーケンス番号が使用されます。1 つはコマンド用、1 つはクエリ用です。
  1. 入力構造体の omac メンバーの後に表示されるデータ ブロックの OMAC タグを計算します。 次に、このタグ値を omac メンバーにコピーします。
  2. ID3D11VideoContext::ConfigureAuthenticatedChannel を呼び出します。
  3. ドライバーは、コマンドからの出力を D3D11_AUTHENTICATED_CONFIGURE_OUTPUT 構造体に配置します。
  4. 出力構造体の omac メンバーの後に表示されるデータ ブロックの OMAC タグを計算します。 これを omac メンバーの値と比較します。 一致しない場合は失敗します。
  5. 出力構造の ConfigureTypehChannelSequenceNumber メンバーの値と、それらのメンバーの値を比較します。 一致しない場合は失敗します。
  6. 次のコマンドのシーケンス番号をインクリメントします。

認証済みチャネル クエリの送信

認証されたチャネルに関する情報を取得するために、一連のクエリが定義されています。 クエリの一覧については、「 Content Protection クエリ」を参照してください。

認証されたチャネルにコマンドを送信するには、次の手順を実行します。

  1. 入力データ構造を入力します。 このデータ構造は常に D3D11_AUTHENTICATED_QUERY_INPUT 構造であり、その後に追加のフィールドが続く可能性があります。 次の表に示すように 、D3D11_AUTHENTICATED_QUERY_INPUT 構造体を入力します。
メンバー 説明
QueryType クエリを識別する GUID。 クエリの一覧については、「 Content Protection クエリ」を参照してください。
hChannel 認証済みチャネルへのハンドル。
SequenceNumber シーケンス番号。 最初のシーケンス番号は、 D3D11_AUTHENTICATED_CONFIGURE_INITIALIZE コマンドを送信することによって指定されます。 別のクエリを送信するたびに、この数値を 1 ずつ増やします。 シーケンス番号は、リプレイ攻撃から保護されます。 メモ: 2 つの個別のシーケンス番号が使用されます。1 つはコマンド用、1 つはクエリ用です。
  1. ID3D11VideoContext::QueryAuthenticatedChannel を呼び出します。
  2. ドライバーは、クエリからの出力を D3D11_AUTHENTICATED_QUERY_OUTPUT 構造に配置します。 この構造体の後には、クエリの種類に応じて追加のフィールドが続きます。
  3. 出力構造体の omac メンバーの後に表示されるデータ ブロックの OMAC タグを計算します。 これを omac メンバーの値と比較します。 一致しない場合は失敗します。
  4. 出力構造の ConfigureTypehChannelSequenceNumber メンバーの値と、それらのメンバーの値を比較します。 一致しない場合は失敗します。
  5. 次のクエリのシーケンス番号をインクリメントします。

Direct3D 11 ビデオ API