Szyfrowanie metadanych

Android 7.0 i nowsze obsługują 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. Klucze te służą do szyfrowania zarówno zawartości plików, jak i nazw plików. Kiedy używany jest FBE, inne informacje, takie jak układ katalogów, rozmiary plików, uprawnienia i czas tworzenia/modyfikacji, nie są szyfrowane. Łącznie te inne informacje nazywane są metadanymi systemu plików.

W Androidzie 9 wprowadzono obsługę szyfrowania metadanych. Dzięki szyfrowaniu metadanych pojedynczy klucz obecny podczas uruchamiania szyfruje całą zawartość, która nie jest szyfrowana przez FBE. Klucz ten 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 także włączyć w pamięci wewnętrznej. Urządzenia z systemem Android 11 lub nowszym muszą mieć włączone szyfrowanie metadanych w pamięci wewnętrznej.

Implementacja w 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 sekwencję inicjującą i włączając szyfrowanie metadanych w pliku fstab urządzenia.

Warunki wstępne

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

Szyfrowanie metadanych wymaga włączenia modułu dm-default-key w jądrze. W Androidzie 11 i nowszych, dm-default-key jest obsługiwany przez popularne jądra Androida w wersji 4.14 i nowszych. Ta wersja dm-default-key wykorzystuje platformę szyfrowania niezależną od sprzętu i dostawcy 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 interfejsu API kryptografii jądra:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

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

W Androidzie 10 i starszych dm-default-key nie był obsługiwany przez wspólne jądro Androida. Dlatego wdrożenie dm-default-key należało do dostawców.

Skonfiguruj system plików metadanych

Ponieważ nic z partycji danych użytkownika nie może zostać odczytane, dopóki nie będzie klucza szyfrowania metadanych, tabela partycji musi wydzielić osobną partycję zwaną „partycją metadanych” do przechowywania obiektów BLOB klucza głównego 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, montując go w /metadata , łącznie z flagą formattable , aby zapewnić sformatowanie go podczas rozruchu. System plików f2fs nie działa na mniejszych partycjach; zamiast tego zalecamy 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 podłączenia /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, przed zamontowaniem /data należy uruchomić polecenie vold . Aby mieć pewność, że zostanie uruchomiony wystarczająco wcześnie, dodaj następującą sekcję do pliku init.hardware.rc :

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

Keymaster musi być uruchomiony i gotowy przed podjęciem prób zamontowania /data .

init.hardware.rc powinien już zawierać instrukcję mount_all , która montuje sam /data w sekcji on late-fs . Przed tą linią dodaj dyrektywę uruchamiającą 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ć następująco:

/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 obejść ustawiając opcję metadata_encryption , również w kolumnie fs_mgr_flags :

  • Na urządzeniach pozbawionych 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ż domyślnym algorytmem jest aes-256-xts ).

Ponieważ interfejs jądra dla dm-default-key zmienił się w Androidzie 11, musisz także 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 API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz także 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, wykonaj testy opisane poniżej. Należy także pamiętać o typowych problemach opisanych poniżej.

Testy

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

adb root
adb shell dmctl table userdata

Dane wyjściowe powinny być podobne 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ą nieznacznie różnić się 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 metody mount_all , która montuje partycję /data zaszyfrowaną metadanymi, init wykonuje narzędzie vdc. Narzędzie vdc łączy się z vold over binder w celu skonfigurowania urządzenia zaszyfrowanego metadanymi i zamontowania partycji. Na czas trwania tego wywołania init jest blokowany, a próby odczytania lub ustawienia właściwości init będą blokowane do czasu zakończenia mount_all . Jeśli na tym etapie jakakolwiek część pracy vold zostanie bezpośrednio lub pośrednio zablokowana podczas odczytywania lub ustawiania właściwości, nastąpi zakleszczenie. Ważne jest, aby upewnić się, że vold może dokończyć pracę polegającą na czytaniu kluczy, interakcji z Keymasterem i montowaniu katalogu danych bez dalszej interakcji z init .

Jeśli Keymaster nie zostanie w pełni uruchomiony podczas działania mount_all , nie odpowie na vold , dopóki nie odczyta pewnych właściwości z init , co spowoduje dokładnie opisany impas. Umieszczenie exec_start wait_for_keymaster nad odpowiednim wywołaniem mount_all , jak określono, gwarantuje, że Keymaster będzie w pełni działać z wyprzedzeniem, co pozwoli uniknąć tego impasu.

Konfiguracja dostępnej pamięci masowej

Od wersji Androida 9 forma szyfrowania metadanych jest zawsze włączona w dostępnej 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 dostępnej pamięci masowej: przestarzała oparta na dm-crypt i nowsza oparta na dm-default-key . Aby mieć pewność, że dla Twojego urządzenia została wybrana prawidłowa implementacja, upewnij się, że ustawiłeś prawidłową wartość PRODUCT_SHIPPING_API_LEVEL w device.mk . Na przykład, jeśli Twoje urządzenie uruchamia się z systemem Android 11 (poziom API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Możesz także ustawić następujące właściwości systemu, aby wymusić użycie nowej metody szyfrowania metadanych woluminów (i nowej domyślnej wersji zasad FBE) niezależnie od poziomu 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

Aktualna metoda

Na urządzeniach z systemem Android 11 lub nowszym szyfrowanie metadanych w dostępnej pamięci masowej wykorzystuje moduł jądra dm-default-key , podobnie jak w przypadku pamięci wewnętrznej. Zobacz wymagania wstępne powyżej, aby dowiedzieć się, które opcje konfiguracji jądra należy włączyć. Należy pamiętać, że wbudowany sprzęt szyfrujący działający w wewnętrznej pamięci urządzenia może być niedostępny w dostępnej pamięci masowej i dlatego może być wymagane ustawienie CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y .

Domyślnie metoda szyfrowania metadanych woluminu dm-default-key wykorzystuje algorytm szyfrowania AES-256-XTS z sektorami kryptograficznymi o wielkości 4096 bajtów. Algorytm można zastąpić, 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 metadata_encryption fstab. Na przykład na urządzeniach pozbawionych akceleracji AES szyfrowanie Adiantum można włączyć, ustawiając ro.crypto.volume.metadata.encryption=adiantum .

Metoda starsza

Na urządzeniach z systemem Android 10 lub starszym szyfrowanie metadanych w dostępnej pamięci wykorzystuje moduł 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, że zawartość pliku jest szyfrowana dwukrotnie: raz kluczem FBE i raz kluczem szyfrowania metadanych. To podwójne szyfrowanie zmniejsza wydajność i nie jest wymagane do osiągnięcia celów bezpieczeństwa szyfrowania metadanych, ponieważ system Android gwarantuje, ż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 poprzez wdrożenie allow_encrypt_override , którą 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 sektorami kryptograficznymi ESSIV i 512-bajtowymi. Można to obejść, 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 . Z Adiantum można korzystać jedynie wtedy, gdy urządzenie nie posiada akceleracji AES.
  • ro.crypto.fde_sector_size wybiera rozmiar sektora kryptograficznego. Dostępne wartości to 512, 1024, 2048 i 4096. W przypadku szyfrowania Adiantum użyj wartości 4096.