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


Отправка запросов состояния COPP

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Чтобы отправить запрос о состоянии протокола COPP, заполните структуру AMCOPPStatusInput данными запроса. Элементы структуры:

  • rApp. 128-разрядное случайное число, введенное в виде GUID. В ответе драйвера возвращается тот же номер. Следует выделить случайное число в куче, а затем скопировать его в структуру. Это защищает от атак, когда злоумышленник изменяет содержимое структуры AMCOPPStatusInput .
  • guidStatusRequestID. Идентификатор GUID, идентифицирующий запрос. См. справочник по запросам COPP.
  • dwSequence. Порядковый номер состояния. Увеличьте это значение после каждого запроса состояния. (В разделе Инициализация сеанса COPP это значение отображается как uStatusSeq в примерах кода.)
  • cbSizeData. Размер (в байтах) всех дополнительных данных, необходимых для запроса.
  • StatusData. Данные для запроса состояния.

Передайте структуру AMCOPPStatusInput методу IAMCertifiedOutputProtection::P rotectionStatus . Например, следующий код отправляет запрос состояния, который запрашивает доступные механизмы защиты:

AMCOPPStatusInput input;
AMCOPPStatusOutput output;

// Create a 128-bit random number.
GUID *pGuid = new GUID();
if (pGuid == NULL)
{
    // Handle out-of-memory condition.
}
CryptGenRandom(hCSP, sizeof(GUID), (BYTE*)pGuid);  

// Copy the random number into the command structure.
memcpy(&input.rApp, pGuid, sizeof(GUID));

// Fill in the other data.
input.guidStatusRequestID = DXVA_COPPQueryProtectionType; // Request type.
input.dwSequence = uStatusSeq;  // Status sequence number.
input.cbSizeData = 0            // No other data for this query.

// Send the request.
hr = pCOPP->ProtectionStatus(&input, &output);

// Increment the sequence number each time.
++uStatusSeq;

Ответ записывается в элемент COPPStatus структуры AMCOPPStatusOutput . Размер допустимых данных в ответе указан в элементе cbSizeData . Чтобы обеспечить целостность сообщения, драйвер вычисляет код проверки подлинности сообщения (MAC) с помощью алгоритма OMAC 1 и возвращает это значение в элементе macKDI структуры. Приложение должно проверить это значение следующим образом:

  1. Вычислите тег OMAC для блока данных, который отображается после элемента macKDI структуры AMCOPPStatusOutput (другими словами, cbSizeData плюс COPPStatus).
  2. Сравните этот тег со значением в macKDI, используя прямую метку memcmp.

Алгоритм OMAC 1 подробно описан на странице https://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html. COPP использует следующие параметры OMAC-1:

  • E = AES
  • t = 128 бит

Данные, возвращаемые из запроса состояния, всегда начинаются с двух элементов:

  • То же значение rApp , которое было передано приложением. Убедитесь, что это значение совпадает с исходным значением, хранящимся в куче.
  • Значение COPP_StatusFlags , указывающее, изменилось ли состояние защиты выходных данных.

Так как подключение может быть потеряно или перенастроено, приложение должно периодически опрашивать драйвер на наличие текущего состояния. Если установлен флаг COPP_RenegotiationRequired, приложение должно попытаться сбросить уровень защиты. Если установлен флаг COPP_LinkLost, приложение должно прекратить воспроизведение содержимого. Например, флаг COPP_LinkLost может быть возвращен, так как пользователь отключил выходной соединитель. Приложение должно освободить текущий экземпляр VMR, создать новый экземпляр VMR и установить новый сеанс COPP (включая обмен ключами и проверку сертификатов).

Использование сертифицированного протокола защиты вывода (COPP)