Шифрування файлової системи в Ubuntu Touch 24.04

Шифрування файлової системи у цьому документі стосується шифрування файлів «кожного окремо» з використанням «Шифрування окремих файлів» («File Based Encryption») на противагу до «Повного шифрування диска» («Full Disk Encryption»).

Шифрування в Ubuntu Touch 24.04 реалізоване з fscrypt.

Технічні подробиці

Замість повного шифрування диска, наприклад, з LUKS, fscrypt активує шифрування для файлових систем ext4 та f2fs для окремих тек та ієрархій. Таким чином система може завантажитися до незашифрованої кореневої файлової системи, відкладаючи введення PIN-коду, поки це не буде потрібно. Це особливо важливо для схеми розділення Ubuntu Touch.

Це досягається шляхом завантаження користувацького ключа або в область (keyring) користувача (політика v1), або в область файлової системи (політика v2), за допомогою чого файлова система зможе потім шифрувати дані. Завантаження ключа в область користувача призводить до заборони дешифрування файлів для інших користувачів, навіть для root. Коли використовується область файлової системи, такі речі, як Docker з доступом до домашнього каталогу, працюють правильно.

Усі теки налаштовані користувачем з використанням захисту облікового запису (пінкодом чи паролем) будуть розблоковані під час завантаження, коли користувач розблокує свій пристрій. Це значить, що користувач потенційно міг би додати кілька додаткових каталогів для шифрування.

Створення файлу fscrypt.conf

Для нового портованого пристрою необхідний попередньо налаштований файл /etc/fscrypt.conf. Для підтримки шифрування на пристрої це потрібно перекрити.

Для генерації нового файлу виконайте sudo fscrypt setup.

В результаті новий файл повинен бути схожий на це:

{
    "source": "custom_passphrase",
    "hash_costs": {
        "time": "12",
        "memory": "131072",
        "parallelism": "8"
    },
    "options": {
        "padding": "32",
        "contents": "AES_256_XTS",
        "filenames": "AES_256_CTS",
        "policy_version": "1"
    },
    "use_fs_keyring_for_v1_policies": false,
    "allow_cross_user_metadata": false
}

Перемикач конфігурації use_fs_keyring_for_v1_policies

Адаптації пристрою, які постачаються з версією політики «2», але хочуть зберегти підтримку версії шифрування «1» та мати можливість на вході розблокувати домашній каталог і зберегти ключ у наборі ключів файлової системи, накопичувач повинен мати для цього перемикача значення true.

Пристрої, які постачаються з новими ядрами (5.4 та вище) працюють без таких змін та можуть залишатися виключно на політиці шифрування версії 2.

Налаштування інформації про пристрій

Щоб переконання про завершену конфігурацію та розблокування інтерфейсу шифрування у lomiri-system-settings, потрібно встановити параметр FilesystemEncryption у налаштуванні інформації про пристрій у значення true.

Зразок:

sargo:
  Vendor: Google
  PrettyName: Pixel 3a
  DeviceType: phone
  GridUnit: 25
  SupportedOrientations:
    - Portrait
    - Landscape
    - InvertedLandscape
  FilesystemEncryption: true

Лише після цього Ви зможете на цьому пристрої налаштувати шифрування.

Зворотне портування (backports) ядер

Якщо у Вашого пристрою ядро версій 4.14 чи 4.19. Ви можете зробити зворотне портування версії 2 політики з репозиторію Android Common Kernel Для отримання джерел звідти додайте їх до свого дерева Git:

git remote add google https://android.googlesource.com/kernel/common

Простий спосіб для «трансплантації» політики версії 2 — це пошук найближчої загальної версії ядра з підтримкою версії 2 до версії ядра Вашого пристрою, перевірка окремих файлів у файловій структурі ядра, пов’язаних із fscrypt та підтримкою файлової системи. Для початку знайдіть коміт з коментарем «fscrypt: v2 encryption policy support» та відповідні коміти до загального ядра.

Наприклад, якщо пристрій з ядром 4.19.81, відповідно до історії Git загального ядра, відповідна основа джерела (source base) буде commit c2ad33f0296a2528fd0bf4e96af0802dad0b1b27, основана на версії 4.19.78 та близько збігається з іншим кодом у дереві. Отримайте цей джерельний код командою:

git fetch google c2ad33f0296a2528fd0bf4e96af0802dad0b1b27

Після визначення правильного коміту перевірте fs/crypto та файлові системи з підтримкою шифрування у цьому коміті (замініть цей хеш коміту у прикладі на свій, який Ви знайшли):

git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/crypto/
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/f2fs/
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/ext4
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/ubifs
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/f2fs_fs.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/fs.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/fscrypt.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/uapi/linux/fs.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/uapi/linux/fscrypt.h

Якщо компіляція Вашого ядра за першим разом буде невдалою з помилками про відсутні ідентифікатори, невизначені посилання чи відсутні файли, порівняйте все із загальним ядром та перевірте відсутні зміни та залежності окремо:

git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/verity
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/unicode
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/direct-io.c
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- fs/inode.c
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- mm/mmap.c
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- block/blk-merge.c
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/mm.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/dcache.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/linux/fsverity.h
git checkout c2ad33f0296a2528fd0bf4e96af0802dad0b1b27 -- include/uapi/linux/fsverity.h

Якщо ядро Вашого пристрою має перехресні залежності між кодом шифрування, кодом файлових систем та іншими драйверами, Вам потрібно для розміщення нового fscrypt розірвати ці залежності ручними змінами коду. Наприклад, на пристроях Qualcomm драйвер «qseecom» може викликати функції, переписані ручними змінами (checkout), і Вам доведеться доповнити ті відсутні функції у своїй адаптації. У ядрі з активованим «sdcardfs» для роботи з новим fscrypt потрібно адаптувати драйвер sdcardfs або через портування відсутніх функцій або просто через видалення їх.