Verwenden des Ausgabeschutz-Managers

In diesem Thema wird beschrieben, wie Sie den Ausgabeschutz-Manager (Output Protection Manager, OPM) verwenden, um Videoinhalte zu schützen, während sie über eine physische Verbindung auf ein Anzeigegerät übertragen werden. Dieses Thema enthält folgende Abschnitte:

Premium-Videoinhalte werden in der Regel verschlüsselt, um sie vor nicht autorisierter Duplizierung zu schützen. Natürlich muss das Video entschlüsselt werden, bevor es angezeigt wird. Die entschlüsselten, nicht komprimierten Frames müssen dann über eine physische Verbindung auf das Anzeigegerät übertragen werden. Contentanbieter erfordern möglicherweise, dass die Videoframes an diesem Punkt geschützt werden, da sie über die physische Verbindung laufen.

Zu diesem Zweck gibt es verschiedene Schutzmechanismen, darunter High-Bandwidth Digital Content Protection (HDCP) und DisplayPort Content Protection (DPCP) für digitale Ausgänge, und das Kopiergenerierungsverwaltungssystem Analog (CGMS-A) für analoge Ausgänge. Im Allgemeinen beinhalten diese Mechanismen, das Signal zu verschlüsseln oder zu scrambeln, bevor es in die Anzeige wechselt.

OPM ermöglicht es einer Anwendung, Inhaltsschutzmechanismen für die Videoausgabe zu erzwingen. Mithilfe von OPM sendet die Anwendung Befehle und Statusanforderungen über einen vertrauenswürdigen, sicheren Kanal an den Grafiktreiber. OPM ermöglicht einer Anwendung Folgendes:

  • Stellen Sie sicher, dass der Grafiktreiber von Microsoft signiert wurde.
  • Richten Sie einen vertrauenswürdigen Kommunikationskanal mit dem Treiber ein.
  • Erzwingen Sie Inhaltsschutzmechanismen für die physische Ausgabe.

OPM ersetzt das Certified Output Protection Protocol (COPP) und verwendet eine ähnliche API. Aus Gründen der Abwärtskompatibilität kann die OPM-Schnittstelle die COPP-Schnittstelle nachbilden. Die Unterschiede zwischen OPM und COPP umfassen Folgendes:

  • OPM verwendet X.509-Zertifikate, während COPP ein proprietäres Zertifikatformat verwendet.
  • OPM unterstützt HDCP-Repeater.
  • Anwendungen, die OPM verwenden, müssen keine HDCP-Systemerneuerungsmeldungen (SRMs) analysieren.
  • OPM kann verwendet werden, wenn die Grafikanzeige den Klonmodus verwendet. COPP unterstützt keinen Klonmodus.

Wenn Ihre Anwendung den geschützten Medienpfad (PMP) zum Wiedergeben von Videoinhalten verwendet, müssen Sie die OPM-API nicht verwenden, da der PMP alle erforderlichen OPM-Aufrufe durchführt. Die OPM-API ist für Anwendungen verfügbar, die den PMP nicht verwenden.

OPM ist in Windows Vista und höher verfügbar, die API wurde jedoch erst nach Windows 7 öffentlich gemacht. Um OPM in einer Anwendung zu verwenden, müssen Sie über die Header und Bibliotheksdateien aus dem Windows 7 SDK verfügen. Sie müssen keine DLLs erneut verteilen, um OPM in Windows Vista oder Windows Server 2008 zu verwenden.

Videoausgabe

Ein Grafikadapter kann über mehrere physische Ausgaben verfügen, die jeweils über eigene Funktionen verfügen. Bevor eine Anwendung geschützte Inhalte wiedergibt, muss sie die entsprechenden Schutzmechanismen für jede Videoausgabe festlegen, die der Grafikkarte zugeordnet ist, die das Video anzeigt. Welche Schutzmechanismen angewendet werden sollen, hängt von den Nutzungsregeln für den Inhalt ab.

Jede Videoausgabe wird durch eine Instanz der IOPMVideoOutput-Schnittstelle dargestellt. Sie können ein Direct3D-Gerät oder Monitor-Handles verwenden, um die Videoausgabe abzurufen.

Verwenden eines Direct3D-Geräts:

  1. Rufen Sie den IDirect3DDevice9-Zeiger für das Direct3D-Gerät ab, mit dem Ihre Anwendung Oberflächen zum Speichern der Videoframes erstellt.
  2. Rufen Sie die OPMGetVideoOutputsFromIDirect3DDevice9Object-Funktion auf. Diese Funktion weist ein Array von IOPMVideoOutput-Zeigern zu, einen für jede Ausgabe.

Verwenden von Monitor-Handles:

  1. Rufen Sie EnumDisplayMonitors auf, um die HMONITOR-Handles abzurufen, die dem Videofenster entsprechen. Mehrere Monitore können demselben Fenster zugeordnet werden, sodass Sie möglicherweise mehrere HMONITOR-Handles erhalten.
  2. Rufen Sie für jeden Monitor-Handle OPMGetVideoOutputsFromHMONITORauf. Diese Funktion weist ein Array von IOPMVideoOutput-Zeigern zu, einen für jede Ausgabe.

Initialisieren einer OPM-Sitzung

Bevor die Anwendung OPM-Befehle oder Statusanforderungen sendet, muss sie überprüfen, ob die Videoausgabe vertrauenswürdig ist und einen Sitzungsschlüssel einrichtet. Der Sitzungsschlüssel wird verwendet, um die Daten zu signieren, die zwischen der Anwendung und dem Grafiktreiber ausgetauscht werden.

Die OPM-API definiert einen Handshake, der vertrauen und den Sitzungsschlüssel festlegt. Sie müssen diesen Handshake für jede Instanz der IOPMVideoOutput-Schnittstelle wie folgt ausführen:

  1. Rufen Sie IOPMVideoOutput::StartInitialization auf. Diese Methode ruft zwei Datenelemente ab:

    • Eine Zufallszahl, die vom Treiber generiert wird. Sie verwenden diese Zahl, um den Handshake abzuschließen.
    • Die X.509-Zertifikatkette des Treibers.
  2. Stellen Sie sicher, dass die Zertifikatkette von Microsoft signiert wurde.

    Hinweis

    Die Zertifikatsperrung liegt außerhalb des Gültigkeitsbereichs von OPM.

     

  3. Rufen Sie den öffentlichen Schlüssel des Treibers aus der Zertifikatkette ab.

  4. Generieren Sie einen 128-Bit-AES-Sitzungsschlüssel.

  5. Generieren Sie zwei zufällige 32-Bit-Zahlen:

    • Die Startsequenznummer für OPM-Statusanforderungen.
    • Die Startsequenznummer für OPM-Befehle.

    Diese Zahlen müssen mithilfe eines kryptografisch sicheren Pseudo-Zufallszahlengenerators wie CryptGenRandom generiert werden.

  6. Kopieren Sie die Zufallszahl des Treibers (abgerufen in Schritt 1), den Sitzungsschlüssel und die beiden Sequenznummern in eine OPM_ENCRYPTED_INITIALIZATION_PARAMETERS-Struktur, wie in IOPMVideoOutput::FinishInitialization beschrieben.

  7. Verschlüsseln Sie die OPM_ENCRYPTED_INITIALIZATION_PARAMETERS-Struktur mit RSAES-OAEP mithilfe des öffentlichen Schlüssels des Treibers, der im Zertifikat des Treibers zu finden ist.

  8. Rufen Sie IOPMVideoOutput::FinishInitialization auf.

Senden von OPM-Statusanforderungen

OPM-Statusanforderungen geben Informationen zur Videoausgabe zurück, z. B. den Typ der physischen Verbindung und die aktuelle Schutzstufe. Eine Liste der Anforderungstypen finden Sie unter OPM-Statusanforderungen.

Führen Sie die folgenden Schritte aus, um eine Statusanforderung zu senden.

  1. Initialisieren Sie eine OPM_GET_INFO_PARAMETERS-Struktur, wie in der folgenden Tabelle dargestellt.

    Member Beschreibung
    omac Dieses Feld vorerst überspringen.
    rnRandomNumber Eine kryptografisch sichere 128-Bit-Zufallszahl. Wenn Sie eine Statusanfrage stellen, generieren Sie immer eine neue Zufallszahl, auch wenn Sie dieselbe Anforderung vornehmen. Speichern Sie die Nummer in einer Variablen, da Sie später darauf verweisen müssen.
    guidInformation Eine GUID, welche die Statusanforderung identifiziert. Eine Liste der Statusanforderungen finden Sie unter OPM-Statusanforderungen.
    ulSequenceNumber Die Sequenznummer. Verwenden Sie für die erste Statusanforderung die Startsequenznummer, die Sie in der IOPMVideoOutput::FinishInitialization-Methode angegeben haben (Schritt 5 der Initialisierung einer OPM-Sitzung.) Jedes Mal, wenn Sie eine weitere Statusanforderung stellen, wird diese Zahl um 1 erhöht.
    abParameters Ein Bytearray, das zusätzliche Eingabedaten für die Anforderung enthält. Das Format der Eingabedaten wird im Referenzthema für jede Statusanforderung aufgeführt.
    cbParametersSize Die Größe der gültigen Daten im abParameters-Array. Der Inhalt des restlichen Arrays ist nicht definiert.

     

  2. Berechnen Sie den CBC MAC (OMAC-1), um einen Hash für den Datenblock zu berechnen, der nach dem Omac-Element angezeigt wird, und legen Sie dann das omac-Element auf diesen Wert fest. Siehe OPM-Beispielcode.

  3. Rufen Sie die IOPMVideoOutput::GetInformation-Methode auf. Übergeben Sie einen Zeiger an die OPM_GET_INFO_PARAMETERS-Struktur und einen Zeiger an eine OPM_REQUESTED_INFORMATION-Struktur. Die Antwort des Treibers wird in die OPM_REQUESTED_INFORMATION-Struktur geschrieben.

    • Das omac-Element dieser Struktur enthält einen OMAC, der für die Daten berechnet wird, die diesem Element folgen.
    • Das abRequestedInformation-Element ist ein Bytearray, das Ausgabedaten für die Antwort enthält. Das Format der Ausgabedaten wird im Referenzthema für jede Statusanforderung aufgeführt.
  4. Berechnen Sie einen OMAC für die OPM_REQUESTED_INFORMATION Struktur, nicht einschließlich des omac-Elements. Stellen Sie sicher, dass der OMAC mit dem Wert im omac-Element übereinstimmt.

  5. Stellen Sie sicher, dass das cbRequestedInformationSize-Element der OPM_REQUESTED_INFORMATION-Struktur die richtige Größe für die Ausgabedaten angibt. Die Ausgabedaten für die OPM_GET_CONNECTOR_TYPE-Abfrage sind z. B. eine OPM_STANDARD_INFORMATION-Struktur, sodass der Wert von cbRequestedInformationSizesizeof(OPM_STANDARD_INFORMATION) sein sollte.

  6. Wandeln Sie das abRequestedInformation-Element der OPM_REQUESTED_INFORMATION-Struktur in die richtige Ausgabedatenstruktur um. Wenn die Statusanforderung z. B. OPM_GET_CONNECTOR_TYPE ist, wandeln Sie abRequestedInformation in eine OPM_STANDARD_INFORMATION Struktur um.

  7. Stellen Sie sicher, dass das rnRandomNumber-Element der Ausgabedatenstruktur dem Wert von rnRandomNumber aus Schritt 1 entspricht.

  8. Überprüfen Sie das ulStatusFlags-Element der Ausgabedatenstruktur, wie in der Behandlung einer deaktivierten Videoausgabe beschrieben.

Wenn eine der Prüfungen in den Schritten 5 bis 8 fehlschlägt, muss die Anwendung die Anzeige geschützter Inhalte beenden.

Senden von OPM-Befehlen

OPM-Befehle werden verwendet, um die Schutzebene und andere Einstellungen für die Videoausgabe festzulegen. Das Senden eines OPM-Befehls ähnelt dem Senden einer Statusanforderung, außer es gibt keine Antwortdaten vom Treiber. Eine Liste der Befehle finden Sie unter OPM-Befehle.

Führen Sie die folgenden Schritte aus, um einen OPM-Befehl zu senden.

  1. Füllen Sie eine OPM_CONFIGURE_PARAMETERS-Struktur aus, wie in der folgenden Tabelle dargestellt.

    Member Beschreibung
    omac Dieses Feld vorerst überspringen.
    guidSetting Eine GUID, die den Befehl identifiziert. Eine Liste der Befehle finden Sie unter OPM-Befehle.
    ulSequenceNumber Die Sequenznummer. Verwenden Sie für den ersten Befehl die Startsequenznummer, die Sie in der IOPMVideoOutput::FinishInitialization-Methode angegeben haben (Schritt 5 von Initialisierung einer OPM-Sitzung.) Jedes Mal, wenn Sie einen weiteren Befehl senden, erhöhen Sie diese Zahl um 1.
    abParameters Ein Bytearray, das zusätzliche Eingabedaten für den Befehl enthält. Das Format der Eingabedaten wird im Referenzthema für jeden Befehl aufgeführt.
    cbSettingDataSize Die Größe der gültigen Daten im abParameters-Array. Der Inhalt des restlichen Arrays ist nicht definiert.

     

  2. Berechnen Sie einen OMAC für den Datenblock, der nach dem omac-Element angezeigt wird, und legen Sie dann das omac-Element auf diesen Wert fest.

  3. Rufen Sie IOPMVideoOutput::Configure auf.

Für die meisten Befehle gibt es eine entsprechende Statusanforderung, die den Status des Befehls zurückgibt. Beispielsweise legt der OPM_SET_PROTECTION_LEVEL-Befehl die Schutzebene fest und der OPM_GET_VIRTUAL_PROTECTION_LEVEL-Befehl ruft die aktuelle Schutzebene ab.

Behandeln einer deaktivierten Videoausgabe

Eine Videoausgabe kann sich jederzeit deaktivieren, um die unbefugte Verwendung von Videoinhalten zu verhindern. Dies könnte auftreten, wenn ein Schutzmechanismus nicht mehr funktioniert, da der Treiber Manipulationen erkennt oder weil die Anzeige von der physischen Verbindung getrennt wurde. Während eine Videoausgabe deaktiviert ist, werden keine Videoframes angezeigt.

Während der Inhaltsschutz aktiviert ist, sollte eine Anwendung in regelmäßigen Abständen (mindestens einmal alle 2 Sekunden) die folgenden Schritte ausführen.

  1. Rufen Sie IOPMVideoOutput::GetInformation auf, um entweder die Statusanforderung OPM_GET_ACTUAL_PROTECTION_LEVEL oder OPM_GET_VIRTUAL_PROTECTION_LEVEL zu senden. Die Rückgabedaten für beide Befehle sind eine OPM_STANDARD_INFORMATION-Struktur.
  2. Überprüfen Sie das ulInformation-Element der OPM_STANDARD_INFORMATION-Struktur. Dieses Element enthält ein Flag, das angibt, ob der Inhaltsschutz noch aktiviert ist. Wenn der Inhaltsschutz deaktiviert ist, beenden Sie die Wiedergabe des Videos sofort.
  3. Wenn der Inhaltsschutz aktiviert ist, überprüfen Sie das ulStatusFlags-Element der OPM_STANDARD_INFORMATION-Struktur. Wenn keine Kennzeichnungen festgelegt sind, funktioniert die Videoausgabe ordnungsgemäß. Andernfalls ist die Videoausgabe deaktiviert.

Die folgenden Flags sind für ulStatusFlagsdefiniert.

Flag Beschreibung
OPM_STATUS_LINK_LOST Der Ausgabeschutz funktionierte aus irgendeinem Grund nicht mehr. Das Anzeigegerät könnte z. B. von der Verbindung getrennt worden werden. Beenden Sie die Wiedergabe und deaktivieren Sie alle Ausgabeschutzmechanismen.
OPM_STATUS_RENEGOTIATION_REQUIRED Die Anwendung muss die OPM-Sitzung neu erstellen. Reagieren Sie wie folgt:
  1. Beenden Sie die Wiedergabe.
  2. Deaktivieren Sie alle Schutzmechanismen.
  3. Geben Sie die IOPMVideoOutput-Schnittstelle frei.
  4. Erstellen Sie alle Videooberflächen neu.
  5. Erstellen Sie ein neues OPM-Objekt und versuchen Sie, den Inhaltsschutz wiederherzustellen. Wenn dies fehlschlägt, zeigen Sie dem Benutzer eine Fehlermeldung an. Spielen Sie keine weiteren Videoinhalte ab.
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED Dieses Flag gilt nur, wenn HDCP verwendet wird, und gibt das Vorhandensein eines widerrufenen HDCP-Geräts an. Beenden Sie die Wiedergabe und deaktivieren Sie alle Schutzmechanismen für diese Videoausgabe. Wenn dieses Kennzeichen festgelegt ist, wird auch das OPM_STATUS_LINK_LOST-Flag festgelegt.
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED Der Treiber hat Manipulationen erkannt. Beenden Sie die Wiedergabe und spielen Sie mit dieser Videoausgabe kein weiteres Video mehr ab. Es empfiehlt sich auch, die Verwendung anderer Videoausgaben zu beenden, da das System möglicherweise kompromittiert ist.

 

Verwenden von HDCP zum Schützen von Inhalten

In diesem Abschnitt wird beschrieben, wie Sie den HDCP-Ausgabeschutz mithilfe von OPM aktivieren. Hier ist eine allgemeine Übersicht über die Schritte, welche die Anwendung ausführen muss. Details werden weiter unten in diesem Abschnitt angegeben.

  1. Die Anwendung muss möglicherweise eine SRM für die Videoausgabe bereitstellen. Der Mechanismus für den Empfang von SRMs liegt außerhalb des Bereichs der OPM-Schnittstelle. Beispielsweise können SRMs als Teil eines Übertragungsstreams übermittelt werden.
  2. Die Anwendung ermöglicht HDCP-Ausgabeschutz.
  3. Die Anwendung gibt den Videoinhalt wieder. In regelmäßigen Abständen fragt die Anwendung den Treiber ab, um sicherzustellen, dass HDCP aktiviert ist.
  4. Wenn die Wiedergabe abgeschlossen ist, deaktiviert die Anwendung HDCP.

Festlegen des SRM

Führen Sie zum Festlegen des SRM die folgenden Schritte aus.

  1. Initialisieren Sie eine OPM_SET_HDCP_SRM_PARAMETERS-Struktur mit der SRM-Versionsnummer.
  2. Speichern Sie das SRM in einer Variablen.
  3. Senden Sie einen OPM_SET_HDCP_SRM-Befehl an die Videoausgabe. Verwenden Sie die unter Senden von OPM-Befehlen beschriebene Prozedur.
  4. Senden Sie eine OPM_GET_CURRENT_HDCP_SRM_VERSION Statusanforderung an die Videoausgabe. Verwenden Sie das unter Senden von OPM-Statusanforderungen beschriebene Verfahren. Diese Statusanforderung enthält keine Eingabedaten, sodass der Inhalt des abParameters-Elements der OPM_GET_INFO_PARAMETERS-Struktur nicht definiert ist.
  5. Wenn die IOPMVideoOutput::GetInformation-Methode zurückgegeben wird, enthält das abRequestedInformation-Array in der OPM_REQUESTED_INFORMATION-Struktur eine OPM_STANDARD_INFORMATION-Struktur. Das ulInformation-Element dieser Struktur enthält die Versionsnummer des aktuellen SRM. Dieser Wert muss dem Wert aus Schritt 2 entsprechen.

Aktivieren von HDCP

Führen Sie die folgenden Schritte aus, um HDCP zu aktivieren.

  1. Initialisieren Sie eine OPM_SET_PROTECTION_LEVEL_PARAMETERS-Struktur mit den folgenden Werten:
    • ulProtectionType = OPM_PROTECTION_TYPE_HDCP
    • ulProtectionLevel = OPM_HDCP_ON
    • Reserviert = 0
    • Reserviert2 = 0
  2. Senden eines OPM_SET_PROTECTION_LEVEL-Befehls. Die Eingabedaten im abParameters-Array sind die OPM_SET_PROTECTION_LEVEL_PARAMETERS-Struktur.
  3. Senden Sie eine OPM_GET_VIRTUAL_PROTECTION_LEVEL-Statusanforderung, um zu überprüfen, ob HDCP aktiviert ist. Die ersten 4 Byte des abParameters-Elements der OPM_GET_INFO_PARAMETERS-Struktur enthalten den Wert OPM_PROTECTION_TYPE_HDCP.

Wenn die GetInformation-Methode zurückgegeben wird, enthält das abRequestedInformation-Array in der OPM_REQUESTED_INFORMATION-Struktur eine OPM_STANDARD_INFORMATION-Struktur. Das ulInformation-Element dieser Struktur enthält einen Wert aus der OPM_HDCP_PROTECTION_LEVEL-Enumeration. Wenn der Wert OPM_HDCP_ON entspricht, bedeutet dies, dass HDCP aktiviert ist. Wiederholen Sie andernfalls die Schritte 1 bis 2, bis HDCP aktiviert ist, ansonsten tritt ein Fehler auf. (Denken Sie daran, die Sequenznummer zu erhöhen und jedes Mal eine neue Zufallszahl zu generieren.)

Es dauert in der Regel zwischen 100 und 200 Millisekunden, um HDCP zu aktivieren, aber es kann auch länger dauern. Gehen Sie nicht davon aus, dass HDCP aktiviert ist, bis Sie es überprüft haben.

Wenn die Anwendung die Wiedergabe geschützter Inhalte beendet hat, deaktivieren Sie HDCP. Die Schritte sind identisch mit dem Aktivieren von HDCP, aber in Schritt 1 legen Sie ulProtectionLevel auf OPM_HDCP_OFF fest.

Hinweis

Aktivieren Sie HDCP nicht, wenn der Verbindungstyp OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED ist. (Siehe OPM Connector Type Flags.)

 

Ausgabeschutz-Manager