Безопасная реализация MOR

Сводка

  • Поведение MorLock, редакция 2

Последнее обновление

  • Август 2020 г.

Применяется к

  • Windows 10

  • Изготовители оборудования и поставщики BIOS, которые хотят поддерживать функцию Credential Guard Windows 10.

Официальные спецификации

Общие сведения

В этом разделе описывается поведение и использование переменной MemoryOverwriteRequestControlLock UEFI версии 2.

Чтобы предотвратить расширенные атаки на память, в существующей системе улучшена защита bios MemoryOverwriteRequestControl для поддержки блокировки для защиты от новых угроз. Модель угроз расширена, чтобы включить ядро ОС узла в качестве злоумышленника, поэтому службы среды выполнения ACPI и UEFI, выполняемые на уровне привилегий ядра, не являются доверенными. Как и реализации безопасной загрузки, MorLock следует реализовать в привилегированном контексте выполнения встроенного ПО, который не может быть изменен ядром ОС узла (например, режим управления системой, TrustZone, BMC и т. д.). Интерфейс основан на службах переменных UEFI, которые описаны в спецификации UEFI версии 2.5, раздел 7.2 с именем "Службы переменных".

Это устранение рисков, называемое MorLock, должно быть реализовано во всех новых системах, а не только в системах с доверенными платформенными модулями. В редакции 2 добавлена новая возможность разблокировки для снижения проблем с производительностью загрузки, особенно в системах с большим объемом памяти.

Что касается метода управления ACPI _DSM для настройки битового состояния MOR (как описано в разделе 6 спецификации по устранению рисков атак с помощью рабочей группы клиента ПК версии 1.10 (скачать PDF)), рекомендуется удалить этот метод _DSM из современных реализаций BIOS.

Однако если BIOS реализует этот метод _DSM, он должен учитывать состояние MorLock. Если MorLock заблокирован с ключом или без нее, этот метод _DSM не должен изменять MOR и возвращать значение 1, соответствующее "Общий сбой". Для разблокировки MorLock версии 2 не определен механизм ACPI.

Обратите внимание, что Windows не вызывает этот метод _DSM напрямую с Windows 7 и считает его устаревшим. Некоторые BIOS косвенно вызывает этот метод _DSM, когда Windows вызывает ACPI _PTS как реализацию автоматического обнаружения mor для чистого завершения работы (как описано в разделе 2.3 спецификации по устранению рисков для сброса платформы клиента ПК версии 1.10 (скачать PDF)).

Этот acPI _PTS реализации автоматического обнаружения MOR является недостаточным и не должен использоваться.

MemoryOverwriteRequestControlLock

BIOS, содержащий улучшенную меру устранения рисков, создает эту переменную UEFI во время ранней загрузки:

VendorGuid:{BB983CCF-151D-40E1-A07B-4A17BE168292}

Имя:MemoryOverwriteRequestControlLock.

Атрибуты: NV+BS+RT

Значение GetVariable в параметре Data: 0x0 (разблокировано); 0x1 (блокировка без ключа); 0x2 (заблокирован ключом)

Значение SetVariable в параметре Data : 0x0 (разблокировано); 0x1 (заблокировано)

Блокировка с помощью SetVariable

При каждой загрузке BIOS должна инициализироваться MemoryOverwriteRequestControlLock до однобайтового значения 0x00 (указывает на разблокировано) перед этапом выбора загрузочного устройства (BDS) (DRIVER######, SYSPREP####, BOOT####, *RECOVERY*, ...). Для MemoryOverwriteRequestControlLockMemoryOverwriteRequestControl) BIOS должен предотвратить удаление переменной, а атрибуты должны быть закреплены в NV+BS+RT.

При первом вызове метода SetVariable для MemoryOverwriteRequestControlLock путем передачи допустимого ненулевого значения в data режим доступа для обоих MemoryOverwriteRequestControlLock и MemoryOverwriteRequestControl меняется на режим только для чтения, что указывает, что они заблокированы.

Реализации редакции 1 принимают только один байт 0x00 или 0x01 для MemoryOverwriteRequestControlLock.

Редакция 2 также принимает 8-байтовое значение, представляющее общий секретный ключ. Если в SetVariable указано любое другое значение, вызов завершается ошибкой с состоянием EFI_INVALID_PARAMETER. Чтобы создать этот ключ, используйте источник энтропии высокого качества, например доверенный платформенный модуль или аппаратный генератор случайных чисел.

После настройки ключа вызывающий объект и встроенное ПО должны сохранять копии этого ключа в защищенном конфиденциальном расположении, например SMRAM в IA32/X64 или в обработчике службы с защищенным хранилищем.

Получение состояния системы

В редакции 2 при MemoryOverwriteRequestControlLock блокировке переменных и MemoryOverwriteRequestControl вызовы SetVariable (для этих переменных) сначала проверяются на соответствие зарегистрированного ключа с помощью алгоритма постоянного времени. Если оба ключа присутствуют и совпадают, переменные возвращаются в состояние разблокировки. После этой первой попытки или если ключ не зарегистрирован, последующие попытки задать эту переменную завершаются сбоем с EFI_ACCESS_DENIED, чтобы предотвратить атаки методом подбора. В этом случае перезагрузка системы должна быть единственным способом разблокировки переменных.

Операционная система определяет наличие MemoryOverwriteRequestControlLock и его состояние, вызывая Метод GetVariable. Затем система может заблокировать текущее значение , MemoryOverwriteRequestControl задав MemoryOverwriteRequestControlLock значение 0x1. Кроме того, он может указать ключ для включения разблокировки в будущем после безопасной очистки секретных данных из памяти.

Вызов Метода GetVariable для MemoryOverwriteRequestControlLock возвращает 0x0, 0x1 или 0x2, чтобы указать состояние разблокировано, заблокировано без ключа или заблокировано с состоянием ключа.

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

Пример использования операционной системой:

if (gSecretsInMemory)
{
    char data = 0x11;
    SetVariable(MemoryOverwriteRequestControl, sizeof(data), &data);
}

// check presence
status = GetVariable(MemoryOverwriteRequestControlLock, &value);  

if (SUCCESS(status))
{
    // first attempt to lock and establish a key
    // note both MOR and MorLock are locked if successful

    GetRNG(8, keyPtr);
    status = SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

    if (status != EFI_SUCCESS)
    {
        // fallback to revision 1 behavior
        char data = 0x01;
        status = SetVariable(MemoryOverwriteRequestControlLock, 1, &data);
        if (status != EFI_SUCCESS) { // log error, warn user }
    }
}
else
{
    // warn user about potentially unsafe system
}

// put secrets in memory

// … time passes …

// remove secrets from memory, flush caches

SetVariable(MemoryOverwriteRequestControlLock, 8, keyPtr);

Поток реализации MorLock

На этих блок-схемах показано ожидаемое поведение реализации:

Инициализация

инициализация morlock.

Поток SetVariable

Поток программирования morlock.

Поток незаблокированного состояния для SetVariable

разблокированные потоки morlock.

Поток заблокированного состояния для SetVariable

поток morlock locked.

Поток для GetVariable

morlock getvariable.

См. также раздел

Требования UEFI, которые применяются ко всем выпускам Windows на платформах SoC

Спецификация по устранению рисков атак на платформе сброса рабочей группы клиента ПК, версия 1.10 (скачать в формате PDF)

Защита BitLocker от холодных атак (и других угроз)

Обзор за пределами BIOS с поддержкой UEFI TPM2 в EDKII

Защита извлеченных учетных данных домена с помощью Credential Guard

Спецификации UEFI