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

В 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:
    • Проверенные реализации загрузки должны предоставлять хэш метаданных версии загрузчику, чтобы загрузчик мог предоставить хэш мастеру ключей.
    • 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 — это выходной параметр, используемый для возврата нового ключевого BLOB-объекта.

Если 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 он также должен быть (и он должен быть устойчивым к откату).

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

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

Для поддержки безопасной доставки информации о версии в ТА в заголовок загрузочного образа было добавлено поле OS_VERSION . Скрипт сборки загрузочного образа автоматически заполняет это поле. OEM-производителям и специалистам по внедрению ключей ТА необходимо совместно модифицировать загрузчики устройств, чтобы извлекать информацию о версии из загрузочного образа и передавать ее в ТА перед загрузкой незащищенной системы. Это гарантирует, что злоумышленники не смогут помешать предоставлению информации о версии 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, но до вызова любых других методов. Если перед конфигурированием вызывается какой-либо другой метод, ТА возвращает ErrorCode::KEYMASTER_NOT_CONFIGURED .

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

Последующие вызовы configure возвращают то же значение, которое было возвращено первым вызовом, и не изменяют состояние мастера ключей. Обратите внимание, что этот процесс ТРЕБУЕТ, чтобы все OTA обновляли как систему, так и загрузочные образы; их нельзя обновить отдельно, чтобы синхронизировать информацию о версии.

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