GPU-Based Protezione contenuto

Questo argomento descrive le funzionalità di protezione dei contenuti video che un driver grafico può fornire.

Introduzione

Il diagramma seguente mostra una visualizzazione semplificata del modo in cui il contenuto video protetto viene eseguito tramite la pipeline da eseguire.

diagramma che mostra il contenuto video protetto.

Nota

Il percorso multimediale protetto (PMP) non è illustrato in questo diagramma. Il flusso di dati visualizzato qui potrebbe verificarsi all'interno di un processo PMP o all'interno di un processo dell'applicazione.

Il decodificatore riceve dati video crittografati e compressi da un'origine esterna. Si presuppone anche che il decodificatore riceva anche una chiave crittografica per decrittografare questi dati. Questo argomento non descrive lo scambio di chiavi tra l'origine video e il decodificatore, ma il PMP definisce un meccanismo possibile. La GPU non è coinvolta in questa fase.

Per la decodifica hardware accelerata, il decodificatore software passa contenuto video compresso alla GPU. Per proteggere questo contenuto, il decodificatore crittografa nuovamente i dati, in genere usando AES-CTR, prima di passarlo all'acceleratore hardware. Un meccanismo di scambio delle chiavi è definito tra il decodificatore e il driver grafico.

I fotogrammi video decodificati vengono archiviati in memoria video, in genere in chiaro. A questo punto, i fotogrammi vengono elaborati e quindi presentati. Esistono due opzioni principali per la presentazione.

  • I fotogrammi possono essere presentati usando una sovrapposizione hardware. Per altre informazioni, vedere Supporto sovrimpressione hardware.
  • I fotogrammi possono essere presentati da Gestione finestra desktop (DWM) usando una superficie condivisa.

L'ultimo passaggio consiste nel visualizzare la cornice sul monitor, che può richiedere la protezione del collegamento tra la scheda grafica e il dispositivo di visualizzazione. Un esempio di protezione dei collegamenti è High-Bandwidth Digital Content Protection (HDCP). La protezione dei collegamenti è configurata con Output Protection Manager (OPM). Questo argomento non descrive OPM; per altre informazioni, vedere Uso di Output Protection Manager.

Panoramica del processo di decodifica

Durante la decodifica hardware accelerata, il decodificatore software deve passare i dati video compressi alla scheda grafica. Per il contenuto Premium, questi dati in genere devono essere crittografati, usando la crittografia simmetrica della chiave, prima di inviarli alla GPU.

Per crittografare il video per la decodifica, il decodificatore software usa le interfacce seguenti:

diagramma che mostra le interfacce di decodifica direct3d9.

Tutte queste interfacce vengono ottenute dal dispositivo Direct3D, come indicato di seguito:

Interfaccia Creazione
IDirectXVideoDecoder Chiamare IDirectXVideoDecoderService::CreateVideoDecoder. Il dispositivo decodificatore DXVA è identificato da un GUID del profilo DXVA.
IDirect3DCryptoSession9 Chiamare IDirect3DDevice9Video::CreateCryptoSession.
IDirect3DAuthenticatedChannel9 Chiamare IDirect3DDevice9Video::CreateAuthenticatedChannel.

Nota

Per ottenere un puntatore all'interfaccia IDirect3DDevice9Video , chiamare QueryInterface in un dispositivo D3D9Ex.

Il canale autenticato fornisce un canale di comunicazione attendibile tra il decodificatore software e il driver. Il canale di comunicazione funziona come indicato di seguito:

  • Il driver fornisce una catena di certificati X.509 il cui certificato radice è firmato da Microsoft.
  • Il certificato contiene una chiave pubblica RSA per il driver.
  • Il decodificatore software usa la chiave pubblica per inviare il driver a una chiave di sessione AES a 128 bit.
  • Il decodificatore software invia query e comandi al canale autenticato.
  • La chiave di sessione viene usata per calcolare i codici di autenticazione dei messaggi per le query e i comandi. Il driver usa i controller di rete per verificare l'integrità dei dati query/comando e il decodificatore software li usa per verificare l'integrità dei dati di risposta dal driver.

Crittografia dei buffer video compressi per il decodificatore

Ecco una panoramica generale del processo di crittografia e decodifica:

  1. Il decodificatore software riceve un flusso di dati crittografati dall'origine video. Il decodificatore decrittografa questo flusso.

  2. Il decodificatore software negozia una chiave di sessione con la sessione crittografica.

  3. Il decodificatore software usa il canale autenticato per associare la sessione crittografica al dispositivo decodificatore DXVA.

  4. Il decodificatore software inserisce i dati compressi nei buffer DXVA che ottiene dal dispositivo decodificatore DXVA (acceleratore). Per il contenuto protetto, il codificatore software crittografa i dati inseriti nei buffer DXVA, usando la chiave di sessione per la crittografia.

    Nota

    Alcuni driver usano una chiave di contenuto, anziché la chiave di sessione, per la crittografia. La chiave di contenuto potrebbe cambiare da un frame al successivo.

  5. Il decodificatore invia i buffer compressi crittografati all'acceleratore. Per AES-CTR, il decodificatore passa anche il vettore di inizializzazione. Se viene usata una chiave di contenuto, il decodificatore passa la chiave del contenuto, crittografata usando la chiave di sessione.

Direct3D ha il supporto standard per AES-CTR a 128 bit, ma è progettato per estendere a tipi di crittografia aggiuntivi.

Le cinque sezioni successive forniscono passaggi più dettagliati.

1. Eseguire query sulle funzionalità di protezione del contenuto del driver

Prima di tentare di applicare la crittografia, ottenere le funzionalità di protezione del contenuto del driver.

  1. Ottenere un puntatore al dispositivo Direct3D 9.
  2. Chiamare QueryInterface per l'interfaccia IDirect3DDevice9Video .
  3. Chiamare IDirect3DDevice9Video::GetContentProtectionCaps. Questo metodo riempie una struttura D3DCONTENTPROTECTIONCAPS con le funzionalità di protezione del contenuto del driver.

In particolare, cercare le funzionalità seguenti:

  • Se il membro Caps contiene il flag D3DCPCAPS_SOFTWARE o D3DCPCAPS_HARDWARE , il driver può eseguire la crittografia.
  • Il membro KeyExchangeType specifica come eseguire lo scambio di chiavi per la chiave di sessione.
  • Se il membro Caps contiene il flag D3DCPCAPS_CONTENTKEY , il driver usa una chiave di contenuto separata per la crittografia. Questo è importante quando si genera la chiave di sessione.

Le funzionalità aggiuntive sono indicate nel membro Caps .

2. Configurare il canale autenticato

Il passaggio successivo consiste nel configurare il canale autenticato.

  1. Chiama IDirect3DDevice9Video::CreateAuthenticatedChannel per creare il canale autenticato. Per il parametro ChannelType specificare un tipo di canale corrispondente alle funzionalità del driver.

    • Il tipo di canale D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE corrisponde a D3DCPCAPS_SOFTWARE.
    • Il tipo di canale D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE corrisponde a D3DCPCAPS_HARDWARE.

    Il metodo CreateAuthenticatedChannel restituisce un puntatore all'interfaccia IDirect3DAuthenticatedChannel9 insieme a un handle per il canale. L'handle viene usato in un secondo momento per associare la sessione di crittografia al canale autenticato.

  2. Chiamare IDirect3DAuthenticatedChannel9::GetCertificateSize per ottenere le dimensioni del certificato X.509 del driver. Allocare un buffer delle dimensioni necessarie.

  3. Chiamare IDirect3DAuthenticatedChannel9::GetCertificate per ottenere il certificato. Il metodo copia il certificato nel buffer allocato nel passaggio precedente.

  4. Verificare che il certificato del driver sia stato firmato da Microsoft e non sia stato revocato.

  5. Ottenere la chiave pubblica dal certificato.

  6. Generare una chiave di sessione RSA casuale. Questa chiave di sessione viene usata per firmare i dati inviati al canale autenticato. Crittografare la chiave di sessione usando la chiave pubblica del driver.

  7. Chiamare IDirect3DAuthenticatedChannel9::NegotiateKeyExchange per inviare la chiave di sessione crittografata al driver.

  8. Inizializzare il canale sicuro come segue:

    1. Compilare una struttura D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE come descritto nella documentazione.
    2. Inviare il comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE chiamando IDirect3DAuthenticatedChannel9::Configure come descritto nella sezione Invio di comandi del canale autenticato. Questo comando contiene i numeri di sequenza iniziale per i comandi e le query inviati al canale autenticato.
  9. Verificare il tipo di canale inviando una query D3DAUTHENTICATEDQUERY_CHANNELTYPE al canale autenticato, come descritto nella sezione Invio di query del canale autenticate. Verificare che il tipo di canale corrisponda a quello specificato nel metodo CreateAuthenticatedChannel .

3. Configurare la sessione di crittografia

Configurare quindi la sessione di crittografia e stabilire la chiave di sessione.

  1. Chiamare IDirect3DDevice9Video::CreateCryptoSession per creare la sessione di crittografia. Questo metodo restituisce un puntatore all'interfaccia IDirect3DCryptoSession9 e un handle per la sessione di crittografia.
  2. Chiamare IDirect3DCryptoSession9::GetCertificateSize per ottenere le dimensioni del certificato X.509 del driver. Allocare un buffer delle dimensioni necessarie.
  3. Chiamare IDirect3DCryptoSession9::GetCertificate per ottenere il certificato. Il metodo copia il certificato nel buffer allocato nel passaggio precedente.
  4. Verificare che il certificato del driver sia stato firmato da Microsoft e non sia stato revocato.
  5. Ottenere la chiave pubblica dal certificato.
  6. Generare una chiave di sessione RSA casuale. Si tratta di una chiave di sessione separata dalla chiave della sessione del canale autenticata. Crittografare la chiave di sessione usando la chiave pubblica del driver.
  7. Chiamare IDirect3DCryptoSession9::NegotiateKeyExchange per inviare la chiave di sessione crittografata al driver.
  8. Se le funzionalità di protezione del contenuto includono D3DCPCAPS_CONTENTKEY, creare una chiave simmetrica RSA casuale. Verrà usato più avanti nel processo di decodifica.

4. Ottenere un handle per il dispositivo decodificatore DXVA

Per il passaggio successivo, è necessario un handle per il dispositivo decodificatore DXVA. Per ottenere questo handle, compilare una struttura DXVA2_DecodeExecuteParams come indicato di seguito:

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

Impostare il membro pExtensionData della struttura DXVA2_DecodeExecuteParams sull'indirizzo di una struttura DXVA2_DecodeExtensionData .

Nella struttura DXVA2_DecodeExtensionData impostare il membro Functionsu DXVA2_DECODE_GET_DRIVER_HANDLE. Impostare pPrivateOutputData sull'indirizzo di un buffer di dimensioni sufficienti per archiviare un valore HANDLE . Nell'esempio precedente questo buffer è la variabile hDecodeDeviceHandle .

Chiama quindi IDirectXVideoDecoder::Execute e passa l'indirizzo della struttura DXVA2_DecodeExecuteParams . L'handle per il decodificatore DXVA viene restituito in pPrivateOutputData.

5. Associare il decodificatore DXVA alla sessione di crittografia

Associare quindi il dispositivo decodificatore DXVA al dispositivo Direct3D e alla sessione di crittografia, come indicato di seguito:

  1. Ottenere un handle per il dispositivo decodificatore DXVA, come descritto nella sezione precedente.
  2. Ottenere un handle per il dispositivo Direct3D inviando una query D3DAUTHENTICATEDQUERY_DEVICEHANDLE al canale autenticato.
  3. Compilare una struttura D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION con le informazioni seguenti:
    • Impostare il membro DXVA2DecodeHandle sull'handle sul dispositivo decodificatore DXVA.
    • Impostare il membro CryptoSessionHandle sull'handle della sessione di crittografia. Questo handle viene restituito dal metodo IDirect3DDevice9Video::CreateCryptoSession .
    • Impostare il membro DeviceHandle sull'handle del dispositivo Direct3D.
  4. Chiamare IDirect3DAuthenticatedChannel9::Configure per inviare un comando D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION al canale autenticato.

Il diagramma seguente illustra lo scambio di handle:

diagramma che mostra come il decodificatore dxva è associato alla sessione di crittografia.

Il decodificatore software può ora usare la chiave di sessione crittografica per crittografare i buffer video compressi. Ogni buffer compresso avrà un proprio vettore di inizializzazione (IV) specificato nel membro pvPVPState della struttura DXVA2_DecodeBufferDesc .

Invio di comandi del canale autenticati

Viene definito un set di comandi per la configurazione del canale autenticato e l'impostazione di varie protezioni del contenuto. Per un elenco dei comandi, vedere Comandi di protezione del contenuto.

Per inviare un comando al canale autenticato, seguire questa procedura.

  1. Compilare la struttura dei dati di input. Questa struttura dei dati è sempre una struttura D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT seguita da campi aggiuntivi. Compilare la struttura D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT come illustrato nella tabella seguente.
Membro Descrizione
Omac Ignorare questo campo per il momento.
ConfigureType GUID che identifica il comando. Per un elenco dei comandi, vedere Comandi di protezione del contenuto.
hChannel Handle per il canale autenticato.
SequenceNumber Numero di sequenza. Il primo numero di sequenza viene specificato inviando un comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Ogni volta che si invia un altro comando, incrementare questo numero di 1. Il numero di sequenza protegge dagli attacchi di riproduzione. Nota: Vengono usati due numeri di sequenza separati, uno per i comandi e uno per le query.
  1. Calcolare il tag OMAC per il blocco di dati visualizzato dopo il membro omac della struttura di input. Copiare quindi questo valore di tag nel membro omac .
  2. Chiamare IDirect3DAuthenticatedChannel9::Configure.
  3. Il driver inserisce l'output del comando nella struttura D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT .
  4. Calcolare il tag OMAC per il blocco di dati visualizzato dopo il membro omac della struttura di output. Confrontarlo con il valore del membro omac . Esito negativo se non corrispondono.
  5. Confrontare i valori dei membri ConfigureType, hChannel e SequenceNumber nella struttura di output con i valori per tali membri. Esito negativo se non corrispondono.
  6. Incrementare il numero di sequenza per il comando successivo.

Invio di query del canale autenticate

Viene definito un set di query per il recupero di informazioni sul canale autenticato. Per un elenco delle query, vedere Query di protezione del contenuto.

Per inviare un comando al canale autenticato, seguire questa procedura.

  1. Compilare la struttura dei dati di input. Questa struttura di dati è sempre una struttura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT , possibilmente seguita da campi aggiuntivi. Compilare la struttura D3DAUTHENTICATEDCHANNEL_QUERY_INPUT come illustrato nella tabella seguente.
Membro Descrizione
QueryType GUID che identifica la query. Per un elenco delle query, vedere Query di protezione del contenuto.
hChannel Handle per il canale autenticato.
SequenceNumber Numero di sequenza. Il primo numero di sequenza viene specificato inviando un comando D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Ogni volta che si invia un'altra query, incrementare questo numero di 1. Il numero di sequenza protegge dagli attacchi di riproduzione. Nota: Vengono usati due numeri di sequenza separati, uno per i comandi e uno per le query.
  1. Chiamare IDirect3DAuthenticatedChannel9::Query.
  2. Il driver inserisce l'output della query in una struttura D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT . Questa struttura è seguita da campi aggiuntivi, a seconda del tipo di query.
  3. Calcolare il tag OMAC per il blocco di dati visualizzato dopo il membro omac della struttura di output. Confrontarlo con il valore del membro omac . Esito negativo se non corrispondono.
  4. Confrontare i valori dei membri ConfigureType, hChannel e SequenceNumber nella struttura di output con i valori per tali membri. Esito negativo se non corrispondono.
  5. Incrementare il numero di sequenza per la query successiva.

API video Direct3D 9