Szyfrowanie metadanych

Android 7.0 i nowszy obsługuje szyfrowanie oparte na plikach (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żywane do szyfrowania zarówno zawartości plików, jak i nazw plików. Podczas korzystania z FBE inne informacje, takie jak układ katalogów, rozmiary plików, uprawnienia i czasy tworzenia/modyfikacji, nie są szyfrowane. Łącznie te inne informacje są znane jako metadane systemu plików.

Android 9 wprowadził obsługę szyfrowania metadanych. Dzięki szyfrowaniu metadanych pojedynczy klucz obecny w czasie rozruchu szyfruje zawartość, która nie jest szyfrowana przez FBE. Ten klucz jest chroniony przez Keymaster, który z kolei jest chroniony przez zweryfikowany rozruch.

Szyfrowanie metadanych jest zawsze włączone w dostępnej pamięci masowej , gdy włączona jest funkcja FBE. Szyfrowanie metadanych można również włączyć w pamięci wewnętrznej. Urządzenia uruchomione z systemem Android 11 lub nowszym muszą mieć włączone szyfrowanie metadanych w pamięci wewnętrznej.

Wdrożenie na pamięci wewnętrznej

Możesz skonfigurować szyfrowanie metadanych w pamięci wewnętrznej nowych urządzeń, konfigurując system plików metadata , zmieniając kolejność init i włączając szyfrowanie metadanych w pliku fstab urządzenia.

Warunki wstępne

Szyfrowanie metadanych można skonfigurować tylko podczas pierwszego sformatowania partycji danych. W rezultacie ta funkcja jest dostępna tylko dla nowych urządzeń; to nie jest coś, co OTA powinna zmienić.

Szyfrowanie metadanych wymaga włączenia modułu dm-default-key w jądrze. W systemie Android 11 i nowszych dm-default-key jest obsługiwany przez wspólne jądra systemu Android w wersji 4.14 i nowszych. Ta wersja dm-default-key korzysta z niezależnej od sprzętu i dostawcy struktury 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 używa wbudowanego sprzętu szyfrującego (sprzętu, który szyfruje/odszyfrowuje dane w drodze do/z urządzenia pamięci masowej), jeśli jest dostępny. Jeśli nie będziesz używać wbudowanego sprzętu szyfrującego, konieczne jest również włączenie awaryjnego API kryptograficznego jądra:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

Jeśli nie używasz wbudowanego sprzętu szyfrującego, powinieneś również włączyć wszelkie dostępne przyspieszenie oparte na procesorze, zgodnie z zaleceniami w dokumentacji FBE .

W systemie Android 10 i starszych, dm-default-key nie był obsługiwany przez wspólne jądro systemu Android. Dlatego do dostawców należało zaimplementowanie dm-default-key .

Skonfiguruj system plików metadanych

Ponieważ nic z partycji danych użytkownika nie może być odczytane, dopóki klucz szyfrowania metadanych nie jest obecny, tabela partycji musi odłożyć oddzielną partycję o nazwie „partycja metadanych” do przechowywania obiektów blob keymastera, 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, montując go w /metadata , w tym flagę formattable , aby zapewnić sformatowanie podczas uruchamiania. System plików f2fs nie działa na mniejszych partycjach; zalecamy zamiast tego użycie ext4. Na przykład:

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

Aby upewnić się, że punkt montowania /metadata istnieje, dodaj następujący wiersz do BoardConfig-common.mk :

BOARD_USES_METADATA_PARTITION := true

Zmiany w sekwencji początkowej

Gdy używane jest szyfrowanie metadanych, vold musi być uruchomiony przed zamontowaniem /data . Aby upewnić się, że zostanie uruchomiony odpowiednio wcześnie, dodaj następującą sekcję do init.hardware.rc :

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

Keymaster musi być uruchomiony i gotowy, zanim init spróbuje zamontować /data .

init.hardware.rc powinien już zawierać instrukcję mount_all , która montuje sam /data w on late-fs . Przed tym wierszem dodaj dyrektywę, aby wykonać usługę 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 wpisu fstab dla userdata . Na przykład pełna linia 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 algorytm szyfrowania metadanych w pamięci wewnętrznej to 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 obsługujących klucze opakowane sprzętowo klucz szyfrowania metadanych można opakować sprzętowo, ustawiając metadata_encryption=aes-256-xts:wrappedkey_v0 (lub równoważnie metadata_encryption=:wrappedkey_v0 , ponieważ aes-256-xts jest algorytmem domyślnym).

Ponieważ interfejs jądra na dm-default-key zmienił się w Androidzie 11, musisz również upewnić się, że ustawiłeś poprawną wartość dla PRODUCT_SHIPPING_API_LEVEL w device.mk . Na przykład, jeśli Twoje urządzenie uruchamia się z systemem Android 11 (poziom interfejsu API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz również ustawić następującą właściwość systemową, aby wymusić użycie nowego interfejsu API dm-default-key niezależnie od poziomu interfejsu API wysyłki:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.dm_default_key.options_format.version=2

Walidacja

Aby sprawdzić, czy szyfrowanie metadanych jest włączone i działa poprawnie, uruchom testy opisane poniżej. Pamiętaj też o typowych problemach opisanych poniżej.

Testy

Zacznij od uruchomienia następującego polecenia, aby sprawdzić, czy szyfrowanie metadanych jest włączone w pamięci wewnętrznej:

adb root
adb shell dmctl table userdata

Wynik powinien być podobny do:

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 fstab urządzenia, dane wyjściowe będą się nieznacznie różnić od powyższych. Na przykład, jeśli włączyłeś szyfrowanie Adiantum , trzecim polem będzie xchacha12,aes-adiantum-plain64 zamiast aes-xts-plain64 .

Następnie uruchom vts_kernel_encryption_test , aby zweryfikować poprawność szyfrowania metadanych i FBE:

atest vts_kernel_encryption_test

lub:

vts-tradefed run vts -m vts_kernel_encryption_test

Powszechne problemy

Podczas wywołania mount_all , które montuje partycję /data zaszyfrowaną metadanymi, init wykonuje narzędzie vdc. Narzędzie vdc łączy się z vold over binder , aby skonfigurować urządzenie zaszyfrowane metadanymi i zamontować partycję. Na czas tego wywołania init jest blokowany, a próby odczytu lub ustawienia właściwości init będą blokowane do momentu zakończenia mount_all . Jeśli na tym etapie jakakolwiek część pracy vold zostanie bezpośrednio lub pośrednio zablokowana podczas odczytu lub ustawienia właściwości, nastąpi zakleszczenie. Ważne jest, aby upewnić się, że vold może dokończyć odczytywanie kluczy, interakcję z Keymasterem i montowanie katalogu danych bez dalszej interakcji z init .

Jeśli Keymaster nie zostanie w pełni uruchomiony po uruchomieniu mount_all , nie zareaguje na vold , dopóki nie odczyta pewnych właściwości z init , co skutkuje dokładnie opisanym zakleszczeniem. Umieszczenie exec_start wait_for_keymaster nad odpowiednim wywołaniem mount_all , zgodnie z opisem, zapewnia, że ​​Keymaster jest w pełni uruchomiony z wyprzedzeniem, co pozwala uniknąć tego zakleszczenia.

Konfiguracja na możliwej do przyjęcia pamięci

Od Androida 9 forma szyfrowania metadanych jest zawsze włączona w przystosowanej pamięci masowej , gdy włączona jest funkcja FBE, nawet jeśli szyfrowanie metadanych nie jest włączone w pamięci wewnętrznej.

W AOSP istnieją dwie implementacje szyfrowania metadanych w zaadaptowanej pamięci: przestarzała oparta na dm-crypt i nowsza oparta na dm-default-key . Aby upewnić się, że została wybrana prawidłowa implementacja dla Twojego urządzenia, upewnij się, że w device.mk ustawiono poprawną wartość parametru PRODUCT_SHIPPING_API_LEVEL . Na przykład, jeśli Twoje urządzenie uruchamia się z systemem Android 11 (poziom interfejsu API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz również ustawić następujące właściwości systemu, aby wymusić użycie nowej metody szyfrowania metadanych woluminu (i nowej domyślnej wersji polityki FBE) niezależnie od poziomu interfejsu API wysyłki:

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 uruchamianych z systemem Android 11 lub nowszym szyfrowanie metadanych w przystosowanej pamięci masowej wykorzystuje moduł jądra dm-default-key , podobnie jak w pamięci wewnętrznej. Zobacz wymagania wstępne powyżej, które opcje konfiguracji jądra włączyć. Należy zauważyć, że sprzęt do szyfrowania inline, który działa w pamięci wewnętrznej urządzenia, może być niedostępny w pamięci możliwej do zaadoptowania, dlatego może być wymagane 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 nadpisać, ustawiając właściwość systemową 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 ro.crypto.volume.metadata.encryption=adiantum .

Wcześniejsza metoda

Na urządzeniach uruchamianych z systemem Android 10 lub starszym szyfrowanie metadanych w przystosowanej pamięci masowej 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 zaszyfrowanie zawartości pliku: 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ą wprowadzać dostosowania jądra, aby uniknąć podwójnego szyfrowania, w szczególności przez zaimplementowanie opcji allow_encrypt_override , którą system Android przekaże do dm-crypt , gdy właściwość systemowa ro.crypto.allow_encrypt_override jest ustawiona na true . Te dostosowania nie są obsługiwane przez wspólne jądro systemu Android.

Domyślnie metoda szyfrowania metadanych woluminu dm-crypt wykorzystuje algorytm szyfrowania AES-128-CBC z ESSIV i 512-bajtowymi sektorami kryptograficznymi. Można to zmienić, ustawiając następujące właściwości systemu (które są również używane w FDE):

  • ro.crypto.fde_algorithm wybiera algorytm szyfrowania metadanych. Do wyboru są 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 kryptograficznego. Dostępne opcje to 512, 1024, 2048 i 4096. W przypadku szyfrowania Adiantum użyj 4096.