Protección de contenido de GPU-Based
En este tema se describen las funcionalidades de protección de contenido de vídeo que puede proporcionar un controlador de gráficos.
- Introducción
- Información general sobre el proceso de descodificación
- Cifrado de búferes de vídeo comprimidos para el descodificador
- Envío de comandos de canal autenticados
- Envío de consultas de canal autenticadas
- Temas relacionados
Introducción
En el diagrama siguiente se muestra una vista simplificada de cómo viaja el contenido de vídeo protegido a través de la canalización que se va a representar.
Nota
La ruta de acceso a medios protegidos (PMP) no se muestra en este diagrama. El flujo de datos que se muestra aquí puede producirse dentro de un proceso PMP o dentro de un proceso de aplicación.
El descodificador recibe datos de vídeo cifrados comprimidos de un origen externo. También se supone que el descodificador también recibe una clave criptográfica para descifrar estos datos. En este tema no se describe el intercambio de claves entre el origen y el descodificador de vídeo, pero el PMP define un posible mecanismo. La GPU no está implicada en esta fase.
Para la descodificación acelerada por hardware, el descodificador de software pasa contenido de vídeo comprimido a la GPU. Para proteger este contenido, el descodificador vuelve a cifrar los datos, normalmente mediante AES-CTR, antes de pasarlo al acelerador de hardware. Un mecanismo de intercambio de claves se define entre el descodificador y el controlador de gráficos.
Los fotogramas de vídeo descodificados se almacenan en memoria de vídeo, por lo general, sin cifrar. En este momento, los fotogramas se procesan y, a continuación, se presentan. Hay dos opciones principales para la presentación.
- Los marcos se pueden presentar mediante una superposición de hardware. Para obtener más información, consulte Compatibilidad con la superposición de hardware.
- Los marcos se pueden presentar mediante la administración de ventanas de escritorio (DWM) mediante una superficie compartida.
El último paso es mostrar el marco en el monitor, que puede requerir protección de vínculos entre la tarjeta gráfica y el dispositivo de visualización. Un ejemplo de protección de vínculos es High-Bandwidth Protección de contenido digital (HDCP). La protección de vínculos se configura mediante el Administrador de protección de salida (OPM). En este tema no se describe OPM; para obtener más información, consulte Uso del Administrador de protección de salida.
Información general sobre el proceso de descodificación
Durante la descodificación acelerada por hardware, el descodificador de software debe pasar datos de vídeo comprimidos a la tarjeta gráfica. En el caso del contenido premium, estos datos normalmente se deben cifrar, mediante el cifrado de clave simétrica, antes de enviarlos a la GPU.
Para cifrar el vídeo para la descodificación, el descodificador de software usa las siguientes interfaces:
- IDirectXVideoDecoder. Representa el dispositivo de descodificador DXVA, también denominado acelerador.
- IDirect3DCryptoSession9. Representa una sesión criptográfica, que proporciona la clave de cifrado.
- IDirect3DAuthenticatedChannel9. Representa un canal autenticado, que permite al descodificador de software asociar la sesión criptográfica con el descodificador DXVA.
Todas estas interfaces se obtienen del dispositivo Direct3D, como se indica a continuación:
Interfaz | Creación |
---|---|
IDirectXVideoDecoder | Llame a IDirectXVideoDecoderService::CreateVideoDecoder. El dispositivo descodificador DXVA se identifica mediante un GUID de perfil DXVA. |
IDirect3DCryptoSession9 | Llame a IDirect3DDevice9Video::CreateCryptoSession. |
IDirect3DAuthenticatedChannel9 | Llame a IDirect3DDevice9Video::CreateAuthenticatedChannel. |
Nota:
Para obtener un puntero a la interfaz IDirect3DDevice9Video , llame a QueryInterface en un dispositivo D3D9Ex.
El canal autenticado proporciona un canal de comunicación de confianza entre el descodificador de software y el controlador. El canal de comunicación funciona de la siguiente manera:
- El controlador proporciona una cadena de certificados X.509 cuyo certificado raíz está firmado por Microsoft.
- El certificado contiene una clave pública RSA para el controlador.
- El descodificador de software usa la clave pública para enviar al controlador una clave de sesión AES de 128 bits.
- El descodificador de software envía consultas y comandos al canal autenticado.
- La clave de sesión se usa para calcular los códigos de autenticación de mensajes (MAC) para las consultas y comandos. El controlador usa los CONTROLADORES de dominio para comprobar la integridad de los datos de consulta o comando, y el descodificador de software los usa para comprobar la integridad de los datos de respuesta del controlador.
Cifrado de búferes de vídeo comprimidos para el descodificador
Esta es una introducción general de alto nivel del proceso de cifrado y descodificación:
El descodificador de software recibe una secuencia de datos cifrados del origen de vídeo. El descodificador descifra esta secuencia.
El descodificador de software negocia una clave de sesión con la sesión criptográfica.
El descodificador de software usa el canal autenticado para asociar la sesión criptográfica con el dispositivo de descodificador DXVA.
El descodificador de software coloca datos comprimidos en búferes DXVA que obtiene del dispositivo de descodificador DXVA (acelerador). En el caso del contenido protegido, el codificador de software cifra los datos que se colocan en los búferes de DXVA, mediante la clave de sesión para el cifrado.
Nota
Algunos controladores usan una clave de contenido, en lugar de la clave de sesión, para el cifrado. La clave de contenido podría cambiar de un fotograma a otro.
El descodificador envía los búferes comprimidos cifrados al acelerador. Para AES-CTR, el descodificador también pasa el vector de inicialización. Si se usa una clave de contenido, el descodificador pasa la clave de contenido, cifrada mediante la clave de sesión.
Direct3D tiene compatibilidad estándar con AES-CTR de 128 bits, pero está diseñado para ampliarse a tipos de cifrado adicionales.
En las cinco secciones siguientes se proporcionan pasos más detallados.
- 1. Consultar las funcionalidades de protección de contenido del controlador
- 2. Configurar el canal autenticado
- 3. Configurar la sesión criptográfica
- 4. Obtener un identificador para el dispositivo de descodificador DXVA
- 5. Asociar el descodificador DXVA a la sesión criptográfica
1. Consultar las funcionalidades de protección de contenido del controlador
Antes de intentar aplicar el cifrado, obtenga las funcionalidades de protección de contenido del controlador.
- Obtenga un puntero al dispositivo Direct3D 9.
- Llame a QueryInterface para la interfaz IDirect3DDevice9Video .
- Llame a IDirect3DDevice9Video::GetContentProtectionCaps. Este método rellena una estructura D3DCONTENTPROTECTIONCAPS con las funcionalidades de protección de contenido del controlador.
En concreto, busque las siguientes funcionalidades:
- Si el miembro Caps contiene la marca D3DCPCAPS_SOFTWARE o D3DCPCAPS_HARDWARE , el controlador puede realizar el cifrado.
- El miembro KeyExchangeType especifica cómo realizar el intercambio de claves para la clave de sesión.
- Si el miembro Caps contiene la marca D3DCPCAPS_CONTENTKEY , el controlador usa una clave de contenido independiente para el cifrado. Esto es importante al generar la clave de sesión.
Se indican funcionalidades adicionales en el miembro Caps .
2. Configurar el canal autenticado
El siguiente paso consiste en configurar el canal autenticado.
Llame a IDirect3DDevice9Video::CreateAuthenticatedChannel para crear el canal autenticado. Para el parámetro ChannelType , especifique un tipo de canal que coincida con las funciones del controlador.
- El tipo de canal D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE corresponde a D3DCPCAPS_SOFTWARE.
- El tipo de canal D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE corresponde a D3DCPCAPS_HARDWARE.
El método CreateAuthenticatedChannel devuelve un puntero a la interfaz IDirect3DAuthenticatedChannel9 junto con un identificador para el canal. El identificador se usa más adelante para asociar la sesión criptográfica con el canal autenticado.
Llame a IDirect3DAuthenticatedChannel9::GetCertificateSize para obtener el tamaño del certificado X.509 del controlador. Asigne un búfer del tamaño necesario.
Llame a IDirect3DAuthenticatedChannel9::GetCertificate para obtener el certificado. El método copia el certificado en el búfer asignado en el paso anterior.
Compruebe que Microsoft firmó el certificado del controlador y no se ha revocado.
Obtenga la clave pública del certificado.
Genere una clave de sesión RSA aleatoria. Esta clave de sesión se usa para firmar los datos que se envían al canal autenticado. Cifre la clave de sesión mediante la clave pública del controlador.
Llame a IDirect3DAuthenticatedChannel9::NegotiateKeyExchange para enviar la clave de sesión cifrada al controlador.
Inicialice el canal seguro de la siguiente manera:
- Rellene una estructura de D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE como se describe en la documentación.
- Envíe el comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE llamando a IDirect3DAuthenticatedChannel9::Configure tal y como se describe en la sección Envío de comandos de canal autenticados. Este comando contiene los números de secuencia iniciales de los comandos y las consultas que se envían al canal autenticado.
Compruebe el tipo de canal mediante el envío de una consulta de D3DAUTHENTICATEDQUERY_CHANNELTYPE al canal autenticado, tal y como se describe en la sección Envío de consultas de canal autenticadas. Compruebe que el tipo de canal coincide con lo que especificó en el método CreateAuthenticatedChannel .
3. Configurar la sesión criptográfica
A continuación, configure la sesión criptográfica y establezca la clave de sesión.
- Llame a IDirect3DDevice9Video::CreateCryptoSession para crear la sesión criptográfica. Este método devuelve un puntero a la interfaz IDirect3DCryptoSession9 y junto con un identificador para la sesión criptográfica.
- Llame a IDirect3DCryptoSession9::GetCertificateSize para obtener el tamaño del certificado X.509 del controlador. Asigne un búfer del tamaño necesario.
- Llame a IDirect3DCryptoSession9::GetCertificate para obtener el certificado. El método copia el certificado en el búfer asignado en el paso anterior.
- Compruebe que Microsoft firmó el certificado del controlador y no se ha revocado.
- Obtenga la clave pública del certificado.
- Genere una clave de sesión RSA aleatoria. Se trata de una clave de sesión independiente de la clave de sesión del canal autenticado. Cifre la clave de sesión mediante la clave pública del controlador.
- Llame a IDirect3DCryptoSession9::NegotiateKeyExchange para enviar la clave de sesión cifrada al controlador.
- Si las funcionalidades de protección de contenido incluyen D3DCPCAPS_CONTENTKEY, cree una clave de contenido RSA aleatoria. Esto se usará más adelante en el proceso de descodificación.
4. Obtener un identificador para el dispositivo de descodificador DXVA
Para el paso siguiente, necesitará un identificador para el dispositivo de descodificador DXVA. Para obtener este identificador, rellene una estructura de DXVA2_DecodeExecuteParams como se indica a continuación:
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);
Establezca el miembro pExtensionData de la estructura DXVA2_DecodeExecuteParams en la dirección de una estructura de DXVA2_DecodeExtensionData .
En la estructura DXVA2_DecodeExtensionData , establezca el miembro Functionen DXVA2_DECODE_GET_DRIVER_HANDLE. Establezca pPrivateOutputData en la dirección de un búfer lo suficientemente grande como para almacenar un valor HANDLE . (En el ejemplo anterior, este búfer es la variable hDecodeDeviceHandle ).
A continuación, llame a IDirectXVideoDecoder::Execute y pase la dirección de la estructura DXVA2_DecodeExecuteParams . El identificador del descodificador DXVA se devuelve en pPrivateOutputData.
5. Asociar el descodificador DXVA a la sesión criptográfica
A continuación, asocie el dispositivo de descodificador DXVA con el dispositivo Direct3D y la sesión criptográfica, como se indica a continuación:
- Obtenga un identificador para el dispositivo de descodificador DXVA, como se describe en la sección anterior.
- Obtenga un identificador para el dispositivo Direct3D mediante el envío de una consulta de D3DAUTHENTICATEDQUERY_DEVICEHANDLE al canal autenticado.
- Rellene una estructura de D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION con la siguiente información:
- Establezca el miembro DXVA2DecodeHandle en el identificador en el dispositivo de descodificador DXVA.
- Establezca el miembro CryptoSessionHandle en el identificador de la sesión criptográfica. El método IDirect3DDevice9Video::CreateCryptoSession devuelve este identificador.
- Establezca el miembro DeviceHandle en el identificador del dispositivo Direct3D.
- Llame a IDirect3DAuthenticatedChannel9::Configure para enviar un comando D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION al canal autenticado.
En el diagrama siguiente se muestra el intercambio de identificadores:
El descodificador de software ahora puede usar la clave de sesión criptográfica para cifrar los búferes de vídeo comprimidos. Cada búfer comprimido tendrá su propio vector de inicialización (IV) especificado en el miembro pvPVPState de la estructura DXVA2_DecodeBufferDesc .
Envío de comandos de canal autenticados
Se define un conjunto de comandos para configurar el canal autenticado y establecer diversas protecciones de contenido. Para obtener una lista de comandos, consulte Comandos de protección de contenido.
Para enviar un comando al canal autenticado, realice los pasos siguientes.
- Rellene la estructura de datos de entrada. Esta estructura de datos siempre es una estructura de D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT seguida de campos adicionales. Rellene la estructura D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT como se muestra en la tabla siguiente.
Miembro | Descripción |
---|---|
Omac | Omita este campo por ahora. |
ConfigureType | GUID que identifica el comando. Para obtener una lista de comandos, consulte Comandos de protección de contenido. |
hChannel | Identificador del canal autenticado. |
SequenceNumber | El número de secuencia global. El primer número de secuencia se especifica mediante el envío de un comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Cada vez que envíe otro comando, incremente este número en 1. El número de secuencia protege contra los ataques de reproducción.
Nota: Se usan dos números de secuencia independientes, uno para los comandos y otro para las consultas. |
- Calcule la etiqueta OMAC para el bloque de datos que aparece después del miembro omac de la estructura de entrada. A continuación, copie este valor de etiqueta en el miembro omac .
- Llame a IDirect3DAuthenticatedChannel9::Configure.
- El controlador coloca la salida del comando en la estructura D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT .
- Calcule la etiqueta OMAC para el bloque de datos que aparece después del miembro omac de la estructura de salida. Compárelo con el valor del miembro omac . Se produce un error si no coinciden.
- Compare los valores de los miembros ConfigureType, hChannel y SequenceNumber en la estructura de salida con los valores de esos miembros. Se produce un error si no coinciden.
- Incremente el número de secuencia para el comando siguiente.
Envío de consultas de canal autenticadas
Se define un conjunto de consultas para recuperar información sobre el canal autenticado. Para obtener una lista de consultas, consulte Consultas de protección de contenido.
Para enviar un comando al canal autenticado, realice los pasos siguientes.
- Rellene la estructura de datos de entrada. Esta estructura de datos siempre es una estructura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT , posiblemente seguida de campos adicionales. Rellene la estructura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT como se muestra en la tabla siguiente.
Miembro | Descripción |
---|---|
QueryType | GUID que identifica la consulta. Para obtener una lista de consultas, consulte Consultas de protección de contenido. |
hChannel | Identificador del canal autenticado. |
SequenceNumber | El número de secuencia global. El primer número de secuencia se especifica mediante el envío de un comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Cada vez que envíe otra consulta, incremente este número en 1. El número de secuencia protege contra los ataques de reproducción.
Nota: Se usan dos números de secuencia independientes, uno para los comandos y otro para las consultas. |
- Llame a IDirect3DAuthenticatedChannel9::Query.
- El controlador coloca la salida de la consulta en una estructura de D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT . Esta estructura va seguida de campos adicionales, según el tipo de consulta.
- Calcule la etiqueta OMAC para el bloque de datos que aparece después del miembro omac de la estructura de salida. Compárelo con el valor del miembro omac . Se produce un error si no coinciden.
- Compare los valores de los miembros ConfigureType, hChannel y SequenceNumber en la estructura de salida con los valores de esos miembros. Se produce un error si no coinciden.
- Incremente el número de secuencia de la siguiente consulta.