Функции KeyMint

На этой странице приведены дополнительные сведения и рекомендации для помощи разработчикам уровня абстракции оборудования KeyMint (HAL). Основной документацией для HAL является спецификация интерфейса AIDL .

Неправильное использование API

Вызывающие могут создавать ключи KeyMint с авторизациями, которые допустимы как параметры API, но которые делают полученные ключи небезопасными или непригодными для использования. Реализации KeyMint не обязаны давать сбой в таких случаях или выдавать диагностику. Использование слишком маленьких ключей, указание нерелевантных входных параметров, повторное использование IV или одноразовых значений, генерация ключей без назначения (следовательно, бесполезных) и тому подобное не должны диагностироваться реализациями.

Приложения, фреймворк и Android Keystore отвечают за то, чтобы вызовы модулей KeyMint были разумными и полезными.

точка входа addRngEntropy

Точка входа addRngEntropy добавляет предоставленную вызывающей стороной энтропию в пул, используемый реализацией KeyMint для генерации случайных чисел для ключей и IV.

Реализации KeyMint должны безопасно смешивать предоставленную энтропию в свой пул, который также должен содержать внутренне сгенерированную энтропию из аппаратного генератора случайных чисел. Смешивание должно быть обработано так, чтобы злоумышленник, имеющий полный контроль над битами, предоставленными addRngEntropy , или битами, сгенерированными аппаратно (но не обоими), не имел значительного преимущества в прогнозировании битов, сгенерированных из пула энтропии.

Основные характеристики

Каждый из механизмов ( generateKey , importKey и importWrappedKey ), создающих ключи KeyMint, возвращает характеристики вновь созданного ключа, разделенные соответствующим образом на уровни безопасности, которые обеспечивают каждую характеристику. Возвращаемые характеристики включают все параметры, указанные для создания ключа, за исключением Tag::APPLICATION_ID и Tag::APPLICATION_DATA . Если эти теги включены в параметры ключа, они удаляются из возвращаемых характеристик, так что невозможно найти их значения, проверив возвращенный keyblob. Однако они криптографически привязаны к keyblob, так что если при использовании ключа не предоставлены правильные значения, использование не удастся. Аналогично, Tag::ROOT_OF_TRUST криптографически привязан к ключу, но его нельзя указать во время создания или импорта ключа, и он никогда не возвращается.

В дополнение к предоставленным тегам реализация KeyMint также добавляет Tag::ORIGIN , указывающий способ создания ключа ( KeyOrigin::GENERATED , KeyOrigin::IMPORTED или KeyOrigin::SECURELY_IMPORTED ).

Сопротивление откату

Устойчивость к откату обозначается Tag::ROLLBACK_RESISTANCE и означает, что после удаления ключа с помощью deleteKey или deleteAllKeys защищенное оборудование гарантирует, что его больше никогда нельзя будет использовать.

Реализации KeyMint возвращают сгенерированный или импортированный материал ключа вызывающей стороне в виде keyblob, зашифрованной и аутентифицированной формы. Когда Keystore удаляет keyblob, ключ исчезает, но злоумышленник, которому ранее удалось получить материал ключа, может потенциально восстановить его на устройстве.

Ключ устойчив к откату, если защищенное оборудование гарантирует, что удаленные ключи не могут быть восстановлены позже. Обычно это делается путем хранения дополнительных метаданных ключа в надежном месте, которое не может быть изменено злоумышленником. На мобильных устройствах механизм, используемый для этого, обычно представляет собой защищенные блоки памяти воспроизведения (RPMB). Поскольку количество ключей, которые могут быть созданы, по сути, неограниченно, а доверенное хранилище, используемое для сопротивления откату, может быть ограничено по размеру, реализация может отказать в запросах на создание ключей, устойчивых к откату, когда хранилище заполнено.

начинать

Точка входа begin() начинает криптографическую операцию, используя указанный ключ, для указанной цели, с указанными параметрами (по мере необходимости). Она возвращает новый объект IKeyMintOperation Binder, который используется для завершения операции. Кроме того, возвращается значение вызова, которое используется как часть токена аутентификации в аутентифицированных операциях.

Реализация KeyMint поддерживает не менее 16 одновременных операций. Keystore использует до 15, оставляя одну для vold для шифрования пароля. Когда у Keystore выполняется 15 операций ( begin() был вызван, но finish или abort не были вызваны) и он получает запрос на начало 16-й, он вызывает abort() для самой последней использованной операции, чтобы сократить количество активных операций до 14, прежде чем вызвать begin() для начала новой запрошенной операции.

Если во время генерации или импорта ключа были указаны Tag::APPLICATION_ID или Tag::APPLICATION_DATA , вызовы begin() должны включать эти теги с изначально указанными значениями в аргументе params этого метода.

Обработка ошибок

Если метод IKeyMintOperation возвращает код ошибки, отличный от ErrorCode::OK , операция прерывается, а объект Binder операции становится недействительным. Любое дальнейшее использование объекта возвращает ErrorCode::INVALID_OPERATION_HANDLE .

Исполнение авторизации

Принудительная авторизация ключа выполняется в основном в begin() . Единственным исключением является случай, когда ключ имеет одно или несколько значений Tag::USER_SECURE_ID и не имеет значения Tag::AUTH_TIMEOUT .

В этом случае ключ требует авторизации на операцию, а методы update() или finish() получают токен аутентификации в аргументе authToken . Чтобы гарантировать, что токен действителен, реализация KeyMint:

  • Проверяет подпись HMAC на токене аутентификации.
  • Проверяет, содержит ли токен защищенный идентификатор пользователя, соответствующий идентификатору, связанному с ключом.
  • Проверяет, соответствует ли тип аутентификации токена типу ключа Tag::USER_AUTH_TYPE .
  • Проверяет, содержит ли токен значение вызова для текущей операции в поле вызова.

Если эти условия не выполняются, KeyMint возвращает ErrorCode::KEY_USER_NOT_AUTHENTICATED .

Вызывающий предоставляет токен аутентификации для каждого вызова update() и finish() . Реализация может проверить токен только один раз.