Хранилище ключей с аппаратной поддержкой

Наличие доверенной среды выполнения в системе на кристалле (SoC) дает возможность устройствам Android предоставлять аппаратные надежные услуги безопасности для ОС Android, службам платформы и даже сторонним приложениям. Разработчики , желающие расширения Android-конкретные должны идти android.security.keystore .

До Android 6.0 в Android уже был простой API-интерфейс криптосервисов с аппаратной поддержкой, предоставляемый версиями 0.2 и 0.3 Keymaster Hardware Abstraction Layer (HAL). Keystore обеспечивает операции цифровой подписи и проверки, а также создание и импорт пар ключей асимметричной подписи. Это уже реализовано на многих устройствах, но есть много целей безопасности, которые не могут быть легко достигнуты с помощью только API подписи. Keystore в Android 6.0 расширяет Keystore API, чтобы предоставить более широкий спектр возможностей.

В Android 6.0, Keystore добавили симметричные криптографические примитивы , AES и HMAC, а также систему контроля доступа для аппаратных поддерживаемых ключей. Контроль доступа указывается во время генерации ключа и применяется в течение всего срока действия ключа. Использование ключей может быть ограничено только после аутентификации пользователя и только для определенных целей или с указанными криптографическими параметрами. Для получения дополнительной информации см авторизации Метки и Функции страницы.

Помимо расширения диапазона криптографических примитивов, Keystore в Android 6.0 добавляет следующее:

  • Схема контроля использования, позволяющая ограничить использование ключей, чтобы снизить риск нарушения безопасности из-за неправильного использования ключей.
  • Схема управления доступом, позволяющая ограничивать ключи указанными пользователями, клиентами и определенным временным диапазоном.

В Android 7.0 в Keymaster 2 добавлена ​​поддержка аттестации ключей и привязки версий. Ключ аттестация предоставляет сертификаты открытых ключей , которые содержат подробное описание ключа и его контроля доступа, чтобы сделать существование ключа в безопасном и конфигурации оборудования удаленно проверяемым.

Версия связывание связывает ключи от операционной системы и версии уровня патча. Это гарантирует, что злоумышленник, обнаруживший слабое место в старой версии системы или программного обеспечения TEE, не сможет откатить устройство до уязвимой версии и использовать ключи, созданные в более новой версии. Кроме того, когда ключ с заданной версией и уровнем исправления используется на устройстве, которое было обновлено до более новой версии или уровня исправления, ключ обновляется до того, как его можно будет использовать, а предыдущая версия ключа становится недействительной. По мере обновления устройства клавиши «храповиком» движутся вперед вместе с устройством, но любое возвращение устройства к предыдущей версии приводит к невозможности использования клавиш.

В Android 8.0 Keymaster 3 перешел от уровня аппаратной абстракции (HAL) старой C-структуры к интерфейсу HAL C ++, сгенерированному на основе определения в новом языке определения аппаратного интерфейса (HIDL). Как часть изменения, изменились многие типы аргументов, хотя типы и методы имеют однозначное соответствие со старыми типами и методами структуры HAL. См Functions страницы для более подробной информации.

В дополнение к этой версии интерфейса, Android 8.0 расширяет функции аттестации Keymaster 2 для поддержки ID аттестации . Аттестация идентификатора предоставляет ограниченный и дополнительный механизм для строгой проверки идентификаторов оборудования, таких как серийный номер устройства, название продукта и идентификатор телефона (IMEI / MEID). Чтобы реализовать это дополнение, измените схему аттестации ASN.1, добавив аттестацию идентификатора. Реализации Keymaster должны найти какой-то безопасный способ извлечения соответствующих элементов данных, а также определить механизм для безопасного и постоянного отключения функции.

В Android 9 обновления включают:

  • Обновление Keymaster 4
  • Поддержка встроенных безопасных элементов
  • Поддержка безопасного импорта ключей
  • Поддержка шифрования 3DES
  • Изменения в привязке версий, так что boot.img и system.img имеют отдельно устанавливаемые версии для обеспечения независимых обновлений.

Глоссарий

Вот краткий обзор компонентов Keystore и их взаимосвязей.

AndroidKeystore является Android Framework API и компонент , используемый приложениями для доступа к функциональности хранилища ключей. Он реализован как расширение стандартных API архитектуры криптографии Java и состоит из кода Java, который выполняется в собственном пространстве процессов приложения. AndroidKeystore выполняет запросы приложения для поведения хранилища ключей, отправляя их в хранилище ключей демона.

Хранилище ключей демон является системным демоном Android , который обеспечивает доступ ко всем функциям хранилища ключей с помощью API Binder . Он отвечает за хранение «ключевых BLOB-объектов», которые содержат фактический материал секретного ключа, зашифрованного, поэтому хранилище ключей может хранить его, но не использовать или раскрывать.

keymasterd является сервером HIDL , который обеспечивает доступ к Keymaster TA. (Это имя не стандартизировано и используется в концептуальных целях.)

Keymaster TA (доверенное приложение) является программным обеспечением , работающим в безопасном контексте, чаще всего в TrustZone на ARM SoC, что обеспечивает все безопасные операции хранилища ключей, имеет доступ к необработанному ключевому материалу, проверяет все условия контроля доступа на ключах , так далее.

LockSettingsService является компонентом Android система отвечает за аутентификацию пользователя, как пароль и отпечаток пальца. Это не часть хранилища ключей, но актуально, потому что многие операции с ключами требуют аутентификации пользователя. LockSettingsService взаимодействует с Gatekeeper TA и отпечатками пальцев ТОЙ , чтобы получить маркеры аутентификации, которые она предоставляет хранилища ключей демона, и которые в конечном счете , потребляемое приложением Keymaster TA.

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

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

Архитектура

Android Keystore API и базовый Keymaster HAL предоставляют базовый, но адекватный набор криптографических примитивов, позволяющих реализовать протоколы с использованием ключей с контролируемым доступом и аппаратной поддержкой.

Keymaster HAL - это предоставляемая производителем оборудования, динамически загружаемая библиотека, используемая службой хранилища ключей для предоставления аппаратных криптографических служб. Для обеспечения безопасности реализации HAL не выполняют никаких конфиденциальных операций в пространстве пользователя или даже в пространстве ядра. Чувствительные операции делегируются защищенному процессору, доступному через некоторый интерфейс ядра. Результирующая архитектура выглядит так:

Доступ к Keymaster

Рисунок 1. Доступ к Keymaster

В устройстве Android «клиент» Keymaster HAL состоит из нескольких уровней (например, приложение, структура, демон Keystore), но это можно игнорировать для целей этого документа. Это означает, что описанный Keymaster HAL API является низкоуровневым, используется внутренними компонентами платформы и не предоставляется разработчикам приложений. API более высокого уровня описывается на сайте разработчиков Android .

Целью Keymaster HAL является не реализация чувствительных к безопасности алгоритмов, а только маршалинг и демаршалинг запросов в безопасный мир. Формат провода определяется реализацией.

Совместимость с предыдущими версиями

Keymaster 1 HAL полностью несовместим с ранее выпущенными HAL, например, Keymaster 0.2 и 0.3. Для облегчения взаимодействия на устройствах под управлением Android 5.0 и более ранних версий, запущенных со старыми HAL Keymaster, Keystore предоставляет адаптер, который реализует Keymaster 1 HAL с вызовами существующей аппаратной библиотеки. Результат не может обеспечить полный набор функций Keymaster 1 HAL. В частности, он поддерживает только алгоритмы RSA и ECDSA, а все действия по авторизации ключей выполняются адаптером в незащищенном мире.

Keymaster 2 дополнительно упрощается интерфейс HAL путем удаления get_supported_* методы и позволяя finish() метод , чтобы принимать входные данные . Это сокращает количество обращений к TEE в тех случаях, когда все входные данные доступны одновременно, и упрощает реализацию дешифрования AEAD.

В Android 8.0 Keymaster 3 перешел от HAL C-структуры старого стиля к интерфейсу HAL C ++, сгенерированному на основе определения в новом языке определения аппаратного интерфейса (HIDL). Реализация HAL нового стиля создается наследование сгенерированного IKeymasterDevice класса и реализации чистых виртуальных методов. В рамках этого изменения были изменены многие типы аргументов, хотя типы и методы имеют однозначное соответствие со старыми типами и методами структуры HAL.

Обзор HIDL

Язык определения аппаратного интерфейса (HIDL) обеспечивает независимый от языка реализации механизм для определения аппаратных интерфейсов. Инструментарий HIDL в настоящее время поддерживает создание интерфейсов C ++ и Java. Ожидается, что большинство разработчиков Trusted Execution Environment (TEE) сочтут инструменты C ++ более удобными, поэтому в этом документе обсуждается только представление C ++.

Интерфейсы HIDL состоят из набора методов, выраженных как:

  methodName(INPUT ARGUMENTS) generates (RESULT ARGUMENTS);

Существуют различные предопределенные типы, и HAL могут определять новые перечислимые и структурные типы. Для получения более подробной информации о HIDL см справочный раздел .

Пример метода из Keymaster 3 IKeymasterDevice.hal является:

generateKey(vec<KeyParameter> keyParams)
        generates(ErrorCode error, vec<uint8_t> keyBlob,
                  KeyCharacteristics keyCharacteristics);

Это эквивалент следующего из HAL keymaster2:

keymaster_error_t (*generate_key)(
        const struct keymaster2_device* dev,
        const keymaster_key_param_set_t* params,
        keymaster_key_blob_t* key_blob,
        keymaster_key_characteristics_t* characteristics);

В версии HIDL, то dev аргумент удаляется, потому что это неявно. Не params аргумент больше не является структура , содержащая указатель , ссылающийся массив key_parameter_t объектов, но vec (вектор) , содержащий KeyParameter объекты. Возвращаемые значения перечислены в « generates » пункт, в том числе вектора uint8_t значений для ключа сгустка.

Виртуальный метод C ++, созданный компилятором HIDL:

Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
                         generateKey_cb _hidl_cb) override;

Где generate_cb это указатель функции определяется как:

std::function<void(ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
                   const KeyCharacteristics& keyCharacteristics)>

То есть, generate_cb это функция , которая принимает возвращаемые значения , указанные в пункте генерировать. Класс реализации HAL переопределяет этот generateKey метод и вызывает generate_cb указатель на функцию возврата результата операции с вызывающим абонентом. Обратите внимание , что вызов функции указатель синхронно. Вызывающий абонент звонит generateKey и generateKey вызывает прилагающийся указатель на функцию, которая выполняет до завершения, возвращая управление generateKey реализации, который затем возвращается к абоненту.

Для подробного примера см реализации по умолчанию в hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp по hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp . Реализация по умолчанию обеспечивает обратную совместимость для устройств с HALS старого стиля keymaster0, keymaster1 или keymaster2.

Контроль доступа

Самым основным правилом управления доступом к хранилищу ключей является то, что каждое приложение имеет собственное пространство имен. Но для каждого правила есть исключения. В хранилище ключей есть несколько жестко запрограммированных карт, которые позволяют определенным компонентам системы получать доступ к определенным другим пространствам имен. Это очень грубый инструмент, поскольку он дает одному компоненту полный контроль над другим пространством имен. И еще есть вопрос о компонентах поставщика в качестве клиентов Keystore. В настоящее время у нас нет возможности создать пространство имен для компонентов поставщика, например, запрашивающего WPA.

Чтобы учесть компоненты поставщика и обобщить контроль доступа без жестко закодированных исключений, Keystore 2.0 вводит домены и пространства имен selinux.

Домены хранилища ключей

С доменами Keystore мы можем отделить пространства имен от uid. Клиенты, обращающиеся к ключу в хранилище ключей, должны указать домен, пространство имен и псевдоним, к которому они хотят получить доступ. На основе этого кортежа и идентификатора вызывающего мы можем определить, к какому ключу вызывающий абонент хочет получить доступ и имеет ли он соответствующие разрешения.

Мы вводим пять параметров домена, которые регулируют доступ к ключам. Они контролируют семантику параметра пространства имен дескриптора ключа и способ управления доступом.

  • DOMAIN_APP : Домен приложения охватывает унаследованное поведение. SPI хранилища ключей Java использует этот домен по умолчанию. Когда используется этот домен, аргумент пространства имен игнорируется и вместо него используется uid вызывающего. Доступ к этому домену контролируется ярлыке хранилища ключей к классу keystore_key в политике SELinux.
  • DOMAIN_SELINUX : Этот домен указывает на то, что пространство имен имеет метку в политике SELinux. Параметр пространства имен просматривается и переводится в нужный контекст, и проверка разрешений выполняется для вызывающего SELinux контекста для keystore_key класса. Когда для данной операции установлено разрешение, для поиска ключа используется полный кортеж.
  • DOMAIN_GRANT : Домен гранта указывает на то, что параметр пространства имен является идентификатором гранта. Параметр псевдонима игнорируется. Проверки Selinux выполняются при создании гранта. Дальнейший контроль доступа только проверяет, совпадает ли uid вызывающего абонента с uid получателя запрошенного гранта.
  • DOMAIN_KEY_ID : Этот домен указует на то, что параметр пространства имен является уникальным идентификатором ключа. Сам ключ может быть создан с DOMAIN_APP или DOMAIN_SELINUX . Проверка разрешения выполняется после того , как domain и namespace , были загружены из базы данных ключей таким же образом , как если бы капля была загружена домена, имен и псевдонимов кортежа. Основанием для ключевого идентификатора домена является непрерывность. При доступе к ключу по псевдониму последующие вызовы могут работать с разными ключами, потому что новый ключ мог быть сгенерирован или импортирован и привязан к этому псевдониму. Однако идентификатор ключа никогда не меняется. Таким образом, при использовании ключа по идентификатору ключа после того, как он был загружен из базы данных хранилища ключей с использованием псевдонима один раз, можно быть уверенным, что это тот же ключ, пока идентификатор ключа все еще существует. Эта функция не предоставляется разработчикам приложений, вместо этого используется в Android Keystore SPI для обеспечения более согласованного взаимодействия даже при одновременном использовании небезопасным способом.
  • DOMAIN_BLOB : Домен блоб указывает на то, что абонент управляет блоб сам по себе. Это используется для клиентов, которым необходимо получить доступ к хранилищу ключей до монтирования раздела данных. Ключ блоб входит в blob поле ключа дескриптора.

Используя домен SELinux, мы можем предоставить компонентам поставщика доступ к очень специфическим пространствам имен хранилища ключей, которые могут совместно использоваться компонентами системы, такими как диалог настроек.

Политика SELinux для keystore_key

Пространство имен метки настраиваются с помощью keystore2_key_context файла.
Каждая строка в этих файлах сопоставляет числовой идентификатор пространства имен метке SELinux. Например,

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share keystore keys.
102            u:object_r:wifi_key:s0

Настроив таким образом новое пространство имен ключей, мы можем предоставить к нему доступ, добавив соответствующую политику. Например, чтобы wpa_supplicant получить и ключи использовать в новом пространстве имен мы могли бы добавить следующую строку в hal_wifi_supplicant.te :

allow hal_wifi_supplicant wifi_keys:keystore2_key { get, use };

После настройки нового пространства имен AndroidKeyStore можно использовать почти как обычно. Единственное отличие состоит в том, что необходимо указать ID пространства имен. Для загрузки и импорта ключей из и в хранилище ключей, то идентификатор пространства имен задаются с помощью AndroidKeyStoreLoadStoreParameter . Например,

import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
import java.security.KeyStore;

KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
keystore.load(new AndroidKeyStoreLoadStoreParameter(102));

Для генерации ключа в заданном пространстве имен, то идентификатор пространства имен должны быть предоставлены с использованием KeyGenParameterSpec.Builder#setNamespace():

import android.security.keystore.KeyGenParameterSpec;
KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder();
specBuilder.setNamespace(102);

Следующие файлы контекста могут использоваться для настройки пространств имен SELinux Keystore 2.0. У каждого раздела есть свой зарезервированный диапазон из 10 000 идентификаторов пространств имен, чтобы избежать конфликтов.

Раздел Диапазон Файлы конфигурации
Система 0 ... 9 999
/system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Расширенная система 10 000 ... 19 999
/system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Продукт 20 000 ... 29 999
/product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Продавец 30 000 ... 39 999
/vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Просит ключ, запрашивая домен SELinux и желаемого виртуального пространства имен, здесь клиент "wifi_keys" , по ее числовым идентификатором.

Выше были определены следующие пространства имен. Там, где они заменяют специальные правила, в следующей таблице указан UID, которому они соответствовали.

ID пространства имен SEPolicy Label UID Описание
0 su_key N / A Ключ суперпользователя. Используется только для тестирования сборок userdebug и eng. Не актуально для пользовательских сборок.
1 shell_key N / A Пространство имен, доступное оболочке. В основном используется для тестирования, но может использоваться и в пользовательских сборках из командной строки.
100 vold_key N / A Предназначен для использования компанией vold.
101 odsing_key N / A Используется демоном подписи на устройстве.
102 wfi_key AID_WIFI (1010) Используется системой Wi-Fi Android, включая wpa_supplicant.
120 resume_on_reboot_key AID_SYSTEM (1000) Используется системным сервером Android для поддержки возобновления при перезагрузке.

Векторы доступа

Класс SELinux keystore_key постарел совсем немного , и некоторые из разрешений, например, verify или sign потеряли свой смысл. Вот новый набор разрешений, keystore2_key , что Keystore 2,0 будет проводить в жизнь.

Разрешение Имея в виду
delete Проверено при удалении ключей из Keystore.
get_info Проверяется при запросе метаданных ключа.
grant Вызывающей стороне требуется это разрешение для создания предоставления ключа в целевом контексте.
manage_blob Абонент может использовать DOMAIN_BLOB на данном SELinux пространстве имен, таким образом , управление сгустки само по себе. Это особенно полезно для vold.
rebind Это разрешение определяет, может ли псевдоним быть повторно привязан к новому ключу. Это требуется для вставки и подразумевает, что ранее связанный ключ будет удален. По сути, это разрешение на вставку, но оно лучше отражает семантику хранилища ключей.
req_forced_op Клиенты с этим разрешением могут создавать невыпадающие операции, и создание операции никогда не завершается ошибкой, если все слоты операций не заняты невыпадающими операциями.
update Требуется для обновления подкомпонента ключа.
use Проверяется при создании операции Keymint, использующей материал ключа, например, для подписи, шифрования / дешифрования.
use_dev_id Требуется при генерации идентификационной информации устройства, такой как аттестация идентификатора устройства.

Кроме того, мы разбиваем из набора ключевых разрешений неспецифического хранилища ключей в SELinux класс безопасности keystore2 :

Разрешение Имея в виду
add_auth Требуется поставщиком аутентификации, таким как Gatekeeper или BiometricsManager, для добавления токенов аутентификации.
clear_ns Ранее clear_uid, это разрешение позволяет не владельцу пространства имен удалять все ключи в этом пространстве имен.
list Требуется системой для перечисления ключей по различным свойствам, таким как владение или ограниченность аутентификации. Это разрешение не требуется вызывающим абонентам, перечисляющим свои собственные пространства имен. Это охватывается get_info разрешения.
lock Это разрешение позволяет заблокировать хранилище ключей, то есть удалить главный ключ, так что связанные с аутентификацией ключи станут непригодными для использования и не могут быть созданы.
reset Это разрешение позволяет сбросить хранилище ключей до заводских значений по умолчанию, удалив все ключи, которые не являются жизненно важными для функционирования операционной системы Android.
unlock Это разрешение требуется, чтобы попытаться разблокировать главный ключ для ключей, привязанных к аутентификации.