GPU-Based Content Protection

In diesem Thema werden die Funktionen zum Schutz von Videoinhalten beschrieben, die ein Grafiktreiber bereitstellen kann.

Einführung

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

Ein Diagramm, das geschützte Videoinhalte zeigt.

Hinweis

Der Geschützte Medienpfad (Protected Media Path , PMP) ist in diesem Diagramm nicht dargestellt. Der hier gezeigte Datenfluss kann innerhalb eines PMP-Prozesses oder innerhalb eines Anwendungsprozesses auftreten.

Der Decoder empfängt verschlüsselte, komprimierte Videodaten von einer externen Quelle. Es wird davon ausgegangen, 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, aber der PMP definiert einen möglichen Mechanismus. Die GPU ist in dieser Phase nicht beteiligt.

Für die hardwarebeschleunigte Decodierung übergibt der Softwaredecoder komprimierte Videoinhalte an die GPU. Um diesen Inhalt zu schützen, verschlüsselt der Decoder die Daten erneut, in der Regel mit AES-CTR, bevor er sie an den Hardwarebeschleuniger übergibt. Zwischen dem Decoder und dem Grafiktreiber wird ein Schlüsselaustauschmechanismus definiert.

Decodierte Videoframes werden im Videospeicher gespeichert, in der Regel im Klarbild. An diesem Punkt werden die Frames verarbeitet und dann angezeigt. Es gibt zwei Standard Optionen 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 (Desktop Window Manage, DWM) mithilfe einer freigegebenen Oberfläche dargestellt werden.

Der letzte Schritt besteht darin, den Rahmen auf dem Monitor anzuzeigen, was möglicherweise einen Linkschutz zwischen der Grafik Karte und dem Anzeigegerät erfordert. Ein Beispiel für den Linkschutz ist High-Bandwidth Digital Content Protection (HDCP). Der Linkschutz wird mithilfe des Ausgabeschutz-Managers (OPM) konfiguriert. In diesem Thema wird opm nicht beschrieben. weitere Informationen finden Sie unter Verwenden des Ausgabeschutz-Managers.

Übersicht über den Decodierungsprozess

Während der hardwarebeschleunigten Decodierung muss der Softwaredecoder komprimierte Videodaten an die Grafik Karte übergeben. Bei Premium-Inhalten müssen diese Daten in der Regel mithilfe der Verschlüsselung mit symmetrischen Schlüsseln verschlüsselt werden, bevor sie an die GPU gesendet werden.

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

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

Ein Diagramm, das die Direct3d9-Decodierungsschnittstellen zeigt.

Alle diese Schnittstellen werden wie folgt vom Direct3D-Gerät 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 zu erhalten, rufen Sie QueryInterface auf einem D3D9Ex-Gerät auf.

Der authentifizierte Kanal stellt einen vertrauenswürdigen Kommunikationskanal zwischen dem Softwaredecoder und dem Treiber bereit. Der Kommunikationskanal funktioniert wie folgt:

  • Der Treiber stellt eine X.509-Zertifikatkette bereit, deren Stammzertifikat von Microsoft signiert ist.
  • Das Zertifikat enthält einen öffentlichen RSA-Schlüssel für den Treiber.
  • Der Softwaredecoder verwendet den öffentlichen Schlüssel, um dem Treiber einen 128-Bit-AES-Sitzungsschlüssel zu senden.
  • Der Softwaredecoder sendet Abfragen und Befehle an den authentifizierten Kanal.
  • Der Sitzungsschlüssel wird verwendet, um Nachrichtenauthentifizierungscodes (Message Authentication Codes, 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 Softwaredecoder verwendet sie, um die Integrität der Antwortdaten des Treibers zu überprüfen.

Verschlüsseln komprimierter Videopuffer für den Decoder

Hier ist eine allgemeine Übersicht über den Verschlüsselungs- und Decodierungsprozess:

  1. Der Softwaredecoder empfängt einen Datenstrom mit verschlüsselten Daten von der Videoquelle. Der Decoder entschlüsselt diesen Stream.

  2. Der Softwaredecoder handelt einen Sitzungsschlüssel mit der kryptografischen Sitzung aus.

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

  4. Der Softwaredecoder platziert komprimierte Daten in DXVA-Puffern, die vom DXVA-Decodergerät (Accelerator) abgerufen werden. Bei geschützten Inhalten verschlüsselt der Softwareencoder die Daten, die in die DXVA-Puffer eingefügt werden, und verwendet dabei den Sitzungsschlüssel für die Verschlüsselung.

    Hinweis

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

  5. Der Decoder übermittelt 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 den Inhaltsschlüssel, verschlüsselt mit dem Sitzungsschlüssel.

Direct3D bietet standardmäßige Unterstützung für 128-Bit-AES-CTR, ist jedoch für die Erweiterung auf zusätzliche Verschlüsselungstypen konzipiert.

Die nächsten fünf Abschnitte enthalten ausführlichere Schritte.

1. Abfragen der Inhaltsschutzfunktionen des Treibers

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

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

Achten Sie insbesondere auf die folgenden Funktionen:

  • Wenn das Caps-Element das D3DCPCAPS_SOFTWARE- oder D3DCPCAPS_HARDWARE-Flag enthält, kann der Treiber die Verschlüsselung durchführen.
  • Das KeyExchangeType-Element gibt an, wie der Schlüsselaustausch für den Sitzungsschlüssel durchgeführt wird.
  • Wenn das Caps-Element das flag D3DCPCAPS_CONTENTKEY 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-Member 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 auf den 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 zu erhalten. Die -Methode kopiert das Zertifikat in den Puffer, der im vorherigen Schritt zugeordnet wurde.

  4. Vergewissern Sie sich, dass das Zertifikat des Treibers von Microsoft signiert 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 aufrufen, wie im Abschnitt Senden authentifizierter Kanalbefehle beschrieben. 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 mit dem übereinstimmt, den Sie in der CreateAuthenticatedChannel-Methode angegeben haben.

3. Konfigurieren der kryptografischen Sitzung

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 ein 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 zu erhalten. Die -Methode kopiert das Zertifikat in den Puffer, der im vorherigen Schritt zugeordnet wurde.
  4. Vergewissern Sie sich, dass das Zertifikat des Treibers von Microsoft signiert 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 beim Decodierungsprozess verwendet.

4. Abrufen eines Handle für das DXVA-Decodergerät

Für den nächsten Schritt benötigen Sie ein Handle für das DXVA-Decodergerät. Um dieses Handle zu erhalten, füllen Sie wie folgt eine DXVA2_DecodeExecuteParams-Struktur 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 den pExtensionData-Member der DXVA2_DecodeExecuteParams-Struktur auf die Adresse einer DXVA2_DecodeExtensionData-Struktur fest.

Legen Sie in der DXVA2_DecodeExtensionData-Struktur den Member Function auf 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 . Das Handle für den DXVA-Decoder wird in pPrivateOutputData zurückgegeben.

5. Zuordnen des DXVA-Decoders zur kryptografischen Sitzung

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 für das DXVA-Decodergerät ab, wie im vorherigen Abschnitt beschrieben.
  2. Rufen Sie ein Handle an das Direct3D-Gerät ab, indem Sie eine D3DAUTHENTICATEDQUERY_DEVICEHANDLE Abfrage an den authentifizierten Kanal senden.
  3. Geben Sie eine D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION-Struktur mit den folgenden Informationen ein:
    • Legen Sie das DXVA2DecodeHandle-Element auf das Handle auf das DXVA-Decodergerät fest.
    • Legen Sie das CryptoSessionHandle-Element auf das Handle auf die kryptografische Sitzung fest. Dieses Handle wird von der IDirect3DDevice9Video::CreateCryptoSession-Methode zurückgegeben.
    • Legen Sie das DeviceHandle-Element auf das Direct3D-Gerätehandle 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 Handles:

Ein Diagramm, das zeigt, wie der dxva-Decoder der kryptografischen Sitzung zugeordnet ist.

Der Softwaredecoder kann jetzt 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 von Authentifizierten Kanalbefehlen

Es werden mehrere Befehle zum Konfigurieren des authentifizierten Kanals und zum Festlegen verschiedener Inhaltsschutzfunktionen definiert. Eine Liste der Befehle finden Sie unter Content Protection-Befehle.

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

  1. Geben Sie die Eingabedatenstruktur ein. 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 gezeigt.
Member BESCHREIBUNG
omac Überspringen Sie dieses Feld vorerst.
ConfigureType GUID, die den Befehl identifiziert. Eine Liste der Befehle finden Sie unter Content Protection-Befehle.
hChannel Das Handle für den authentifizierten Kanal.
SequenceNumber Die Sequenznummer. Die erste Sequenznummer wird durch Senden eines D3DAUTHENTICATEDCONFIGURE_INITIALIZE-Befehls angegeben. Erhöhen Sie diese Zahl jedes Mal, wenn Sie einen anderen Befehl senden, um 1. Die Sequenznummer schützt vor Wiedergabeangriffen. Hinweis: Es werden zwei separate Sequenznummern 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 dann diesen Tagwert 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 von authentifizierten Kanalabfragen

Es werden eine Reihe von Abfragen 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. Geben Sie die Eingabedatenstruktur ein. 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 gezeigt.
Member BESCHREIBUNG
QueryType GUID, die die Abfrage identifiziert. Eine Liste der Abfragen finden Sie unter Inhaltsschutzabfragen.
hChannel Das Handle für den authentifizierten Kanal.
SequenceNumber Die Sequenznummer. Die erste Sequenznummer wird durch Senden eines D3DAUTHENTICATEDCONFIGURE_INITIALIZE-Befehls angegeben. Erhöhen Sie diese Zahl jedes Mal, wenn Sie eine weitere Abfrage senden, um 1. Die Sequenznummer schützt vor Wiedergabeangriffen. Hinweis: Es werden zwei separate Sequenznummern verwendet, eine für Befehle und eine für Abfragen.
  1. Rufen Sie IDirect3DAuthenticatedChannel9::Query auf.
  2. Der Treiber platziert die Ausgabe der Abfrage in einer D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT-Struktur . Auf diese Struktur folgen 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