В 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
вызывается очень рано при загрузке системы, должно затруднить использование этой возможности.