Как и большинство программ для шифрования дисков и файлов, шифрование хранилища Android традиционно основано на наличии необработанных ключей шифрования в системной памяти, что позволяет выполнить шифрование. Даже если шифрование выполняется специальным оборудованием, а не программным обеспечением, программному обеспечению, как правило, все равно необходимо управлять необработанными ключами шифрования.
Традиционно это не рассматривается как проблема, поскольку ключи не будут присутствовать во время автономной атаки, которая является основным типом атаки, от которой предназначено шифрование хранилища. Однако существует желание обеспечить повышенную защиту от других типов атак, таких как атаки с холодной загрузкой и онлайн-атаки, при которых злоумышленник может получить утечку системной памяти без полной компрометации устройства.
Чтобы решить эту проблему, в Android 11 появилась поддержка аппаратных ключей , где присутствует аппаратная поддержка. Аппаратные ключи — это ключи хранилища, которые известны выделенному оборудованию только в необработанной форме; программное обеспечение видит и работает с этими ключами только в завернутой (зашифрованной) форме. Это оборудование должно быть способно генерировать и импортировать ключи хранения, упаковывать ключи хранения в эфемерную и долгосрочную формы, получать подразделы, напрямую программировать один подраздел во встроенный криптографический механизм и возвращать отдельный подраздел в программное обеспечение.
Примечание. Под встроенным криптографическим механизмом (или аппаратным обеспечением встроенного шифрования ) понимается оборудование, которое шифрует/дешифрует данные на пути к устройству хранения/от него. Обычно это хост-контроллер UFS или eMMC, реализующий криптографические расширения, определенные соответствующей спецификацией JEDEC.
Дизайн
В этом разделе представлена конструкция функции аппаратных клавиш, включая необходимую для нее аппаратную поддержку. В этом обсуждении основное внимание уделяется шифрованию на основе файлов (FBE), но решение применимо и к шифрованию метаданных .
Один из способов избежать необходимости хранить необработанные ключи шифрования в системной памяти — хранить их только в слотах для ключей встроенного криптографического механизма. Однако этот подход сталкивается с некоторыми проблемами:
- Количество ключей шифрования может превышать количество слотов для ключей.
- Встроенные криптографические механизмы можно использовать только для шифрования/дешифрования полных блоков данных на диске. Однако в случае FBE программное обеспечение все равно должно иметь возможность выполнять другую криптографическую работу, например шифрование имен файлов и получение идентификаторов ключей. Программному обеспечению по-прежнему потребуется доступ к необработанным ключам FBE, чтобы выполнять другую работу.
Чтобы избежать этих проблем, ключи хранилища вместо этого преобразуются в аппаратно упакованные ключи , которые можно развернуть и использовать только на выделенном оборудовании. Это позволяет поддерживать неограниченное количество ключей. Кроме того, иерархия ключей изменена и частично перенесена на это оборудование, что позволяет вернуть подраздел в программное обеспечение для задач, которые не могут использовать встроенный криптографический механизм.
Ключевая иерархия
Ключи могут быть получены из других ключей с использованием KDF (функции деривации ключей) , например HKDF , что приводит к созданию иерархии ключей .
На следующей диаграмме показана типичная иерархия ключей для FBE, когда аппаратные ключи не используются:
Ключ класса FBE — это необработанный ключ шифрования, который Android передает ядру Linux для разблокировки определенного набора зашифрованных каталогов, например хранилища, зашифрованного учетными данными для конкретного пользователя Android. (В ядре этот ключ называется главным ключом fscrypt .) Из этого ключа ядро получает следующие подразделы:
- Ключевой идентификатор. Это значение не используется для шифрования, а скорее является значением, используемым для идентификации ключа, которым защищен конкретный файл или каталог.
- Ключ шифрования содержимого файла
- Ключ шифрования имен файлов
Напротив, на следующей диаграмме показана иерархия ключей для 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 — это необработанный ключ шифрования, который Android передает ядру Linux для разблокировки определенного набора зашифрованных каталогов, например хранилища, зашифрованного учетными данными для конкретного пользователя Android. (В ядре этот ключ называется главным ключом fscrypt .) Из этого ключа ядро получает следующие подразделы:
- Ключевой идентификатор. Это значение не используется для шифрования, а скорее является значением, используемым для идентификации ключа, которым защищен конкретный файл или каталог.
- Ключ шифрования содержимого файла
- Ключ шифрования имен файлов
Напротив, на следующей диаграмме показана иерархия ключей для 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 — это необработанный ключ шифрования, который Android передает ядру Linux для разблокировки определенного набора зашифрованных каталогов, например хранилища, зашифрованного учетными данными для конкретного пользователя Android. (В ядре этот ключ называется главным ключом fscrypt .) Из этого ключа ядро получает следующие подразделы:
- Ключевой идентификатор. Это значение не используется для шифрования, а скорее является значением, используемым для идентификации ключа, которым защищен конкретный файл или каталог.
- Ключ шифрования содержимого файла
- Ключ шифрования имен файлов
Напротив, на следующей диаграмме показана иерархия ключей для 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-это необработанный ключ шифрования, который Android передает ядра Linux, чтобы разблокировать определенный набор зашифрованных каталогов, таких как хранение, заполненное учетными данными, для конкретного пользователя Android. (В ядре этот ключ называется основным ключом fScrypt .) Из этого ключа ядро получает следующие подказки:
- Ключевой идентификатор. Это не используется для шифрования, а скорее является значением, используемым для определения ключа, с помощью которого защищен конкретный файл или каталог.
- Ключ шифрования содержимого файла
- Ключ шифрования файлов
Напротив, на следующей диаграмме изображена ключевая иерархия для 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
. Для получения более подробной информации см. Документацию по шифрованию метаданных .