Защита содержимого GPU-Based
В этом разделе описываются возможности защиты видеоконтента, которые может предоставить графический драйвер.
- Введение
- Общие сведения о процессе декодирования
- Шифрование сжатых буферов видео для декодера
- Отправка команд канала, прошедших проверку подлинности
- Отправка запросов канала с проверкой подлинности
- Связанные темы
Введение
На следующей схеме показано упрощенное представление того, как защищенное видеоконтент проходит через конвейер для отрисовки.
Примечание
Защищенный путь к носителю (PMP) не показан на этой схеме. Поток данных, показанный здесь, может происходить в рамках процесса PMP или процесса приложения.
Декодер получает зашифрованные сжатые видеоданные из внешнего источника. Предполагается, что декодер также получает криптографический ключ для расшифровки этих данных. В этом разделе не описывается обмен ключами между источником видео и декодером, но PMP определяет один из возможных механизмов. Gpu не используется на данном этапе.
Для аппаратного ускорения декодирования программный декодер передает сжатое видеосодержимое в GPU. Для защиты этого содержимого декодер повторно шифрует данные, как правило, с помощью AES-CTR, прежде чем передавать их в аппаратный ускоритель. Механизм обмена ключами определяется между декодером и графическим драйвером.
Декодированные видеокадры хранятся в видеопамяти, как правило, в чистом виде. На этом этапе кадры обрабатываются и отображаются. Существует два main варианта представления.
- Кадры можно представить с помощью аппаратного наложения. Дополнительные сведения см. в разделе Поддержка аппаратного перекрытия.
- Кадры можно представить с помощью управления окном рабочего стола (DWM) с помощью общей поверхности.
Последним шагом является отображение кадра на мониторе, что может потребовать защиты связи между графическим карта и устройством отображения. Примером защиты ссылок является High-Bandwidth Защита цифрового содержимого (HDCP). Защита ссылок настраивается с помощью диспетчера защиты выходных данных (OPM). В этом разделе не описывается OPM; Дополнительные сведения см. в разделе Использование диспетчера защиты выходных данных.
Общие сведения о процессе декодирования
Во время аппаратного ускорения декодирования программный декодер должен передавать сжатые видеоданные в графические карта. Для содержимого уровня "Премиум" эти данные, как правило, должны быть зашифрованы с помощью шифрования с симметричным ключом перед отправкой в GPU.
Чтобы зашифровать видео для декодирования, программный декодер использует следующие интерфейсы:
- IDirectXVideoDecoder. Представляет устройство декодера DXVA, также называемое ускорителем.
- IDirect3DCryptoSession9. Представляет сеанс шифрования, предоставляющий ключ шифрования.
- IDirect3DAuthenticatedChannel9. Представляет канал, прошедший проверку подлинности, который позволяет декодеру программного обеспечения связать сеанс шифрования с декодером DXVA.
Все эти интерфейсы получены с устройства Direct3D следующим образом:
Интерфейс | Создание |
---|---|
IDirectXVideoDecoder | Вызовите метод IDirectXVideoDecoderService::CreateVideoDecoder. Устройство декодера DXVA идентифицируется по GUID профиля DXVA. |
IDirect3DCryptoSession9 | Вызовите метод IDirect3Device9Video::CreateCryptoSession. |
IDirect3DAuthenticatedChannel9 | Вызовите метод IDirect3DDevice9Video::CreateAuthenticatedChannel. |
Примечание
Чтобы получить указатель на интерфейс IDirect3Ddevice9Video , вызовите QueryInterface на устройстве D3D9Ex.
Канал, прошедший проверку подлинности, предоставляет доверенный канал связи между декодером программного обеспечения и драйвером. Канал связи работает следующим образом:
- Драйвер предоставляет цепочку сертификатов X.509, корневой сертификат которой подписан корпорацией Майкрософт.
- Сертификат содержит открытый ключ RSA для драйвера.
- Программный декодер использует открытый ключ для отправки драйверу 128-разрядного ключа сеанса AES.
- Программный декодер отправляет запросы и команды в канал, прошедший проверку подлинности.
- Ключ сеанса используется для вычисления кодов проверки подлинности сообщений (MAC) для запросов и команд. Драйвер использует macs для проверки целостности данных запроса или команды, а декодер программного обеспечения использует их для проверки целостности данных ответа от драйвера.
Шифрование сжатых буферов видео для декодера
Ниже приведен общий обзор процесса шифрования и декодирования.
Программный декодер получает поток зашифрованных данных из источника видео. Декодер расшифровывает этот поток.
Программный декодер согласовывает ключ сеанса с сеансом шифрования.
Программный декодер использует канал, прошедший проверку подлинности, для связывания сеанса шифрования с устройством декодера DXVA.
Программный декодер помещает сжатые данные в буферы DXVA, которые он получает с устройства декодера DXVA (ускоритель). Для защищенного содержимого программный кодировщик шифрует данные, помещаемые в буферы DXVA, используя сеансовый ключ для шифрования.
Примечание
Некоторые драйверы используют для шифрования ключ содержимого вместо ключа сеанса. Ключ содержимого может меняться от одного кадра к другому.
Декодер отправляет зашифрованные сжатые буферы в ускоритель. Для AES-CTR декодер также передает вектор инициализации. Если используется ключ содержимого, декодер передает ключ содержимого, зашифрованный с помощью сеансового ключа.
Direct3D имеет стандартную поддержку 128-разрядных AES-CTR, но предназначен для расширения до дополнительных типов шифрования.
В следующих пяти разделах приведены более подробные инструкции.
- 1. Запрос возможностей защиты содержимого драйвера
- 2. Настройка канала с проверкой подлинности
- 3. Настройка сеанса шифрования
- 4. Получение дескриптора для устройства декодера DXVA
- 5. Связывание декодера DXVA с сеансом шифрования
1. Запрос возможностей защиты содержимого драйвера
Перед попыткой применить шифрование получите возможности защиты содержимого драйвера.
- Получение указателя на устройство Direct3D 9.
- Вызовите QueryInterface для интерфейса IDirect3DDevice9Video .
- Вызовите IDirect3DDevice9Video::GetContentProtectionCaps. Этот метод заполняет структуру D3DCONTENTPROTECTIONCAPS возможностями защиты содержимого драйвера.
В частности, найдите следующие возможности:
- Если элемент CAPS содержит флаг D3DCPCAPS_SOFTWARE или D3DCPCAPS_HARDWARE , драйвер может выполнять шифрование.
- Член KeyExchangeType указывает, как выполнять обмен ключами для ключа сеанса.
- Если элемент Caps содержит флаг D3DCPCAPS_CONTENTKEY , драйвер использует отдельный ключ содержимого для шифрования. Это важно при создании ключа сеанса.
Дополнительные возможности указаны в элементе Caps .
2. Настройка канала с проверкой подлинности
Следующим шагом является настройка канала, прошедшего проверку подлинности.
Вызовите IDirect3DDevice9Video::CreateAuthenticatedChannel , чтобы создать канал, прошедший проверку подлинности. Для параметра ChannelType укажите тип канала, соответствующий возможностям драйвера.
- Тип канала D3DAUTHENTICATEDCHANNEL_DRIVER_SOFTWARE соответствует D3DCPCAPS_SOFTWARE.
- Тип канала D3DAUTHENTICATEDCHANNEL_DRIVER_HARDWARE соответствует D3DCPCAPS_HARDWARE.
Метод CreateAuthenticatedChannel возвращает указатель на интерфейс IDirect3DAuthenticatedChannel9 , а также дескриптор канала. Дескриптор используется позже для связывания сеанса шифрования с каналом, прошедшим проверку подлинности.
Вызовите метод IDirect3DAuthenticatedChannel9::GetCertificateSize , чтобы получить размер сертификата X.509 драйвера. Выделите буфер требуемого размера.
Вызовите метод IDirect3DAuthenticatedChannel9::GetCertificate , чтобы получить сертификат. Метод копирует сертификат в буфер, выделенный на предыдущем шаге.
Убедитесь, что сертификат драйвера подписан корпорацией Майкрософт и не был отозван.
Получите открытый ключ из сертификата.
Создайте случайный ключ сеанса RSA. Этот ключ сеанса используется для подписывания данных, отправляемых в канал, прошедший проверку подлинности. Зашифруйте ключ сеанса с помощью открытого ключа драйвера.
Вызовите метод IDirect3DAuthenticatedChannel9::NegotiateKeyExchange , чтобы отправить зашифрованный ключ сеанса драйверу.
Инициализируйте безопасный канал следующим образом:
- Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGUREINITIALIZE , как описано в документации.
- Отправьте команду D3DAUTHENTICATEDCONFIGURE_INITIALIZE , вызвав метод IDirect3DAuthenticatedChannel9::Configure , как описано в разделе Отправка команд канала, прошедших проверку подлинности. Эта команда содержит начальные порядковые номера для команд и запросов, отправляемых в канал, прошедший проверку подлинности.
Проверьте тип канала, отправив запрос D3DAUTHENTICATEDQUERY_CHANNELTYPE в канал, прошедший проверку подлинности, как описано в разделе Отправка запросов канала, прошедших проверку подлинности. Убедитесь, что тип канала соответствует указанному в методе CreateAuthenticatedChannel .
3. Настройка сеанса шифрования
Затем настройте сеанс шифрования и установите ключ сеанса.
- Вызовите IDirect3DDevice9Video::CreateCryptoSession , чтобы создать сеанс шифрования. Этот метод возвращает указатель на интерфейс IDirect3DCryptoSession9 и дескриптор на криптографический сеанс.
- Вызовите метод IDirect3DCryptoSession9::GetCertificateSize , чтобы получить размер сертификата X.509 драйвера. Выделите буфер требуемого размера.
- Вызовите IDirect3DCryptoSession9::GetCertificate , чтобы получить сертификат. Метод копирует сертификат в буфер, выделенный на предыдущем шаге.
- Убедитесь, что сертификат драйвера подписан корпорацией Майкрософт и не был отозван.
- Получите открытый ключ из сертификата.
- Создайте случайный ключ сеанса RSA. Это отдельный ключ сеанса от ключа сеанса канала, прошедшего проверку подлинности. Зашифруйте ключ сеанса с помощью открытого ключа драйвера.
- Вызовите метод IDirect3DCryptoSession9::NegotiateKeyExchange , чтобы отправить зашифрованный ключ сеанса драйверу.
- Если возможности защиты содержимого включают 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 и криптографическим сеансом следующим образом:
- Получите дескриптор устройства декодера DXVA, как описано в предыдущем разделе.
- Получите дескриптор для устройства Direct3D, отправив запрос D3DAUTHENTICATEDQUERY_DEVICEHANDLE в канал, прошедший проверку подлинности.
- Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGURECRYPTOSESSION следующими сведениями:
- Задайте для элемента DXVA2DecodeHandle дескриптор устройства декодера DXVA.
- Присвойте члену CryptoSessionHandle дескриптор криптографического сеанса. Этот дескриптор возвращается методом IDirect3Device9Video::CreateCryptoSession .
- Задайте для элемента DeviceHandle дескриптор устройства Direct3D.
- Вызовите метод IDirect3DAuthenticatedChannel9::Configure , чтобы отправить команду D3DAUTHENTICATEDCONFIGURE_CRYPTOSESSION в канал, прошедший проверку подлинности.
На следующей схеме показан обмен дескрипторами:
Программный декодер теперь может использовать ключ сеанса шифрования для шифрования сжатых буферов видео. Каждый сжатый буфер будет иметь собственный вектор инициализации (IV), указанный в элементе pvPVPStateструктуры DXVA2_DecodeBufferDesc .
Отправка команд канала, прошедших проверку подлинности
Набор команд определяется для настройки канала, прошедшего проверку подлинности, и настройки различных средств защиты содержимого. Список команд см. в разделе Команды защиты содержимого.
Чтобы отправить команду в канал, прошедший проверку подлинности, выполните следующие действия.
- Заполните структуру входных данных. Эта структура данных всегда представляет собой D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT структуру, за которой следуют дополнительные поля. Заполните структуру D3DAUTHENTICATEDCHANNEL_CONFIGURE_INPUT , как показано в следующей таблице.
Член | Описание |
---|---|
omac | Пока пропустите это поле. |
ConfigureType | GUID, идентифицирующий команду. Список команд см. в разделе Команды защиты содержимого. |
hChannel | Дескриптор канала, прошедшего проверку подлинности. |
SequenceNumber | Порядковый номер. Первый порядковый номер указывается путем отправки команды D3DAUTHENTICATEDCONFIGURE_INITIALIZE . При каждой отправке другой команды увеличиваете это число на 1. Порядковый номер защищает от атак воспроизведения.
Примечание: Используются два отдельных порядковых номера: один для команд и один для запросов. |
- Вычислите тег OMAC для блока данных, который отображается после элемента omac входной структуры. Затем скопируйте это значение тега в элемент omac .
- Вызовите IDirect3DAuthenticatedChannel9::Configure.
- Драйвер помещает выходные данные команды в структуру D3DAUTHENTICATEDCHANNEL_CONFIGURE_OUTPUT .
- Вычислите тег OMAC для блока данных, который отображается после элемента omac выходной структуры. Сравните это со значением элемента omac . Сбой, если они не совпадают.
- Сравните значения элементов ConfigureType, hChannel и SequenceNumber в выходной структуре со значениями для этих элементов. Сбой, если они не совпадают.
- Увеличить порядковый номер для следующей команды.
Отправка запросов канала, прошедших проверку подлинности
Набор запросов определяется для получения сведений о канале, прошедшем проверку подлинности. Список запросов см. в разделе Запросы защиты содержимого.
Чтобы отправить команду в канал, прошедший проверку подлинности, выполните следующие действия.
- Заполните структуру входных данных. Эта структура данных всегда является D3DAUTHENTICATEDCHANNEL_QUERY_INPUT структурой, за которой, возможно, следуют дополнительные поля. Заполните структуру D3DAUTHENTICATEDCHANNEL_QUERY_INPUT , как показано в следующей таблице.
Член | Описание |
---|---|
QueryType | GUID, идентифицирующий запрос. Список запросов см. в разделе Запросы защиты содержимого. |
hChannel | Дескриптор канала, прошедшего проверку подлинности. |
SequenceNumber | Порядковый номер. Первый порядковый номер указывается путем отправки команды D3DAUTHENTICATEDCONFIGURE_INITIALIZE . Каждый раз, когда вы отправляете другой запрос, увеличиваете это число на 1. Порядковый номер защищает от атак воспроизведения.
Примечание: Используются два отдельных порядковых номера: один для команд и один для запросов. |
- Вызовите IDirect3DAuthenticatedChannel9::Query.
- Драйвер помещает выходные данные запроса в D3DAUTHENTICATEDCHANNEL_QUERY_OUTPUT структуру. За этой структурой следуют дополнительные поля в зависимости от типа запроса.
- Вычислите тег OMAC для блока данных, который отображается после элемента omac выходной структуры. Сравните это со значением элемента omac . Сбой, если они не совпадают.
- Сравните значения элементов ConfigureType, hChannel и SequenceNumber в выходной структуре со значениями для этих элементов. Сбой, если они не совпадают.
- Увеличить порядковый номер для следующего запроса.