Udostępnij za pośrednictwem


GPU-Based ochrona zawartości

W tym temacie opisano możliwości ochrony zawartości wideo, które może zapewnić sterownik graficzny.

Wprowadzenie

Na poniższym diagramie przedstawiono uproszczony widok sposobu renderowania chronionej zawartości wideo przez potok.

diagram przedstawiający chronioną zawartość wideo.

Nuta

Ścieżka chronionego nośnika (PMP) nie jest przedstawiona na tym diagramie. Przepływ danych przedstawiony w tym miejscu może wystąpić w procesie PMP lub w procesie aplikacji.

Dekoder odbiera zaszyfrowane, skompresowane dane wideo z zewnętrznego źródła. Zakłada się również, że dekoder otrzymuje również klucz kryptograficzny w celu odszyfrowania tych danych. W tym temacie nie opisano wymiany kluczy między źródłem wideo i dekoderem, ale protokół PMP definiuje jeden możliwy mechanizm. Procesor GPU nie jest zaangażowany na tym etapie.

W przypadku dekodowania przyspieszanego sprzętowo dekoder oprogramowania przekazuje skompresowaną zawartość wideo do procesora GPU. Aby chronić tę zawartość, dekoder ponownie szyfruje dane, zazwyczaj przy użyciu AES-CTR, przed przekazaniem go do akceleratora sprzętowego. Mechanizm wymiany kluczy jest definiowany między dekoderem a sterownikiem graficznym.

Zdekodowane ramki wideo są przechowywane w pamięci wideo, ogólnie w czytelnej postaci. W tym momencie ramki są przetwarzane, a następnie prezentowane. Istnieją dwie główne opcje prezentacji.

  • Ramki można prezentować przy użyciu nakładki sprzętowej. Aby uzyskać więcej informacji, zobacz Sprzętowa obsługa nakładek.
  • Ramki mogą być prezentowane przez zarządzanie oknami pulpitu (DWM) przy użyciu powierzchni udostępnionej.

Ostatnim krokiem jest wyświetlenie ramki na monitorze, która może wymagać ochrony połączenia między kartą graficzną a urządzeniem wyświetlania. Przykładem ochrony linków jest High-Bandwidth Digital Content Protection (HDCP). Ochrona łączy jest konfigurowana przy użyciu programu Output Protection Manager (OPM). W tym temacie nie opisano platformy OPM; Aby uzyskać więcej informacji, zobacz Using Output Protection Manager.

Omówienie procesu dekodowania

Podczas dekodowania przyspieszanego sprzętowo dekoder oprogramowania musi przekazać skompresowane dane wideo do karty graficznej. W przypadku zawartości w warstwie Premium te dane muszą być zwykle szyfrowane przy użyciu szyfrowania kluczem symetrycznym, zanim zostaną wysłane do procesora GPU.

Aby zaszyfrować wideo na potrzeby dekodowania, dekoder oprogramowania używa następujących interfejsów:

diagram przedstawiający interfejsy dekodowania direct3d9.

Wszystkie te interfejsy są uzyskiwane z urządzenia Direct3D w następujący sposób:

Interfejs Kreacja
IDirectXVideoDecoder Wywołaj IDirectXVideoDecoderService::CreateVideoDecoder. Urządzenie dekodera DXVA jest identyfikowane przez identyfikator GUID profilu DXVA.
IDirect3DCryptoSession9 Wywołaj IDirect3DDevice9Video::CreateCryptoSession.
IDirect3DAuthenticatedChannel9 Wywołaj IDirect3DDevice9Video::CreateAuthenticatedChannel.

Nuta

Aby uzyskać wskaźnik do interfejsu IDirect3DDevice9Video, wywołaj QueryInterface na urządzeniu D3D9Ex.

Uwierzytelniony kanał zapewnia zaufany kanał komunikacyjny między dekoderem oprogramowania a sterownikiem. Kanał komunikacyjny działa w następujący sposób:

  • Sterownik udostępnia łańcuch certyfikatów X.509, którego certyfikat główny jest podpisany przez firmę Microsoft.
  • Certyfikat zawiera klucz publiczny RSA dla sterownika.
  • Dekoder oprogramowania używa klucza publicznego do wysyłania sterownika 128-bitowego klucza sesji AES.
  • Dekoder oprogramowania wysyła zapytania i polecenia do uwierzytelnioowanego kanału.
  • Klucz sesji służy do obliczania kodów uwierzytelniania komunikatów (MACs) dla zapytań i poleceń. Sterownik używa macs do zweryfikowania integralności danych zapytania/polecenia, a dekoder oprogramowania używa ich do zweryfikowania integralności danych odpowiedzi ze sterownika.

Szyfrowanie skompresowanych wideo dla dekodera

Poniżej przedstawiono ogólne omówienie procesu szyfrowania i dekodowania:

  1. Dekoder oprogramowania odbiera strumień zaszyfrowanych danych ze źródła wideo. Dekoder odszyfrowuje ten strumień.

  2. Dekoder oprogramowania negocjuje klucz sesji z sesją kryptograficzną.

  3. Dekoder oprogramowania używa uwierzytelnionych kanałów do skojarzenia sesji kryptograficznych z urządzeniem dekodera DXVA.

  4. Dekoder oprogramowania umieszcza skompresowane dane w DXVA pobieranych z urządzenia dekodera DXVA (akcelerator). W przypadku zawartości chronionej koder oprogramowania szyfruje dane wprowadzane do DXVA przy użyciu klucza sesji na potrzeby szyfrowania.

    Nuta

    Niektóre sterowniki używają klucza zawartości zamiast klucza sesji do szyfrowania. Klucz zawartości może zmienić się z jednej ramki na następną.

  5. Dekoder przesyła zaszyfrowane skompresowane do akceleratora. W przypadku AES-CTR dekoder przekazuje również wektor inicjowania. Jeśli używany jest klucz zawartości, dekoder przekazuje klucz zawartości zaszyfrowany przy użyciu klucza sesji.

Direct3D ma standardową obsługę 128-bitowej AES-CTR, ale ma na celu rozszerzenie na dodatkowe typy szyfrowania.

W kolejnych pięciu sekcjach przedstawiono bardziej szczegółowe kroki.

1. Wykonywanie zapytań dotyczących możliwości ochrony zawartości sterownika

Przed podjęciem próby zastosowania szyfrowania uzyskaj możliwości ochrony zawartości sterownika.

  1. Pobierz wskaźnik do urządzenia Direct3D 9.
  2. Wywołaj QueryInterface dla interfejsu IDirect3DDevice9Video.
  3. Wywołaj IDirect3DDevice9Video::GetContentProtectionCaps. Ta metoda wypełnia strukturę D3DCONTENTPROTECTIONCAPS z funkcjami ochrony zawartości sterownika.

W szczególności poszukaj następujących możliwości:

  • Jeśli element członkowski caps zawiera flagę D3DCPCAPS_SOFTWARE lub D3DCPCAPS_HARDWARE, sterownik może wykonać szyfrowanie.
  • Element członkowski KeyExchangeType określa sposób wykonywania wymiany kluczy dla klucza sesji.
  • Jeśli element członkowski caps zawiera flagę D3DCPCAPS_CONTENTKEY, sterownik używa oddzielnego klucza zawartości do szyfrowania. Jest to ważne podczas generowania klucza sesji.

Dodatkowe możliwości są wskazywane w caps elementu członkowskiego.

2. Skonfiguruj uwierzytelniony kanał

Następnym krokiem jest skonfigurowanie uwierzytelnioowanego kanału.

  1. Wywołaj IDirect3DDevice9Video::CreateAuthenticatedChannel, aby utworzyć uwierzytelniony kanał. Dla parametru ChannelType określ typ kanału pasujący do możliwości sterownika.

    • Typ kanału D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE odpowiada D3DCPCAPS_SOFTWARE.
    • Typ kanału D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE odpowiada D3DCPCAPS_HARDWARE.

    Metoda CreateAuthenticatedChannel zwraca wskaźnik do interfejsu IDirect3DAuthenticatedChannel9IDirect3DAuthenticatedChannel9 wraz z uchwytem do kanału. Dojście jest używane później do skojarzenia sesji kryptograficznych z uwierzytelniony kanał.

  2. Wywołaj IDirect3DAuthenticatedChannel9::GetCertificateSize, aby uzyskać rozmiar certyfikatu X.509 sterownika. Przydziel bufor wymaganego rozmiaru.

  3. Wywołaj IDirect3DAuthenticatedChannel9::GetCertificate, aby pobrać certyfikat. Metoda kopiuje certyfikat do buforu przydzielonego w poprzednim kroku.

  4. Sprawdź, czy certyfikat sterownika został podpisany przez firmę Microsoft i nie został odwołany.

  5. Pobierz klucz publiczny z certyfikatu.

  6. Generowanie losowego klucza sesji RSA. Ten klucz sesji służy do podpisywania danych wysyłanych do uwierzytelnionego kanału. Szyfruj klucz sesji przy użyciu klucza publicznego sterownika.

  7. Wywołaj IDirect3DAuthenticatedChannel9::NegotiateKeyExchange, aby wysłać zaszyfrowany klucz sesji do sterownika.

  8. Zainicjuj bezpieczny kanał w następujący sposób:

    1. Wypełnij strukturę D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE zgodnie z opisem w dokumentacji.
    2. Wyślij polecenie D3DAUTHENTICATEDCONFIGURE_INITIALIZE, wywołując IDirect3DAuthenticatedChannel9::Configure zgodnie z opisem w sekcji wysyłanie uwierzytelnionych poleceń kanału. To polecenie zawiera numery sekwencji początkowej dla poleceń i zapytań wysyłanych do uwierzytelnioowanego kanału.
  9. Sprawdź typ kanału, wysyłając zapytanie D3DAUTHENTICATEDQUERY_CHANNELTYPE do uwierzytelnionego kanału, zgodnie z opisem w sekcji Wysyłanie uwierzytelnionych zapytań kanału. Sprawdź, czy typ kanału jest zgodny z określonymi w metodzie CreateAuthenticatedChannel.

3. Konfigurowanie sesji kryptograficznych

Następnie skonfiguruj sesję kryptograficzną i ustanów klucz sesji.

  1. Wywołaj IDirect3DDevice9Video::CreateCryptoSession, aby utworzyć sesję kryptograficzną. Ta metoda zwraca wskaźnik do interfejsu IDirect3DCryptoSession9 oraz uchwyt sesji kryptograficznych.
  2. Wywołaj IDirect3DCryptoSession9::GetCertificateSize, aby uzyskać rozmiar certyfikatu X.509 sterownika. Przydziel bufor wymaganego rozmiaru.
  3. Wywołaj IDirect3DCryptoSession9::GetCertificate, aby pobrać certyfikat. Metoda kopiuje certyfikat do buforu przydzielonego w poprzednim kroku.
  4. Sprawdź, czy certyfikat sterownika został podpisany przez firmę Microsoft i nie został odwołany.
  5. Pobierz klucz publiczny z certyfikatu.
  6. Generowanie losowego klucza sesji RSA. Jest to oddzielny klucz sesji od uwierzytelnionego klucza sesji kanału. Szyfruj klucz sesji przy użyciu klucza publicznego sterownika.
  7. Wywołaj IDirect3DCryptoSession9::NegotiateKeyExchange, aby wysłać zaszyfrowany klucz sesji do sterownika.
  8. Jeśli możliwości ochrony zawartości obejmują D3DCPCAPS_CONTENTKEY, utwórz losowy klucz zawartości RSA. Będzie to używane w dalszej części procesu dekodowania.

4. Pobieranie uchwytu do urządzenia dekodera DXVA

W następnym kroku będziesz potrzebować dojścia do urządzenia dekodera DXVA. Aby uzyskać ten uchwyt, wypełnij strukturę DXVA2_DecodeExecuteParams w następujący sposób:

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

Ustaw element pExtensionData struktury DXVA2_DecodeExecuteParams na adres struktury DXVA2_DecodeExtensionData.

W strukturze DXVA2_DecodeExtensionData ustaw element członkowski funkcji na wartość DXVA2_DECODE_GET_DRIVER_HANDLE. Ustaw pPrivateOutputData adres buforu, który jest wystarczająco duży, aby przechowywać wartość HANDLE. (W poprzednim przykładzie ten bufor jest zmienną hDecodeDeviceHandle).

Następnie wywołaj IDirectXVideoDecoder::Execute i przekaż adres struktury DXVA2_DecodeExecuteParams. Uchwyt do dekodera DXVA jest zwracany w pPrivateOutputData.

5. Skojarz dekoder DXVA z sesją kryptograficzną

Następnie skojarz urządzenie dekodera DXVA z urządzeniem Direct3D i sesją kryptograficzną w następujący sposób:

  1. Pobierz dojście do urządzenia dekodera DXVA zgodnie z opisem w poprzedniej sekcji.
  2. Pobierz dojście do urządzenia Direct3D, wysyłając zapytanie D3DAUTHENTICATEDQUERY_DEVICEHANDLE do uwierzytelnionego kanału.
  3. Wypełnij strukturę D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION następującymi informacjami:
    • Ustaw element członkowski DXVA2DecodeHandle na dojście do urządzenia dekodera DXVA.
    • Ustaw element członkowski CryptoSessionHandle na uchwyt sesji kryptograficznej. Ten uchwyt jest zwracany przez metodę IDirect3DDevice9Video::CreateCryptoSession.
    • Ustaw element członkowski DeviceHandle na uchwyt urządzenia Direct3D.
  4. Wywołaj IDirect3DAuthenticatedChannel9::Configure w celu wysłania polecenia D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION do uwierzytelnionego kanału.

Na poniższym diagramie przedstawiono wymianę dojść:

diagram przedstawiający sposób skojarzenia dekodera dxva z sesją kryptograficzną.

Dekoder oprogramowania może teraz używać klucza sesji kryptograficznego do szyfrowania skompresowanych wideo. Każdy skompresowany bufor będzie miał własny wektor inicjalizacji (IV) określony w pvPVPState składowej struktury DXVA2_DecodeBufferDesc.

Wysyłanie uwierzytelnionych poleceń kanału

Zestaw poleceń jest definiowany do konfigurowania uwierzytelnionego kanału i ustawiania różnych ochrony zawartości. Aby uzyskać listę poleceń, zobacz polecenia ochrony zawartości.

Aby wysłać polecenie do uwierzytelnionego kanału, wykonaj następujące kroki.

  1. Wypełnij strukturę danych wejściowych. Ta struktura danych jest zawsze strukturą D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT, po której następują dodatkowe pola. Wypełnij strukturę D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT, jak pokazano w poniższej tabeli.
Członek Opis
omac Pomiń to pole na razie.
ConfigureType Identyfikator GUID identyfikujący polecenie. Aby uzyskać listę poleceń, zobacz polecenia ochrony zawartości.
hChannel Dojście do uwierzytelnioowanego kanału.
SequenceNumber Numer sekwencji. Pierwszy numer sekwencji jest określony przez wysłanie D3DAUTHENTICATEDCONFIGURE_INITIALIZE polecenia. Za każdym razem, gdy wysyłasz kolejne polecenie, zwiększ tę liczbę o 1. Numer sekwencji chroni przed atakami powtarzania. Uwaga: są używane dwa oddzielne numery sekwencji, jeden dla poleceń i jeden dla zapytań.
  1. Oblicz tag OMAC dla bloku danych wyświetlanych po omac składowej struktury wejściowej. Następnie skopiuj tę wartość tagu do elementu członkowskiego omac.
  2. Wywołaj IDirect3DAuthenticatedChannel9::Configure.
  3. Sterownik umieszcza dane wyjściowe polecenia w strukturze D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT.
  4. Oblicz tag OMAC dla bloku danych wyświetlanych po omac składowej struktury danych wyjściowych. Porównaj to z wartością elementu członkowskiego omac. Niepowodzenie, jeśli nie są zgodne.
  5. Porównaj wartości elementów członkowskich ConfigureType, hChanneli elementy członkowskie SequenceNumber w strukturze danych wyjściowych względem wartości tych elementów członkowskich. Niepowodzenie, jeśli nie są zgodne.
  6. Zwiększ numer sekwencji dla następnego polecenia.

Wysyłanie uwierzytelnionych zapytań kanału

Zestaw zapytań jest definiowany na potrzeby pobierania informacji o uwierzytelnianym kanale. Aby uzyskać listę zapytań, zobacz Zapytania ochrony zawartości.

Aby wysłać polecenie do uwierzytelnionego kanału, wykonaj następujące kroki.

  1. Wypełnij strukturę danych wejściowych. Ta struktura danych jest zawsze strukturą D3DAUTHENTICATEDCHANNEL_QUERY_INPUT, po której mogą znajdować się dodatkowe pola. Wypełnij strukturę D3DAUTHENTICATEDCHANNEL_QUERY_INPUT, jak pokazano w poniższej tabeli.
Członek Opis
QueryType Identyfikator GUID identyfikujący zapytanie. Aby uzyskać listę zapytań, zobacz Zapytania ochrony zawartości.
hChannel Dojście do uwierzytelnioowanego kanału.
SequenceNumber Numer sekwencji. Pierwszy numer sekwencji jest określony przez wysłanie D3DAUTHENTICATEDCONFIGURE_INITIALIZE polecenia. Za każdym razem, gdy wysyłasz kolejne zapytanie, zwiększ tę liczbę o 1. Numer sekwencji chroni przed atakami powtarzania. Uwaga: są używane dwa oddzielne numery sekwencji, jeden dla poleceń i jeden dla zapytań.
  1. Wywołaj IDirect3DAuthenticatedChannel9::Query.
  2. Sterownik umieszcza dane wyjściowe zapytania w strukturze D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT. Po tej strukturze znajdują się dodatkowe pola, w zależności od typu zapytania.
  3. Oblicz tag OMAC dla bloku danych wyświetlanych po omac składowej struktury danych wyjściowych. Porównaj to z wartością elementu członkowskiego omac. Niepowodzenie, jeśli nie są zgodne.
  4. Porównaj wartości elementów członkowskich ConfigureType, hChanneli elementy członkowskie SequenceNumber w strukturze danych wyjściowych względem wartości tych elementów członkowskich. Niepowodzenie, jeśli nie są zgodne.
  5. Zwiększ numer sekwencji dla następnego zapytania.

interfejsy API wideo Direct3D 9