protection du contenu GPU-Based

Cette rubrique décrit les fonctionnalités de protection du contenu vidéo qu’un pilote graphique peut fournir.

Introduction

Le diagramme suivant montre une vue simplifiée de la façon dont le contenu vidéo protégé transite par le pipeline pour être rendu.

diagramme montrant le contenu vidéo protégé.

Notes

Le chemin d’accès du média protégé (PMP) n’est pas représenté dans ce diagramme. Le flux de données présenté ici peut se produire dans un processus PMP ou dans un processus d’application.

Le décodeur reçoit des données vidéo chiffrées et compressées à partir d’une source externe. Il est également supposé que le décodeur reçoit également une clé de chiffrement pour déchiffrer ces données. Cette rubrique ne décrit pas l’échange de clés entre la source vidéo et le décodeur, mais le PMP définit un mécanisme possible. Le GPU n’est pas impliqué à ce stade.

Pour le décodage avec accélération matérielle, le décodeur logiciel transmet le contenu vidéo compressé au GPU. Pour protéger ce contenu, le décodeur rechiffre les données, généralement à l’aide d’AES-CTR, avant de les transmettre à l’accélérateur matériel. Un mécanisme d’échange de clés est défini entre le décodeur et le pilote graphique.

Les trames vidéo décodées sont stockées en mémoire vidéo, généralement en clair. À ce stade, les images sont traitées, puis présentées. Il existe deux options main pour la présentation.

  • Les images peuvent être présentées à l’aide d’une superposition matérielle. Pour plus d’informations, consultez Prise en charge de la superposition matérielle.
  • Les cadres peuvent être présentés par la gestion des fenêtres du bureau (DWM) à l’aide d’une surface partagée.

La dernière étape consiste à afficher le cadre sur le moniteur, ce qui peut nécessiter une protection de liaison entre le carte graphique et le périphérique d’affichage. Un exemple de protection de lien est High-Bandwidth protection de contenu numérique (HDCP). La protection des liens est configurée à l’aide de Output Protection Manager (OPM). Cette rubrique ne décrit pas opm; Pour plus d’informations, consultez Utilisation de Output Protection Manager.

Vue d’ensemble du processus de décodage

Pendant le décodage à accélération matérielle, le décodeur logiciel doit passer des données vidéo compressées aux carte graphiques. Pour le contenu Premium, ces données doivent généralement être chiffrées à l’aide d’un chiffrement à clé symétrique avant d’être envoyées au GPU.

Pour chiffrer la vidéo à des fins de décodage, le décodeur logiciel utilise les interfaces suivantes :

diagramme montrant les interfaces de décodage direct3d9.

Toutes ces interfaces sont obtenues à partir de l’appareil Direct3D, comme suit :

Interface Création
IDirectXVideoDecoder Appelez IDirectXVideoDecoderService::CreateVideoDecoder. L’appareil décodeur DXVA est identifié par un GUID de profil DXVA.
IDirect3DCryptoSession9 Appelez IDirect3DDevice9Video::CreateCryptoSession.
IDirect3DAuthenticatedChannel9 Appelez IDirect3DDevice9Video::CreateAuthenticatedChannel.

Notes

Pour obtenir un pointeur vers l’interface IDirect3DDevice9Video , appelez QueryInterface sur un appareil D3D9Ex.

Le canal authentifié fournit un canal de communication approuvé entre le décodeur logiciel et le pilote. Le canal de communication fonctionne comme suit :

  • Le pilote fournit une chaîne de certificats X.509 dont le certificat racine est signé par Microsoft.
  • Le certificat contient une clé publique RSA pour le pilote.
  • Le décodeur logiciel utilise la clé publique pour envoyer au pilote une clé de session AES 128 bits.
  • Le décodeur logiciel envoie des requêtes et des commandes au canal authentifié.
  • La clé de session est utilisée pour calculer les codes d’authentification des messages (MAC) pour les requêtes et les commandes. Le pilote utilise les contrôleurs de domaine pour vérifier l’intégrité des données de requête/commande, et le décodeur logiciel les utilise pour vérifier l’intégrité des données de réponse du pilote.

Chiffrement des mémoires tampons vidéo compressées pour le décodeur

Voici une vue d’ensemble générale du processus de chiffrement et de décodage :

  1. Le décodeur logiciel reçoit un flux de données chiffrées à partir de la source vidéo. Le décodeur déchiffre ce flux.

  2. Le décodeur logiciel négocie une clé de session avec la session de chiffrement.

  3. Le décodeur logiciel utilise le canal authentifié pour associer la session de chiffrement au périphérique décodeur DXVA.

  4. Le décodeur logiciel place les données compressées dans les mémoires tampons DXVA qu’il obtient à partir du périphérique de décodeur DXVA (accélérateur). Pour le contenu protégé, l’encodeur logiciel chiffre les données placées dans les mémoires tampons DXVA, en utilisant la clé de session pour le chiffrement.

    Notes

    Certains pilotes utilisent une clé de contenu, au lieu de la clé de session, pour le chiffrement. La clé de contenu peut changer d’une image à l’autre.

  5. Le décodeur envoie les mémoires tampons compressées chiffrées à l’accélérateur. Pour AES-CTR, le décodeur transmet également le vecteur d’initialisation. Si une clé de contenu est utilisée, le décodeur transmet la clé de contenu chiffrée à l’aide de la clé de session.

Direct3D prend en charge en standard AES-CTR 128 bits, mais est conçu pour s’étendre à d’autres types de chiffrement.

Les cinq sections suivantes fournissent des étapes plus détaillées.

1. Interroger les fonctionnalités de protection du contenu du pilote

Avant d’essayer d’appliquer le chiffrement, obtenez les fonctionnalités de protection du contenu du pilote.

  1. Obtenez un pointeur vers l’appareil Direct3D 9.
  2. Appelez QueryInterface pour l’interface IDirect3DDevice9Video .
  3. Appelez IDirect3DDevice9Video::GetContentProtectionCaps. Cette méthode remplit une structure D3DCONTENTPROTECTIONCAPS avec les fonctionnalités de protection du contenu du pilote.

En particulier, recherchez les fonctionnalités suivantes :

  • Si le membre Caps contient l’indicateur D3DCPCAPS_SOFTWARE ou D3DCPCAPS_HARDWARE , le pilote peut effectuer le chiffrement.
  • Le membre KeyExchangeType spécifie comment effectuer l’échange de clés pour la clé de session.
  • Si le membre Caps contient l’indicateur D3DCPCAPS_CONTENTKEY , le pilote utilise une clé de contenu distincte pour le chiffrement. Cela est important lorsque vous générez la clé de session.

Des fonctionnalités supplémentaires sont indiquées dans le membre Caps .

2. Configurer le canal authentifié

L’étape suivante consiste à configurer le canal authentifié.

  1. Appelez IDirect3DDevice9Video::CreateAuthenticatedChannel pour créer le canal authentifié. Pour le paramètre ChannelType , spécifiez un type de canal qui correspond aux fonctionnalités du pilote.

    • Le type de canal D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE correspond à D3DCPCAPS_SOFTWARE.
    • Le type de canal D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE correspond à D3DCPCAPS_HARDWARE.

    La méthode CreateAuthenticatedChannel retourne un pointeur vers l’interface IDirect3DAuthenticatedChannel9 , ainsi qu’un handle vers le canal. Le handle est utilisé ultérieurement pour associer la session de chiffrement au canal authentifié.

  2. Appelez IDirect3DAuthenticatedChannel9::GetCertificateSize pour obtenir la taille du certificat X.509 du pilote. Allouez une mémoire tampon de la taille requise.

  3. Appelez IDirect3DAuthenticatedChannel9::GetCertificate pour obtenir le certificat. La méthode copie le certificat dans la mémoire tampon allouée à l’étape précédente.

  4. Vérifiez que le certificat du pilote a été signé par Microsoft et qu’il n’a pas été révoqué.

  5. Obtenez la clé publique à partir du certificat.

  6. Générez une clé de session RSA aléatoire. Cette clé de session est utilisée pour signer les données envoyées au canal authentifié. Chiffrez la clé de session à l’aide de la clé publique du pilote.

  7. Appelez IDirect3DAuthenticatedChannel9::NegotiateKeyExchange pour envoyer la clé de session chiffrée au pilote.

  8. Initialisez le canal sécurisé comme suit :

    1. Renseignez une structure D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE comme décrit dans la documentation.
    2. Envoyez la commande D3DAUTHENTICATEDCONFIGURE_INITIALIZE en appelant IDirect3DAuthenticatedChannel9::Configure , comme décrit dans la section Envoi de commandes de canal authentifié. Cette commande contient les numéros de séquence de départ pour les commandes et requêtes envoyées au canal authentifié.
  9. Vérifiez le type de canal en envoyant une requête D3DAUTHENTICATEDQUERY_CHANNELTYPE au canal authentifié, comme décrit dans la section Envoi de requêtes de canal authentifiées. Vérifiez que le type de canal correspond à ce que vous avez spécifié dans la méthode CreateAuthenticatedChannel .

3. Configurer la session de chiffrement

Ensuite, configurez la session de chiffrement et établissez la clé de session.

  1. Appelez IDirect3DDevice9Video::CreateCryptoSession pour créer la session de chiffrement. Cette méthode retourne un pointeur vers l’interface IDirect3DCryptoSession9 et un handle vers la session de chiffrement.
  2. Appelez IDirect3DCryptoSession9::GetCertificateSize pour obtenir la taille du certificat X.509 du pilote. Allouez une mémoire tampon de la taille requise.
  3. Appelez IDirect3DCryptoSession9::GetCertificate pour obtenir le certificat. La méthode copie le certificat dans la mémoire tampon allouée à l’étape précédente.
  4. Vérifiez que le certificat du pilote a été signé par Microsoft et qu’il n’a pas été révoqué.
  5. Obtenez la clé publique à partir du certificat.
  6. Générez une clé de session RSA aléatoire. Il s’agit d’une clé de session distincte de la clé de session de canal authentifiée. Chiffrez la clé de session à l’aide de la clé publique du pilote.
  7. Appelez IDirect3DCryptoSession9::NegotiateKeyExchange pour envoyer la clé de session chiffrée au pilote.
  8. Si les fonctionnalités de protection du contenu incluent D3DCPCAPS_CONTENTKEY, créez une clé de contenu RSA aléatoire. Elle sera utilisée plus tard dans le processus de décodage.

4. Obtenir un handle sur l’appareil décodeur DXVA

Pour l’étape suivante, vous aurez besoin d’un handle pour l’appareil décodeur DXVA. Pour obtenir ce handle, renseignez une structure DXVA2_DecodeExecuteParams comme suit :

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);

Définissez le membre pExtensionData de la structure DXVA2_DecodeExecuteParams sur l’adresse d’une structure DXVA2_DecodeExtensionData .

Dans la structure DXVA2_DecodeExtensionData , définissez le membre Function sur DXVA2_DECODE_GET_DRIVER_HANDLE. Définissez pPrivateOutputData sur l’adresse d’une mémoire tampon suffisamment grande pour stocker une valeur HANDLE . (Dans l’exemple précédent, cette mémoire tampon est la variable hDecodeDeviceHandle .)

Appelez ensuite IDirectXVideoDecoder::Execute et transmettez l’adresse de la structure DXVA2_DecodeExecuteParams . Le handle du décodeur DXVA est retourné dans pPrivateOutputData.

5. Associer le décodeur DXVA à la session de chiffrement

Ensuite, associez l’appareil décodeur DXVA à l’appareil Direct3D et à la session de chiffrement, comme suit :

  1. Obtenez un handle pour l’appareil décodeur DXVA, comme décrit dans la section précédente.
  2. Obtenez un handle sur l’appareil Direct3D en envoyant une requête D3DAUTHENTICATEDQUERY_DEVICEHANDLE au canal authentifié.
  3. Renseignez une structure D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION avec les informations suivantes :
    • Définissez le membre DXVA2DecodeHandle sur le handle de l’appareil décodeur DXVA.
    • Définissez le membre CryptoSessionHandle sur le handle de la session de chiffrement. Ce handle est retourné par la méthode IDirect3DDevice9Video::CreateCryptoSession .
    • Définissez le membre DeviceHandle sur le handle d’appareil Direct3D.
  4. Appelez IDirect3DAuthenticatedChannel9::Configure pour envoyer une commande D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION au canal authentifié.

Le diagramme suivant illustre l’échange de handles :

diagramme montrant comment le décodeur dxva est associé à la session de chiffrement.

Le décodeur logiciel peut désormais utiliser la clé de session de chiffrement pour chiffrer les mémoires tampons vidéo compressées. Chaque mémoire tampon compressée aura son propre vecteur d’initialisation (IV) spécifié dans le membre pvPVPState de la structure DXVA2_DecodeBufferDesc .

Envoi de commandes de canal authentifié

Un ensemble de commandes est défini pour configurer le canal authentifié et définir diverses protections de contenu. Pour obtenir la liste des commandes, consultez Commandes de protection du contenu.

Pour envoyer une commande au canal authentifié, procédez comme suit.

  1. Renseignez la structure des données d’entrée. Cette structure de données est toujours une structure D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT suivie de champs supplémentaires. Renseignez la structure D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT comme indiqué dans le tableau suivant.
Membre Description
omac Ignorez ce champ pour l’instant.
ConfigureType GUID qui identifie la commande. Pour obtenir la liste des commandes, consultez Commandes de protection du contenu.
hChannel Handle du canal authentifié.
SequenceNumber Numéro séquentiel. Le premier numéro de séquence est spécifié en envoyant une commande D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Chaque fois que vous envoyez une autre commande, incrémentez ce nombre de 1. Le numéro de séquence protège contre les attaques par relecture. Note: Deux numéros de séquence distincts sont utilisés, l’un pour les commandes et l’autre pour les requêtes.
  1. Calculez la balise OMAC pour le bloc de données qui apparaît après le membre omac de la structure d’entrée. Copiez ensuite cette valeur de balise dans le membre omac .
  2. Appelez IDirect3DAuthenticatedChannel9::Configure.
  3. Le pilote place la sortie de la commande dans la structure D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT .
  4. Calculez la balise OMAC pour le bloc de données qui apparaît après le membre omac de la structure de sortie. Comparez cela avec la valeur du membre omac . Échoue s’ils ne correspondent pas.
  5. Comparez les valeurs des membres ConfigureType, hChannel et SequenceNumber dans la structure de sortie à vos valeurs pour ces membres. Échoue s’ils ne correspondent pas.
  6. Incrémentez le numéro de séquence de la commande suivante.

Envoi de requêtes de canal authentifié

Un ensemble de requêtes est défini pour récupérer des informations sur le canal authentifié. Pour obtenir la liste des requêtes, consultez Requêtes de protection du contenu.

Pour envoyer une commande au canal authentifié, effectuez les étapes suivantes.

  1. Renseignez la structure des données d’entrée. Cette structure de données est toujours une structure D3DAUTHENTICATEDCHANNEL_QUERY_INPUT , éventuellement suivie de champs supplémentaires. Renseignez la structure D3DAUTHENTICATEDCHANNEL_QUERY_INPUT comme indiqué dans le tableau suivant.
Membre Description
QueryType GUID qui identifie la requête. Pour obtenir la liste des requêtes, consultez Requêtes de protection du contenu.
hChannel Handle du canal authentifié.
SequenceNumber Numéro séquentiel. Le premier numéro de séquence est spécifié en envoyant une commande D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Chaque fois que vous envoyez une autre requête, incrémentez ce nombre de 1. Le numéro de séquence protège contre les attaques par relecture. Note: Deux numéros de séquence distincts sont utilisés, l’un pour les commandes et l’autre pour les requêtes.
  1. Appelez IDirect3DAuthenticatedChannel9::Query.
  2. Le pilote place la sortie de la requête dans une structure D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT . Cette structure est suivie de champs supplémentaires, en fonction du type de requête.
  3. Calculez la balise OMAC pour le bloc de données qui apparaît après le membre omac de la structure de sortie. Comparez cela à la valeur du membre omac . Échec s’ils ne correspondent pas.
  4. Comparez les valeurs des membres ConfigureType, hChannel et SequenceNumber de la structure de sortie à vos valeurs pour ces membres. Échec s’ils ne correspondent pas.
  5. Incrémentez le numéro de séquence de la requête suivante.

API vidéo Direct3D 9