Utilisation d’Output Protection Manager

Cette rubrique décrit comment utiliser Output Protection Manager (OPM) pour protéger le contenu vidéo quand il est transféré sur un périphérique d’affichage en passant par un connecteur physique. Cette rubrique contient les sections suivantes :

Le contenu vidéo Premium est généralement chiffré pour le protéger contre la duplication non autorisée. Naturellement, la vidéo doit être déchiffrée pour être affichée. Les images déchiffrées et décompressées doivent ensuite être transférées sur le périphérique d’affichage en passant par un connecteur physique. Les fournisseurs de contenu peuvent demander la protection des trames vidéo à ce stade, car elles passent par le connecteur physique.

Pour ce faire, il existe divers mécanismes de protection, notamment la protection des contenus numériques haute définition (HDCP, High-Bandwidth Digital Content Protection) et la protection de contenu DisplayPort (DPCP, DisplayPort Content Protection) pour les sorties numériques, ainsi que le système de gestion de génération de copie analogique (CGMS-A, Copy Generation Management System - Analog) pour les sorties analogiques. En règle générale, ces mécanismes impliquent le chiffrement ou le brouillage du signal avant son affichage.

OPM permet à une application d’appliquer des mécanismes de protection de contenu sur la sortie vidéo. Avec OPM, l’application envoie des commandes et des demandes d’état au pilote graphique sur un canal sécurisé et approuvé. OPM permet à une application de :

  • Vérifier qu’un pilote graphique a été signé par Microsoft.
  • Configurer un canal de communication approuvé avec le pilote.
  • Appliquer des mécanismes de protection de contenu sur la sortie physique.

OPM remplace le protocole COPP (Certified Output Protection Protocol) et utilise une API similaire. Pour une compatibilité descendante, l’interface OPM peut émuler l’interface COPP. Les différences entre OPM et COPP sont les suivantes :

  • OPM utilise des certificats X.509, tandis que COPP utilise un format de certificat propriétaire.
  • OPM prend en charge les répéteurs HDCP.
  • Les applications qui utilisent OPM n’ont pas besoin d’analyser les messages de renouvelabilité du système HDCP (SRM).
  • OPM peut être utilisé quand l’affichage graphique utilise le mode clone. COPP ne prend pas en charge le mode clone.

Si votre application utilise le chemin multimédia protégé (PMP) pour lire du contenu vidéo, vous n’avez pas besoin d’utiliser l’API OPM, car le PMP effectue tous les appels OPM nécessaires. L’API OPM est disponible pour les applications qui n’utilisent pas le PMP.

OPM est disponible dans Windows Vista et versions ultérieures, mais l’API n’est pas publique avant Windows 7. Pour utiliser OPM dans une application, vous devez avoir les en-têtes et les fichiers de bibliothèque du SDK Windows 7. Vous n’avez pas besoin de redistribuer de DLL pour utiliser OPM dans Windows Vista ou Windows Server 2008.

Sorties vidéo

Un adaptateur graphique peut avoir plusieurs sorties physiques, chacune avec ses propres fonctionnalités. Pour qu’une application puisse lire du contenu protégé, elle doit définir les mécanismes de protection appropriés sur chaque sortie vidéo associée aux cartes graphiques qui affichent la vidéo. Les mécanismes de protection à appliquer dépendent des règles d’utilisation du contenu.

Chaque sortie vidéo est représentée par une instance de l’interface IOPMVideoOutput. Vous pouvez utiliser un appareil Direct3D ou des handles de moniteur pour obtenir les sorties vidéo.

Utilisation d’un appareil Direct3D :

  1. Obtenez le pointeur IDirect3DDevice9 correspondant à l’appareil Direct3D que votre application doit utiliser pour créer les surfaces contenant les trames vidéo.
  2. Appelez la fonction OPMGetVideoOutputsFromIDirect3DDevice9Object. Cette fonction alloue un tableau de pointeurs IOPMVideoOutput, un pour chaque sortie.

Utilisation de handles de moniteur :

  1. Appelez EnumDisplayMonitors pour obtenir les handles HMONITOR qui correspondent à la fenêtre vidéo. Comme plusieurs moniteurs peuvent être associés à la même fenêtre, vous pouvez obtenir plusieurs handles HMONITOR.
  2. Pour chaque handle de moniteur, appelez OPMGetVideoOutputsFromHMONITOR. Cette fonction alloue un tableau de pointeurs IOPMVideoOutput, un pour chaque sortie.

Initialisation d’une session OPM

Pour que l’application puisse envoyer des commandes OPM ou des demandes d’état, elle doit vérifier que la sortie vidéo est approuvée et établir une clé de session. La clé de session est utilisée pour signer les données échangées entre l’application et le pilote graphique.

L’API OPM définit une négociation qui établit l’approbation et définit la clé de session. Vous devez effectuer cette négociation pour chaque instance de l’interface IOPMVideoOutput, de la façon suivante :

  1. Appelez IOPMVideoOutput::StartInitialization. Cette méthode récupère deux éléments de données :

    • Un nombre aléatoire généré par le pilote. Vous utilisez ce nombre pour effectuer la négociation.
    • La chaîne de certificats X.509 du pilote.
  2. Vérifiez que la chaîne de certificats a été signée par Microsoft.

    Remarque

    La révocation de certificats n’est pas dans l’étendue d’OPM.

     

  3. Obtenez la clé publique du pilote à partir de la chaîne de certificats.

  4. Générez une clé de session AES 128 bits.

  5. Générez deux nombres 32 bits aléatoires :

    • Le numéro de séquence de départ des demandes d’état OPM.
    • Le numéro de séquence de départ des commandes OPM.

    Ces nombres doivent être générés avec un générateur de nombres pseudo-aléatoires sécurisés par chiffrement, comme CryptGenRandom.

  6. Copiez le nombre aléatoire du pilote (obtenu à l’étape 1), la clé de session et les deux numéros de séquence dans une structure OPM_ENCRYPTED_INITIALIZATION_PARAMETERS, comme décrit dans IOPMVideoOutput::FinishInitialization.

  7. Chiffrez la structure OPM_ENCRYPTED_INITIALIZATION_PARAMETERS avec RSAES-OAEP, en utilisant la clé publique du pilote, qui se trouve dans le certificat du pilote.

  8. Appelez IOPMVideoOutput::FinishInitialization.

Envoi de demandes d’état OPM

Les demandes d’état OPM renvoient des informations sur la sortie vidéo, comme le type de connecteur physique et le niveau de protection actuel. Pour obtenir la liste des types de demande, consultez Demandes d’état OPM.

Pour envoyer une demande d’état, effectuez les étapes suivantes.

  1. Initialisez une structure OPM_GET_INFO_PARAMETERS, comme indiqué dans le tableau suivant.

    Membre Description
    omac Ignorez ce champ pour l’instant.
    rnRandomNumber Nombre aléatoire 128 bits sécurisé par chiffrement. Chaque fois que vous effectuez une demande d’état, générez toujours un nouveau nombre aléatoire, même si vous effectuez la même demande. Stockez le nombre dans une variable, car vous en avez besoin par la suite.
    guidInformation GUID qui identifie la demande d’état. Pour obtenir la liste des demandes d’état, consultez Demandes d’état OPM.
    ulSequenceNumber Numéro séquentiel. Pour la première demande d’état, utilisez le numéro de séquence de départ que vous avez spécifié dans la méthode IOPMVideoOutput::FinishInitialization (étape 5 de Initialisation d’une session OPM.) Chaque fois que vous effectuez une autre demande d’état, incrémentez ce nombre de 1.
    abParameters Tableau d’octets qui contient des données d’entrée supplémentaires pour la demande. Le format des données d’entrée est listé dans la rubrique de référence de chaque demande d’état.
    cbParametersSize Taille des données valides dans le tableau abParameters. Le contenu du reste du tableau n’est pas défini.

     

  2. Calculez le code MAC CBC à une seule clé (OMAC-1) pour calculer le hachage du bloc de données qui s’affiche après le membre omac, puis définissez le membre omac sur cette valeur. Consultez Exemple de code OPM.

  3. Appelez la méthode IOPMVideoOutput::GetInformation. Passez un pointeur vers la structure OPM_GET_INFO_PARAMETERS et un pointeur vers une structure OPM_REQUESTED_INFORMATION. La réponse du pilote est écrite dans la structure OPM_REQUESTED_INFORMATION.

    • Le membre omac de cette structure contient un code OMAC calculé pour les données qui suivent ce membre.
    • Le membre abRequestedInformation est un tableau d’octets contenant des données de sortie pour la réponse. Le format des données de sortie est listé dans la rubrique de référence de chaque demande d’état.
  4. Calculez un code OMAC pour la structure OPM_REQUESTED_INFORMATION, sans inclure le membre omac. Vérifiez que le code OMAC correspond à la valeur du membre omac.

  5. Vérifiez que le membre cbRequestedInformationSize de la structure OPM_REQUESTED_INFORMATION donne la taille appropriée pour les données de sortie. Par exemple, les données de sortie de la requête OPM_GET_CONNECTOR_TYPE sont une structure OPM_STANDARD_INFORMATION, la valeur de cbRequestedInformationSize doit donc être sizeof(OPM_STANDARD_INFORMATION).

  6. Castez le membre abRequestedInformation de la structure OPM_REQUESTED_INFORMATION en structure de données de sortie appropriée. Par exemple, si la demande d’état est OPM_GET_CONNECTOR_TYPE, castez abRequestedInformation en structure OPM_STANDARD_INFORMATION.

  7. Vérifiez que le membre rnRandomNumber de la structure de données de sortie correspond à la valeur de rnRandomNumber de l’étape 1.

  8. Vérifiez le membre ulStatusFlags de la structure de données de sortie, comme décrit dans Traitement d’une sortie vidéo désactivée.

Si une des vérifications des étapes 5 à 8 échoue, l’application doit cesser d’afficher le contenu protégé.

Envoi de commandes OPM

Les commandes OPM sont utilisées pour définir le niveau de protection et d’autres paramètres sur la sortie vidéo. L’envoi d’une commande OPM est similaire à l’envoi d’une demande d’état, sauf qu’il n’y a pas de données de réponse du pilote. Pour obtenir la liste des commandes, consultez Commandes OPM.

Pour envoyer une commande OPM, effectuez les étapes suivantes.

  1. Remplissez une structure OPM_CONFIGURE_PARAMETERS, comme indiqué dans le tableau suivant.

    Membre Description
    omac Ignorez ce champ pour l’instant.
    guidSetting GUID qui identifie la commande. Pour obtenir la liste des commandes, consultez Commandes OPM.
    ulSequenceNumber Numéro séquentiel. Pour la première commande, utilisez le numéro de séquence de départ que vous avez spécifié dans la méthode IOPMVideoOutput::FinishInitialization (étape 5 de Initialisation d’une session OPM.) Chaque fois que vous envoyez une autre commande, incrémentez ce nombre de 1.
    abParameters Tableau d’octets qui contient des données d’entrée supplémentaires pour la commande. Le format des données d’entrée est listé dans la rubrique de référence de chaque commande.
    cbSettingDataSize Taille des données valides dans le tableau abParameters. Le contenu du reste du tableau n’est pas défini.

     

  2. Calculez un code OMAC pour le bloc de données qui s’affiche après le membre omac, puis définissez le membre omac sur cette valeur.

  3. Appelez IOPMVideoOutput::Configure.

Pour la plupart des commandes, une demande d’état correspondante renvoie l’état de la commande. Par exemple, la commande OPM_SET_PROTECTION_LEVEL définit le niveau de protection et la commande OPM_GET_VIRTUAL_PROTECTION_LEVEL obtient le niveau de protection actuel.

Traitement d’une sortie vidéo désactivée

Une sortie vidéo peut se désactiver à tout moment pour empêcher l’utilisation non autorisée du contenu vidéo. Cela peut se produire si un mécanisme de protection cesse de fonctionner, parce que le pilote détecte une falsification ou parce que l’affichage a été déconnecté du connecteur physique. Quand une sortie vidéo est désactivée, aucune trame vidéo n’est affichée.

Quand la protection du contenu est activée, une application doit régulièrement (au moins une fois toutes les 2 secondes) effectuer les étapes suivantes.

  1. Appeler IOPMVideoOutput::GetInformation pour envoyer la demande d’état OPM_GET_ACTUAL_PROTECTION_LEVEL ou OPM_GET_VIRTUAL_PROTECTION_LEVEL. Les données renvoyées pour les deux commandes sont une structure OPM_STANDARD_INFORMATION.
  2. Vérifier le membre ulInformation de la structure OPM_STANDARD_INFORMATION. Ce membre contient un indicateur spécifiant si la protection du contenu est toujours activée. Si la protection du contenu est désactivée, arrêter de lire la vidéo immédiatement.
  3. Si la protection du contenu est activée, vérifier le membre ulStatusFlags de la structure OPM_STANDARD_INFORMATION. Si aucun indicateur n’est défini, la sortie vidéo fonctionne correctement. Sinon, la sortie vidéo est désactivée.

Les indicateurs suivants sont définis pour ulStatusFlags.

Indicateur Description
OPM_STATUS_LINK_LOST La protection de sortie a cessé de fonctionner pour une raison quelconque, par exemple, le périphérique d’affichage est déconnecté du connecteur. Arrêtez la lecture et désactivez tous les mécanismes de protection de sortie.
OPM_STATUS_RENEGOTIATION_REQUIRED L’application doit rétablir la session OPM. Répondez comme suit :
  1. Arrêter la lecture.
  2. Désactivez tous les mécanismes de protection.
  3. Libérez l’interface IOPMVideoOutput.
  4. Recréez toutes les surfaces vidéo.
  5. Créez un objet OPM et tentez de rétablir la protection du contenu. Si cela échoue, affichez un message d’erreur à l’utilisateur. Ne lisez plus de contenu vidéo.
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED Cet indicateur s’applique uniquement quand HDCP est utilisé et indique la présence d’un appareil HDCP révoqué. Arrêtez la lecture et désactivez tous les mécanismes de protection sur cette sortie vidéo. Quand cet indicateur est défini, l’indicateur OPM_STATUS_LINK_LOST est également défini.
OPM_STATUS_REVOKED_HDCP_DEVICE_ATTACHED Le pilote a détecté une falsification. Arrêtez la lecture et ne lisez plus de vidéo en utilisant cette sortie vidéo. Il est également judicieux d’arrêter d’utiliser les autres sorties vidéo, car le système est peut-être compromis.

 

Utilisation de HDCP pour protéger le contenu

Cette section décrit comment activer la protection de sortie HDCP avec OPM. Voici un aperçu général des étapes à suivre pour l’application. Plus d’informations sont données plus loin dans cette section.

  1. L’application peut avoir à fournir un SRM à la sortie vidéo. Le mécanisme de réception des SRM n’est pas dans l’étendue de l’interface OPM. Par exemple, des SRM peuvent être remis dans le cadre d’un flux de diffusion.
  2. L’application active la protection de sortie HDCP.
  3. L’application lit le contenu vidéo. Régulièrement, l’application interroge le pilote pour vérifier que HDCP est activé.
  4. Une fois la lecture terminée, l’application désactive HDCP.

Définition du SRM

Pour définir le SRM, effectuez les étapes suivantes.

  1. Initialisez une structure OPM_SET_HDCP_SRM_PARAMETERS avec le numéro de version du SRM.
  2. Stockez le SRM dans une variable.
  3. Envoyez une commande OPM_SET_HDCP_SRM à la sortie vidéo. Utilisez la procédure décrite dans Envoi de commandes OPM.
  4. Envoyez une demande d’état OPM_GET_CURRENT_HDCP_SRM_VERSION à la sortie vidéo. Utilisez la procédure décrite dans Envoi de demandes d’état OPM. Comme cette demande d’état n’a pas de données d’entrée, le contenu du membre abParameters de la structure OPM_GET_INFO_PARAMETERS n’est pas défini.
  5. Quand la méthode IOPMVideoOutput::GetInformation renvoie une réponse, le tableau abRequestedInformation dans la structure OPM_REQUESTED_INFORMATION contient une structure OPM_STANDARD_INFORMATION. Le membre ulInformation de cette structure contient le numéro de version du SRM actuel. Cette valeur doit être égale à la valeur de l’étape 2.

Activation de HDCP

Pour activer HDCP, effectuez les étapes suivantes.

  1. Initialisez une structure OPM_SET_PROTECTION_LEVEL_PARAMETERS avec les valeurs suivantes :
    • ulProtectionType = OPM_PROTECTION_TYPE_HDCP
    • ulProtectionLevel = OPM_HDCP_ON
    • Reserved = 0
    • Reserved2 = 0
  2. Envoyez une commande OPM_SET_PROTECTION_LEVEL. Les données d’entrée dans le tableau abParameters sont la structure OPM_SET_PROTECTION_LEVEL_PARAMETERS.
  3. Envoyez une demande d’état OPM_GET_VIRTUAL_PROTECTION_LEVEL pour vérifier que HDCP est activé. Les 4 premiers octets du membre abParameters de la structure OPM_GET_INFO_PARAMETERS contiennent la valeur OPM_PROTECTION_TYPE_HDCP.

Quand la méthode GetInformation renvoie une réponse, le tableau abRequestedInformation dans la structure OPM_REQUESTED_INFORMATION contient une structure OPM_STANDARD_INFORMATION. Le membre ulInformation de cette structure contient une valeur de l’énumération OPM_HDCP_PROTECTION_LEVEL. Si la valeur est égale à OPM_HDCP_ON, HDCP est activé. Sinon, répétez les étapes 1 à 2 jusqu’à ce que HDCP soit activé, ou qu’une erreur se produise. (N’oubliez pas d’incrémenter le numéro de séquence et de générer un nouveau nombre aléatoire à chaque fois.)

Il faut généralement entre 100 et 200 millisecondes pour activer HDCP, mais cela peut prendre plus de temps. Ne supposez pas que HDCP est activé tant que vous ne l’avez pas vérifié.

Quand l’application termine la lecture du contenu protégé, désactivez HDCP. Les étapes sont les mêmes que pour activer HDCP, mais à l’étape 1, définissez ulProtectionLevel sur OPM_HDCP_OFF.

Remarque

N’activez pas HDCP si le type de connecteur est OPM_CONNECTOR_TYPE_DISPLAYPORT_EMBEDDED. (Consultez Indicateurs du type de connecteur OPM.)

 

Output Protection Manager