Поделиться через


Защита содержимого GPU-Based

В этом разделе описываются возможности защиты видеоконтента, которые может предоставить графический драйвер.

Введение

На следующей схеме показано упрощенное представление того, как защищенное видеоконтент проходит через конвейер для отрисовки.

Схема, показывающая защищенное видеосодержимое.

Примечание

Защищенный путь к носителю (PMP) не показан на этой схеме. Поток данных, показанный здесь, может происходить в рамках процесса PMP или процесса приложения.

Декодер получает зашифрованные сжатые видеоданные из внешнего источника. Предполагается, что декодер также получает криптографический ключ для расшифровки этих данных. В этом разделе не описывается обмен ключами между источником видео и декодером, но PMP определяет один из возможных механизмов. Gpu не используется на данном этапе.

Для аппаратного ускорения декодирования программный декодер передает сжатое видеосодержимое в GPU. Для защиты этого содержимого декодер повторно шифрует данные, как правило, с помощью AES-CTR, прежде чем передавать их в аппаратный ускоритель. Механизм обмена ключами определяется между декодером и графическим драйвером.

Декодированные видеокадры хранятся в видеопамяти, как правило, в чистом виде. На этом этапе кадры обрабатываются и отображаются. Существует два main варианта представления.

  • Кадры можно представить с помощью аппаратного наложения. Дополнительные сведения см. в разделе Поддержка аппаратного перекрытия.
  • Кадры можно представить с помощью управления окном рабочего стола (DWM) с помощью общей поверхности.

Последним шагом является отображение кадра на мониторе, что может потребовать защиты связи между графическим карта и устройством отображения. Примером защиты ссылок является High-Bandwidth Защита цифрового содержимого (HDCP). Защита ссылок настраивается с помощью диспетчера защиты выходных данных (OPM). В этом разделе не описывается OPM; Дополнительные сведения см. в разделе Использование диспетчера защиты выходных данных.

Общие сведения о процессе декодирования

Во время аппаратного ускорения декодирования программный декодер должен передавать сжатые видеоданные в графические карта. Для содержимого уровня "Премиум" эти данные, как правило, должны быть зашифрованы с помощью шифрования с симметричным ключом перед отправкой в GPU.

Чтобы зашифровать видео для декодирования, программный декодер использует следующие интерфейсы:

  • IDirectXVideoDecoder. Представляет устройство декодера DXVA, также называемое ускорителем.
  • IDirect3DCryptoSession9. Представляет сеанс шифрования, предоставляющий ключ шифрования.
  • IDirect3DAuthenticatedChannel9. Представляет канал, прошедший проверку подлинности, который позволяет декодеру программного обеспечения связать сеанс шифрования с декодером DXVA.

Схема, на которую показаны интерфейсы декодирования direct3d9.

Все эти интерфейсы получены с устройства Direct3D следующим образом:

Интерфейс Создание
IDirectXVideoDecoder Вызовите метод IDirectXVideoDecoderService::CreateVideoDecoder. Устройство декодера DXVA идентифицируется по GUID профиля DXVA.
IDirect3DCryptoSession9 Вызовите метод IDirect3Device9Video::CreateCryptoSession.
IDirect3DAuthenticatedChannel9 Вызовите метод IDirect3DDevice9Video::CreateAuthenticatedChannel.

Примечание

Чтобы получить указатель на интерфейс IDirect3Ddevice9Video , вызовите QueryInterface на устройстве D3D9Ex.

Канал, прошедший проверку подлинности, предоставляет доверенный канал связи между декодером программного обеспечения и драйвером. Канал связи работает следующим образом:

  • Драйвер предоставляет цепочку сертификатов X.509, корневой сертификат которой подписан корпорацией Майкрософт.
  • Сертификат содержит открытый ключ RSA для драйвера.
  • Программный декодер использует открытый ключ для отправки драйверу 128-разрядного ключа сеанса AES.
  • Программный декодер отправляет запросы и команды в канал, прошедший проверку подлинности.
  • Ключ сеанса используется для вычисления кодов проверки подлинности сообщений (MAC) для запросов и команд. Драйвер использует macs для проверки целостности данных запроса или команды, а декодер программного обеспечения использует их для проверки целостности данных ответа от драйвера.

Шифрование сжатых буферов видео для декодера

Ниже приведен общий обзор процесса шифрования и декодирования.

  1. Программный декодер получает поток зашифрованных данных из источника видео. Декодер расшифровывает этот поток.

  2. Программный декодер согласовывает ключ сеанса с сеансом шифрования.

  3. Программный декодер использует канал, прошедший проверку подлинности, для связывания сеанса шифрования с устройством декодера DXVA.

  4. Программный декодер помещает сжатые данные в буферы DXVA, которые он получает с устройства декодера DXVA (ускоритель). Для защищенного содержимого программный кодировщик шифрует данные, помещаемые в буферы DXVA, используя сеансовый ключ для шифрования.

    Примечание

    Некоторые драйверы используют для шифрования ключ содержимого вместо ключа сеанса. Ключ содержимого может меняться от одного кадра к другому.

  5. Декодер отправляет зашифрованные сжатые буферы в ускоритель. Для AES-CTR декодер также передает вектор инициализации. Если используется ключ содержимого, декодер передает ключ содержимого, зашифрованный с помощью сеансового ключа.

Direct3D имеет стандартную поддержку 128-разрядных AES-CTR, но предназначен для расширения до дополнительных типов шифрования.

В следующих пяти разделах приведены более подробные инструкции.

1. Запрос возможностей защиты содержимого драйвера

Перед попыткой применить шифрование получите возможности защиты содержимого драйвера.

  1. Получение указателя на устройство Direct3D 9.
  2. Вызовите QueryInterface для интерфейса IDirect3DDevice9Video .
  3. Вызовите IDirect3DDevice9Video::GetContentProtectionCaps. Этот метод заполняет структуру D3DCONTENTPROTECTIONCAPS возможностями защиты содержимого драйвера.

В частности, найдите следующие возможности:

  • Если элемент CAPS содержит флаг D3DCPCAPS_SOFTWARE или D3DCPCAPS_HARDWARE , драйвер может выполнять шифрование.
  • Член KeyExchangeType указывает, как выполнять обмен ключами для ключа сеанса.
  • Если элемент Caps содержит флаг D3DCPCAPS_CONTENTKEY , драйвер использует отдельный ключ содержимого для шифрования. Это важно при создании ключа сеанса.

Дополнительные возможности указаны в элементе Caps .

2. Настройка канала с проверкой подлинности

Следующим шагом является настройка канала, прошедшего проверку подлинности.

  1. Вызовите IDirect3DDevice9Video::CreateAuthenticatedChannel , чтобы создать канал, прошедший проверку подлинности. Для параметра ChannelType укажите тип канала, соответствующий возможностям драйвера.

    • Тип канала D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE соответствует D3DCPCAPS_SOFTWARE.
    • Тип канала D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE соответствует D3DCPCAPS_HARDWARE.

    Метод CreateAuthenticatedChannel возвращает указатель на интерфейс IDirect3DAuthenticatedChannel9 , а также дескриптор канала. Дескриптор используется позже для связывания сеанса шифрования с каналом, прошедшим проверку подлинности.

  2. Вызовите метод IDirect3DAuthenticatedChannel9::GetCertificateSize , чтобы получить размер сертификата X.509 драйвера. Выделите буфер требуемого размера.

  3. Вызовите метод IDirect3DAuthenticatedChannel9::GetCertificate , чтобы получить сертификат. Метод копирует сертификат в буфер, выделенный на предыдущем шаге.

  4. Убедитесь, что сертификат драйвера подписан корпорацией Майкрософт и не был отозван.

  5. Получите открытый ключ из сертификата.

  6. Создайте случайный ключ сеанса RSA. Этот ключ сеанса используется для подписывания данных, отправляемых в канал, прошедший проверку подлинности. Зашифруйте ключ сеанса с помощью открытого ключа драйвера.

  7. Вызовите метод IDirect3DAuthenticatedChannel9::NegotiateKeyExchange , чтобы отправить зашифрованный ключ сеанса драйверу.

  8. Инициализируйте безопасный канал следующим образом:

    1. Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE , как описано в документации.
    2. Отправьте команду D3DAUTHENTICATEDCONFIGURE_INITIALIZE , вызвав метод IDirect3DAuthenticatedChannel9::Configure , как описано в разделе Отправка команд канала, прошедших проверку подлинности. Эта команда содержит начальные порядковые номера для команд и запросов, отправляемых в канал, прошедший проверку подлинности.
  9. Проверьте тип канала, отправив запрос D3DAUTHENTICATEDQUERY_CHANNELTYPE в канал, прошедший проверку подлинности, как описано в разделе Отправка запросов канала, прошедших проверку подлинности. Убедитесь, что тип канала соответствует указанному в методе CreateAuthenticatedChannel .

3. Настройка сеанса шифрования

Затем настройте сеанс шифрования и установите ключ сеанса.

  1. Вызовите IDirect3DDevice9Video::CreateCryptoSession , чтобы создать сеанс шифрования. Этот метод возвращает указатель на интерфейс IDirect3DCryptoSession9 и дескриптор на криптографический сеанс.
  2. Вызовите метод IDirect3DCryptoSession9::GetCertificateSize , чтобы получить размер сертификата X.509 драйвера. Выделите буфер требуемого размера.
  3. Вызовите IDirect3DCryptoSession9::GetCertificate , чтобы получить сертификат. Метод копирует сертификат в буфер, выделенный на предыдущем шаге.
  4. Убедитесь, что сертификат драйвера подписан корпорацией Майкрософт и не был отозван.
  5. Получите открытый ключ из сертификата.
  6. Создайте случайный ключ сеанса RSA. Это отдельный ключ сеанса от ключа сеанса канала, прошедшего проверку подлинности. Зашифруйте ключ сеанса с помощью открытого ключа драйвера.
  7. Вызовите метод IDirect3DCryptoSession9::NegotiateKeyExchange , чтобы отправить зашифрованный ключ сеанса драйверу.
  8. Если возможности защиты содержимого включают D3DCPCAPS_CONTENTKEY, создайте случайный ключ содержимого RSA. Он будет использоваться позже в процессе декодирования.

4. Получение дескриптора для устройства декодера DXVA

Для следующего шага потребуется дескриптор устройства декодера DXVA. Чтобы получить этот дескриптор, заполните структуру DXVA2_DecodeExecuteParams следующим образом:

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

Задайте для элемента pExtensionData структуры DXVA2_DecodeExecuteParams адрес структуры DXVA2_DecodeExtensionData .

В структуре DXVA2_DecodeExtensionData задайте для элемента Функциизначение DXVA2_DECODE_GET_DRIVER_HANDLE. Задайте pPrivateOutputData адрес буфера, который достаточно велик для хранения значения HANDLE . (В предыдущем примере этим буфером является переменная hDecodeDeviceHandle .)

Затем вызовите IDirectXVideoDecoder::Execute и передайте адрес структуры DXVA2_DecodeExecuteParams . Дескриптор DXVA возвращается в pPrivateOutputData.

5. Свяжите декодер DXVA с криптографическим сеансом

Затем свяжите устройство декодера DXVA с устройством Direct3D и криптографическим сеансом следующим образом:

  1. Получите дескриптор устройства декодера DXVA, как описано в предыдущем разделе.
  2. Получите дескриптор для устройства Direct3D, отправив запрос D3DAUTHENTICATEDQUERY_DEVICEHANDLE в канал, прошедший проверку подлинности.
  3. Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION следующими сведениями:
    • Задайте для элемента DXVA2DecodeHandle дескриптор устройства декодера DXVA.
    • Присвойте члену CryptoSessionHandle дескриптор криптографического сеанса. Этот дескриптор возвращается методом IDirect3Device9Video::CreateCryptoSession .
    • Задайте для элемента DeviceHandle дескриптор устройства Direct3D.
  4. Вызовите метод IDirect3DAuthenticatedChannel9::Configure , чтобы отправить команду D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION в канал, прошедший проверку подлинности.

На следующей схеме показан обмен дескрипторами:

схема, показывающая, как декодер dxva связан с криптографическим сеансом.

Программный декодер теперь может использовать ключ сеанса шифрования для шифрования сжатых буферов видео. Каждый сжатый буфер будет иметь собственный вектор инициализации (IV), указанный в элементе pvPVPStateструктуры DXVA2_DecodeBufferDesc .

Отправка команд канала, прошедших проверку подлинности

Набор команд определяется для настройки канала, прошедшего проверку подлинности, и настройки различных средств защиты содержимого. Список команд см. в разделе Команды защиты содержимого.

Чтобы отправить команду в канал, прошедший проверку подлинности, выполните следующие действия.

  1. Заполните структуру входных данных. Эта структура данных всегда представляет собой D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT структуру, за которой следуют дополнительные поля. Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT , как показано в следующей таблице.
Член Описание
omac Пока пропустите это поле.
ConfigureType GUID, идентифицирующий команду. Список команд см. в разделе Команды защиты содержимого.
hChannel Дескриптор канала, прошедшего проверку подлинности.
SequenceNumber Порядковый номер. Первый порядковый номер указывается путем отправки команды D3DAUTHENTICATEDCONFIGURE_INITIALIZE . При каждой отправке другой команды увеличиваете это число на 1. Порядковый номер защищает от атак воспроизведения. Примечание: Используются два отдельных порядковых номера: один для команд и один для запросов.
  1. Вычислите тег OMAC для блока данных, который отображается после элемента omac входной структуры. Затем скопируйте это значение тега в элемент omac .
  2. Вызовите IDirect3DAuthenticatedChannel9::Configure.
  3. Драйвер помещает выходные данные команды в структуру D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT .
  4. Вычислите тег OMAC для блока данных, который отображается после элемента omac выходной структуры. Сравните это со значением элемента omac . Сбой, если они не совпадают.
  5. Сравните значения элементов ConfigureType, hChannel и SequenceNumber в выходной структуре со значениями для этих элементов. Сбой, если они не совпадают.
  6. Увеличить порядковый номер для следующей команды.

Отправка запросов канала, прошедших проверку подлинности

Набор запросов определяется для получения сведений о канале, прошедшем проверку подлинности. Список запросов см. в разделе Запросы защиты содержимого.

Чтобы отправить команду в канал, прошедший проверку подлинности, выполните следующие действия.

  1. Заполните структуру входных данных. Эта структура данных всегда является D3DAUTHENTICATEDCHANNEL_QUERY_INPUT структурой, за которой, возможно, следуют дополнительные поля. Заполните структуру D3DAUTHENTICATEDCHANNEL_QUERY_INPUT , как показано в следующей таблице.
Член Описание
QueryType GUID, идентифицирующий запрос. Список запросов см. в разделе Запросы защиты содержимого.
hChannel Дескриптор канала, прошедшего проверку подлинности.
SequenceNumber Порядковый номер. Первый порядковый номер указывается путем отправки команды D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Каждый раз, когда вы отправляете другой запрос, увеличиваете это число на 1. Порядковый номер защищает от атак воспроизведения. Примечание: Используются два отдельных порядковых номера: один для команд и один для запросов.
  1. Вызовите IDirect3DAuthenticatedChannel9::Query.
  2. Драйвер помещает выходные данные запроса в D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT структуру. За этой структурой следуют дополнительные поля в зависимости от типа запроса.
  3. Вычислите тег OMAC для блока данных, который отображается после элемента omac выходной структуры. Сравните это со значением элемента omac . Сбой, если они не совпадают.
  4. Сравните значения элементов ConfigureType, hChannel и SequenceNumber в выходной структуре со значениями для этих элементов. Сбой, если они не совпадают.
  5. Увеличить порядковый номер для следующего запроса.

API видео Direct3D 9