Freigeben über


GPU-Based Inhaltsschutz

In diesem Thema werden videoinhaltsschutzfunktionen beschrieben, die von einem Grafiktreiber bereitgestellt werden können.

Einleitung

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

ein Diagramm, das geschützte Videoinhalte anzeigt.

Anmerkung

Der Geschützte Medienpfad (PMP) wird 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 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 Videoquelle und Decoder nicht beschrieben, aber der PMP definiert einen möglichen Mechanismus. Die GPU ist in dieser Phase nicht beteiligt.

Bei hardwarebeschleunigter 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 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 dieser Stelle werden die Frames verarbeitet und anschließend dargestellt. 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 vom Desktop Window Manage (DWM) mithilfe einer freigegebenen Oberfläche dargestellt werden.

Der letzte Schritt besteht darin, den Frame auf dem Monitor anzuzeigen, was möglicherweise einen Linkschutz zwischen der Grafikkarte und dem Anzeigegerät erfordert. Ein Beispiel für den Linkschutz ist High-Bandwidth Digital Content Protection (HDCP). Der Linkschutz wird mit Output Protection Manager (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 Grafikkarte übergeben. Bei Premiuminhalten müssen diese Daten in der Regel mit symmetrischer Schlüsselverschlüsselung verschlüsselt werden, bevor sie an die GPU gesendet wird.

Zum Verschlüsseln des Videos zum Decodieren verwendet der Softwaredecoder die folgenden Schnittstellen:

  • IDirectXVideoDecoder. Stellt das DXVA-Decodergerät dar, das auch als Zugriffstaste bezeichnet wird.
  • IDirect3DCryptoSession9. Stellt eine kryptografische Sitzung dar, die den Verschlüsselungsschlüssel bereitstellt.
  • IDirect3DAuthenticatedChannel9. Stellt einen authentifizierten Kanal dar, mit dem der Softwaredecoder die kryptografische Sitzung dem DXVA-Decoder zuordnen kann.

ein Diagramm, das die Direct3d9-Decodierungsschnittstellen zeigt.

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

Schnittstelle Kreation
IDirectXVideoDecoder- Rufen Sie IDirectXVideoDecoderService::CreateVideoDecoderauf. Das DXVA-Decodergerät wird durch eine DXVA-Profil-GUID identifiziert.
IDirect3DCryptoSession9 Rufen Sie IDirect3DDevice9Video::CreateCryptoSessionauf.
IDirect3DAuthenticatedChannel9 Rufen Sie IDirect3DDevice9Video::CreateAuthenticatedChannelauf.

Anmerkung

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 zum Berechnen von Nachrichtenauthentifizierungscodes (MACs) für die Abfragen und Befehle verwendet. 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 verschlüsselter Daten aus der Videoquelle. Der Decoder entschlüsselt diesen Datenstrom.

  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 fügt komprimierte Daten in DXVA-Puffer ein, die es vom DXVA-Decodergerät (Accelerator) abruft. Bei geschützten Inhalten verschlüsselt der Software-Encoder die Daten, die in die DXVA-Puffer eingefügt werden, mithilfe des Sitzungsschlüssels für die Verschlüsselung.

    Anmerkung

    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 sendet die verschlüsselten komprimierten Puffer an die Zugriffstaste. Für AES-CTR übergibt der Decoder auch den Initialisierungsvektor. Wenn ein Inhaltsschlüssel verwendet wird, übergibt der Decoder 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 ausgelegt.

Die nächsten fünf Abschnitte enthalten 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. Rufen Sie QueryInterface- für die IDirect3DDevice9Video--Schnittstelle auf.
  3. Rufen Sie IDirect3DDevice9Video::GetContentProtectionCapsauf. Diese Methode füllt eine D3DCONTENTPROTECTIONCAPS Struktur mit den Inhaltsschutzfunktionen des Treibers aus.

Suchen Sie insbesondere nach den folgenden Funktionen:

  • Wenn das Caps--Mitglied das D3DCPCAPS_SOFTWARE- oder D3DCPCAPS_HARDWARE-Flag enthält, kann der Treiber Verschlüsselung ausführen.
  • Der KeyExchangeType Member gibt an, wie der Schlüsselaustausch für den Sitzungsschlüssel ausgeführt werden soll.
  • Wenn das Caps Member 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 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 parameter ChannelType 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 zugeordnet wurde.

  4. Stellen Sie sicher, dass das Zertifikat des Treibers 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 D3DAUTHENTICATEDCONFIGURE_INITIALIZE Befehl, indem Sie IDirect3DAuthenticatedChannel9::Configure aufrufen, wie im Abschnitt Senden von authentifizierten Kanalbefehlenbeschrieben. 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 von authentifizierten Kanalabfragenbeschrieben. Überprüfen Sie, ob der Kanaltyp mit dem in der CreateAuthenticatedChannel--Methode angegebenen Wert übereinstimmt.

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 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 zugeordnet wurde.
  4. Stellen Sie sicher, dass das Zertifikat des Treibers 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_CONTENTKEYenthalten, erstellen Sie einen zufälligen RSA-Inhaltsschlüssel. Dies wird später im Decodierungsprozess verwendet.

4. Abrufen eines Handle zum 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 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 element Function auf DXVA2_DECODE_GET_DRIVER_HANDLEfest. 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 hDecodeDeviceHandle Variable.)

Rufen Sie dann IDirectXVideoDecoder::Execute auf und übergeben Sie die Adresse der DXVA2_DecodeExecuteParams-Struktur. Das Handle an 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 zum 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 den DXVA2DecodeHandle- Member auf das Handle auf das DXVA-Decodergerät fest.
    • Legen Sie das CryptoSessionHandle Mitglied auf das Handle für die kryptografische Sitzung fest. Dieses Handle wird von der IDirect3DDevice9Video::CreateCryptoSession-Methode zurückgegeben.
    • Legen Sie den DeviceHandle- Member 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 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 Member der DXVA2_DecodeBufferDesc Struktur angegeben ist.

Senden von Authentifizierten Kanalbefehlen

Eine Reihe von Befehlen werden zum Konfigurieren des authentifizierten Kanals und zum Festlegen verschiedener Inhaltsschutzfunktionen 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.
Mitglied Beschreibung
omac Dieses Feld vorerst überspringen.
ConfigureType- GUID, die den Befehl identifiziert. Eine Liste der Befehle finden Sie unter Inhaltsschutzbefehle.
hChannel- Das Handle für den 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 Replay-Angriffen. 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 dann diesen Tagwert in das omac Member.
  2. Rufen Sie IDirect3DAuthenticatedChannel9::Configureauf.
  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 Member der Ausgabestruktur angezeigt wird. Vergleichen Sie dies mit dem Wert des omac Members. Schlägt fehl, wenn sie nicht übereinstimmen.
  5. Vergleichen Sie die Werte der ConfigureType, hChannelund SequenceNumber Member in der Ausgabestruktur mit Ihren Werten für diese Member. Schlägt fehl, wenn sie nicht übereinstimmen.
  6. Erhöhen Sie die Sequenznummer für den nächsten Befehl.

Senden von authentifizierten Kanalabfragen

Eine Reihe von Abfragen werden 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.
Mitglied 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. Jedes Mal, wenn Sie eine andere Abfrage senden, erhöhen Sie diese Zahl um 1. Die Sequenznummer schützt vor Replay-Angriffen. Hinweis: Zwei separate Sequenznummern werden verwendet, eine für Befehle und eine für Abfragen.
  1. Rufen Sie IDirect3DAuthenticatedChannel9::Queryauf.
  2. Der Treiber platziert die Ausgabe aus 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 Member der Ausgabestruktur angezeigt wird. Vergleichen Sie dies mit dem Wert des omac Members. Schlägt fehl, wenn sie nicht übereinstimmen.
  4. Vergleichen Sie die Werte der ConfigureType, hChannelund SequenceNumber Member in der Ausgabestruktur mit Ihren Werten für diese Member. Schlägt fehl, wenn sie nicht übereinstimmen.
  5. Erhöhen Sie die Sequenznummer für die nächste Abfrage.

Direct3D 9-Video-APIs