Szyfrowanie oparte na plikach

Android 7.0 i nowsze wersje obsługują szyfrowanie oparte na plikach (FBE). Szyfrowanie oparte na plikach umożliwia szyfrowanie różnych plików za pomocą różnych kluczy, które można odblokowywać niezależnie od siebie.

W tym artykule opisujemy, jak włączyć szyfrowanie oparte na plikach na nowych urządzeniach i jak aplikacje systemowe mogą korzystać z interfejsów API Direct Boot, aby zapewnić użytkownikom jak najlepsze i najbezpieczniejsze wrażenia.

Wszystkie urządzenia z Androidem 10 lub nowszym muszą używać szyfrowania opartego na plikach.

Bezpośredni rozruch

Szyfrowanie oparte na plikach umożliwia korzystanie z nowej funkcji wprowadzonej w Androidzie 7.0, która nazywa się bezpośrednie uruchamianie. Bezpośrednie uruchamianie umożliwia uruchamianie zaszyfrowanych urządzeń bezpośrednio na ekranie blokady. Wcześniej na urządzeniach zaszyfrowanych za pomocą pełnego szyfrowania dysku (FDE) użytkownicy musieli podać dane logowania, zanim uzyskali dostęp do jakichkolwiek danych. Uniemożliwiało to wykonywanie na telefonie wszystkich operacji oprócz tych najbardziej podstawowych. Na przykład alarmy nie działały, usługi ułatwień dostępu były niedostępne, a telefony nie mogły odbierać połączeń, ale były ograniczone tylko do podstawowych operacji wybierania numerów alarmowych.

Dzięki wprowadzeniu szyfrowania opartego na plikach (FBE) i nowych interfejsów API, które informują aplikacje o szyfrowaniu, aplikacje mogą działać w ograniczonym kontekście. Może to nastąpić, zanim użytkownicy podadzą swoje dane logowania, przy jednoczesnej ochronie prywatnych informacji o użytkownikach.

Na urządzeniu z szyfrowaniem opartym na plikach każdy użytkownik ma do dyspozycji 2 lokalizacje pamięci dostępne dla aplikacji:

  • zaszyfrowane miejsce na dane (CE), które jest domyślnym miejscem przechowywania danych i jest dostępne tylko po odblokowaniu urządzenia przez użytkownika;
  • pamięć urządzenia zaszyfrowanego (DE), która jest dostępna zarówno w trybie bezpośredniego rozruchu, jak i po odblokowaniu urządzenia przez użytkownika;

To rozdzielenie zwiększa bezpieczeństwo profili służbowych, ponieważ umożliwia ochronę więcej niż jednego użytkownika naraz, ponieważ szyfrowanie nie jest już oparte wyłącznie na haśle rozruchowym.

Interfejs Direct Boot API umożliwia aplikacjom obsługującym szyfrowanie dostęp do każdego z tych obszarów. Wprowadziliśmy zmiany w cyklu życia aplikacji, aby uwzględnić potrzebę powiadamiania aplikacji, gdy pamięć CE użytkownika zostanie odblokowana w odpowiedzi na pierwsze podanie danych logowania na ekranie blokady lub w przypadku profilu służbowego – po podaniu hasła do profilu służbowego. Urządzenia z Androidem 7.0 muszą obsługiwać te nowe interfejsy API i cykle życia niezależnie od tego, czy implementują FBE. Bez FBE pamięć DE i CE jest zawsze odblokowana.

Pełna implementacja szyfrowania opartego na plikach w systemach plików Ext4 i F2FS jest dostępna w projekcie Android Open Source Project (AOSP) i wymaga jedynie włączenia na urządzeniach spełniających wymagania. Producenci, którzy zdecydują się na korzystanie z FBE, mogą poszukać sposobów na optymalizację tej funkcji na podstawie używanego układu SOC.

Wszystkie niezbędne pakiety w AOSP zostały zaktualizowane, aby obsługiwały bezpośrednie uruchamianie. Jeśli jednak producenci urządzeń używają dostosowanych wersji tych aplikacji, muszą zadbać o to, aby były dostępne co najmniej pakiety obsługujące bezpośredni rozruch, które zapewniają te usługi:

  • Usługi telefoniczne i dialer
  • Metoda wprowadzania haseł na ekranie blokady

Przykłady i źródło

Android udostępnia referencyjną implementację szyfrowania opartego na plikach, w której vold (system/vold) zapewnia funkcje zarządzania urządzeniami pamięci masowej i woluminami na Androidzie. Dodanie FBE zapewnia usłudze vold kilka nowych poleceń, które obsługują zarządzanie kluczami CE i DE wielu użytkowników. Oprócz podstawowych zmian umożliwiających korzystanie z funkcji szyfrowania opartego na plikach w jądrze zmodyfikowano wiele pakietów systemowych, w tym ekran blokady i interfejs systemu, aby obsługiwały funkcje FBE i Direct Boot. Są to między innymi:

  • Aplikacja Telefon w AOSP (pakiety/aplikacje/Telefon)
  • Zegar na biurko (packages/apps/DeskClock)
  • LatinIME (packages/inputmethods/LatinIME)*
  • Aplikacja Ustawienia (packages/apps/Settings)*
  • SystemUI (frameworks/base/packages/SystemUI)*

* Aplikacje systemowe, które używają atrybutu manifestu defaultToDeviceProtectedStorage

Więcej przykładów aplikacji i usług, które obsługują szyfrowanie, znajdziesz, uruchamiając polecenie mangrep directBootAware w katalogu frameworks lub packages drzewa źródłowego AOSP.

Zależności

Aby bezpiecznie korzystać z implementacji FBE w AOSP, urządzenie musi spełniać te wymagania:

  • Obsługa jądra w przypadku szyfrowania Ext4 lub F2FS.
  • Obsługa KeyMint (lub Keymaster 1.0 lub nowszego). Nie obsługujemy Keymastera 0.3, ponieważ nie zapewnia on niezbędnych funkcji ani wystarczającej ochrony kluczy szyfrowania.
  • KeyMint/Keymaster i Gatekeeper muszą być zaimplementowane w zaufanym środowisku wykonawczym (TEE), aby zapewnić ochronę kluczy DE, dzięki czemu nieautoryzowany system operacyjny (niestandardowy system operacyjny zainstalowany na urządzeniu) nie będzie mógł po prostu zażądać kluczy DE.
  • Aby mieć pewność, że klucze DE nie są dostępne dla nieautoryzowanego systemu operacyjnego, wymagane jest sprzętowe źródło zaufania i weryfikacja podczas uruchamiania powiązane z inicjalizacją KeyMint.

Implementacja

Przede wszystkim aplikacje takie jak budzik, telefon i funkcje ułatwień dostępu powinny być oznaczone jako android:directBootAware zgodnie z dokumentacją dla deweloperów dotyczącą bezpośredniego uruchamiania.

Obsługa jądra systemu

Obsługa szyfrowania Ext4 i F2FS w jądrach Androida w wersji 3.18 i nowszych. Aby włączyć go w jądrze w wersji 5.1 lub nowszej, użyj:

CONFIG_FS_ENCRYPTION=y

W przypadku starszych jąder użyj CONFIG_EXT4_ENCRYPTION=y, jeśli system plików userdata urządzenia to Ext4, lub CONFIG_F2FS_FS_ENCRYPTION=y, jeśli system plikówuserdata urządzenia to F2FS.

Jeśli Twoje urządzenie obsługuje pamięć adaptacyjną lub korzysta z szyfrowania metadanych w pamięci wewnętrznej, włącz też opcje konfiguracji jądra wymagane do szyfrowania metadanych zgodnie z opisem w dokumentacji szyfrowania metadanych.

Oprócz funkcjonalnej obsługi szyfrowania Ext4 lub F2FS producenci urządzeń powinni też włączyć akcelerację kryptograficzną, aby przyspieszyć szyfrowanie oparte na plikach i poprawić wrażenia użytkownika. Na przykład na urządzeniach z architekturą ARM64 akcelerację ARMv8 CE (Cryptography Extensions) można włączyć, ustawiając te opcje konfiguracji jądra:

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

Aby jeszcze bardziej zwiększyć wydajność i zmniejszyć zużycie energii, producenci urządzeń mogą też rozważyć wdrożenie sprzętu do szyfrowania w trybie inline, który szyfruje i odszyfrowuje dane podczas ich przesyłania do i z urządzenia pamięci masowej. Wspólne jądra Androida (w wersji 4.14 i nowszych) zawierają platformę, która umożliwia korzystanie z szyfrowania inline, gdy dostępne jest wsparcie sprzętowe i sterowniki dostawcy. Platformę szyfrowania wbudowanego można włączyć, ustawiając te opcje konfiguracji jądra:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

Jeśli urządzenie korzysta z pamięci UFS, włącz też:

CONFIG_SCSI_UFS_CRYPTO=y

Jeśli urządzenie korzysta z pamięci masowej eMMC, włącz też:

CONFIG_MMC_CRYPTO=y

Włączanie szyfrowania opartego na plikach

Włączenie szyfrowania FBE na urządzeniu wymaga włączenia go w pamięci wewnętrznej (userdata). Spowoduje to też automatyczne włączenie FBE w pamięci dostosowywanej, ale w razie potrzeby format szyfrowania w pamięci dostosowywanej można zastąpić.

Pamięć wewnętrzna

Szyfrowanie oparte na plikach włącza się, dodając opcję fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] do kolumny fs_mgr_flags w wierszu fstab dla userdata. Ta opcja określa format szyfrowania na wewnętrznej pamięci masowej. Zawiera maksymalnie 3 parametry rozdzielone dwukropkami:

  • Parametr contents_encryption_mode określa, którego algorytmu kryptograficznego używa się do szyfrowania zawartości pliku. Może to być aes-256-xts lub adiantum. Od Androida 11 można też pozostawić to pole puste, aby określić domyślny algorytm, którym jest aes-256-xts.
  • Parametr filenames_encryption_mode określa, który algorytm kryptograficzny jest używany do szyfrowania nazw plików. Może to być aes-256-cts, aes-256-heh, adiantum lub aes-256-hctr2. Jeśli nie zostanie określona, domyślnie będzie to aes-256-cts, gdy contents_encryption_mode to aes-256-xts, lub adiantum, gdy contents_encryption_mode to adiantum.
  • Parametr flags, który jest nowością w Androidzie 11, to lista flag rozdzielonych znakiem +. Obsługiwane są te flagi:
    • Flaga v1 wybiera zasady szyfrowania w wersji 1, a flaga v2 wybiera zasady szyfrowania w wersji 2. Zasady szyfrowania w wersji 2 używają bezpieczniejszej i bardziej elastycznej funkcji wyprowadzania klucza. Domyślna wersja to 2, jeśli urządzenie zostało wprowadzone na rynek z Androidem 11 lub nowszym (zgodnie z ro.product.first_api_level), lub 1, jeśli urządzenie zostało wprowadzone na rynek z Androidem 10 lub starszym.
    • Flaga inlinecrypt_optimized wybiera format szyfrowania zoptymalizowany pod kątem sprzętu do szyfrowania wbudowanego, który nie obsługuje wydajnie dużej liczby kluczy. W tym celu generuje tylko jeden klucz szyfrowania zawartości pliku na klucz CE lub DE, a nie jeden na plik. Generowanie wektorów inicjujących (IV) jest odpowiednio dostosowywane.
    • Flaga emmc_optimized jest podobna do inlinecrypt_optimized, ale wybiera też metodę generowania wektora inicjującego, która ogranicza wektory inicjujące do 32 bitów. Tej flagi należy używać tylko na sprzęcie do szyfrowania inline, który jest zgodny ze specyfikacją JEDEC eMMC v5.2 i dlatego obsługuje tylko 32-bitowe wektory IV. W przypadku innego sprzętu do szyfrowania wbudowanego użyj inlinecrypt_optimized. Tej flagi nie należy używać w przypadku pamięci masowej opartej na UFS. Specyfikacja UFS umożliwia korzystanie z 64-bitowych wektorów IV.
    • Na urządzeniach, które obsługują klucze szyfrowania inline opakowane sprzętowo, klucze FBE można opakować sprzętowo, dodając flagę wrappedkey lub wrappedkey_v0. wrappedkey to nowoczesna wersja. wrappedkey_v0 należy używać tylko na urządzeniach, które nie obsługują wrappedkey lub zostały już wprowadzone na rynek z wrappedkey_v0. Więcej informacji znajdziesz w artykule o włączaniu opakowanych kluczy.
    • Flaga dusize_4k wymusza rozmiar jednostki danych szyfrowania na 4096 bajtów, nawet jeśli rozmiar bloku systemu plików nie wynosi 4096 bajtów. Rozmiar jednostki danych szyfrowania to poziom szczegółowości szyfrowania zawartości pliku. Ta flaga jest dostępna od Androida 15. Tej flagi należy używać tylko do włączania korzystania ze sprzętu do szyfrowania wbudowanego, który nie obsługuje jednostek danych większych niż 4096 bajtów, na urządzeniu, które używa rozmiaru strony większego niż 4096 bajtów i systemu plików f2fs.

Jeśli nie używasz sprzętu do szyfrowania wbudowanego, zalecane ustawienie dla większości urządzeń to fileencryption=aes-256-xts. Jeśli używasz sprzętu do szyfrowania wbudowanego, zalecane ustawienie dla większości urządzeń to fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (lub równoważnie fileencryption=::inlinecrypt_optimized). Na urządzeniach bez żadnej formy akceleracji AES zamiast AES można użyć Adiantum, ustawiając fileencryption=adiantum.

Od Androida 14 preferowanym trybem szyfrowania nazw plików na urządzeniach z przyspieszonymi instrukcjami kryptograficznymi jest AES-HCTR2. Jednak tylko nowsze jądra Androida obsługują AES-HCTR2. W przyszłej wersji Androida ma się stać domyślnym trybem szyfrowania nazw plików. Jeśli jądro obsługuje AES-HCTR2, możesz włączyć tę funkcję do szyfrowania nazw plików, ustawiając filenames_encryption_mode na aes-256-hctr2. W najprostszym przypadku można to zrobić za pomocą znaku fileencryption=aes-256-xts:aes-256-hctr2.

Na urządzeniach, które zostały wprowadzone na rynek z Androidem 10 lub starszym, można też używać wartości fileencryption=ice, aby określić użycie trybu szyfrowania zawartości plików FSCRYPT_MODE_PRIVATE. Ten tryb nie jest zaimplementowany w wersjach jądra Androida, ale może być zaimplementowany przez dostawców za pomocą niestandardowych poprawek jądra. Format na dysku generowany w tym trybie był specyficzny dla dostawcy. Na urządzeniach z Androidem 11 lub nowszym ten tryb nie jest już dozwolony i należy używać standardowego formatu szyfrowania.

Domyślnie zawartość plików jest szyfrowana za pomocą interfejsu API kryptografii jądra systemu Linux. Jeśli zamiast tego chcesz używać sprzętu do szyfrowania wbudowanego, dodaj też opcję montowania inlinecrypt. Na przykład pełna liniafstab może wyglądać tak:

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

Pamięć dostosowywana

Od Androida 9 można używać FBE i pamięci dostosowywanej.

Określenie opcji fileencryption fstab dla userdata automatycznie włącza zarówno FBE, jak i szyfrowanie metadanych na pamięci masowej, którą można zaadaptować. Możesz jednak zastąpić formaty szyfrowania FBE lub metadanych w pamięci dostosowywanej, ustawiając właściwości w pliku PRODUCT_PROPERTY_OVERRIDES.

Na urządzeniach wprowadzonych na rynek z Androidem 11 lub nowszym użyj tych właściwości:

  • ro.crypto.volume.options (nowość w Androidzie 11) wybiera format szyfrowania FBE w pamięci dostosowywanej. Ma taką samą składnię jak argument opcji fileencryption w pliku fstab i używa tych samych wartości domyślnych. W sekcji rekomendacji dotyczących fileencryption powyżej znajdziesz informacje o tym, co tutaj wpisać.
  • ro.crypto.volume.metadata.encryption wybiera format szyfrowania metadanych w pamięci dostosowywanej. Zapoznaj się z dokumentacją szyfrowania metadanych.

Na urządzeniach wprowadzonych na rynek z Androidem 10 lub starszym używaj tych właściwości:

  • ro.crypto.volume.contents_mode wybiera tryb szyfrowania treści. Jest to odpowiednik pierwszego pola rozdzielonego dwukropkiem w elemencie ro.crypto.volume.options.
  • ro.crypto.volume.filenames_mode wybiera tryb szyfrowania nazw plików. Odpowiada to drugiemu polu rozdzielonemu dwukropkiem w ro.crypto.volume.options, z tym że domyślną wartością na urządzeniach, które zostały wprowadzone na rynek z Androidem 10 lub starszym, jest aes-256-heh. Na większości urządzeń należy to wyraźnie zastąpić wartością aes-256-cts.
  • ro.crypto.fde_algorithm i ro.crypto.fde_sector_size wybierz format szyfrowania metadanych na pamięci dostosowywanej. Zapoznaj się z dokumentacją dotyczącą szyfrowania metadanych.

Integracja z KeyMint

Warstwa HAL KeyMint powinna być uruchamiana jako część klasy early_hal. Dzieje się tak, ponieważ FBE wymaga, aby KeyMint był gotowy do obsługi żądań w fazie uruchamiania post-fs-data, czyli wtedy, gdy vold konfiguruje klucze początkowe.

Wykluczanie katalogów

init stosuje systemowy klucz DE do wszystkich katalogów najwyższego poziomu w /data z wyjątkiem katalogów, które muszą być niezaszyfrowane, takich jak katalog zawierający sam systemowy klucz DE i katalogi zawierające katalogi CE lub DE użytkownika. Klucze szyfrowania są stosowane rekursywnie i nie można ich zastąpić w podkatalogach.

W Androidzie 11 i nowszych klucz, który init stosuje się do katalogów, można kontrolować za pomocą argumentu encryption=<action> polecenia mkdir w skryptach inicjujących. Możliwe wartości <action> są opisane w pliku README języka inicjowania Androida.

W Androidzie 10 działania szyfrowania init były zakodowane na stałe w tej lokalizacji:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

Na Androidzie 9 i starszych lokalizacja była następująca:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

Można dodać wyjątki, aby zapobiec szyfrowaniu niektórych katalogów. Jeśli takie modyfikacje zostaną wprowadzone, producent urządzenia powinien uwzględnić zasady SELinux, które przyznają dostęp tylko aplikacjom, które muszą korzystać z niezaszyfrowanego katalogu. Powinno to wykluczyć wszystkie niezaufane aplikacje.

Jedynym znanym dopuszczalnym przypadkiem użycia jest obsługa starszych funkcji OTA.

Obsługa bezpośredniego uruchamiania w aplikacjach systemowych

Dostosowywanie aplikacji do bezpośredniego uruchamiania

Aby ułatwić szybką migrację aplikacji systemowych, wprowadziliśmy 2 nowe atrybuty, które można ustawić na poziomie aplikacji. Atrybut defaultToDeviceProtectedStorage jest dostępny tylko w przypadku aplikacji systemowych. Atrybut directBootAware jest dostępny dla wszystkich.

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

Atrybut directBootAware na poziomie aplikacji jest skrótem oznaczającym, że wszystkie komponenty w aplikacji są świadome szyfrowania.

Atrybut defaultToDeviceProtectedStorage przekierowuje domyślną lokalizację pamięci aplikacji, aby wskazywała pamięć DE zamiast pamięci CE. Aplikacje systemowe korzystające z tego flagi muszą dokładnie sprawdzić wszystkie dane przechowywane w domyślnej lokalizacji i zmienić ścieżki danych wrażliwych, aby korzystać z pamięci CE. Producenci urządzeń korzystający z tej opcji powinni dokładnie sprawdzać przechowywane dane, aby upewnić się, że nie zawierają one danych osobowych.

W tym trybie dostępne są te interfejsy API systemu, które umożliwiają bezpośrednie zarządzanie kontekstem opartym na pamięci CE, gdy jest to potrzebne. Są one odpowiednikami interfejsów API chronionych na urządzeniu.

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

Obsługa wielu użytkowników

Każdy użytkownik w środowisku z wieloma użytkownikami otrzymuje osobny klucz szyfrowania. Każdy użytkownik otrzymuje 2 klucze: DE i CE. Użytkownik 0 musi najpierw zalogować się na urządzeniu, ponieważ jest to specjalny użytkownik. Jest to istotne w przypadku administrowania urządzeniami.

Aplikacje obsługujące szyfrowanie wchodzą w interakcje z użytkownikami w ten sposób: INTERACT_ACROSS_USERS i INTERACT_ACROSS_USERS_FULL umożliwiają aplikacji działanie na wszystkich użytkownikach urządzenia. Mogą one jednak uzyskiwać dostęp tylko do katalogów zaszyfrowanych za pomocą szyfrowania po stronie klienta w przypadku użytkowników, którzy są już odblokowani.

Aplikacja może swobodnie działać w obszarach DE, ale odblokowanie jednego użytkownika nie oznacza, że wszyscy użytkownicy na urządzeniu są odblokowani. Aplikacja powinna sprawdzić ten stan przed próbą uzyskania dostępu do tych obszarów.

Każdy identyfikator użytkownika profilu służbowego otrzymuje też 2 klucze: DE i CE. Gdy wyzwanie służbowe zostanie spełnione, użytkownik profilu zostanie odblokowany, a KeyMint (w TEE) może udostępnić klucz TEE profilu.

Obsługa aktualizacji

Partycja odzyskiwania nie może uzyskać dostępu do pamięci chronionej przez DE na partycji userdata. Urządzenia z szyfrowaniem opartym na plikach powinny obsługiwać aktualizacje OTA za pomocą aktualizacji systemu A/B. Aktualizację OTA można zastosować podczas normalnego działania, więc nie ma potrzeby przywracania, aby uzyskać dostęp do danych na zaszyfrowanym dysku.

Jeśli używasz starszego rozwiązania OTA, które wymaga trybu odzyskiwania, aby uzyskać dostęp do pliku OTA na partycji userdata:

  1. Utwórz katalog najwyższego poziomu (na przykład misc_ne) na partycji userdata.
  2. Skonfiguruj ten katalog najwyższego poziomu jako niezaszyfrowany (patrz Wykluczanie katalogów).
  3. Utwórz katalog w katalogu najwyższego poziomu, aby przechowywać pakiety OTA.
  4. Dodaj regułę SELinux i konteksty plików, aby kontrolować dostęp do tego katalogu i jego zawartości. Tylko proces lub aplikacje otrzymujące aktualizacje OTA powinny mieć możliwość odczytywania i zapisywania danych w tym katalogu. Żadna inna aplikacja ani proces nie powinny mieć dostępu do tego katalogu.

Walidacja

Aby upewnić się, że wdrożona wersja funkcji działa zgodnie z oczekiwaniami, najpierw uruchom liczne testy szyfrowania CTS, takie jak DirectBootHostTest i EncryptionTest.

Jeśli urządzenie ma Androida 11 lub nowszego, uruchom też vts_kernel_encryption_test:

atest vts_kernel_encryption_test

lub:

vts-tradefed run vts -m vts_kernel_encryption_test

Dodatkowo producenci urządzeń mogą przeprowadzać te testy ręczne. Na urządzeniu z włączonym szyfrowaniem FBE:

  • Sprawdź, czy ro.crypto.state istnieje.
    • Sprawdź, czy ro.crypto.state jest zaszyfrowany
  • Sprawdź, czy ro.crypto.type istnieje.
    • Upewnij się, że ro.crypto.type ma wartość file

Testerzy mogą też sprawdzić, czy pamięć CE jest zablokowana, zanim urządzenie zostanie odblokowane po raz pierwszy od uruchomienia. Aby to zrobić, użyj kompilacji userdebug lub eng, ustaw kod PIN, wzór lub hasło na głównym użytkowniku i ponownie uruchom urządzenie. Przed odblokowaniem urządzenia uruchom to polecenie, aby sprawdzić pamięć CE głównego użytkownika. Jeśli urządzenie korzysta z trybu użytkownika systemu bez interfejsu graficznego (większość urządzeń Automotive), głównym użytkownikiem jest użytkownik 10, więc uruchom:

adb root; adb shell ls /data/user/10

Na innych urządzeniach (większości urządzeń innych niż Automotive) głównym użytkownikiem jest użytkownik 0, więc wykonaj to polecenie:

adb root; adb shell ls /data/user/0

Sprawdź, czy nazwy plików na liście są zakodowane w formacie Base64, co oznacza, że są zaszyfrowane, a klucz do ich odszyfrowania nie jest jeszcze dostępny. Jeśli nazwy plików są wyświetlane w postaci zwykłego tekstu, coś jest nie tak.

Zachęcamy też producentów urządzeń do przeprowadzenia na swoich urządzeniach lub jądrach testów fscrypt w systemie Linux. Te testy są częścią zestawu testów systemu plików xfstests. Jednak te testy upstream nie są oficjalnie obsługiwane przez Androida.

Szczegóły implementacji AOSP

W tej sekcji znajdziesz szczegółowe informacje o implementacji AOSP i opis działania szyfrowania opartego na plikach. Aby korzystać z FBE i bezpośredniego uruchamiania na urządzeniach, producenci nie muszą wprowadzać żadnych zmian.

Szyfrowanie fscrypt

Implementacja AOSP korzysta z szyfrowania „fscrypt” (obsługiwanego przez ext4 i f2fs) w jądrze i jest zwykle skonfigurowana w ten sposób:

  • Szyfrowanie zawartości pliku za pomocą AES-256 w trybie XTS
  • Szyfrowanie nazw plików za pomocą algorytmu AES-256 w trybie CBC-CTS

Obsługiwane jest też szyfrowanie Adiantum. Gdy szyfrowanie Adiantum jest włączone, zarówno zawartość plików, jak i ich nazwy są szyfrowane za pomocą Adiantum.

fscrypt obsługuje 2 wersje zasad szyfrowania: wersję 1 i wersję 2. Wersja 1 została wycofana, a wymagania dokumentu CDD dotyczące urządzeń z Androidem 11 lub nowszym są zgodne tylko z wersją 2. Zasady szyfrowania w wersji 2 używają HKDF-SHA512 do uzyskiwania rzeczywistych kluczy szyfrowania z kluczy dostarczonych przez przestrzeń użytkownika.

Więcej informacji o fscrypt znajdziesz w dokumentacji jądra upstream.

Klasy pamięci

W tabeli poniżej znajdziesz szczegółowe informacje o kluczach FBE i katalogach, które chronią:

Klasa pamięci masowej Opis Katalogi
Niezaszyfrowane Katalogi w /data, które nie mogą być lub nie muszą być chronione przez FBE. Na urządzeniach, które używają szyfrowania metadanych, te katalogi nie są tak naprawdę niezaszyfrowane, ale są chronione przez klucz szyfrowania metadanych, który jest odpowiednikiem klucza DE systemu.
  • /data/apex, z wyjątkiem /data/apex/decompressed i /data/apex/ota_reserved, które są systemowymi DE
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • Wszystkie katalogi, których podkatalogi używają różnych kluczy FBE. Na przykład ponieważ każdy katalog /data/user/${user_id} używa klucza dla użytkownika, /data/user nie używa żadnego klucza.
System DE Dane zaszyfrowane na urządzeniu, które nie są powiązane z konkretnym użytkownikiem.
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • Wszystkie pozostałe podkatalogi katalogu /data, które nie są wymienione w tej tabeli jako należące do innej klasy
Na uruchomienie pliki systemowe, które nie muszą być zachowane po ponownym uruchomieniu; /data/per_boot
Użytkownik CE (wewnętrzny) Dane zaszyfrowane przy użyciu danych logowania poszczególnych użytkowników w pamięci wewnętrznej
  • /data/data (alias /data/user/0)
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
Użytkownik DE (wewnętrzny) Dane zaszyfrowane na urządzeniu dla każdego użytkownika w pamięci wewnętrznej
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
CE użytkownika (możliwe do przeniesienia) Dane zaszyfrowane za pomocą danych logowania poszczególnych użytkowników w pamięci dostosowywanej
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
User DE (adoptable) Dane poszczególnych użytkowników zaszyfrowane na urządzeniu w pamięci dostosowywanej
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

Przechowywanie i ochrona kluczy

Wszystkimi kluczami FBE zarządza vold. Są one przechowywane na dysku w postaci zaszyfrowanej, z wyjątkiem klucza uruchamiania, który nie jest przechowywany. W tabeli poniżej znajdziesz lokalizacje, w których są przechowywane różne klucze FBE:

Typ klucza Lokalizacja klucza Klasa pamięci masowej lokalizacji klucza
Klucz DE systemu /data/unencrypted Niezaszyfrowane
Klucze CE użytkownika (wewnętrzne) /data/misc/vold/user_keys/ce/${user_id} System DE
Klucze użytkownika DE (wewnętrzne) /data/misc/vold/user_keys/de/${user_id} System DE
Klucze CE użytkownika (możliwe do zaadoptowania) /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} User CE (internal)
Klucze DE użytkownika (możliwe do zaadoptowania) /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} User DE (internal)

Jak widać w tabeli powyżej, większość kluczy FBE jest przechowywana w katalogach zaszyfrowanych za pomocą innego klucza FBE. Kluczy nie można odblokować, dopóki nie zostanie odblokowana klasa pamięci, w której się znajdują.

vold stosuje też warstwę szyfrowania do wszystkich kluczy FBE. Każdy klucz oprócz kluczy CE do pamięci wewnętrznej jest szyfrowany za pomocą algorytmu AES-256-GCM przy użyciu własnego klucza Keystore, który nie jest ujawniany poza TEE. Dzięki temu klucze FBE nie mogą zostać odblokowane, dopóki nie zostanie uruchomiony zaufany system operacyjny, co jest wymuszane przez weryfikację podczas uruchamiania. W przypadku klucza Keystore wymagana jest też odporność na przywracanie, co umożliwia bezpieczne usuwanie kluczy FBE na urządzeniach, na których KeyMint obsługuje odporność na przywracanie. Jeśli ochrona przed przywróceniem poprzedniej wersji jest niedostępna, jako Tag::APPLICATION_ID klucza Keystore używany jest skrót SHA-512 16 384 losowych bajtów zapisanych w pliku secdiscardable przechowywanym razem z kluczem. Aby odzyskać klucz FBE, trzeba odzyskać wszystkie te bajty.

Klucze CE do pamięci wewnętrznej są lepiej chronione, dzięki czemu nie można ich odblokować bez znajomości czynnika wiedzy ekranu blokady (LSKF) użytkownika (kodu PIN, wzoru lub hasła), tokena bezpiecznego resetowania hasła lub kluczy po stronie klienta i serwera na potrzeby operacji wznowienia po ponownym uruchomieniu. Tokeny resetowania hasła można tworzyć tylko w przypadku profili służbowych i urządzeń w pełni zarządzanych.

W tym celu vold szyfruje każdy klucz CE do przechowywania wewnętrznego za pomocą klucza AES-256-GCM pochodzącego z syntetycznego hasła użytkownika. Hasło syntetyczne to niezmienny, kryptograficzny klucz tajny o wysokiej entropii, który jest generowany losowo dla każdego użytkownika. LockSettingsService w system_server zarządza hasłem syntetycznym i sposobami jego ochrony.

Aby chronić hasło syntetyczne za pomocą LSKF, funkcja LockSettingsService najpierw rozciąga LSKF, przekazując go przez scrypt, co zajmuje około 25 ms i wykorzystuje około 2 MiB pamięci. Ponieważ klucze LSKF są zwykle krótkie, ten krok zwykle nie zapewnia dużego bezpieczeństwa. Główną warstwą zabezpieczeń jest Secure Element (SE) lub opisane poniżej ograniczenie szybkości wymuszane przez TEE.

Jeśli urządzenie implementuje Weaver HAL, LockSettingsService mapuje rozciągnięte hasło LSKF na losowy obiekt tajny o wysokiej entropii przechowywany w SE lub TEE za pomocą Weaver. LockSettingsService następnie szyfruje syntetyczne hasło dwukrotnie: najpierw za pomocą klucza programowego pochodzącego z rozszerzonego klucza LSKF i tajnego klucza Weaver, a potem za pomocą klucza Keystore niezwiązanego z uwierzytelnianiem. Zapewnia to ograniczenie liczby prób odgadnięcia LSKF wymuszane przez SE lub TEE.

Jeśli urządzenie nie implementuje Weaver, LockSettingsService używa rozciągniętego LSKF jako hasła Gatekeeper. Następnie LockSettingsService dwukrotnie szyfruje hasło syntetyczne: najpierw za pomocą klucza programowego pochodzącego z rozszerzonego LSKF i skrótu pliku secdiscardable, a następnie za pomocą klucza Keystore, który jest powiązany z rejestracją Gatekeepera. Zapewnia to wymuszane przez TEE ograniczanie liczby prób odgadnięcia klucza LSKF.

Gdy LSKF zostanie zmieniony, LockSettingsService usunie wszystkie informacje powiązane z powiązaniem hasła syntetycznego ze starym LSKF. Na urządzeniach, które obsługują klucze Weaver lub klucze Keystore odporne na przywracanie, gwarantuje to bezpieczne usunięcie starego powiązania. Z tego powodu opisane tutaj zabezpieczenia są stosowane nawet wtedy, gdy użytkownik nie ma LSKF.