Аппаратные ключи

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

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

Чтобы решить эту проблему, Android - 11 была введена поддержка аппаратных ключей обернутый, где аппаратная поддержка присутствует. Ключи с аппаратной оболочкой - это ключи хранилища, которые в необработанном виде известны только выделенному оборудованию; программное обеспечение видит и работает с этими ключами только в зашифрованном виде. Это оборудование должно быть способно генерировать и импортировать ключи хранилища, упаковывать ключи хранилища в эфемерные и долгосрочные формы, получать подключи, напрямую программировать один подключ во встроенном криптографическом механизме и возвращать отдельный подключ программному обеспечению.

Примечание: встроенный криптографический двигатель (или встроенное аппаратное шифрование) относится к оборудованию , который шифрует / дешифрует данные , в то время как он находится на своем пути в / из запоминающего устройства. Обычно это хост-контроллер UFS или eMMC, который реализует криптографические расширения, определенные соответствующей спецификацией JEDEC.

Дизайн

В этом разделе представлена ​​конструкция функции ключей с аппаратной оболочкой, в том числе необходимая для нее аппаратная поддержка. Это обсуждение фокусируется на шифрование на основе файлов (НЭП), но решение относится к метаданным шифрования тоже.

Один из способов избежать необходимости использовать необработанные ключи шифрования в системной памяти - хранить их только в слотах для ключей встроенного механизма шифрования. Однако этот подход сталкивается с некоторыми проблемами:

  • Количество ключей шифрования может превышать количество слотов для ключей.
  • Встроенные механизмы шифрования могут использоваться только для шифрования / дешифрования полных блоков данных на диске. Однако в случае FBE программное обеспечение по-прежнему должно иметь возможность выполнять другую криптографическую работу, такую ​​как шифрование имен файлов и получение идентификаторов ключей. Программному обеспечению по-прежнему потребуется доступ к необработанным ключам FBE для выполнения этой другой работы.

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

Ключевая иерархия

Ключи могут быть получены из других ключей с использованием KDF (функция формирования ключа) , такие как HKDF , в результате чего в иерархии ключей.

На следующей схеме изображена типичная иерархии ключей для НЭПА , когда аппаратные обернутых ключей не используются:

Иерархия ключей FBE (стандарт)
Рисунок 1. Иерархия ключа НЭП (стандарт)

Ключ класса FBE - это необработанный ключ шифрования, который Android передает ядру Linux для разблокировки определенного набора зашифрованных каталогов, например хранилища с шифрованием учетных данных для конкретного пользователя Android. (В ядре, этот ключ называется fscrypt мастер - ключ) . Из этого ключа, ядро получает следующие подразделы:

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

Напротив, следующая диаграмма изображает иерархию ключей для FBE, когда используются ключи с аппаратной оболочкой:

Иерархия ключей FBE (с аппаратным ключом)
Рисунок 2. Иерархия ключа НЭП (с аппаратным ключом-обернутые)

По сравнению с предыдущим случаем, к иерархии ключей был добавлен дополнительный уровень, а ключ шифрования содержимого файла был перемещен. Корневой узел по-прежнему представляет собой ключ, который Android передает Linux для разблокировки набора зашифрованных каталогов. Однако теперь этот ключ имеет временную оболочку, и для того, чтобы его можно было использовать, он должен быть передан на выделенное оборудование. Это оборудование должно реализовывать два интерфейса, которые принимают временно завернутый ключ:

  • Один интерфейс для получения inline_encryption_key и непосредственно программировать его в слот ключей от встроенного крипто двигателя. Это позволяет зашифровать / расшифровать содержимое файла без доступа программного обеспечения к необработанному ключу. В Android общих ядер, этот интерфейс соответствует blk_ksm_ll_ops::keyslot_program операции, которые должны быть реализованы с помощью драйвера хранилища.
  • Один интерфейс для получения и возврата sw_secret ( «программное обеспечение тайны» - также называют «сырой секрет» в некоторых местах), которая является ключом , который Linux использует для вывода подразделы для всего, кроме шифрования содержимого файлов. В Android общих ядер, этот интерфейс соответствует blk_ksm_ll_ops::derive_raw_secret операции, которые должны быть реализованы с помощью драйвера хранилища.

Для получения inline_encryption_key и sw_secret от ключа сырым хранения, аппаратные средства должны использовать криптостойкий KDF. Этот KDF должен соответствовать лучшим методам криптографии; он должен иметь степень защиты не менее 256 бит, то есть достаточно для любого алгоритма, используемого в дальнейшем. Он также должен использовать отдельную метку, контекст и / или информационную строку, зависящую от приложения, при выводе каждого типа подключей, чтобы гарантировать, что результирующие подключи криптографически изолированы, т. Е. Знание одного из них не раскрывает никаких других. Растягивание ключа не требуется, поскольку необработанный ключ хранилища уже является равномерно случайным ключом.

Технически можно использовать любой KDF, отвечающий требованиям безопасности. Однако в целях тестирования необходимо повторно реализовать тот же KDF в тестовом коде. В настоящее время проверена и внедрена одна KDF; его можно найти в исходном коде vts_kernel_encryption_test . Рекомендуется использовать аппаратное это KDF, который использует NIST SP 800-108 «KDF в режиме счетчика» с AES-256-КЦР как ЧПИ. Обратите внимание, что для обеспечения совместимости все части алгоритма должны быть идентичными, включая выбор контекстов и меток KDF для каждого подключа.

Упаковка ключей

Чтобы обеспечить безопасность ключей с аппаратной оболочкой, определены два типа упаковки ключей:

  • Ephemeral упаковка: аппаратное шифрование необработанного ключа с помощью ключа , который генерируется случайным образом при каждой загрузке и непосредственно не подвергается снаружи оборудования.
  • Долгосрочная упаковка: аппаратное шифрование необработанного ключа , используя уникальный постоянный ключ , встроенный в аппаратное обеспечение , которое не непосредственно нагреваемые снаружи оборудования.

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

В то же время Android по-прежнему должна иметь возможность хранить зашифрованную версию ключей на диске, чтобы их можно было разблокировать в первую очередь. Для этой цели подойдут необработанные ключи. Однако желательно, чтобы необработанные ключи вообще никогда не присутствовали в системной памяти, чтобы их нельзя было извлечь для использования вне устройства, даже если они были извлечены во время загрузки. По этой причине определено понятие длительного обертывания.

Для поддержки управления ключами, заключенными в эти два разных способа, оборудование должно реализовывать следующие интерфейсы:

  • Интерфейсы для генерации и импорта ключей хранилища с возвратом их в долгосрочной упаковке. Эти интерфейсы доступны косвенно через KeyMint, и они соответствуют TAG_STORAGE_KEY тегу KeyMint. Способность «генерировать» используются vold для генерации новых ключей для хранения использования Android, в то время как способность «импорт» используются vts_kernel_encryption_test для тестирования импорта ключей.
  • Интерфейс для преобразования ключа хранения с долгосрочной оболочкой в ​​ключ с временной оболочкой. Это соответствует convertStorageKeyToEphemeral методы KeyMint. Этот метод используется как vold и vts_kernel_encryption_test для того , чтобы разблокировать хранение.

Алгоритм переноса ключей является деталью реализации, но он должен использовать сильный AEAD, такой как AES-256-GCM, со случайными IV.

Требуются изменения программного обеспечения

У AOSP уже есть базовая структура для поддержки ключей с аппаратной оболочкой. Это включает в себя поддержку в компонентах пользовательского пространства , такие как vold , а также поддержку ядра Linux в BLK-крипто, fscrypt и ого-умолчанию ключе.

Однако требуются некоторые изменения, связанные с реализацией.

Изменения KeyMint

Реализация KeyMint устройства должна быть модифицирована для поддержки TAG_STORAGE_KEY и реализации convertStorageKeyToEphemeral методы.

В Keymaster, exportKey использовали вместо convertStorageKeyToEphemeral .

Изменения ядра Linux

Драйвер Ядро Linux для встроенных крипто двигатель устройства должно быть изменен , чтобы установить BLK_CRYPTO_FEATURE_WRAPPED_KEYS , сделать keyslot_program() и keyslot_evict() операции поддерживают программирование / выселять аппаратные обернутых ключей, и реализовать derive_raw_secret() операцию.

Тестирование

Хотя шифрование с ключами с аппаратной оболочкой труднее протестировать, чем шифрование со стандартными ключами, все же можно проверить, импортировав тестовый ключ и повторно реализовав получение ключа, которое выполняет аппаратное обеспечение. Это реализуется в vts_kernel_encryption_test . Чтобы запустить этот тест, запустите:

atest -v vts_kernel_encryption_test

Прочитайте журнал тестирование и проверки того, что ключевое Тестовые аппаратных обернутой (например FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy и DmDefaultKeyTest.TestHwWrappedKey ) не были пропущены из - за поддержку аппаратных обернутый ключей не обнаруженными, а результаты испытаний по- прежнему будут «приняты» в тот случай.

Включение

После того, как ключ аппаратной поддержки обернутого устройства работает правильно, вы можете сделать следующие изменения в устройстве fstab файл , чтобы сделать Android использовать его для НЭПА и метаданных шифрования:

  • НЭП: добавить wrappedkey_v0 флаг в fileencryption параметра. Например, используйте fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Для получения более подробной информации см документации FBE .
  • Метаданные шифрования: добавить wrappedkey_v0 флаг в metadata_encryption параметра. Например, использование metadata_encryption=:wrappedkey_v0 . Для получения более подробной информации см документации метаданных шифрования .