Привязка версии

В Keymaster 1 все ключи мастера ключей были криптографически привязаны к корню доверия устройства или ключу проверенной загрузки. В Keymaster 2 и 3 все ключи также привязаны к операционной системе и уровню исправления образа системы. Это гарантирует, что злоумышленник, обнаруживший уязвимость в старой версии системы или программного обеспечения TEE, не сможет откатить устройство до уязвимой версии и использовать ключи, созданные с помощью более новой версии. Кроме того, когда ключ с заданной версией и уровнем исправления используется на устройстве, которое было обновлено до более новой версии или уровня исправления, ключ обновляется, прежде чем его можно будет использовать, а предыдущая версия ключа становится недействительной. Таким образом, по мере обновления устройства ключи *храпового* перемещаются вперед вместе с устройством, но любой возврат устройства к предыдущей версии приводит к тому, что ключи становятся непригодными для использования.

Чтобы поддержать модульную структуру Treble и разорвать привязку system.img к boot.img, Keymaster 4 изменил модель привязки версии ключа, чтобы иметь отдельные уровни исправлений для каждого раздела. Это позволяет обновлять каждый раздел независимо, сохраняя при этом защиту от отката.

В Android 9 boot , system и vendor разделы имеют свой собственный уровень исправлений.

  • Устройства с проверенной загрузкой Android (AVB) могут поместить все уровни исправлений и версию системы в vbmeta, чтобы загрузчик мог предоставить их Keymaster. Для связанных разделов информация о версии раздела находится в связанном файле vbmeta. Как правило, информация о версии должна находиться в vbmeta struct , содержащей данные проверки (хэш или хеш-дерево) для данного раздела.
  • На устройствах без AVB:
    • Реализации проверенной загрузки должны предоставлять хэш метаданных версии загрузчику, чтобы загрузчик мог предоставить хеш Keymaster.
    • boot.img может продолжать хранить уровень патча в заголовке
    • system.img может продолжать хранить уровень исправления и версию ОС в свойствах, доступных только для чтения.
    • vendor.img сохраняет уровень исправления в свойстве ro.vendor.build.version.security_patch , доступном только для чтения.
    • Загрузчик может предоставить хэш всех данных, подтвержденных проверенной загрузкой, мастеру ключей.
  • В Android 9 используйте следующие теги для предоставления информации о версии для следующих разделов:
    • VENDOR_PATCH_LEVEL : раздел vendor
    • BOOT_PATCH_LEVEL : boot раздел.
    • OS_PATCH_LEVEL и OS_VERSION : system раздел. ( OS_VERSION удален из заголовка boot.img .
  • Реализации Keymaster должны обрабатывать все уровни исправлений независимо. Ключи можно использовать, если вся информация о версии соответствует значениям, связанным с ключом, а IKeymaster::upgradeDevice() при необходимости переходит на более высокий уровень исправления.

Изменения HAL

Для поддержки привязки версии и подтверждения версии в Android 7.1 добавлены теги Tag::OS_VERSION и Tag::OS_PATCHLEVEL , а также методы configure и upgradeKey . Теги версии автоматически добавляются реализациями Keymaster 2+ ко всем вновь созданным (или обновленным) ключам. Кроме того, любая попытка использовать ключ, версия ОС или уровень исправления которого не соответствуют текущей версии ОС системы или уровню исправления соответственно, отклоняется с помощью ErrorCode::KEY_REQUIRES_UPGRADE .

Tag::OS_VERSION — это значение UINT , которое представляет основную, дополнительную и дополнительную части версии системы Android в виде MMmmss, где MM — основная версия, mm — дополнительная версия, а ss — дополнительная версия. Например, 6.1.2 будет представлен как 060102.

Tag::OS_PATCHLEVEL — это значение UINT , которое представляет год и месяц последнего обновления системы в формате ГГГГММ, где ГГГГ — это четырехзначный год, а ММ — двузначный месяц. Например, март 2016 года будет представлен как 201603.

ОбновлениеКлюч

Чтобы разрешить обновление ключей до новой версии ОС и уровня исправления образа системы, в Android 7.1 в HAL добавлен метод upgradeKey :

Ключник 3

    upgradeKey(vec keyBlobToUpgrade, vec upgradeParams)
        generates(ErrorCode error, vec upgradedKeyBlob);

Ключник 2

keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev,
    const keymaster_key_blob_t* key_to_upgrade,
    const keymaster_key_param_set_t* upgrade_params,
    keymaster_key_blob_t* upgraded_key);
  • dev — структура устройства
  • keyBlobToUpgrade — ключ, который необходимо обновить.
  • upgradeParams — это параметры, необходимые для обновления ключа. К ним относятся Tag::APPLICATION_ID и Tag::APPLICATION_DATA , которые необходимы для расшифровки ключа, если они были предоставлены во время генерации.
  • upgradedKeyBlob — это выходной параметр, используемый для возврата нового ключевого объекта.

Если upgradeKey вызывается с большим двоичным объектом ключа, который не может быть проанализирован или является недействительным по другой причине, он возвращает ErrorCode::INVALID_KEY_BLOB . Если он вызывается с ключом, уровень исправления которого превышает текущее системное значение, он возвращает ErrorCode::INVALID_ARGUMENT . Если он вызывается с ключом, версия ОС которого больше текущего системного значения, а системное значение не равно нулю, он возвращает ErrorCode::INVALID_ARGUMENT . Допускается обновление версии ОС с ненулевой до нулевой. В случае ошибок связи с защищенным миром он возвращает соответствующее значение ошибки (например, ErrorCode::SECURE_HW_ACCESS_DENIED , ErrorCode::SECURE_HW_BUSY ). В противном случае он возвращает ErrorCode::OK и возвращает новый ключевой объект в upgradedKeyBlob .

keyBlobToUpgrade остается действительным после вызова upgradeKey и теоретически может использоваться снова, если устройство было понижено. На практике хранилище ключей обычно вызывает deleteKey для большого двоичного объекта keyBlobToUpgrade вскоре после вызова upgradeKey . Если keyBlobToUpgrade был тег Tag::ROLLBACK_RESISTANT , то upgradedKeyBlob он также должен быть (и он должен быть устойчив к откату).

Безопасная конфигурация

Чтобы реализовать привязку версии, TA keymaster должен иметь способ безопасно получать текущую версию ОС и уровень исправлений (информацию о версии), а также гарантировать, что получаемая информация строго соответствует информации о работающей системе.

Для поддержки безопасной доставки информации о версии в ТА в заголовок загрузочного образа было добавлено поле OS_VERSION . Скрипт построения загрузочного образа автоматически заполняет это поле. OEM-производителям и разработчикам TA keymaster необходимо работать вместе, чтобы модифицировать загрузчики устройств, чтобы извлечь информацию о версии из загрузочного образа и передать ее TA до загрузки незащищенной системы. Это гарантирует, что злоумышленники не смогут помешать предоставлению информации о версии ТА.

Также необходимо убедиться, что образ системы имеет ту же информацию о версии, что и загрузочный образ. С этой целью в ключевой HAL был добавлен метод configure:

keymaster_error_t (*configure)(const struct keymaster2_device* dev,
  const keymaster_key_param_set_t* params);

Аргумент params содержит Tag::OS_VERSION и Tag::OS_PATCHLEVEL . Этот метод вызывается клиентами keymaster2 после открытия HAL, но перед вызовом любых других методов. Если перед настройкой вызывается какой-либо другой метод, TA возвращает ErrorCode::KEYMASTER_NOT_CONFIGURED .

При первом вызове configure после загрузки устройства он должен убедиться, что предоставленная информация о версии соответствует информации, предоставленной загрузчиком. Если информация о версии не совпадает, configure возвращает ErrorCode::INVALID_ARGUMENT , а все остальные методы мастера ключей продолжают возвращать ErrorCode::KEYMASTER_NOT_CONFIGURED . Если информация совпадает, configure возвращает ErrorCode::OK , и другие методы мастера ключей начинают работать нормально.

Последующие вызовы configure возвращают то же значение, возвращенное первым вызовом, и не меняют состояние мастера ключей.

Поскольку configure вызывается системой, содержимое которой она должна проверить, у злоумышленника есть узкая возможность скомпрометировать образ системы и заставить его предоставить информацию о версии, которая соответствует загрузочному образу, но не является фактической. версия системы. Сочетание проверки загрузочного образа, проверки dm-verity содержимого образа системы и того факта, что configure вызывается на очень раннем этапе загрузки системы, должно затруднить использование этого окна возможностей.