Proteção de Conteúdo GPU-Based
Este tópico descreve os recursos de proteção de conteúdo de vídeo que um driver gráfico pode fornecer.
- introdução
- visão geral do processo de decodificação
- Criptografar buffers de vídeo compactados para o decodificador
- enviar comandos de canal autenticado
- enviar consultas de canal autenticado
- tópicos relacionados
Introdução
O diagrama a seguir mostra uma exibição simplificada de como o conteúdo de vídeo protegido viaja pelo pipeline a ser renderizado.
Nota
O PMP ( de Caminho de Mídia Protegido) não é descrito neste diagrama. O fluxo de dados mostrado aqui pode ocorrer dentro de um processo PMP ou em um processo de aplicativo.
O decodificador recebe dados de vídeo criptografados e compactados de uma fonte externa. Supõe-se também que o decodificador também recebe uma chave criptográfica para descriptografar esses dados. Este tópico não descreve a troca de chaves entre a origem do vídeo e o decodificador, mas o PMP define um mecanismo possível. A GPU não está envolvida neste estágio.
Para a decodificação acelerada por hardware, o decodificador de software passa o conteúdo de vídeo compactado para a GPU. Para proteger esse conteúdo, o decodificador criptografa novamente os dados, normalmente usando a AES-CTR, antes de passá-los para o acelerador de hardware. Um mecanismo de troca de chaves é definido entre o decodificador e o driver gráfico.
Quadros de vídeo decodificados são armazenados na memória de vídeo, geralmente na limpeza. Neste ponto, os quadros são processados e, em seguida, apresentados. Há duas opções principais para apresentação.
- Os quadros podem ser apresentados usando uma sobreposição de hardware. Para obter mais informações, consulte suporte à sobreposição de hardware.
- Os quadros podem ser apresentados pelo DWM (Gerenciamento de Janelas da Área de Trabalho) usando uma superfície compartilhada.
A última etapa é exibir o quadro no monitor, o que pode exigir proteção de vínculo entre a placa gráfica e o dispositivo de exibição. Um exemplo de proteção de link é High-Bandwidth HDCP (Proteção de Conteúdo Digital). A proteção de link é configurada usando OPM (Output Protection Manager). Este tópico não descreve o OPM; para obter mais informações, consulte Usando odo Output Protection Manager.
Visão geral do processo de decodificação
Durante a decodificação acelerada por hardware, o decodificador de software deve passar dados de vídeo compactados para a placa gráfica. Para conteúdo premium, esses dados normalmente devem ser criptografados, usando criptografia de chave simétrica, antes de serem enviados para a GPU.
Para criptografar o vídeo para decodificação, o decodificador de software usa as seguintes interfaces:
- IDirectXVideoDecoder . Representa o dispositivo de decodificador DXVA, também chamado de acelerador.
- IDirect3DCryptoSession9 . Representa uma sessão criptográfica, que fornece a chave de criptografia.
- IDirect3DAuthenticatedChannel9 . Representa um canal autenticado, que permite que o decodificador de software associe a sessão criptográfica ao decodificador DXVA.
Todas essas interfaces são obtidas do dispositivo Direct3D, da seguinte maneira:
Interface | Criação |
---|---|
IDirectXVideoDecoder | Chamar IDirectXVideoDecoderService::CreateVideoDecoder. O dispositivo de decodificador DXVA é identificado por um GUID de perfil DXVA. |
IDirect3DCryptoSession9 | Chamar IDirect3DDevice9Video::CreateCryptoSession. |
IDirect3DAuthenticatedChannel9 | Chamar IDirect3DDevice9Video::CreateAuthenticatedChannel. |
Nota
Para obter um ponteiro para a interfaceIDirect3DDevice9Video, chame QueryInterface em um dispositivo D3D9Ex.
O canal autenticado fornece um canal de comunicação confiável entre o decodificador de software e o driver. O canal de comunicação funciona da seguinte maneira:
- O driver fornece uma cadeia de certificados X.509 cujo certificado raiz é assinado pela Microsoft.
- O certificado contém uma chave pública RSA para o driver.
- O decodificador de software usa a chave pública para enviar ao driver uma chave de sessão AES de 128 bits.
- O decodificador de software envia consultas e comandos para o canal autenticado.
- A chave de sessão é usada para calcular os MACs (códigos de autenticação de mensagens) para as consultas e comandos. O driver usa os MACs para verificar a integridade dos dados de consulta/comando e o decodificador de software os usa para verificar a integridade dos dados de resposta do driver.
Criptografando buffers de vídeo compactados para o decodificador
Aqui está uma visão geral de alto nível do processo de criptografia e decodificação:
O decodificador de software recebe um fluxo de dados criptografados da fonte de vídeo. O decodificador descriptografa esse fluxo.
O decodificador de software negocia uma chave de sessão com a sessão criptográfica.
O decodificador de software usa o canal autenticado para associar a sessão criptográfica ao dispositivo de decodificador DXVA.
O decodificador de software coloca dados compactados em buffers DXVA que obtém do dispositivo de decodificador DXVA (acelerador). Para conteúdo protegido, o codificador de software criptografa os dados que são colocados nos buffers DXVA, usando a chave de sessão para a criptografia.
Nota
Alguns drivers usam uma chave de conteúdo, em vez da chave de sessão, para criptografia. A chave de conteúdo pode mudar de um quadro para o outro.
O decodificador envia os buffers compactados criptografados para o acelerador. Para AES-CTR, o decodificador também passa o vetor de inicialização. Se uma chave de conteúdo for usada, o decodificador passará a chave de conteúdo, criptografada usando a chave de sessão.
O Direct3D tem suporte padrão para AES-CTR de 128 bits, mas foi projetado para estender para tipos de criptografia adicionais.
As próximas cinco seções fornecem etapas mais detalhadas.
- 1. Consultar os recursos de proteção de conteúdo do driver
- 2. Configurar o canal autenticado
- 3. Configurar a sessão criptográfica
- 4. Obter um identificador para o dispositivo decodificador DXVA
- 5. Associar o decodificador DXVA ao de Sessão Criptográfica
1. Consultar os recursos de proteção de conteúdo do driver
Antes de tentar aplicar a criptografia, obtenha os recursos de proteção de conteúdo do driver.
- Obtenha um ponteiro para o dispositivo Direct3D 9.
- Chame QueryInterface para a interface deIDirect3DDevice9Video.
- Chamar IDirect3DDevice9Video::GetContentProtectionCaps. Esse método preenche uma estrutura D3DCONTENTPROTECTIONCAPS com os recursos de proteção de conteúdo do driver.
Em particular, procure os seguintes recursos:
- Se o membro Caps contiver o sinalizador D3DCPCAPS_SOFTWARE ou D3DCPCAPS_HARDWARE, o driver poderá executar a criptografia.
- O membro KeyExchangeType especifica como executar a troca de chaves para a chave de sessão.
- Se o membro Caps contiver o sinalizador D3DCPCAPS_CONTENTKEY, o driver usará uma chave de conteúdo separada para criptografia. Isso é importante quando você gera a chave de sessão.
Recursos adicionais são indicados no membro do Caps.
2. Configurar o Canal Autenticado
A próxima etapa é configurar o canal autenticado.
Chame IDirect3DDevice9Video::CreateAuthenticatedChannel para criar o canal autenticado. Para o parâmetro ChannelType, especifique um tipo de canal que corresponda aos recursos do driver.
- O tipo de canal D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE corresponde a D3DCPCAPS_SOFTWARE.
- O tipo de canal D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE corresponde a D3DCPCAPS_HARDWARE.
O método CreateAuthenticatedChannel retorna um ponteiro para a interface deIDirect3DAuthenticatedChannel9, juntamente com um identificador para o canal. O identificador é usado posteriormente para associar a sessão criptográfica ao canal autenticado.
Chame IDirect3DAuthenticatedChannel9::GetCertificateSize para obter o tamanho do certificado X.509 do driver. Aloque um buffer do tamanho necessário.
Chame IDirect3DAuthenticatedChannel9::GetCertificate para obter o certificado. O método copia o certificado para o buffer que foi alocado na etapa anterior.
Verifique se o certificado do driver foi assinado pela Microsoft e se não foi revogado.
Obtenha a chave pública do certificado.
Gere uma chave de sessão RSA aleatória. Essa chave de sessão é usada para assinar dados enviados para o canal autenticado. Criptografe a chave de sessão usando a chave pública do driver.
Chame IDirect3DAuthenticatedChannel9::NegotiateKeyExchange para enviar a chave de sessão criptografada para o driver.
Inicialize o canal seguro da seguinte maneira:
- Preencha uma estrutura D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE conforme descrito na documentação.
- Envie o comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE chamando IDirect3DAuthenticatedChannel9::Configure conforme descrito na seção Envio de Comandos de Canal Autenticado. Esse comando contém os números de sequência inicial para os comandos e consultas que são enviados para o canal autenticado.
Verifique o tipo de canal enviando uma consulta D3DAUTHENTICATEDQUERY_CHANNELTYPE para o canal autenticado, conforme descrito na seção Envio de Consultas de Canal Autenticado. Verifique se o tipo de canal corresponde ao que você especificou no métodoCreateAuthenticatedChannel.
3. Configurar a Sessão Criptográfica
Em seguida, configure a sessão criptográfica e estabeleça a chave de sessão.
- Chame IDirect3DDevice9Video::CreateCryptoSession para criar a sessão criptográfica. Esse método retorna um ponteiro para a interface deIDirect3DCryptoSession9 e, juntamente com um identificador para a sessão criptográfica.
- Chame IDirect3DCryptoSession9::GetCertificateSize para obter o tamanho do certificado X.509 do driver. Aloque um buffer do tamanho necessário.
- Chame IDirect3DCryptoSession9::GetCertificate para obter o certificado. O método copia o certificado para o buffer que foi alocado na etapa anterior.
- Verifique se o certificado do driver foi assinado pela Microsoft e se não foi revogado.
- Obtenha a chave pública do certificado.
- Gere uma chave de sessão RSA aleatória. Essa é uma chave de sessão separada da chave de sessão do canal autenticado. Criptografe a chave de sessão usando a chave pública do driver.
- Chame IDirect3DCryptoSession9::NegotiateKeyExchange para enviar a chave de sessão criptografada para o driver.
- Se os recursos de proteção de conteúdo incluirem D3DCPCAPS_CONTENTKEY, crie uma chave de conteúdo RSA aleatória. Isso será usado posteriormente no processo de decodificação.
4. Obter um identificador para o dispositivo de decodificador DXVA
Para a próxima etapa, você precisará de um identificador para o dispositivo de decodificador DXVA. Para obter esse identificador, preencha uma estrutura de DXVA2_DecodeExecuteParams da seguinte maneira:
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);
Defina o pExtensionData membro da estrutura DXVA2_DecodeExecuteParams como o endereço de uma estrutura DXVA2_DecodeExtensionData.
Na estrutura DXVA2_DecodeExtensionData, defina o membro da Função como DXVA2_DECODE_GET_DRIVER_HANDLE. Defina pPrivateOutputData para o endereço de um buffer grande o suficiente para armazenar um valor de HANDLE. (No exemplo anterior, esse buffer é a variável hDecodeDeviceHandle.)
Em seguida, chame IDirectXVideoDecoder::Execute e passe o endereço da estrutura DXVA2_DecodeExecuteParams. O identificador para o decodificador DXVA é retornado em pPrivateOutputData.
5. Associar o decodificador DXVA à Sessão Criptográfica
Em seguida, associe o dispositivo de decodificador DXVA ao dispositivo Direct3D e à sessão criptográfica, da seguinte maneira:
- Obtenha um identificador para o dispositivo decodificador DXVA, conforme descrito na seção anterior.
- Obtenha um identificador para o dispositivo Direct3D enviando uma consulta D3DAUTHENTICATEDQUERY_DEVICEHANDLE para o canal autenticado.
- Preencha uma estrutura de D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION com as seguintes informações:
- Defina o membro DXVA2DecodeHandle para o identificador para o dispositivo de decodificador DXVA.
- Defina o membro CryptoSessionHandle como o identificador para a sessão criptográfica. Esse identificador é retornado pelo métodoIDirect3DDevice9Video::CreateCryptoSession.
- Defina o membro DeviceHandle para o identificador de dispositivo Direct3D.
- Chame IDirect3DAuthenticatedChannel9::Configure para enviar um comando D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION para o canal autenticado.
O diagrama a seguir ilustra a troca de identificadores:
O decodificador de software agora pode usar a chave de sessão criptográfica para criptografar os buffers de vídeo compactados. Cada buffer compactado terá seu próprio IV (vetor de inicialização) especificado no pvPVPState membro da estrutura DXVA2_DecodeBufferDesc.
Enviando comandos de canal autenticado
Um conjunto de comandos é definido para configurar o canal autenticado e definir várias proteções de conteúdo. Para obter uma lista de comandos, consulte Comandos de Proteção de Conteúdo.
Para enviar um comando para o canal autenticado, execute as etapas a seguir.
- Preencha a estrutura de dados de entrada. Essa estrutura de dados é sempre uma estrutura D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT seguida por campos adicionais. Preencha a estrutura D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT conforme mostrado na tabela a seguir.
Membro | Descrição |
---|---|
omac | Ignore este campo por enquanto. |
ConfigureType | GUID que identifica o comando. Para obter uma lista de comandos, consulte Comandos de Proteção de Conteúdo. |
hChannel | O identificador para o canal autenticado. |
SequenceNumber | O número da sequência. O primeiro número de sequência é especificado enviando um comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE. Cada vez que você enviar outro comando, incremente esse número em 1. O número de sequência protege contra ataques de repetição.
Observação: Dois números de sequência separados são usados, um para comandos e outro para consultas. |
- Calcule a marca OMAC para o bloco de dados que aparece após o omac membro da estrutura de entrada. Em seguida, copie esse valor de marca para o membro omac do.
- Chame IDirect3DAuthenticatedChannel9::Configure.
- O driver coloca a saída do comando na estrutura de D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT.
- Calcule a marca OMAC para o bloco de dados que aparece após o omac membro da estrutura de saída. Compare isso com o valor do membro omac do. Falhar se eles não corresponderem.
- Compare os valores dos membros ConfigureType, hChannele SequenceNumber na estrutura de saída em relação aos seus valores para esses membros. Falhar se eles não corresponderem.
- Incremente o número de sequência para o próximo comando.
Enviando consultas de canal autenticado
Um conjunto de consultas é definido para recuperar informações sobre o canal autenticado. Para obter uma lista de consultas, consulte Consultas de Proteção de Conteúdo.
Para enviar um comando para o canal autenticado, execute as etapas a seguir.
- Preencha a estrutura de dados de entrada. Essa estrutura de dados é sempre uma estrutura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT, possivelmente seguida por campos adicionais. Preencha a estrutura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT conforme mostrado na tabela a seguir.
Membro | Descrição |
---|---|
queryType | GUID que identifica a consulta. Para obter uma lista de consultas, consulte Consultas de Proteção de Conteúdo. |
hChannel | O identificador para o canal autenticado. |
SequenceNumber | O número da sequência. O primeiro número de sequência é especificado enviando um comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE. Cada vez que você enviar outra consulta, incremente esse número em 1. O número de sequência protege contra ataques de repetição.
Observação: Dois números de sequência separados são usados, um para comandos e outro para consultas. |
- Chamar IDirect3DAuthenticatedChannel9::Query.
- O driver coloca a saída da consulta em uma estrutura de D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT. Essa estrutura é seguida por campos adicionais, dependendo do tipo de consulta.
- Calcule a marca OMAC para o bloco de dados que aparece após o omac membro da estrutura de saída. Compare isso com o valor do membro omac do. Falhar se eles não corresponderem.
- Compare os valores dos membros ConfigureType, hChannele SequenceNumber na estrutura de saída em relação aos seus valores para esses membros. Falhar se eles não corresponderem.
- Incremente o número de sequência para a próxima consulta.
Tópicos relacionados
-
APIs de vídeo do Direct3D 9