Я цитирую руководство по Android здесь , но:
НОТА:
Источник, который я использовал, не имеет прямого отношения к Зефиру, но имеет отношение к Леденцу и выше.
TL: DR
Я просто сейчас отвечу на вопросы ОП. Технические детали будут следовать.
Ключ шифрования по умолчанию исходит от аппаратного источника (микросхема, похожая на TPM) и пароля AOSP по умолчанию, определенного как default_passwordв cryptfs.cисходном файле, см. Ниже.
Да, не только по умолчанию, но любой пароль превращается в ключ и хранится в микросхеме типа TPM, называемой TEE (сокращение от «Trusted Execution Environment», дополнительную информацию см. Ниже).
Хакер с UART / JTAG-доступом к микросхемам на SoC устройства может технически получить доступ к ключу TEE, или пользовательское ядро может передать эту информацию хакеру. Некоторые трехбуквенные агентства в теориях заговора могут, возможно, вступить в партнерские отношения с ОЕМ, чтобы эти небезопасные ядра использовались в производственных устройствах, но я бы не стал прилагать к этому много усилий. Снова, посмотрите последний раздел этого ответа для получения дополнительной информации.
Единственное, что мешает хакеру получить доступ к ключу, - это огромное количество усилий, необходимых для этого.
- Проверка хеша (контрольной суммы) микропрограммы (называемой Google «Verified Boot» ) фактически выполняется на Lollipop и выше по умолчанию (и доступна из JellyBean 4.3 и далее) с помощью модуля ядра, который называется
dm-verity. Однако это не зависит от состояния шифрования.
Источник: руководство по безопасности AOSP здесь .
- О процессе расшифровки системы с помощью пользовательского пароля см. Ниже. Я просто скажу вам, что пароль пользователя участвует как в создании, так и в использовании ключа шифрования.
обзор
При первой загрузке устройство создает случайно сгенерированный 128-битный мастер-ключ, а затем хэширует его с паролем по умолчанию и сохраненной солью. Пароль по умолчанию: «default_password». Однако полученный хеш также подписывается через TEE (такой как TrustZone), который использует хэш подписи для шифрования главного ключа.
Вы можете найти пароль по умолчанию, определенный в файле cryptfs.c проекта Android с открытым исходным кодом .
Когда пользователь устанавливает PIN-код / пароль или пароль на устройстве, только 128-битный ключ повторно шифруется и сохраняется. (т.е. изменения ПИН-кода / пароля / шаблона пользователя НЕ вызывают повторное шифрование раздела пользовательских данных.)
Запуск зашифрованного устройства с шифрованием по умолчанию
Это то, что происходит, когда вы загружаете зашифрованное устройство без пароля. Поскольку устройства Android 5.0 шифруются при первой загрузке, не должно быть установленного пароля, и поэтому это состояние шифрования по умолчанию.
- Обнаружение зашифрованных / данных без пароля
Определите, что устройство Android зашифровано, потому что / данные не могут быть подключены, и один из флагов encryptableили forceencryptустановлен.
voldустанавливает vold.decryptзначение trigger_default_encryption, которое запускает defaultcryptoслужбу. trigger_default_encryptionпроверяет тип шифрования, чтобы узнать, зашифрованы ли / data с паролем или без него.
- Расшифровать / данные
Создает dm-cryptустройство поверх блочного устройства, чтобы оно было готово к использованию.
- Mount / data
voldзатем монтирует дешифрованный раздел реального / данных и затем готовит новый раздел. Он устанавливает свойство vold.post_fs_data_doneк 0и затем устанавливает vold.decryptв trigger_post_fs_data. Это вызывает init.rcзапуск его post-fs-dataкоманд. Они будут создавать необходимые каталоги и ссылки , а затем установить vold.post_fs_data_doneв 1.
После того, как voldвидит 1 в этой собственности, она устанавливает свойство vold.decryptв: trigger_restart_framework. Это заставляет init.rcснова запускать службы в классе, mainа также запускать службы в классе late_start впервые после загрузки.
- Начать рамки
Теперь платформа загружает все свои сервисы, используя расшифрованные данные / данные, и система готова к использованию.
Запуск зашифрованного устройства без шифрования по умолчанию
Это то, что происходит при загрузке зашифрованного устройства с установленным паролем. Пароль устройства может быть пин-кодом, шаблоном или паролем.
- Обнаружение зашифрованного устройства с помощью пароля
Определите, что устройство Android зашифровано, потому что флаг ro.crypto.state = "encrypted"
voldустанавливается vold.decryptна trigger_restart_min_frameworkпотому что / данные зашифрованы паролем.
- Гора tmpfs
initустанавливает пять свойств для сохранения начальных параметров монтирования, заданных для / data, с параметрами, переданными из init.rc. voldиспользует эти свойства для настройки криптографического отображения:
ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags (8-значный шестнадцатеричный номер ASCII, которому предшествует 0x)
- Запустите фреймворк, чтобы запросить пароль
Фреймворк запускается и видит, что vold.decryptустановлено trigger_restart_min_framework. Это говорит фреймворку, что он загружается с tmpfs /dataдиска и ему нужно получить пароль пользователя.
Однако сначала необходимо убедиться, что диск был правильно зашифрован. Он посылает команду cryptfs cryptocompleteк vold. voldвозвращает 0, если шифрование было успешно завершено, -1 при внутренней ошибке или -2, если шифрование не было успешно завершено. voldопределяет это, просматривая крипто-метаданные для CRYPTO_ENCRYPTION_IN_PROGRESSфлага. Если он установлен, процесс шифрования был прерван, и на устройстве нет доступных данных.
Если voldвозвращается ошибка, пользовательский интерфейс должен отобразить сообщение для пользователя, чтобы перезагрузить устройство и выполнить заводские настройки устройства, и дать пользователю кнопку, чтобы нажать для этого.
- Расшифровать данные с помощью пароля
После cryptfs cryptocompleteуспешного завершения среда отображает пользовательский интерфейс, запрашивающий пароль диска. Чеки UI пароль, отправив команду cryptfs checkpwв vold. Если пароль правильный (что определяется путем успешного монтирования дешифрованного /dataво временном местоположении, а затем его размонтирования), vold сохраняет имя дешифрованного блочного устройства в свойстве ro.crypto.fs_crypto_blkdevи возвращает статус 0 в пользовательский интерфейс. Если пароль неверный, он возвращает -1 в пользовательский интерфейс.
- Стоп рамки
Пользовательский интерфейс создает криптографическую загрузку и затем вызывает команду vold cryptfs restart. voldустанавливает свойство vold.decryptна trigger_reset_main, что вызывает init.rcделать class_reset main. Это останавливает все службы в mainклассе, что позволяет tmpfs /dataотключаться.
- Mount / data
voldзатем монтирует дешифрованный реальный /dataраздел и подготавливает новый раздел (который, возможно, никогда не был подготовлен, если он был зашифрован с помощью параметра очистки, которое не поддерживается в первом выпуске). Он устанавливает свойство vold.post_fs_data_doneк 0и затем устанавливает vold.decryptв trigger_post_fs_data. Это заставляет init.rcего запускать post-fs-data commands. Они будут создавать необходимые каталоги и ссылки , а затем установить vold.post_fs_data_doneв 1. Как только voldвидит 1в этом свойстве, оно устанавливает свойство vold.decryptв trigger_restart_framework. Это вызывает init.rcзапуск служб в классе mainснова, а также запуск служб в классе late_startвпервые после загрузки.
- Начать полный каркас
Теперь фреймворк загружает все свои сервисы, используя расшифрованную файловую систему / data, и система готова к использованию.
Хранение зашифрованного ключа
Зашифрованный ключ хранится в крипто-метаданных. Аппаратное обеспечение реализовано с использованием возможности подписи Trusted Execution Environment (TEE). Ранее мы шифровали мастер-ключ с помощью ключа, сгенерированного путем обращения scryptк паролю пользователя и сохраненной соли.
Чтобы сделать ключ устойчивым к внешним атакам, мы расширяем этот алгоритм, подписывая полученный ключ хранимым ключом TEE. Результирующая подпись затем превращается в ключ соответствующей длины еще одним применением scrypt. Этот ключ затем используется для шифрования и дешифрования главного ключа. Чтобы сохранить этот ключ:
- Генерация случайного 16-байтового ключа шифрования диска (DEK) и 16-байтовой соли.
- Применить
scryptпароль пользователя и соль для получения 32-байтового промежуточного ключа 1 (IK1).
- Дополните IK1 нулевым байтом до размера аппаратно-привязанного закрытого ключа (HBK). В частности, мы дополняем как: 00 || IK1 || 00..00; один нулевой байт, 32 байта IK1, 223 нулевых байта.
- Знак дополнен IK1 с HBK для получения 256-байтового IK2.
- Применить
scryptк IK2 и соли (та же соль, что и на шаге 2) для получения 32-байтового IK3.
- Используйте первые 16 байтов IK3 в качестве KEK и последние 16 байтов в качестве IV.
- Зашифруйте DEK с помощью AES_CBC, с ключом KEK и вектором инициализации IV.