Szyfrowanie metadanych

Android 7.0 lub nowszy obsługuje szyfrowanie na podstawie plików (FBE). FBE umożliwia szyfrowanie różnych plików za pomocą różnych kluczy, które można odblokować niezależnie. Te klucze służą do szyfrowania zarówno zawartości plików, jak i ich nazw. Gdy jest używany FBE, inne informacje, takie jak układy katalogów, rozmiary plików, uprawnienia oraz czasy tworzenia i modyfikowania, nie są szyfrowane. Te pozostałe informacje są zbiorczo określane jako metadane systemu plików.

Android 9 wprowadził obsługę szyfrowania metadanych. W przypadku szyfrowania metadanych jeden klucz obecny podczas uruchamiania szyfruje wszystkie treści, które nie są szyfrowane przez FBE. Ten klucz jest chroniony przez program Keymaster, który z kolei chroni go przez funkcję weryfikacji podczas uruchamiania.

Szyfrowanie metadanych jest zawsze włączone w przechowywaniu dostosowywanym, gdy włączona jest funkcja FBE. Szyfrowanie metadanych można też włączyć w pamięci wewnętrznej. Urządzenia z Androidem 11 lub nowszym muszą mieć włączone szyfrowanie metadanych w pamięci wewnętrznej.

Implementacja w pamięci wewnętrznej

Aby skonfigurować szyfrowanie metadanych w pamięci wewnętrznej nowych urządzeń, możesz skonfigurować system plików metadata, zmienić sekwencję inicjowania i włączyć szyfrowanie metadanych w pliku fstab urządzenia.

Wymagania wstępne

Szyfrowanie metadanych można skonfigurować tylko wtedy, gdy partycja danych zostanie po raz pierwszy sformatowana. Dlatego ta funkcja jest dostępna tylko w przypadku nowych urządzeń i to nie jest cokolwiek, co powinno się zmienić.

Szyfrowanie metadanych wymaga włączenia modułu dm-default-key w jądrze. W Androidzie 11 i nowszych pakiet dm-default-key jest obsługiwany przez typowe jądra Androida w wersji 4.14 lub nowszej. Ta wersja dm-default-key wykorzystuje sprzęt i niezależną od dostawcy platformę 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

dm-default-key korzysta ze wbudowanego sprzętu do szyfrowania (sprzętu, który szyfruje/odszyfrowuje dane podczas przesyłania do/z urządzenia pamięci masowej), jeśli jest dostępny. Jeśli nie używasz sprzętowego szyfrowania wbudowanego w urządzenie, musisz też włączyć alternatywne szyfrowanie za pomocą interfejsu kryptograficznego jądra:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

Jeśli nie używasz sprzętu do szyfrowania wbudowanego, musisz też włączyć dowolną dostępną akcelerację opartą na CPU zgodnie z zaleceniami w dokumentacji FBE.

W Androidzie 10 i starszych dm-default-key nie było obsługiwane przez wspólne jądro Androida. W związku z tym implementacja dm-default-key zależała od dostawców.

Konfigurowanie systemu plików metadanych

Ponieważ nie ma klucza szyfrowania metadanych, z partycji danych użytkownika nie można odczytać żadnych danych, dlatego tabela partycji musi przeznaczyć osobną partycję o nazwie „partycja metadanych” do przechowywania obiektów blob Keymaster chroniących 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 podczas podłączania do niej pod adresem /metadata, w tym flagę formattable, która zapewnia formatowanie podczas uruchamiania. System plików f2fs nie działa na mniejszych partycjach. Zalecamy użycie systemu plików ext4. Na przykład:

/dev/block/bootdevice/by-name/metadata              /metadata          ext4        noatime,nosuid,nodev,discard                          wait,check,formattable

Aby mieć pewność, że punkt zamontowania /metadata istnieje, dodaj ten wiersz do pliku BoardConfig-common.mk:

BOARD_USES_METADATA_PARTITION := true

Zmiany w sekwencji inicjacji

Jeśli używasz szyfrowania metadanych, vold musi być uruchomiony, zanim /data zostanie zamontowany. Aby zapewnić, że zostanie ona uruchomiona odpowiednio wcześnie, dodaj do pliku init.hardware.rc ten wers:

# We need vold early for metadata encryption
on early-fs
    start vold

Keymaster musi być uruchomiony i gotowy, zanim rozpocznie próbę podłączenia /data.

Plik init.hardware.rc powinien już zawierać instrukcję mount_all, która powoduje zamontowanie pliku /data w sekcji 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 w rekordzie fstab dla userdata. Pełny wiersz fstab może na przykład 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 algorytm szyfrowania metadanych w pamięci wewnętrznej to AES-256-XTS. Można to zastąpić, 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 wartość metadata_encryption=adiantum.
  • Na urządzeniach, które obsługują klucze opakowane sprzętowo, klucz szyfrowania metadanych można opakować sprzętowo za pomocą ustawienia metadata_encryption=aes-256-xts:wrappedkey_v0 (lub odpowiednika metadata_encryption=:wrappedkey_v0, ponieważ aes-256-xts jest domyślnym algorytmem).

Ponieważ interfejs jądra dla dm-default-key zmienił się w Androidzie 11, musisz też ustawić prawidłową wartość dla PRODUCT_SHIPPING_API_LEVELdevice.mk. Jeśli na przykład urządzenie jest uruchamiane z Androidem 11 (poziom API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz też ustawić tę właściwość systemową, aby wymuszać użycie nowego interfejsu API dm-default-key niezależnie od poziomu interfejsu 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, wykonaj opisane poniżej testy. Zwróć też uwagę na częste problemy opisane poniżej.

Testy

Najpierw uruchom to polecenie, aby sprawdzić, czy szyfrowanie metadanych jest włączone w pamięci wewnętrznej:

adb root
adb shell dmctl table userdata

Dane wyjściowe powinny wyglądać tak:

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 domyślne ustawienia szyfrowania zostały zastąpione przez ustawienie opcji metadata_encryption w ustawieniach fstab urządzenia, dane wyjściowe będą się nieco różnić od podanych powyżej. Jeśli na przykład masz włączone szyfrowanie Adiantum, trzecie pole to xchacha12,aes-adiantum-plain64, a nie aes-xts-plain64.

Następnie uruchom polecenie 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ływania funkcji mount_all, która podłącza partycję /data szyfrowaną przez metadane, init wykonuje narzędzie vdc. Narzędzie vdc łączy się z vold przez binder, aby skonfigurować urządzenie zaszyfrowane metadanymi i podłączyć partycję. Podczas trwania tego wywołania init jest zablokowany, a próby odczytu lub ustawienia właściwości init są blokowane, dopóki nie zakończy się mount_all. Jeśli na tym etapie jakakolwiek część pracy vold jest bezpośrednio lub pośrednio zablokowana w odtwarzaniu lub ustawianiu właściwości, w wynikach blokady zakleszczeń. Ważne jest, aby vold mogło odczytać klucze, nawiązać połączenie z Keymaster i zamontować katalog danych bez dalszej interakcji z init.

Jeśli Keymaster nie jest w pełni uruchomiony, gdy mount_all jest uruchamiany, nie odpowiada na vold, dopóki nie odczyta pewnych właściwości z init, co powoduje dokładnie opisany wyżej impas. Umieszczenie funkcji exec_start wait_for_keymaster przed odpowiednim wywołaniem funkcji mount_all zapewnia, że Keymaster jest w pełni uruchomiony z wyprzedzeniem, co zapobiega blokadzie.

Konfiguracja pamięci dostosowywanej

Od Androida 9 w przypadku włączonego FBE zawsze włączana jest forma szyfrowania metadanych w adoptowalnej pamięci, nawet jeśli szyfrowanie metadanych nie jest włączone w pamięci wewnętrznej.

W AOSP istnieją 2 implementacje szyfrowania metadanych w przystosowywalnej pamięci masowej: przestarzała oparta na dm-crypt i nowsza oparta na dm-default-key. Aby mieć pewność, że dla Twojego urządzenia wybrano prawidłową implementację, sprawdź, czy w polu PRODUCT_SHIPPING_API_LEVEL ustawiona jest prawidłowa wartość device.mk. Jeśli na przykład urządzenie uruchamia się z Androidem 11 (poziom API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz też skonfigurować te właściwości systemowe, aby wymuszać użycie nowej metody szyfrowania metadanych woluminu (i nowej domyślnej wersji zasady FBE) niezależnie od poziomu interfejsu 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

Bieżąca metoda

Na urządzeniach z Androidem 11 lub nowszym szyfrowanie metadanych na adoptowanej pamięci używa modułu jądra dm-default-key, tak jak w przypadku pamięci wewnętrznej. Aby dowiedzieć się, które opcje konfiguracji jądra należy włączyć, zapoznaj się z wymaganiami wstępnymi powyżej. Pamiętaj, że wbudowane urządzenie do szyfrowania, które działa w pamięci wewnętrznej urządzenia, może być niedostępne w pamięci adekwatnej, 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 szyfrowania. 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 fstab metadata_encryption. Na przykład na urządzeniach, które nie mają akceleracji AES, szyfrowanie Adiantum można włączyć, ustawiając wartość ro.crypto.volume.metadata.encryption=adiantum.

Starsza metoda

Na urządzeniach z Androidem 10 lub starszym szyfrowanie metadanych na adoptowanym miejscu na dane używa modułu jądra dm-crypt, a nie dm-default-key:

CONFIG_DM_CRYPT=y

W przeciwieństwie do metody dm-default-key metoda dm-crypt powoduje dwukrotne szyfrowanie zawartości pliku: raz za pomocą klucza FBE, a drugi raz za pomocą klucza szyfrowania metadanych. Podwójne szyfrowanie zmniejsza wydajność i nie jest wymagane do osiągnięcia celów w zakresie bezpieczeństwa, czyli szyfrowania metadanych, ponieważ Android zapewnia, że klucze FBE są co najmniej tak trudne do naruszenia, jak klucz szyfrowania metadanych. Dostawcy mogą dostosować jądro, aby uniknąć podwójnego szyfrowania, zwłaszcza przez wdrożenie opcji allow_encrypt_override, która Android przekazuje do dm-crypt, gdy właściwość systemowa ro.crypto.allow_encrypt_override ma wartość true. Te dostosowania nie są obsługiwane przez popularne jądro Androida.

Domyślnie metoda szyfrowania metadanych woluminu dm-crypt używa algorytmu szyfrowania AES-128-CBC z ESSIV i 512-bajtowymi sektorami szyfrowania. Można je zastąpić, ustawiając te właściwości systemu (które są też używane do szyfrowania całego dysku):

  • ro.crypto.fde_algorithm wybiera algorytm szyfrowania metadanych. Dostępne opcje to aes-128-cbc i adiantum. Adiantum można używać tylko wtedy, gdy urządzenie nie ma akceleracji AES.
  • ro.crypto.fde_sector_size wybiera rozmiar sektora kryptowalut. Dostępne opcje to 512, 1024, 2048 i 4096. W przypadku szyfrowania Adiantum użyj kodu 4096.