Android 7.0 i nowsze wersje obsługują szyfrowanie oparte na plikach (FBE). FBE umożliwia szyfrowanie różnych plików za pomocą różnych kluczy, które można odblokowywać niezależnie. Te klucze służą do szyfrowania zarówno zawartości plików, jak i ich nazw. Gdy używane jest FBE, inne informacje, takie jak układy katalogów, rozmiary plików, uprawnienia oraz czasy utworzenia i modyfikacji, nie są szyfrowane. Te inne informacje są zbiorczo nazywane metadanymi systemu plików.
Android 9 wprowadził obsługę szyfrowania metadanych. W przypadku szyfrowania metadanych pojedynczy klucz obecny w momencie uruchomienia szyfruje wszystkie treści, które nie są szyfrowane przez FBE. Ten klucz jest chroniony przez KeyMint (wcześniej Keymaster), który z kolei jest chroniony przez weryfikację podczas uruchamiania.
Szyfrowanie metadanych jest zawsze włączone w przypadku pamięci dostosowywanej, gdy włączone jest FBE. Szyfrowanie metadanych można też włączyć w pamięci wewnętrznej. Urządzenia, które zostały wprowadzone na rynek z Androidem 11 lub nowszym, muszą mieć włączone szyfrowanie metadanych w pamięci wewnętrznej.
Implementacja w pamięci wewnętrznej
Szyfrowanie metadanych w pamięci wewnętrznej nowych urządzeń możesz skonfigurować, konfigurując system plików metadata, zmieniając sekwencję init i włączając szyfrowanie metadanych w pliku fstab urządzenia.
Wymagania wstępne
Szyfrowanie metadanych można skonfigurować tylko wtedy, gdy partycja danych jest formatowana po raz pierwszy. Dlatego ta funkcja jest przeznaczona tylko dla nowych urządzeń. Nie jest to coś, co powinna zmienić aktualizacja OTA.
Szyfrowanie metadanych wymaga, aby w jądrze był włączony moduł dm-default-key. W Androidzie 11 i nowszych wersjach dm-default-key jest obsługiwany przez wspólne jądra Androida w wersji 4.14 i nowszych. Ta wersja dm-default-key używa niezależnej od sprzętu i dostawcy platformy szyfrowania o nazwie blk-crypto.
Aby włączyć dm-default-key, użyj:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_DM_DEFAULT_KEY=y
Gdy jest dostępny, dm-default-key używa sprzętu do szyfrowania wbudowanego (sprzętu, który szyfruje i odszyfrowuje dane podczas ich przesyłania do i z urządzenia pamięci masowej). Jeśli nie używasz sprzętu do szyfrowania wbudowanego, musisz też włączyć rezerwowy interfejs API kryptografii jądra:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
Jeśli nie używasz sprzętu do szyfrowania wbudowanego, włącz też dowolną dostępną akcelerację opartą na procesorze, zgodnie z zaleceniami w dokumentacji FBE.
W Androidzie 10 i starszych wersjach dm-default-key nie był obsługiwany przez wspólne jądro Androida. Dlatego to dostawcy musieli implementować dm-default-key.
Konfigurowanie systemu plików metadanych
Ponieważ niczego nie można odczytać z partycji userdata, dopóki nie będzie dostępny klucz szyfrowania metadanych, w tabeli partycji trzeba wydzielić osobną partycję o nazwie partycja metadanych do przechowywania obiektów blob KeyMint, które chronią ten klucz. Partycja metadanych powinna mieć rozmiar 16 MB.
fstab.hardware musi zawierać wpis dotyczący systemu plików metadanych, który znajduje się na tej partycji, i montować go w /metadata, w tym flagę formattable, aby zapewnić jego formatowanie podczas uruchamiania. System plików f2fs nie działa na mniejszych partycjach. Zalecamy używanie zamiast niego systemu ext4. Przykład:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
Aby upewnić się, że punkt podłączania /metadata istnieje, dodaj ten wiersz do BoardConfig-common.mk:
BOARD_USES_METADATA_PARTITION := true
Zmiany w sekwencji init
Gdy używane jest szyfrowanie metadanych, vold musi być uruchomiony przed zamontowaniem /data. Aby upewnić się, że jest on uruchamiany wystarczająco wcześnie, dodaj ten blok do init.hardware.rc:
# We need vold early for metadata encryption
on early-fs
start vold
Przed próbą zamontowania /data przez init KeyMint musi być uruchomiony i gotowy.
init.hardware.rc powinien już zawierać instrukcję mount_all
, która montuje /data samą w bloku on
late-fs. Przed tym wierszem dodaj dyrektywę do wykonania usługi 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
Włączanie szyfrowania metadanych
Na koniec dodaj keydirectory=/metadata/vold/metadata_encryption do kolumny fs_mgr_flags we wpisie fstab dla userdata. Na przykład pełny wiersz fstab może wyglądać tak:
/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
Domyślnie algorytmem szyfrowania metadanych w pamięci wewnętrznej jest AES-256-XTS. Można to zmienić, ustawiając opcję metadata_encryption, również w kolumnie fs_mgr_flags:
- Na urządzeniach, które nie mają akceleracji AES, szyfrowanie Adiantum można
włączyć, ustawiając
metadata_encryption=adiantum. Na urządzeniach, które obsługują klucze szyfrowania wbudowanego zawinięte w sprzęt, klucz szyfrowania metadanych można zawinąć w sprzęt, ustawiając
metadata_encryption=aes-256-xts:wrappedkeylubmetadata_encryption=aes-256-xts:wrappedkey_v0.wrappedkeyto nowoczesna wersja.wrappedkey_v0należy używać tylko na urządzeniach, które nie obsługująwrappedkeylub zostały już wprowadzone na rynek zwrappedkey_v0. Więcej informacji znajdziesz w artykule Włączanie kluczy zawiniętych.W obu przypadkach
aes-256-xtsmożna pominąć, ponieważ jest to algorytm domyślny. Na przykład,metadata_encryption=:wrappedkeyjest równoważne zmetadata_encryption=aes-256-xts:wrappedkey.
Ponieważ interfejs jądra do dm-default-key zmienił się w Androidzie 11, musisz też upewnić się, że w device.mk masz ustawioną prawidłową wartość PRODUCT_SHIPPING_API_LEVEL. Jeśli na przykład Twoje urządzenie zostało wprowadzone na rynek z Androidem 11 (poziom API 30), device.mk powinien zawierać:
PRODUCT_SHIPPING_API_LEVEL := 30
Możesz też ustawić tę właściwość systemu, aby wymusić użycie nowego interfejsu API dm-default-key niezależnie od poziomu API dostawy:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.dm_default_key.options_format.version=2
Weryfikacja
Aby sprawdzić, czy szyfrowanie metadanych jest włączone i działa prawidłowo, uruchom testy opisane poniżej. Pamiętaj też o typowych problemach opisanych poniżej.
Testy
Zacznij od uruchomienia tego polecenia, aby sprawdzić, czy szyfrowanie metadanych jest włączone w pamięci wewnętrznej:
adb rootadb shell dmctl table userdata
Dane wyjściowe powinny być podobne do tych:
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
Jeśli zastąpisz domyślne ustawienia szyfrowania, ustawiając opcję metadata_encryption w pliku fstab urządzenia, dane wyjściowe będą się nieco różnić od powyższych. Jeśli na przykład włączysz szyfrowanie Adiantum, trzecie
pole będzie miało wartość xchacha12,aes-adiantum-plain64 zamiast
aes-xts-plain64.
Następnie uruchom vts_kernel_encryption_test aby sprawdzić poprawność szyfrowania metadanych i FBE:
atest vts_kernel_encryption_test
lub:
vts-tradefed run vts -m vts_kernel_encryption_test
Typowe problemy
Podczas wywołania mount_all, które montuje zaszyfrowaną metadanymi partycję /data, init wykonuje narzędzie vdc. Narzędzie vdc łączy się z vold przez binder, aby skonfigurować urządzenie zaszyfrowane metadanymi i zamontować partycję. Podczas tego wywołania init jest zablokowany, a próby odczytania lub ustawienia właściwości init są blokowane do momentu zakończenia mount_all.
Jeśli na tym etapie jakakolwiek część pracy vold jest bezpośrednio lub pośrednio blokowana przez odczytywanie lub ustawianie właściwości, dochodzi do zakleszczenia. Ważne jest, aby vold mógł zakończyć odczytywanie kluczy, interakcję z KeyMint i montowanie katalogu danych bez dalszej interakcji z init.
Jeśli KeyMint nie jest w pełni uruchomiony, gdy działa mount_all, nie odpowiada na vold, dopóki nie odczyta określonych właściwości z init, co powoduje opisane zakleszczenie. Umieszczenie exec_start wait_for_keymaster nad odpowiednim wywołaniem mount_all zgodnie z instrukcjami zapewnia, że KeyMint jest w pełni uruchomiony z wyprzedzeniem, co pozwala uniknąć tego zakleszczenia.
Konfiguracja w pamięci dostosowywanej
Od Androida 9 forma szyfrowania metadanych jest zawsze włączona w przypadku pamięci adaptacyjnej, gdy włączone jest FBE, nawet jeśli szyfrowanie metadanych nie jest włączone w pamięci wewnętrznej.
W AOSP są 2 implementacje szyfrowania metadanych w pamięci adaptacyjnej: przestarzała oparta na dm-crypt i nowsza oparta na dm-default-key. Aby upewnić się, że dla Twojego urządzenia jest wybrana prawidłowa implementacja, sprawdź, czy w device.mk masz ustawioną prawidłową wartość PRODUCT_SHIPPING_API_LEVEL. Jeśli na przykład Twoje urządzenie zostało wprowadzone na rynek z Androidem 11 (poziom API 30), device.mk powinien zawierać:
PRODUCT_SHIPPING_API_LEVEL := 30
Możesz też ustawić te właściwości systemu, aby wymusić użycie nowej metody szyfrowania metadanych woluminu (i nowej domyślnej wersji zasad FBE) niezależnie od poziomu API dostawy:
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
Obecna metoda
Na urządzeniach wprowadzonych na rynek z Androidem 11 lub nowszym szyfrowanie metadanych w pamięci dostosowywanej używa modułu jądra dm-default-key, tak jak w pamięci wewnętrznej. Wymagania wstępne dotyczące tego, które opcje konfiguracji jądra należy włączyć, znajdziesz powyżej. Pamiętaj, że sprzęt do szyfrowania wbudowanego, który działa w pamięci wewnętrznej urządzenia, może być niedostępny w pamięci adaptacyjnej, dlatego może być wymagane ustawienie CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y.
Domyślnie metoda szyfrowania metadanych woluminu dm-default-key używa algorytmu szyfrowania AES-256-XTS z 4096-bajtowymi sektorami kryptograficznymi. Algorytm można zastąpić, ustawiając właściwość systemu ro.crypto.volume.metadata.encryption. Wartość tej właściwości ma taką samą składnię jak opisana powyżej opcja metadata_encryption fstab. Na przykład na urządzeniach, które nie mają akceleracji AES
, szyfrowanie Adiantum
można włączyć, ustawiając
ro.crypto.volume.metadata.encryption=adiantum.
Starsza metoda
Na urządzeniach wprowadzonych na rynek z Androidem 10 i starszymi wersjami szyfrowanie metadanych w pamięci dostosowywanej używa modułu jądra dm-crypt zamiast dm-default-key:
CONFIG_DM_CRYPT=y
W przeciwieństwie do metody dm-default-key metoda dm-crypt powoduje dwukrotne szyfrowanie zawartości plików: raz za pomocą klucza FBE i raz za pomocą klucza szyfrowania metadanych. To podwójne szyfrowanie zmniejsza wydajność i nie jest wymagane do osiągnięcia celów bezpieczeństwa szyfrowania metadanych, ponieważ Android zapewnia, że klucze FBE są co najmniej tak samo trudne do złamania jak klucz szyfrowania metadanych. Dostawcy mogą dostosować jądro, aby uniknąć podwójnego
szyfrowania, w szczególności przez zaimplementowanie opcji
allow_encrypt_override którą Android przekazuje do
dm-crypt gdy właściwość systemu
ro.crypto.allow_encrypt_override jest ustawiona na true.
Te dostosowania nie są obsługiwane przez wspólne jądro Androida.
Domyślnie metoda szyfrowania metadanych woluminu dm-crypt używa algorytmu szyfrowania AES-128-CBC z ESSIV i 512-bajtowymi sektorami kryptograficznymi. Można to zmienić, ustawiając te właściwości systemu (które są też używane w przypadku FDE):
ro.crypto.fde_algorithmwybiera algorytm szyfrowania metadanych. Dostępne opcje toaes-128-cbciadiantum. Adiantum można używać tylko wtedy, gdy urządzenie nie ma akceleracji AES.ro.crypto.fde_sector_sizewybiera rozmiar sektora kryptograficznego. Dostępne opcje to 512, 1024, 2048 i 4096. W przypadku szyfrowania Adiantum użyj 4096.