Я цитирую руководство по 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.