GPU-Based Inhaltsschutz

In diesem Thema werden videoinhaltsschutzfunktionen beschrieben, die ein Grafiktreiber bereitstellen kann.

Einführung

Das folgende Diagramm zeigt eine vereinfachte Ansicht, wie geschützte Videoinhalte durch die Pipeline gerendert werden.

a diagram that shows protected video content.

Hinweis

Der geschützte Medienpfad (PMP) wird in diesem Diagramm nicht dargestellt. Der hier gezeigte Datenfluss kann in einem PMP-Prozess oder in einem Anwendungsprozess auftreten.

Der Decoder empfängt verschlüsselte, komprimierte Videodaten aus einer externen Quelle. Es wird auch angenommen, dass der Decoder auch einen kryptografischen Schlüssel erhält, um diese Daten zu entschlüsseln. In diesem Thema wird der Schlüsselaustausch zwischen der Videoquelle und dem Decoder nicht beschrieben, der PMP definiert jedoch einen möglichen Mechanismus. Die GPU ist in dieser Phase nicht beteiligt.

Für die hardwarebeschleunigte Decodierung übergibt der Software-Decoder komprimierte Videoinhalte an die GPU. Um diesen Inhalt zu schützen, verschlüsselt der Decoder die Daten in der Regel mithilfe von AES-CTR, bevor er an den Hardwarebeschleuniger übergeben wird. Ein Schlüsselaustauschmechanismus wird zwischen dem Decoder und dem Grafiktreiber definiert.

Decodierte Videoframes werden im Videospeicher gespeichert, im Allgemeinen im Klaren. An diesem Punkt werden die Frames verarbeitet und dann angezeigt. Es gibt zwei Hauptoptionen für die Präsentation.

  • Frames können mithilfe einer Hardwareüberlagerung dargestellt werden. Weitere Informationen finden Sie unter Hardwareüberlagerungsunterstützung.
  • Frames können von der Desktopfensterverwaltung (DWM) mithilfe einer freigegebenen Oberfläche dargestellt werden.

Der letzte Schritt besteht darin, den Frame auf dem Monitor anzuzeigen, der möglicherweise den Schutz zwischen der Grafikkarte und dem Anzeigegerät erfordert. Ein Beispiel für den Linkschutz ist High-Bandwidth Digital Content Protection (HDCP). Der Linkschutz wird mithilfe des Output Protection Manager (OPM) konfiguriert. Dieses Thema beschreibt OPM nicht; weitere Informationen finden Sie unter Verwenden des Ausgabeschutz-Managers.

Übersicht über den Decodierungsprozess

Während der hardwarebeschleunigten Decodierung muss der Software-Decoder videokomprimierte Videodaten an die Grafikkarte übergeben. Für Premiuminhalte muss diese Daten in der Regel mit symmetrischer Schlüsselverschlüsselung verschlüsselt werden, bevor sie an die GPU gesendet wird.

Um das Video für die Decodierung zu verschlüsseln, verwendet der Software-Decoder die folgenden Schnittstellen:

  • IDirectXVideoDecoder. Stellt das DXVA-Decodergerät dar, auch als Tastenkombination bezeichnet.
  • IDirect3DCryptoSession9. Stellt eine kryptografische Sitzung dar, die den Verschlüsselungsschlüssel bereitstellt.
  • IDirect3DAuthenticatedChannel9. Stellt einen authentifizierten Kanal dar, der es dem Software-Decoder ermöglicht, die kryptografische Sitzung dem DXVA-Decoder zuzuordnen.

a diagram that shows the direct3d9 decoding interfaces.

Alle diese Schnittstellen werden vom Direct3D-Gerät wie folgt abgerufen:

Schnittstelle Erstellung
IDirectXVideoDecoder Rufen Sie IDirectXVideoDecoderService::CreateVideoDecoder auf. Das DXVA-Decodergerät wird durch eine DXVA-Profil-GUID identifiziert.
IDirect3DCryptoSession9 Rufen Sie IDirect3DDevice9Video::CreateCryptoSession auf.
IDirect3DAuthenticatedChannel9 Rufen Sie IDirect3DDevice9Video::CreateAuthenticatedChannel auf.

Hinweis

Um einen Zeiger auf die IDirect3DDevice9Video-Schnittstelle abzurufen, rufen Sie QueryInterface auf einem D3D9Ex-Gerät auf.

Der authentifizierte Kanal bietet einen vertrauenswürdigen Kommunikationskanal zwischen dem Software-Decoder und dem Treiber. Der Kommunikationskanal funktioniert wie folgt:

  • Der Treiber stellt eine X.509-Zertifikatkette bereit, deren Stammzertifikat von Microsoft signiert wird.
  • Das Zertifikat enthält einen RSA-öffentlichen Schlüssel für den Treiber.
  • Der Software-Decoder verwendet den öffentlichen Schlüssel, um den Treiber an einen AES-Sitzungsschlüssel von 128 Bit zu senden.
  • Der Software-Decoder sendet Abfragen und Befehle an den authentifizierten Kanal.
  • Der Sitzungsschlüssel wird verwendet, um Nachrichtenauthentifizierungscodes (MACs) für die Abfragen und Befehle zu berechnen. Der Treiber verwendet die MACs, um die Integrität der Abfrage-/Befehlsdaten zu überprüfen, und der Software-Decoder verwendet sie, um die Integrität der Antwortdaten des Treibers zu überprüfen.

Verschlüsseln komprimierter Videopuffer für den Decoder

Hier sehen Sie einen Überblick über den Verschlüsselungs- und Decodierungsprozess auf hoher Ebene:

  1. Der Software-Decoder empfängt einen Datenstrom verschlüsselter Daten aus der Videoquelle. Der Decoder entschlüsselt diesen Datenstrom.

  2. Der Software-Decoder verhandelt einen Sitzungsschlüssel mit der kryptografischen Sitzung.

  3. Der Software-Decoder verwendet den authentifizierten Kanal, um die kryptografische Sitzung mit dem DXVA-Decodergerät zuzuordnen.

  4. Der Software-Decoder fügt komprimierte Daten in DXVA-Puffern ein, die er vom DXVA-Decodergerät (Accelerator) abruft. Für geschützte Inhalte verschlüsselt der Software-Encoder die Daten, die in die DXVA-Puffer eingefügt werden, mithilfe des Sitzungsschlüssels für die Verschlüsselung.

    Hinweis

    Einige Treiber verwenden einen Inhaltsschlüssel anstelle des Sitzungsschlüssels für die Verschlüsselung. Der Inhaltsschlüssel könnte sich von einem Frame zum nächsten ändern.

  5. Der Decoder sendet die verschlüsselten komprimierten Puffer an den Accelerator. Für AES-CTR übergibt der Decoder auch den Initialisierungsvektor. Wenn ein Inhaltsschlüssel verwendet wird, übergibt der Decoder inhaltsschlüssel, verschlüsselt mithilfe des Sitzungsschlüssels.

Direct3D hat standardmäßige Unterstützung für 128-Bit AES-CTR, ist jedoch so konzipiert, dass sie auf zusätzliche Verschlüsselungstypen erweitert wird.

Die nächsten fünf Abschnitte geben detailliertere Schritte.

1. Abfragen der Inhaltsschutzfunktionen des Treibers

Bevor Sie versuchen, Verschlüsselung anzuwenden, rufen Sie die Inhaltsschutzfunktionen des Treibers ab.

  1. Rufen Sie einen Zeiger auf das Direct3D 9-Gerät ab.
  2. Call QueryInterface für die IDirect3DDevice9Video-Schnittstelle .
  3. Rufen Sie IDirect3DDevice9Video::GetContentProtectionCaps auf. Diese Methode füllt eine D3DCONTENTPROTECTIONCAPS-Struktur mit den Inhaltsschutzfunktionen des Treibers aus.

Suchen Sie insbesondere nach den folgenden Funktionen:

  • Wenn das Caps-Element das D3DCPCAPS_SOFTWARE - oder D3DCPCAPS_HARDWARE-Flag enthält, kann der Treiber Verschlüsselung ausführen.
  • Das KeyExchangeType-Element gibt an, wie Der Schlüsselaustausch für den Sitzungsschlüssel ausgeführt wird.
  • Wenn das Caps-Element das D3DCPCAPS_CONTENTKEY-Flag enthält, verwendet der Treiber einen separaten Inhaltsschlüssel für die Verschlüsselung. Dies ist wichtig, wenn Sie den Sitzungsschlüssel generieren.

Zusätzliche Funktionen werden im Caps-Element angegeben.

2. Konfigurieren des authentifizierten Kanals

Der nächste Schritt besteht darin, den authentifizierten Kanal zu konfigurieren.

  1. Rufen Sie IDirect3DDevice9Video::CreateAuthenticatedChannel auf, um den authentifizierten Kanal zu erstellen. Geben Sie für den ChannelType-Parameter einen Kanaltyp an, der den Funktionen des Treibers entspricht.

    • Der D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE Kanaltyp entspricht D3DCPCAPS_SOFTWARE.
    • Der D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE Kanaltyp entspricht D3DCPCAPS_HARDWARE.

    Die CreateAuthenticatedChannel-Methode gibt einen Zeiger auf die IDirect3DAuthenticatedChannel9-Schnittstelle zusammen mit einem Handle zum Kanal zurück. Das Handle wird später verwendet, um die kryptografische Sitzung dem authentifizierten Kanal zuzuordnen.

  2. Rufen Sie IDirect3DAuthenticatedChannel9::GetCertificateSize auf, um die Größe des X.509-Zertifikats des Treibers abzurufen. Weisen Sie einen Puffer der erforderlichen Größe zu.

  3. Rufen Sie IDirect3DAuthenticatedChannel9::GetCertificate auf, um das Zertifikat abzurufen. Die Methode kopiert das Zertifikat in den Puffer, der im vorherigen Schritt zugewiesen wurde.

  4. Stellen Sie sicher, dass das Treiberzertifikat von Microsoft signiert wurde und nicht widerrufen wurde.

  5. Rufen Sie den öffentlichen Schlüssel aus dem Zertifikat ab.

  6. Generieren Sie einen zufälligen RSA-Sitzungsschlüssel. Dieser Sitzungsschlüssel wird verwendet, um Daten zu signieren, die an den authentifizierten Kanal gesendet werden. Verschlüsseln Sie den Sitzungsschlüssel mithilfe des öffentlichen Schlüssels des Treibers.

  7. Rufen Sie IDirect3DAuthenticatedChannel9::NegotiateKeyExchange auf, um den verschlüsselten Sitzungsschlüssel an den Treiber zu senden.

  8. Initialisieren Sie den sicheren Kanal wie folgt:

    1. Füllen Sie eine D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE Struktur aus, wie in der Dokumentation beschrieben.
    2. Senden Sie den befehl D3DAUTHENTICATEDCONFIGURE_INITIALIZE , indem Sie IDirect3DAuthenticatedChannel9::Configure wie im Abschnitt Senden authentifizierter Kanalbefehle beschrieben aufrufen. Dieser Befehl enthält die Startsequenznummern für die Befehle und Abfragen, die an den authentifizierten Kanal gesendet werden.
  9. Überprüfen Sie den Kanaltyp, indem Sie eine D3DAUTHENTICATEDQUERY_CHANNELTYPE Abfrage an den authentifizierten Kanal senden, wie im Abschnitt Senden authentifizierter Kanalabfragen beschrieben. Überprüfen Sie, ob der Kanaltyp dem entspricht, was Sie in der CreateAuthenticatedChannel-Methode angegeben haben.

3. Konfigurieren der Kryptografiesitzung

Konfigurieren Sie als Nächstes die kryptografische Sitzung, und richten Sie den Sitzungsschlüssel ein.

  1. Rufen Sie IDirect3DDevice9Video::CreateCryptoSession auf, um die kryptografische Sitzung zu erstellen. Diese Methode gibt einen Zeiger auf die IDirect3DCryptoSession9-Schnittstelle und zusammen mit einem Handle auf die kryptografische Sitzung zurück.
  2. Rufen Sie IDirect3DCryptoSession9::GetCertificateSize auf, um die Größe des X.509-Zertifikats des Treibers abzurufen. Weisen Sie einen Puffer der erforderlichen Größe zu.
  3. Rufen Sie IDirect3DCryptoSession9::GetCertificate auf, um das Zertifikat abzurufen. Die Methode kopiert das Zertifikat in den Puffer, der im vorherigen Schritt zugewiesen wurde.
  4. Stellen Sie sicher, dass das Treiberzertifikat von Microsoft signiert wurde und nicht widerrufen wurde.
  5. Rufen Sie den öffentlichen Schlüssel aus dem Zertifikat ab.
  6. Generieren Sie einen zufälligen RSA-Sitzungsschlüssel. Dies ist ein separater Sitzungsschlüssel vom authentifizierten Kanalsitzungsschlüssel. Verschlüsseln Sie den Sitzungsschlüssel mithilfe des öffentlichen Schlüssels des Treibers.
  7. Rufen Sie IDirect3DCryptoSession9::NegotiateKeyExchange auf, um den verschlüsselten Sitzungsschlüssel an den Treiber zu senden.
  8. Wenn die Inhaltsschutzfunktionen D3DCPCAPS_CONTENTKEY enthalten, erstellen Sie einen zufälligen RSA-Inhaltsschlüssel. Dies wird später im Decodierungsprozess verwendet.

4. Abrufen eines Handles zum DXVA-Decodergerät

Für den nächsten Schritt benötigen Sie ein Handle für das DXVA-Decodergerät. Um diesen Handle zu erhalten, füllen Sie eine DXVA2_DecodeExecuteParams Struktur wie folgt aus:

HANDLE hDecodeDeviceHandle;

DXVA2_DecodeExecuteParams execParams = {0};
DXVA2_DecodeExtensionData ExtensionExecute = {0};
    
execParams.NumCompBuffers = 0;
execParams.pCompressedBuffers = NULL;
execParams.pExtensionData = &ExtensionExecute;

ExtensionExecute.Function = DXVA2_DECODE_GET_DRIVER_HANDLE;
ExtensionExecute.pPrivateInputData = NULL;
ExtensionExecute.PrivateInputDataSize = 0;
ExtensionExecute.pPrivateOutputData = &hDecodeDeviceHandle;
ExtensionExecute.PrivateOutputDataSize = sizeof(HANDLE);

Legen Sie das pExtensionData-Element der DXVA2_DecodeExecuteParams Struktur auf die Adresse einer DXVA2_DecodeExtensionData Struktur fest.

Legen Sie in der DXVA2_DecodeExtensionData Struktur das Funktionselementauf DXVA2_DECODE_GET_DRIVER_HANDLE fest. Legen Sie pPrivateOutputData auf die Adresse eines Puffers fest, der groß genug ist, um einen HANDLE-Wert zu speichern. (Im vorherigen Beispiel ist dieser Puffer die Variable "hDecodeDeviceHandle ".)

Rufen Sie dann IDirectXVideoDecoder::Execute auf und übergeben Sie die Adresse der DXVA2_DecodeExecuteParams Struktur. Der Handle an den DXVA-Decoder wird in pPrivateOutputData zurückgegeben.

5. Zuordnen des DXVA-Decoders zur Kryptografiesitzung

Ordnen Sie als Nächstes das DXVA-Decodergerät dem Direct3D-Gerät und der kryptografischen Sitzung wie folgt zu:

  1. Rufen Sie ein Handle auf das DXVA-Decodergerät ab, wie im vorherigen Abschnitt beschrieben.
  2. Rufen Sie ein Handle auf das Direct3D-Gerät ab, indem Sie eine D3DAUTHENTICATEDQUERY_DEVICEHANDLE Abfrage an den authentifizierten Kanal senden.
  3. Füllen Sie eine D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION Struktur mit den folgenden Informationen aus:
    • Legen Sie das DXVA2DecodeHandle-Element auf das Handle auf das DXVA-Decodergerät fest.
    • Legen Sie das CryptoSessionHandle-Mitglied auf das Handle auf die kryptografische Sitzung fest. Dieser Handle wird von der IDirect3DDevice9Video::CreateCryptoSession-Methode zurückgegeben.
    • Legen Sie das DeviceHandle-Element auf den Direct3D-Gerätepunkt fest.
  4. Rufen Sie IDirect3DAuthenticatedChannel9::Configure auf, um einen D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION Befehl an den authentifizierten Kanal zu senden.

Das folgende Diagramm veranschaulicht den Austausch von Handlen:

a diagram that shows how the dxva decoder is associated with the cryptographic session.

Der Software-Decoder kann nun den kryptografischen Sitzungsschlüssel verwenden, um die komprimierten Videopuffer zu verschlüsseln. Jeder komprimierte Puffer verfügt über einen eigenen Initialisierungsvektor (IV), der im pvPVPState-Element der DXVA2_DecodeBufferDesc-Struktur angegeben ist.

Senden authentifizierter Kanalbefehle

Eine Reihe von Befehlen wird zum Konfigurieren des authentifizierten Kanals und zum Festlegen verschiedener Inhaltsschutz definiert. Eine Liste der Befehle finden Sie unter Inhaltsschutzbefehle.

Führen Sie die folgenden Schritte aus, um einen Befehl an den authentifizierten Kanal zu senden.

  1. Füllen Sie die Eingabedatenstruktur aus. Diese Datenstruktur ist immer eine D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT Struktur gefolgt von zusätzlichen Feldern. Füllen Sie die D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT Struktur aus, wie in der folgenden Tabelle dargestellt.
Member BESCHREIBUNG
omac Überspringen Sie dieses Feld jetzt.
ConfigureType GUID, die den Befehl identifiziert. Eine Liste der Befehle finden Sie unter Inhaltsschutzbefehle.
hChannel Das Handle zum authentifizierten Kanal.
SequenceNumber Die Sequenznummer. Die erste Sequenznummer wird durch Senden eines D3DAUTHENTICATEDCONFIGURE_INITIALIZE Befehls angegeben. Jedes Mal, wenn Sie einen anderen Befehl senden, erhöhen Sie diese Zahl um 1. Die Sequenznummer schützt vor Wiederholungsangriffen.
[! Hinweis]
Zwei separate Sequenznummern werden verwendet, eine für Befehle und eine für Abfragen.


  1. Berechnen Sie das OMAC-Tag für den Datenblock, der nach dem Omac-Element der Eingabestruktur angezeigt wird. Kopieren Sie diesen Tagwert dann in das omac-Element .
  2. Rufen Sie IDirect3DAuthenticatedChannel9::Configure auf.
  3. Der Treiber platziert die Ausgabe des Befehls in der D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT Struktur.
  4. Berechnen Sie das OMAC-Tag für den Datenblock, der nach dem Omac-Element der Ausgabestruktur angezeigt wird. Vergleichen Sie dies mit dem Wert des omac-Elements . Fehler, wenn sie nicht übereinstimmen.
  5. Vergleichen Sie die Werte der Member ConfigureType, hChannel und SequenceNumber in der Ausgabestruktur mit Ihren Werten für diese Member. Fehler, wenn sie nicht übereinstimmen.
  6. Erhöhen Sie die Sequenznummer für den nächsten Befehl.

Senden authentifizierter Kanalabfragen

Eine Reihe von Abfragen wird zum Abrufen von Informationen über den authentifizierten Kanal definiert. Eine Liste der Abfragen finden Sie unter Inhaltsschutzabfragen.

Führen Sie die folgenden Schritte aus, um einen Befehl an den authentifizierten Kanal zu senden.

  1. Füllen Sie die Eingabedatenstruktur aus. Diese Datenstruktur ist immer eine D3DAUTHENTICATEDCHANNEL_QUERY_INPUT Struktur, möglicherweise gefolgt von zusätzlichen Feldern. Füllen Sie die D3DAUTHENTICATEDCHANNEL_QUERY_INPUT Struktur aus, wie in der folgenden Tabelle dargestellt.
Member BESCHREIBUNG
QueryType GUID, die die Abfrage identifiziert. Eine Liste der Abfragen finden Sie unter Inhaltsschutzabfragen.
hChannel Das Handle zum authentifizierten Kanal.
SequenceNumber Die Sequenznummer. Die erste Sequenznummer wird durch Senden eines D3DAUTHENTICATEDCONFIGURE_INITIALIZE Befehls angegeben. Jedes Mal, wenn Sie eine andere Abfrage senden, erhöhen Sie diese Zahl um 1. Die Sequenznummer schützt vor Wiederholungsangriffen.
[! Hinweis]
Zwei separate Sequenznummern werden verwendet, eine für Befehle und eine für Abfragen.


  1. Rufen Sie IDirect3DAuthenticatedChannel9::Query auf.
  2. Der Treiber platziert die Ausgabe aus der Abfrage in einer D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT Struktur. Diese Struktur folgt je nach Abfragetyp zusätzliche Felder.
  3. Berechnen Sie das OMAC-Tag für den Datenblock, der nach dem Omac-Element der Ausgabestruktur angezeigt wird. Vergleichen Sie dies mit dem Wert des omac-Elements . Fehler, wenn sie nicht übereinstimmen.
  4. Vergleichen Sie die Werte der Member ConfigureType, hChannel und SequenceNumber in der Ausgabestruktur mit Ihren Werten für diese Member. Fehler, wenn sie nicht übereinstimmen.
  5. Erhöhen Sie die Sequenznummer für die nächste Abfrage.

Direct3D 9 Video-APIs