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. Te klucze służą do szyfrowania zarówno zawartości, jak i nazw plików. Gdy używany jest FBE, inne informacje, takie jak układy 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 podczas uruchamiania systemu szyfruje zawartość, która nie została zaszyfrowana przez FBE. Ten klucz jest chroniony przez Keymaster, który z kolei jest chroniony przez zweryfikowany rozruch.

Szyfrowanie metadanych jest zawsze włączone w przypadku adaptowalnej pamięci masowej , gdy włączone jest 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.

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

Wymagania 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ń; to nie jest coś, co OTA powinno zmienić.

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 niezależną od sprzętu i producenta strukturę 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ęt, 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ć sprzętu do szyfrowania wbudowanego, konieczne jest również włączenie awaryjnego interfejsu API kryptografii jądra:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

Jeśli nie korzystasz ze sprzętu do szyfrowania wbudowanego, należy również włączyć dostępne przyspieszenie oparte na procesorze, zgodnie z zaleceniami w dokumentacji FBE .

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

Skonfiguruj system plików metadanych

Ponieważ niczego w partycji danych użytkownika nie można odczytać, dopóki nie będzie obecny klucz szyfrowania metadanych, tablica partycji musi odłożyć oddzielną partycję zwaną „partycją metadanych” do przechowywania obiektów BLOB wzorca klucza, które chronią ten klucz. Partycja metadanych powinna mieć rozmiar 16 MB.

fstab.hardware musi zawierać wpis dla systemu plików metadanych, który znajduje się na tej partycji, montując go w /metadata , w tym flagę formattable , aby upewnić się, że jest sformatowany podczas uruchamiania. 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 init

Gdy używane jest szyfrowanie metadanych, vold musi być uruchomione przed zamontowaniem /data . Aby upewnić się, że zostanie uruchomiony wystarczająco 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 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 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ślnym 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 bez 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 do 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 jest uruchamiane 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, uruchom testy opisane poniżej. Należy również pamiętać 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

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ą się nieznacznie różnić od powyższych. Na przykład, jeśli włączyłeś szyfrowanie Adiantum , trzecie pole będzie miało postać 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 z szyfrowaniem metadanych i zamontować partycję. Na czas trwania tego wywołania init jest blokowany, a próby odczytania 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 przy czytaniu lub ustawianiu właściwości, nastąpi zakleszczenie. Ważne jest, aby vold mógł ukończyć odczytywanie kluczy, interakcję z Keymaster i montowanie katalogu danych bez dalszej interakcji z init .

Jeśli Keymaster nie jest w pełni uruchomiony podczas uruchamiania 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, zapewnia, że ​​Keymaster jest w pełni uruchomiony z wyprzedzeniem, a tym samym pozwala uniknąć impasu.

Konfiguracja na adaptowalnej pamięci masowej

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

W AOSP istnieją dwie implementacje szyfrowania metadanych w pamięci masowej: przestarzała oparta na dm-crypt i nowsza oparta na dm-default-key . Aby upewnić się, że wybrano poprawną implementację dla Twojego urządzenia, upewnij się, że ustawiłeś prawidłową wartość dla PRODUCT_SHIPPING_API_LEVEL w device.mk . Na przykład, jeśli Twoje urządzenie jest uruchamiane z systemem Android 11 (poziom API 30), device.mk powinien zawierać:

PRODUCT_SHIPPING_API_LEVEL := 30

Można również ustawić następujące właściwości systemu, aby wymusić użycie nowej metody szyfrowania metadanych woluminu (oraz nowej domyślnej wersji zasad 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 adaptowalnej pamięci masowej wykorzystuje moduł jądra dm-default-key , podobnie jak w przypadku pamięci wewnętrznej. Zobacz powyższe wymagania wstępne , aby dowiedzieć się, które opcje konfiguracji jądra włączyć. Należy pamiętać, ż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ć wymagany CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y .

Domyślnie metoda szyfrowania metadanych woluminu dm-default-key wykorzystuje algorytm szyfrowania AES-256-XTS z 4096-bajtowymi sektorami kryptograficznymi. Algorytm można przesłonić, 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 bez akceleracji AES szyfrowanie Adiantum można włączyć, ustawiając ro.crypto.volume.metadata.encryption=adiantum .

Starsza metoda

Na urządzeniach uruchamianych z Androidem 10 lub starszym szyfrowanie metadanych w możliwej do adaptacji pamięci masowej wykorzystuje moduł 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 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ą dostosowywać jądro, aby uniknąć podwójnego szyfrowania, w szczególności poprzez implementację opcji allow_encrypt_override , którą system Android przekaże 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 zmienić, ustawiając następujące właściwości systemowe (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że być używane tylko wtedy, gdy urządzenie nie posiada akceleracji AES.
  • ro.crypto.fde_sector_size wybiera rozmiar sektora kryptograficznego. Do wyboru są 512, 1024, 2048 i 4096. Do szyfrowania Adiantum użyj 4096.