Шифрование метаданных

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

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

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

Реализация во внутренней памяти

Вы можете настроить шифрование метаданных во внутренней памяти новых устройств, настроив файловую систему metadata , изменив последовательность инициализации и включив шифрование метаданных в файле fstab устройства.

Предварительные условия

Шифрование метаданных можно настроить только при первом форматировании раздела данных. В результате эта функция доступна только для новых устройств; это не то, что OTA должно изменить.

Для шифрования метаданных необходимо, чтобы в вашем ядре был включен модуль dm-default-key . В 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 и более ранних версиях dm-default-key не поддерживался общим ядром Android. Поэтому поставщики должны были реализовать dm-default-key .

Настройка файловой системы метаданных

Поскольку ничто в разделе пользовательских данных не может быть прочитано до тех пор, пока не будет присутствовать ключ шифрования метаданных, в таблице разделов должен быть выделен отдельный раздел, называемый «разделом метаданных», для хранения больших двоичных объектов мастера ключей, которые защищают этот ключ. Раздел метаданных должен иметь размер 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

Изменения в последовательности инициализации

Если используется шифрование метаданных, перед монтированием /data должен быть запущен vold . Чтобы гарантировать, что он запускается достаточно рано, добавьте следующий раздел в init.hardware.rc :

# We need vold early for metadata encryption
on early-fs
    start vold

Keymaster должен быть запущен и готов, прежде чем init попытается смонтировать /data .

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_v0 (или, что эквивалентно, metadata_encryption=:wrappedkey_v0 , поскольку aes-256-xts является алгоритмом по умолчанию).

Поскольку интерфейс ядра для 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 root
adb 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 сможет завершить работу по чтению ключей, взаимодействию с Keymaster и монтированию каталога данных без дальнейшего взаимодействия с init .

Если Keymaster не запускается полностью при запуске mount_all , он не отвечает на vold до тех пор, пока не прочитает определенные свойства из init , что приводит к точно описанной взаимоблокировке. Размещение exec_start wait_for_keymaster над соответствующим вызовом mount_all , как указано, гарантирует, что Keymaster полностью запущен заранее, и, таким образом, позволяет избежать этой тупиковой ситуации.

Конфигурация на приемлемом хранилище

Начиная с 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 . Значение этого свойства имеет тот же синтаксис, что и параметр fstab metadata_encryption описанный выше. Например, на устройствах, где отсутствует ускорение 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 . Адиантум можно использовать только в том случае, если в устройстве отсутствует ускорение AES.
  • ro.crypto.fde_sector_size выбирает размер криптосектора. Возможные значения: 512, 1024, 2048 и 4096. Для шифрования Adiantum используйте 4096.