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