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

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

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

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

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

Дизайн

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Для достижения целей безопасности аппаратных ключей определены два типа упаковки ключей:

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

Все ключи, передаваемые ядру 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-crypto , fscrypt и dm-default-key .

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

Изменения в KeyMint

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

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

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

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

Для ядер android14 и более поздних версий установите BLK_CRYPTO_KEY_TYPE_HW_WRAPPED в blk_crypto_profile::key_types_supported , сделайте blk_crypto_ll_ops::keyslot_program и blk_crypto_ll_ops::keyslot_evict для поддержки программирования/вытеснения аппаратных ключей и реализуйте blk_crypto_ll_ops::derive_sw_secret .

Для ядер android12 и android13 установите BLK_CRYPTO_FEATURE_WRAPPED_KEYS в blk_keyslot_manager::features , сделайте blk_ksm_ll_ops::keyslot_program и blk_ksm_ll_ops::keyslot_evict для поддержки программирования/вытеснения аппаратных ключей и реализуйте blk_ksm_ll_ops::derive_raw_secret .

keyslot_mgmt_ll_ops::keyslot_program android11 keyslot_mgmt_ll_ops::derive_raw_secret установка BLK_CRYPTO_FEATURE_WRAPPED_KEYS keyslot_mgmt_ll_ops::keyslot_evict keyslot_manager::features

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

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

atest -v vts_kernel_encryption_test

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

Включить ключи

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

  • FBE: добавьте флаг wrappedkey_v0 в параметр fileencryption . Например, используйте fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Более подробную информацию смотрите в документации FBE .
  • Шифрование метаданных: добавьте флаг wrappedkey_v0 в параметр metadata_encryption . Например, используйте metadata_encryption=:wrappedkey_v0 . Более подробную информацию можно найти в документации по шифрованию метаданных .
,

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

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

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

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

Дизайн

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Для достижения целей безопасности аппаратных ключей определены два типа упаковки ключей:

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

Все ключи, передаваемые ядру 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-crypto , fscrypt и dm-default-key .

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

Изменения в KeyMint

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

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

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

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

Для ядер android14 и более поздних версий установите BLK_CRYPTO_KEY_TYPE_HW_WRAPPED в blk_crypto_profile::key_types_supported , сделайте blk_crypto_ll_ops::keyslot_program и blk_crypto_ll_ops::keyslot_evict для поддержки программирования/вытеснения аппаратных ключей и реализуйте blk_crypto_ll_ops::derive_sw_secret .

Для ядер android12 и android13 установите BLK_CRYPTO_FEATURE_WRAPPED_KEYS в blk_keyslot_manager::features , сделайте blk_ksm_ll_ops::keyslot_program и blk_ksm_ll_ops::keyslot_evict для поддержки программирования/вытеснения аппаратных ключей и реализуйте blk_ksm_ll_ops::derive_raw_secret .

keyslot_mgmt_ll_ops::keyslot_program android11 keyslot_mgmt_ll_ops::derive_raw_secret установка BLK_CRYPTO_FEATURE_WRAPPED_KEYS keyslot_mgmt_ll_ops::keyslot_evict keyslot_manager::features

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

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

atest -v vts_kernel_encryption_test

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

Включить ключи

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

  • FBE: добавьте флаг wrappedkey_v0 в параметр fileencryption . Например, используйте fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Более подробную информацию смотрите в документации FBE .
  • Шифрование метаданных: добавьте флаг wrappedkey_v0 в параметр metadata_encryption . Например, используйте metadata_encryption=:wrappedkey_v0 . Более подробную информацию можно найти в документации по шифрованию метаданных .
,

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

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

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

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

Дизайн

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ключевая упаковка

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

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

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

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

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

  • Интерфейсы для генерации и импорта клавиш хранения, возвращая их в долгосрочную обернутую форму. Эти интерфейсы доступны косвенно через 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-Crypto , FSCRYPT и DM-Default-Key .

Тем не менее, требуются некоторые изменения, специфичные для реализации.

Кейминт меняется

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

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

Linux ядра меняется

Драйвер ядра Linux для встроенного крипто-двигателя устройства должен быть изменен для поддержки оборудования для оборудования.

For android14 and higher kernels, set BLK_CRYPTO_KEY_TYPE_HW_WRAPPED in blk_crypto_profile::key_types_supported , make blk_crypto_ll_ops::keyslot_program and blk_crypto_ll_ops::keyslot_evict support programming/evicting hardware-wrapped keys, and implement blk_crypto_ll_ops::derive_sw_secret .

Для android12 и android13 установите BLK_CRYPTO_FEATURE_WRAPPED_KEYS в blk_keyslot_manager::features MAKE blk_ksm_ll_ops::keyslot_program и blk_ksm_ll_ops::keyslot_evict SCORTINGSION/ blk_ksm_ll_ops::derive_raw_secret

keyslot_mgmt_ll_ops::keyslot_program android11 keyslot_mgmt_ll_ops::derive_raw_secret установка BLK_CRYPTO_FEATURE_WRAPPED_KEYS keyslot_mgmt_ll_ops::keyslot_evict keyslot_manager::features

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

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

atest -v vts_kernel_encryption_test

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

Включить ключи

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

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

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

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

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

ПРИМЕЧАНИЕ. Встроенный крипто -двигатель (или встроенное оборудование для шифрования ) относится к оборудованию, которое шифрует/дешифрует данные, пока он находится на пути к/из устройства хранения. Обычно это контроллер хоста UFS или EMMC, который реализует крипто -расширения, определяемые соответствующей спецификацией JEDEC.

Дизайн

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

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

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

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

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

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

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

Ключевая иерархия FBE (стандарт)
Рисунок 1. иерархия ключа FBE (стандарт)

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

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

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

Ключевая иерархия FBE (с ключом с аппаратным покрытием)
Рисунок 2. Иерархия ключа FBE (с оборудованным ключом для оборудования)

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

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

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

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

Ключевая упаковка

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

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

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

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

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

  • Интерфейсы для генерации и импорта клавиш хранения, возвращая их в долгосрочную обернутую форму. Эти интерфейсы доступны косвенно через 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-Crypto , FSCRYPT и DM-Default-Key .

Тем не менее, требуются некоторые изменения, специфичные для реализации.

Кейминт меняется

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

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

Linux ядра меняется

Драйвер ядра Linux для встроенного крипто-двигателя устройства должен быть изменен для поддержки оборудования для оборудования.

For android14 and higher kernels, set BLK_CRYPTO_KEY_TYPE_HW_WRAPPED in blk_crypto_profile::key_types_supported , make blk_crypto_ll_ops::keyslot_program and blk_crypto_ll_ops::keyslot_evict support programming/evicting hardware-wrapped keys, and implement blk_crypto_ll_ops::derive_sw_secret .

Для android12 и android13 установите BLK_CRYPTO_FEATURE_WRAPPED_KEYS в blk_keyslot_manager::features MAKE blk_ksm_ll_ops::keyslot_program и blk_ksm_ll_ops::keyslot_evict SCORTINGSION/ blk_ksm_ll_ops::derive_raw_secret

keyslot_mgmt_ll_ops::keyslot_program android11 keyslot_mgmt_ll_ops::derive_raw_secret установка BLK_CRYPTO_FEATURE_WRAPPED_KEYS keyslot_mgmt_ll_ops::keyslot_evict keyslot_manager::features

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

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

atest -v vts_kernel_encryption_test

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

Включить ключи

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

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