Android 7.0 и выше поддерживают шифрование на основе файлов (FBE). FBE позволяет шифровать разные файлы с помощью разных ключей, которые можно расшифровать независимо друг от друга. Эти ключи используются для шифрования как содержимого файлов, так и их имен. При использовании FBE другая информация, такая как структура каталогов, размеры файлов, разрешения и время создания/изменения, не шифруется. В совокупности эта информация известна как метаданные файловой системы.
В Android 9 появилась поддержка шифрования метаданных. При шифровании метаданных единственный ключ, присутствующий при загрузке, шифрует любое содержимое, не зашифрованное функцией FBE. Этот ключ защищен KeyMint (ранее Keymaster), который, в свою очередь, защищен функцией Verified Boot.
Шифрование метаданных всегда включено на расширяемой памяти , если включена функция FBE. Шифрование метаданных также можно включить во внутренней памяти. На устройствах, выпущенных под управлением Android 11 или выше, шифрование метаданных во внутренней памяти должно быть включено.
Реализация на внутренней памяти
Настроить шифрование метаданных во внутренней памяти новых устройств можно, настроив файловую систему metadata , изменив последовательность инициализации и включив шифрование метаданных в файле fstab устройства.
Предварительные требования
Шифрование метаданных можно настроить только при первом форматировании раздела данных. Поэтому эта функция доступна только для новых устройств; обновление по воздуху (OTA) не должно это менять.
Для шифрования метаданных необходимо включить модуль dm-default-key в ядре Android. В Android 11 и выше dm-default-key поддерживается стандартными ядрами Android, начиная с версии 4.14. Эта версия dm-default-key использует аппаратно- и сторонних разработчиков независимую от платформы систему шифрования blk-crypto .
Чтобы включить dm-default-key , используйте:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_DM_DEFAULT_KEY=y
dm-default-key использует встроенное аппаратное шифрование (оборудование, которое шифрует/дешифрует данные во время их передачи к/от устройства хранения), если оно доступно. Если вы не используете встроенное аппаратное шифрование, также необходимо включить резервный вариант с использованием криптографического API ядра:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
Если вы не используете встроенное аппаратное шифрование, вам также следует включить любое доступное ускорение на основе ЦП, как это рекомендовано в документации FBE .
В Android 10 и более ранних версиях стандартное ядро Android не поддерживало dm-default-key . Поэтому реализация dm-default-key была обязанностью производителей.
Настройка файловой системы метаданных
Поскольку данные в разделе userdata нельзя прочитать, пока не будет присутствовать ключ шифрования метаданных, в таблице разделов необходимо выделить отдельный раздел, называемый разделом метаданных, для хранения больших двоичных объектов KeyMint, защищающих этот ключ. Размер раздела метаданных должен составлять 16 МБ.
В fstab.hardware необходимо указать запись для файловой системы метаданных, расположенной на этом разделе и монтирующей его в /metadata , включая флаг formattable , чтобы гарантировать форматирование при загрузке. Файловая система f2fs не работает на небольших разделах; мы рекомендуем использовать ext4. Например:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
Чтобы убедиться в существовании точки монтирования /metadata , добавьте следующую строку в BoardConfig-common.mk :
BOARD_USES_METADATA_PARTITION := true
Изменения в последовательности инициализации
При использовании шифрования метаданных vold должен быть запущен до монтирования /data . Чтобы обеспечить его запуск достаточно рано, добавьте следующий фрагмент кода в файл init.hardware.rc :
# We need vold early for metadata encryption
on early-fs
start vold Перед тем как init попытается смонтировать /data необходимо, чтобы KeyMint был запущен и готов к работе.
В init.hardware.rc уже должна содержаться инструкция mount_all , которая монтирует сам каталог /data в разделе on late-fs . Перед этой строкой добавьте директиву для выполнения службы wait_for_keymaster :
on late-fs … # Wait for Keymaster exec_start wait_for_keymaster # Mount RW partitions which need run fsck mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
Включите шифрование метаданных
Наконец, добавьте keydirectory=/metadata/vold/metadata_encryption в столбец fs_mgr_flags записи в файле fstab для userdata . Например, полная строка в файле fstab может выглядеть так:
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota,formattable
По умолчанию алгоритм шифрования метаданных во внутренней памяти — AES-256-XTS. Это можно изменить, задав параметр metadata_encryption , который также находится в столбце fs_mgr_flags :
- На устройствах, не поддерживающих AES-ускорение, шифрование Adiantum можно включить, установив параметр
metadata_encryption=adiantum. На устройствах, поддерживающих аппаратную обертку ключей шифрования , ключ шифрования метаданных можно сделать аппаратно обернутым, установив параметр
metadata_encryption=aes-256-xts:wrappedkeyилиmetadata_encryption=aes-256-xts:wrappedkey_v0.wrappedkeyэто современная версия;wrappedkey_v0следует использовать только на устройствах, которые не поддерживаютwrappedkeyили уже запущены сwrappedkey_v0. Для получения дополнительной информации см. раздел «Включение обернутых ключей» .В любом случае,
aes-256-xtsможно опустить, поскольку это алгоритм по умолчанию. Например,metadata_encryption=:wrappedkeyэквивалентноmetadata_encryption=aes-256-xts:wrappedkey.
Поскольку интерфейс ядра к dm-default-key изменился в Android 11, вам также необходимо убедиться, что вы установили правильное значение для PRODUCT_SHIPPING_API_LEVEL в device.mk . Например, если ваше устройство запускается с Android 11 (уровень API 30), device.mk должен содержать:
PRODUCT_SHIPPING_API_LEVEL := 30
Вы также можете установить следующее системное свойство, чтобы принудительно использовать новый API dm-default-key независимо от уровня API доставки:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.dm_default_key.options_format.version=2
Валидация
Чтобы убедиться, что шифрование метаданных включено и работает корректно, выполните описанные ниже тесты. Также обратите внимание на распространенные проблемы, описанные ниже.
Тесты
Для начала выполните следующую команду, чтобы убедиться, что шифрование метаданных включено во внутренней памяти:
adb rootadb shell dmctl table userdata
Результат должен выглядеть примерно так:
Targets in the device-mapper table for userdata: 0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors
Если вы переопределили настройки шифрования по умолчанию, установив параметр metadata_encryption в fstab устройства, то вывод будет немного отличаться от приведенного выше. Например, если вы включили шифрование Adiantum , то третье поле будет xchacha12,aes-adiantum-plain64 вместо aes-xts-plain64 .
Далее запустите vts_kernel_encryption_test , чтобы проверить корректность шифрования метаданных и FBE:
atest vts_kernel_encryption_test
или:
vts-tradefed run vts -m vts_kernel_encryption_test
Общие проблемы
Во время вызова функции mount_all , которая монтирует зашифрованный метаданными раздел /data , init запускает инструмент vdc. Инструмент vdc подключается к vold через binder для настройки зашифрованного метаданными устройства и монтирования раздела. На время этого вызова init блокируется и пытается либо читать, либо устанавливать свойства init , пока не завершится mount_all . Если на этом этапе какая-либо часть работы vold прямо или косвенно блокируется на чтении или установке свойства, возникает взаимоблокировка. Важно убедиться, что vold может завершить работу по чтению ключей, взаимодействию с KeyMint и монтированию каталога данных без дальнейшего взаимодействия с init .
Если KeyMint не запущен полностью к моменту выполнения mount_all , он не отвечает vold до тех пор, пока не прочтет определенные свойства из init , что приводит к описанной выше взаимоблокировке. Размещение exec_start wait_for_keymaster перед соответствующим вызовом mount_all как указано выше, гарантирует, что KeyMint будет полностью запущен заранее, и, таким образом, предотвращает эту взаимоблокировку.
Конфигурация на подключаемом хранилище
Начиная с Android 9, шифрование метаданных всегда включено на подключаемой памяти , если включена функция FBE, даже если шифрование метаданных не включено на внутренней памяти.
В AOSP существует две реализации шифрования метаданных для адаптируемого хранилища: устаревшая, основанная на dm-crypt , и более новая, основанная на dm-default-key . Чтобы убедиться, что для вашего устройства выбрана правильная реализация, проверьте правильность значения параметра PRODUCT_SHIPPING_API_LEVEL в device.mk . Например, если ваше устройство запускается с Android 11 (уровень API 30), device.mk должен содержать:
PRODUCT_SHIPPING_API_LEVEL := 30
Также можно установить следующие системные параметры, чтобы принудительно использовать новый метод шифрования метаданных тома (и новую версию политики FBE по умолчанию) независимо от уровня API поставки:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.volume.metadata.method=dm-default-key \
ro.crypto.dm_default_key.options_format.version=2 \
ro.crypto.volume.options=::v2
Текущий метод
На устройствах с Android 11 и выше шифрование метаданных на подключаемом хранилище использует модуль ядра dm-default-key , как и на внутреннем хранилище. См. приведенные выше предварительные требования , чтобы узнать, какие параметры конфигурации ядра следует включить. Обратите внимание, что встроенное шифрование, работающее на внутреннем хранилище устройства, может быть недоступно на подключаемом хранилище, поэтому может потребоваться CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y .
По умолчанию метод шифрования метаданных тома dm-default-key использует алгоритм шифрования AES-256-XTS с криптографическими секторами размером 4096 байт. Алгоритм можно переопределить, установив системное свойство ro.crypto.volume.metadata.encryption . Значение этого свойства имеет тот же синтаксис, что и параметр metadata_encryption в файле fstab, описанный выше. Например, на устройствах, не имеющих ускорения AES, шифрование Adiantum можно включить, установив ro.crypto.volume.metadata.encryption=adiantum .
Метод наследия
На устройствах с Android 10 и ниже шифрование метаданных в расширяемой памяти использует модуль ядра dm-crypt а не dm-default-key :
CONFIG_DM_CRYPT=y
В отличие от метода dm-default-key , метод dm-crypt приводит к двойному шифрованию содержимого файла: один раз с помощью ключа FBE и один раз с помощью ключа шифрования метаданных. Это двойное шифрование снижает производительность и не требуется для достижения целей безопасности шифрования метаданных, поскольку Android гарантирует, что ключи FBE как минимум так же сложно скомпрометировать, как и ключ шифрования метаданных. Производители могут вносить изменения в ядро, чтобы избежать двойного шифрования, в частности, путем реализации параметра allow_encrypt_override , который Android передает в dm-crypt когда системное свойство ro.crypto.allow_encrypt_override установлено в true . Эти изменения не поддерживаются стандартным ядром Android.
По умолчанию метод шифрования метаданных тома dm-crypt использует алгоритм шифрования AES-128-CBC с ESSIV и 512-байтовыми криптографическими секторами. Это можно изменить, задав следующие системные свойства (которые также используются для FDE):
-
ro.crypto.fde_algorithmвыбирает алгоритм шифрования метаданных. Доступны вариантыaes-128-cbcиadiantum. Adiantum можно использовать только в том случае, если устройство не поддерживает ускорение AES. -
ro.crypto.fde_sector_sizeвыбирает размер криптографического сектора. Доступные значения: 512, 1024, 2048 и 4096. Для шифрования Adiantum используйте значение 4096.