Szyfrowanie całego dysku

Szyfrowanie całego dysku to proces kodowania wszystkich danych użytkownika na urządzeniu z Androidem przy użyciu zaszyfrowanego klucza. Po zaszyfrowaniu urządzenia wszystkie dane utworzone przez użytkownika są automatycznie szyfrowane przed zapisaniem ich na dysku, a wszystkie odczyty automatycznie odszyfrowują dane przed zwróceniem ich do procesu wywołującego.

Szyfrowanie całego dysku zostało wprowadzone do Androida w wersji 4.4, ale Android 5.0 wprowadził następujące nowe funkcje:

  • Utworzono szybkie szyfrowanie, które szyfruje tylko używane bloki na partycji danych, aby uniknąć długiego czasu pierwszego uruchomienia. Tylko systemy plików ext4 i f2fs obsługują obecnie szybkie szyfrowanie.
  • Dodano flagę forceencrypt fstab do szyfrowania przy pierwszym uruchomieniu.
  • Dodano obsługę wzorców i szyfrowania bez hasła.
  • Dodano sprzętowe przechowywanie klucza szyfrowania przy użyciu funkcji podpisywania Trusted Execution Environment (TEE) (na przykład w strefie TrustZone). Zobacz Przechowywanie zaszyfrowanego klucza, aby uzyskać więcej informacji.

Uwaga: urządzenia zaktualizowane do Androida 5.0, a następnie zaszyfrowane, mogą zostać przywrócone do stanu niezaszyfrowanego przez przywrócenie danych fabrycznych. Nowe urządzenia z systemem Android 5.0 zaszyfrowane przy pierwszym uruchomieniu nie mogą zostać przywrócone do stanu niezaszyfrowanego.

Jak działa szyfrowanie całego dysku w systemie Android

Szyfrowanie całego dysku w systemie Android jest oparte na dm-crypt , która jest funkcją jądra działającą w warstwie urządzenia blokowego. Z tego powodu szyfrowanie działa z Embedded MultiMediaCard ( eMMC) i podobnymi urządzeniami flash, które przedstawiają się jądru jako urządzenia blokowe. Szyfrowanie nie jest możliwe w przypadku YAFFS, który komunikuje się bezpośrednio z surowym układem flash NAND.

Algorytm szyfrowania to 128 Advanced Encryption Standard (AES) z łańcuchem bloków szyfrowania (CBC) i ESSIV: SHA256. Klucz główny jest szyfrowany 128-bitowym kluczem AES za pośrednictwem wywołań biblioteki OpenSSL. Musisz użyć 128 bitów lub więcej dla klucza (256 jest opcjonalne).

Uwaga: producenci OEM mogą używać wersji 128-bitowej lub nowszej do szyfrowania klucza głównego.

W wersji Androida 5.0 istnieją cztery rodzaje stanów szyfrowania:

  • domyślny
  • SZPILKA
  • hasło
  • wzór

Przy pierwszym uruchomieniu urządzenie tworzy losowo generowany 128-bitowy klucz główny, a następnie miesza go z domyślnym hasłem i przechowywaną solą. Domyślne hasło to: „default_password” Jednak wynikowy skrót jest również podpisany przez TEE (taki jak TrustZone), który używa skrótu podpisu do zaszyfrowania klucza głównego.

Domyślne hasło można znaleźć w pliku cryptfs.cpp projektu Android Open Source Project.

Gdy użytkownik ustawia kod PIN/hasło lub hasło na urządzeniu, tylko klucz 128-bitowy jest ponownie szyfrowany i przechowywany. (tj. zmiany kodu PIN/hasła/wzorca użytkownika NIE powodują ponownego zaszyfrowania danych użytkownika). Należy pamiętać, że zarządzane urządzenie może podlegać ograniczeniom dotyczącym kodu PIN, wzoru lub hasła.

Szyfrowanie jest zarządzane przez init i vold . init wywołuje vold , a vold ustawia właściwości wyzwalające zdarzenia w init. Inne części systemu również patrzą na właściwości, aby wykonywać zadania, takie jak raportowanie stanu, prośba o hasło lub monit o przywrócenie ustawień fabrycznych w przypadku błędu krytycznego. Aby wywołać funkcje szyfrowania w vold , system używa poleceń cryptfs narzędzia wiersza cryptfs vdc : checkpw , restart , enablecrypto , changepw , cryptocomplete , verifypw , setfield , getfield , mountdefaultencrypted , getpwtype , getpw i clearpw .

Aby zaszyfrować, odszyfrować lub wyczyścić /data , /data nie może być montowany. Jednak aby wyświetlić dowolny interfejs użytkownika (UI), platforma musi zostać uruchomiona, a struktura wymaga uruchomienia /data . Aby rozwiązać tę zagadkę, tymczasowy system plików jest montowany na /data . Dzięki temu system Android może w razie potrzeby pytać o hasło, pokazywać postęp lub sugerować wymazanie danych. Narzuca to ograniczenie, że aby przełączyć się z tymczasowego systemu plików na prawdziwy system plików /data , system musi zatrzymać każdy proces z otwartymi plikami w tymczasowym systemie plików i ponownie uruchomić te procesy w rzeczywistym systemie plików /data . Aby to zrobić, wszystkie usługi muszą należeć do jednej z trzech grup: core , main i late_start .

  • core : Nigdy nie wyłączaj po uruchomieniu.
  • main : Zamknij, a następnie uruchom ponownie po wprowadzeniu hasła do dysku.
  • late_start : Nie uruchamia się, dopóki /data nie zostanie odszyfrowane i zamontowane.

Aby wywołać te akcje, właściwość vold.decrypt jest ustawiana na różne ciągi znaków . Aby zabić i ponownie uruchomić usługi, polecenia init to:

  • class_reset : zatrzymuje usługę, ale umożliwia jej ponowne uruchomienie za pomocą class_start.
  • class_start : Ponownie uruchamia usługę.
  • class_stop : Zatrzymuje usługę i dodaje flagę SVC_DISABLED . Zatrzymane usługi nie odpowiadają na class_start .

przepływy

Istnieją cztery przepływy dla zaszyfrowanego urządzenia. Urządzenie jest szyfrowane tylko raz, a następnie następuje normalny proces rozruchu.

  • Zaszyfruj wcześniej niezaszyfrowane urządzenie:
    • Zaszyfruj nowe urządzenie za pomocą forceencrypt : Obowiązkowe szyfrowanie przy pierwszym uruchomieniu (począwszy od Androida L).
    • Zaszyfruj istniejące urządzenie: szyfrowanie inicjowane przez użytkownika (Android K i wcześniejsze).
  • Uruchom zaszyfrowane urządzenie:
    • Uruchamianie zaszyfrowanego urządzenia bez hasła: Uruchamianie zaszyfrowanego urządzenia, które nie ma ustawionego hasła (dotyczy urządzeń z systemem Android 5.0 lub nowszym).
    • Uruchamianie zaszyfrowanego urządzenia z hasłem: Uruchamianie zaszyfrowanego urządzenia z ustawionym hasłem.

Oprócz tych przepływów urządzenie może również nie zaszyfrować /data . Każdy z przepływów został szczegółowo wyjaśniony poniżej.

Zaszyfruj nowe urządzenie za pomocą forceencrypt

Jest to normalne pierwsze uruchomienie urządzenia z systemem Android 5.0.

  1. Wykryj niezaszyfrowany system plików za pomocą flagi forceencrypt

    /data nie jest szyfrowane, ale musi być, ponieważ wymusza to forceencrypt . Odmontuj /data .

  2. Rozpocznij szyfrowanie /data

    vold.decrypt = "trigger_encryption" wyzwala init.rc , co spowoduje, że vold zaszyfruje /data bez hasła. (Żaden nie jest ustawiony, ponieważ powinno to być nowe urządzenie).

  3. Zamontuj tmpfs

    vold montuje tmpfs /data (używając opcji tmpfs z ro.crypto.tmpfs_options ) i ustawia właściwość vold.encrypt_progress na 0. vold przygotowuje tmpfs /data do uruchomienia zaszyfrowanego systemu i ustawia właściwość vold.decrypt na: trigger_restart_min_framework

  4. Wyświetl ramkę, aby pokazać postęp

    Ponieważ urządzenie praktycznie nie ma danych do zaszyfrowania, pasek postępu często nie pojawia się, ponieważ szyfrowanie odbywa się bardzo szybko. Zobacz Szyfrowanie istniejącego urządzenia, aby uzyskać więcej informacji na temat interfejsu postępu.

  5. Gdy /data jest zaszyfrowany, zdejmij platformę

    vold ustawia vold.decrypt na trigger_default_encryption , który uruchamia usługę defaultcrypto . (Spowoduje to rozpoczęcie poniższego przepływu montowania domyślnych zaszyfrowanych danych użytkownika.) trigger_default_encryption sprawdza typ szyfrowania, aby zobaczyć, czy /data jest szyfrowane z hasłem czy bez. Ponieważ urządzenia z Androidem 5.0 są szyfrowane przy pierwszym uruchomieniu, nie powinno być ustawione żadne hasło; dlatego odszyfrowujemy i montujemy /data .

  6. Zamontuj /data

    init następnie montuje /data na tmpfs RAMDisk używając parametrów pobieranych z ro.crypto.tmpfs_options , które są ustawione w init.rc .

  7. Uruchom framework

    vold ustawia vold.decrypt na trigger_restart_framework , co kontynuuje zwykły proces uruchamiania.

Zaszyfruj istniejące urządzenie

Tak się dzieje, gdy szyfrujesz niezaszyfrowane urządzenie z Androidem K lub starszym, które zostało przeniesione do L.

Ten proces jest inicjowany przez użytkownika i jest określany w kodzie jako „szyfrowanie w miejscu”. Gdy użytkownik zdecyduje się zaszyfrować urządzenie, interfejs użytkownika upewnia się, że bateria jest w pełni naładowana, a zasilacz sieciowy jest podłączony, aby zapewnić wystarczającą moc do zakończenia procesu szyfrowania.

Ostrzeżenie: jeśli urządzenie wyczerpie się i wyłączy przed zakończeniem szyfrowania, dane pliku pozostaną w stanie częściowo zaszyfrowanym. Urządzenie musi zostać zresetowane do ustawień fabrycznych, a wszystkie dane zostaną utracone.

Aby włączyć szyfrowanie w miejscu, vold uruchamia pętlę w celu odczytania każdego sektora rzeczywistego urządzenia blokowego, a następnie zapisania go w urządzeniu kryptograficznym. vold sprawdza, czy sektor jest używany przed odczytaniem i zapisaniem, co sprawia, że ​​szyfrowanie jest znacznie szybsze na nowym urządzeniu, które ma niewiele danych lub nie ma ich wcale.

Stan urządzenia : Ustaw ro.crypto.state = "unencrypted" i wykonaj wyzwalacz init on nonencrypted aby kontynuować uruchamianie.

  1. Sprawdź hasło

    Interfejs użytkownika wywołuje vold za pomocą polecenia cryptfs enablecrypto inplace , gdzie passwd to hasło użytkownika do ekranu blokady.

  2. Zdejmij ramkę

    vold sprawdza błędy, zwraca -1, jeśli nie może zaszyfrować i wypisuje przyczynę w dzienniku. Jeśli może szyfrować, ustawia właściwość vold.decrypt na trigger_shutdown_framework . Powoduje to, że init.rc zatrzymuje usługi w klasach late_start i main .

  3. Utwórz stopkę kryptograficzną
  4. Utwórz plik nawigacyjny
  5. Ponowne uruchomienie
  6. Wykryj plik breadcrumb
  7. Rozpocznij szyfrowanie /data

    vold następnie konfiguruje mapowanie kryptograficzne, które tworzy wirtualne urządzenie blokowe szyfrujące, które mapuje na rzeczywiste urządzenie blokowe, ale szyfruje każdy sektor podczas zapisywania i odszyfrowuje każdy sektor podczas odczytu. vold następnie tworzy i zapisuje metadane kryptograficzne.

  8. Podczas szyfrowania zamontuj tmpfs

    vold montuje tmpfs /data (używając opcji tmpfs z ro.crypto.tmpfs_options ) i ustawia właściwość vold.encrypt_progress na 0. vold przygotowuje tmpfs /data do uruchomienia zaszyfrowanego systemu i ustawia właściwość vold.decrypt na: trigger_restart_min_framework

  9. Wyświetl ramkę, aby pokazać postęp

    trigger_restart_min_framework powoduje, że init.rc uruchamia main klasę usług. Kiedy framework widzi, że vold.encrypt_progress jest ustawiony na 0, wyświetla interfejs paska postępu, który co pięć sekund wysyła zapytanie o tę właściwość i aktualizuje pasek postępu. Pętla szyfrowania aktualizuje vold.encrypt_progress za każdym razem, gdy szyfruje kolejny procent partycji.

  10. Gdy /data jest szyfrowane, zaktualizuj stopkę kryptograficzną

    Gdy polecenie /data zostanie pomyślnie zaszyfrowane, vold czyści flagę ENCRYPTION_IN_PROGRESS w metadanych.

    Gdy urządzenie zostanie pomyślnie odblokowane, hasło jest następnie używane do zaszyfrowania klucza głównego, a stopka kryptograficzna jest aktualizowana.

    Jeśli ponowne uruchomienie nie powiedzie się z jakiegoś powodu, vold ustawia właściwość vold.encrypt_progress na error_reboot_failed , a interfejs użytkownika powinien wyświetlić komunikat z prośbą o naciśnięcie przycisku w celu ponownego uruchomienia. Nie oczekuje się, że kiedykolwiek to nastąpi.

Uruchamianie zaszyfrowanego urządzenia z domyślnym szyfrowaniem

Tak się dzieje, gdy uruchamiasz zaszyfrowane urządzenie bez hasła. Ponieważ urządzenia z Androidem 5.0 są szyfrowane przy pierwszym uruchomieniu, nie powinno być ustawionego hasła i dlatego jest to domyślny stan szyfrowania .

  1. Wykryj zaszyfrowane /data bez hasła

    Wykryj, że urządzenie z Androidem jest zaszyfrowane, ponieważ /data nie może być zamontowane i ustawiona jest jedna z flag encryptable lub forceencrypt .

    vold ustawia vold.decrypt na trigger_default_encryption , co uruchamia usługę defaultcrypto . trigger_default_encryption sprawdza typ szyfrowania, aby zobaczyć, czy /data jest szyfrowane z hasłem czy bez niego.

  2. Odszyfruj /dane

    Tworzy urządzenie dm-crypt na urządzeniu blokowym, dzięki czemu urządzenie jest gotowe do użycia.

  3. Zamontuj /dane

    vold następnie montuje odszyfrowaną partycję rzeczywistą /data , a następnie przygotowuje nową partycję. Ustawia właściwość vold.post_fs_data_done na 0, a następnie ustawia vold.decrypt na trigger_post_fs_data . To powoduje, że init.rc uruchamia swoje polecenia post-fs-data . Stworzą wszelkie niezbędne katalogi lub linki, a następnie ustawią vold.post_fs_data_done na 1.

    Gdy vold zobaczy 1 w tej właściwości, ustawia właściwość vold.decrypt na: trigger_restart_framework. Powoduje to, że init.rc ponownie uruchamia usługi w klasie main , a także uruchamia usługi w klasie late_start po raz pierwszy od uruchomienia.

  4. Uruchom framework

    Teraz framework uruchamia wszystkie swoje usługi przy użyciu odszyfrowanego /data , a system jest gotowy do użycia.

Uruchamianie zaszyfrowanego urządzenia bez domyślnego szyfrowania

Tak się dzieje, gdy uruchamiasz zaszyfrowane urządzenie z ustawionym hasłem. Hasłem urządzenia może być kod PIN, wzór lub hasło.

  1. Wykryj zaszyfrowane urządzenie za pomocą hasła

    Wykryj, że urządzenie z Androidem jest zaszyfrowane, ponieważ flaga ro.crypto.state = "encrypted"

    vold ustawia vold.decrypt na trigger_restart_min_framework , ponieważ /data jest zaszyfrowane hasłem.

  2. Zamontuj tmpfs

    init ustawia pięć właściwości, aby zapisać początkowe opcje montowania podane dla /data z parametrami przekazanymi z init.rc . vold używa tych właściwości do skonfigurowania mapowania kryptograficznego:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (8-cyfrowy numer szesnastkowy ASCII poprzedzony 0x)
  3. Uruchom platformę, aby monitować o hasło

    Framework uruchamia się i widzi, że vold.decrypt jest ustawiony na trigger_restart_min_framework . Mówi to frameworkowi, że uruchamia się na dysku tmpfs /data i musi uzyskać hasło użytkownika.

    Najpierw jednak musi upewnić się, że dysk został odpowiednio zaszyfrowany. Wysyła polecenie cryptfs cryptocomplete do vold . vold zwraca 0, jeśli szyfrowanie zakończyło się pomyślnie, -1 w przypadku błędu wewnętrznego lub -2, jeśli szyfrowanie nie zakończyło się pomyślnie. vold określa to, wyszukując w metadanych kryptograficznych flagę CRYPTO_ENCRYPTION_IN_PROGRESS . Jeśli jest ustawiona, proces szyfrowania został przerwany i na urządzeniu nie ma użytecznych danych. Jeśli vold zwróci błąd, interfejs użytkownika powinien wyświetlić użytkownikowi komunikat o konieczności ponownego uruchomienia i przywrócenia ustawień fabrycznych urządzenia oraz dać użytkownikowi przycisk do naciśnięcia, aby to zrobić.

  4. Odszyfruj dane za pomocą hasła

    Gdy cryptfs cryptocomplete zakończy się pomyślnie, framework wyświetli interfejs użytkownika z prośbą o podanie hasła do dysku. Interfejs użytkownika sprawdza hasło, wysyłając polecenie cryptfs checkpw do vold . Jeśli hasło jest poprawne (co jest określane przez pomyślne zamontowanie odszyfrowanych /data w tymczasowej lokalizacji, a następnie odmontowanie), vold zapisuje nazwę odszyfrowanego urządzenia blokowego we właściwości ro.crypto.fs_crypto_blkdev i zwraca stan 0 do interfejsu użytkownika . Jeśli hasło jest nieprawidłowe, zwraca -1 do interfejsu użytkownika.

  5. Zatrzymaj ramy

    Interfejs użytkownika wyświetla grafikę rozruchową kryptograficzną, a następnie wywołuje vold za pomocą polecenia cryptfs restart . vold ustawia właściwość vold.decrypt na trigger_reset_main , co powoduje, że init.rc wykonuje class_reset main . Spowoduje to zatrzymanie wszystkich usług w klasie głównej, co umożliwi odmontowanie tmpfs /data .

  6. Zamontuj /data

    vold następnie montuje odszyfrowaną partycję rzeczywistą /data i przygotowuje nową partycję (która mogła nigdy nie zostać przygotowana, jeśli została zaszyfrowana opcją czyszczenia, która nie jest obsługiwana w pierwszym wydaniu). Ustawia właściwość vold.post_fs_data_done na 0, a następnie ustawia vold.decrypt na trigger_post_fs_data . To powoduje, że init.rc uruchamia swoje polecenia post-fs-data . Utworzą wszelkie niezbędne katalogi lub łącza, a następnie ustawią vold.post_fs_data_done na 1. Gdy vold zobaczy 1 w tej właściwości, ustawi właściwość vold.decrypt na trigger_restart_framework . Powoduje to, że init.rc ponownie uruchamia usługi w klasie main , a także uruchamia usługi w klasie late_start po raz pierwszy od uruchomienia.

  7. Uruchom pełną strukturę

    Teraz framework uruchamia wszystkie swoje usługi przy użyciu odszyfrowanego systemu plików /data , a system jest gotowy do użycia.

Awaria

Urządzenie, którego nie udaje się odszyfrować, może działać nieprawidłowo z kilku powodów. Urządzenie rozpoczyna się od normalnej serii kroków do uruchomienia:

  1. Wykryj zaszyfrowane urządzenie za pomocą hasła
  2. Zamontuj tmpfs
  3. Uruchom platformę, aby monitować o hasło

Ale po otwarciu struktury urządzenie może napotkać pewne błędy:

  • Hasło pasuje, ale nie można odszyfrować danych
  • Użytkownik wprowadza błędne hasło 30 razy

Jeśli te błędy nie zostaną rozwiązane, poproś użytkownika o wyczyszczenie ustawień fabrycznych :

Jeśli vold wykryje błąd podczas procesu szyfrowania i jeśli żadne dane nie zostały jeszcze zniszczone, a struktura działa, vold ustawia właściwość vold.encrypt_progress na error_not_encrypted . Interfejs użytkownika monituje użytkownika o ponowne uruchomienie i ostrzega, że ​​proces szyfrowania nigdy się nie rozpoczął. Jeśli błąd wystąpi po rozebraniu frameworka, ale przed wyświetleniem paska postępu, vold zrestartuje system. Jeśli ponowne uruchomienie się nie powiedzie, ustawia vold.encrypt_progress na error_shutting_down i zwraca -1; ale nie będzie co wyłapywać błędu. Nie oczekuje się, że tak się stanie.

Jeśli vold wykryje błąd podczas procesu szyfrowania, ustawia vold.encrypt_progress na error_partially_encrypted i zwraca -1. Interfejs użytkownika powinien następnie wyświetlić komunikat informujący, że szyfrowanie nie powiodło się, i udostępnić przycisk umożliwiający użytkownikowi przywrócenie ustawień fabrycznych urządzenia.

Przechowywanie zaszyfrowanego klucza

Zaszyfrowany klucz jest przechowywany w metadanych kryptograficznych. Wsparcie sprzętowe jest realizowane przy użyciu funkcji podpisywania Trusted Execution Environment (TEE). Wcześniej szyfrowaliśmy klucz główny kluczem generowanym przez zastosowanie skryptu do hasła użytkownika i przechowywanej soli. Aby klucz był odporny na ataki off-box, rozszerzamy ten algorytm, podpisując wynikowy klucz przechowywanym kluczem TEE. Wynikowa sygnatura jest następnie przekształcana w klucz o odpowiedniej długości przez jeszcze jedno zastosowanie skryptu. Ten klucz jest następnie używany do szyfrowania i odszyfrowywania klucza głównego. Aby zapisać ten klucz:

  1. Wygeneruj losowy 16-bajtowy klucz szyfrowania dysku (DEK) i 16-bajtowy klucz soli.
  2. Zastosuj scrypt do hasła użytkownika i soli, aby utworzyć 32-bajtowy klucz pośredni 1 (IK1).
  3. Pad IK1 z zerowymi bajtami do rozmiaru sprzętowego klucza prywatnego (HBK). W szczególności wypełniamy jako: 00 || IK1 || 00..00; jeden bajt zerowy, 32 bajty IK1, 223 bajty zerowe.
  4. Zarejestruj wyściełane IK1 za pomocą HBK, aby uzyskać 256-bajtowy IK2.
  5. Zastosuj skrypt do IK2 i sól (taką samą sól jak w kroku 2), aby utworzyć 32-bajtowy IK3.
  6. Użyj pierwszych 16 bajtów IK3 jako KEK, a ostatnich 16 bajtów jako IV.
  7. Zaszyfruj DEK za pomocą AES_CBC, za pomocą klucza KEK i wektora inicjującego IV.

Zmiana hasła

Gdy użytkownik zdecyduje się zmienić lub usunąć swoje hasło w ustawieniach, interfejs użytkownika wysyła polecenie cryptfs changepw do vold , a vold ponownie szyfruje klucz główny dysku przy użyciu nowego hasła.

Właściwości szyfrowania

vold i init komunikują się ze sobą, ustawiając właściwości. Oto lista dostępnych właściwości do szyfrowania.

Właściwości Volda

Nieruchomość Opis
vold.decrypt trigger_encryption Zaszyfruj dysk bez hasła.
vold.decrypt trigger_default_encryption Sprawdź dysk, aby zobaczyć, czy jest zaszyfrowany bez hasła. Jeśli tak, odszyfruj i zamontuj go, w przeciwnym razie ustaw vold.decrypt na trigger_restart_min_framework.
vold.decrypt trigger_reset_main Ustaw przez vold, aby zamknąć interfejs użytkownika z pytaniem o hasło do dysku.
vold.decrypt trigger_post_fs_data Ustaw przez vold na prep /data z niezbędnymi katalogami i in.
vold.decrypt trigger_restart_framework Ustaw przez vold, aby uruchomić prawdziwy framework i wszystkie usługi.
vold.decrypt trigger_shutdown_framework Ustaw przez vold, aby zamknąć pełną platformę, aby rozpocząć szyfrowanie.
vold.decrypt trigger_restart_min_framework Ustaw przez vold, aby uruchomić interfejs użytkownika paska postępu do szyfrowania lub monitu o hasło, w zależności od wartości ro.crypto.state .
vold.encrypt_progress Po uruchomieniu platformy, jeśli ta właściwość jest ustawiona, wejdź w tryb interfejsu użytkownika paska postępu.
vold.encrypt_progress 0 to 100 Interfejs paska postępu powinien wyświetlać ustawioną wartość procentową.
vold.encrypt_progress error_partially_encrypted Interfejs paska postępu powinien wyświetlać komunikat o niepowodzeniu szyfrowania i umożliwiać użytkownikowi przywrócenie ustawień fabrycznych urządzenia.
vold.encrypt_progress error_reboot_failed Interfejs użytkownika paska postępu powinien wyświetlać komunikat informujący o zakończeniu szyfrowania i udostępniać użytkownikowi przycisk umożliwiający ponowne uruchomienie urządzenia. Nie oczekuje się wystąpienia tego błędu.
vold.encrypt_progress error_not_encrypted Interfejs paska postępu powinien wyświetlać komunikat informujący o wystąpieniu błędu, że żadne dane nie zostały zaszyfrowane ani utracone, a także dać użytkownikowi przycisk umożliwiający ponowne uruchomienie systemu.
vold.encrypt_progress error_shutting_down Interfejs paska postępu nie działa, więc nie jest jasne, kto zareaguje na ten błąd. I tak nigdy nie powinno się to zdarzyć.
vold.post_fs_data_done 0 Ustaw przez vold tuż przed ustawieniem vold.decrypt na trigger_post_fs_data .
vold.post_fs_data_done 1 Ustawiany przez init.rc lub init.rc zaraz po zakończeniu zadania post-fs-data .

właściwości początkowe

Nieruchomość Opis
ro.crypto.fs_crypto_blkdev Ustawiany komendą vold checkpw do późniejszego użycia przez komendę vold restart .
ro.crypto.state unencrypted Ustawiony przez init , aby powiedzieć, że ten system działa z niezaszyfrowanym /data ro.crypto.state encrypted . Ustawiony przez init , aby powiedzieć, że ten system działa z zaszyfrowanym /data .

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

Te pięć właściwości jest ustawianych przez init , gdy próbuje zamontować /data z parametrami przekazanymi z init.rc . vold używa ich do skonfigurowania mapowania kryptograficznego.
ro.crypto.tmpfs_options Ustawiane przez init.rc z opcjami, których init powinien używać podczas montowania systemu plików tmpfs /data .

Rozpocznij działania

on post-fs-data
on nonencrypted
on property:vold.decrypt=trigger_reset_main
on property:vold.decrypt=trigger_post_fs_data
on property:vold.decrypt=trigger_restart_min_framework
on property:vold.decrypt=trigger_restart_framework
on property:vold.decrypt=trigger_shutdown_framework
on property:vold.decrypt=trigger_encryption
on property:vold.decrypt=trigger_default_encryption
,

Szyfrowanie całego dysku to proces kodowania wszystkich danych użytkownika na urządzeniu z Androidem przy użyciu zaszyfrowanego klucza. Po zaszyfrowaniu urządzenia wszystkie dane utworzone przez użytkownika są automatycznie szyfrowane przed zapisaniem ich na dysku, a wszystkie odczyty automatycznie odszyfrowują dane przed zwróceniem ich do procesu wywołującego.

Szyfrowanie całego dysku zostało wprowadzone do Androida w wersji 4.4, ale Android 5.0 wprowadził następujące nowe funkcje:

  • Utworzono szybkie szyfrowanie, które szyfruje tylko używane bloki na partycji danych, aby uniknąć długiego czasu pierwszego uruchomienia. Tylko systemy plików ext4 i f2fs obsługują obecnie szybkie szyfrowanie.
  • Dodano flagę forceencrypt fstab do szyfrowania przy pierwszym uruchomieniu.
  • Dodano obsługę wzorców i szyfrowania bez hasła.
  • Dodano sprzętowe przechowywanie klucza szyfrowania przy użyciu funkcji podpisywania Trusted Execution Environment (TEE) (na przykład w strefie TrustZone). Zobacz Przechowywanie zaszyfrowanego klucza, aby uzyskać więcej informacji.

Uwaga: urządzenia zaktualizowane do Androida 5.0, a następnie zaszyfrowane, mogą zostać przywrócone do stanu niezaszyfrowanego przez przywrócenie danych fabrycznych. Nowe urządzenia z systemem Android 5.0 zaszyfrowane przy pierwszym uruchomieniu nie mogą zostać przywrócone do stanu niezaszyfrowanego.

Jak działa szyfrowanie całego dysku w systemie Android

Szyfrowanie całego dysku w systemie Android jest oparte na dm-crypt , która jest funkcją jądra działającą w warstwie urządzenia blokowego. Z tego powodu szyfrowanie działa z Embedded MultiMediaCard ( eMMC) i podobnymi urządzeniami flash, które przedstawiają się jądru jako urządzenia blokowe. Szyfrowanie nie jest możliwe w przypadku YAFFS, który komunikuje się bezpośrednio z surowym układem flash NAND.

Algorytm szyfrowania to 128 Advanced Encryption Standard (AES) z łańcuchem bloków szyfrowania (CBC) i ESSIV: SHA256. Klucz główny jest szyfrowany 128-bitowym kluczem AES za pośrednictwem wywołań biblioteki OpenSSL. Musisz użyć 128 bitów lub więcej dla klucza (256 jest opcjonalne).

Uwaga: producenci OEM mogą używać wersji 128-bitowej lub nowszej do szyfrowania klucza głównego.

W wersji Androida 5.0 istnieją cztery rodzaje stanów szyfrowania:

  • domyślny
  • SZPILKA
  • hasło
  • wzór

Przy pierwszym uruchomieniu urządzenie tworzy losowo generowany 128-bitowy klucz główny, a następnie miesza go z domyślnym hasłem i przechowywaną solą. Domyślne hasło to: „default_password” Jednak wynikowy skrót jest również podpisany przez TEE (taki jak TrustZone), który używa skrótu podpisu do zaszyfrowania klucza głównego.

Domyślne hasło można znaleźć w pliku cryptfs.cpp projektu Android Open Source Project.

Gdy użytkownik ustawia kod PIN/hasło lub hasło na urządzeniu, tylko klucz 128-bitowy jest ponownie szyfrowany i przechowywany. (tj. zmiany kodu PIN/hasła/wzorca użytkownika NIE powodują ponownego zaszyfrowania danych użytkownika). Należy pamiętać, że zarządzane urządzenie może podlegać ograniczeniom dotyczącym kodu PIN, wzoru lub hasła.

Szyfrowanie jest zarządzane przez init i vold . init wywołuje vold , a vold ustawia właściwości wyzwalające zdarzenia w init. Inne części systemu również patrzą na właściwości, aby wykonywać zadania, takie jak raportowanie stanu, prośba o hasło lub monit o przywrócenie ustawień fabrycznych w przypadku błędu krytycznego. Aby wywołać funkcje szyfrowania w vold , system używa poleceń cryptfs narzędzia wiersza cryptfs vdc : checkpw , restart , enablecrypto , changepw , cryptocomplete , verifypw , setfield , getfield , mountdefaultencrypted , getpwtype , getpw i clearpw .

Aby zaszyfrować, odszyfrować lub wyczyścić /data , /data nie może być montowany. Jednak aby wyświetlić dowolny interfejs użytkownika (UI), platforma musi zostać uruchomiona, a struktura wymaga uruchomienia /data . Aby rozwiązać tę zagadkę, tymczasowy system plików jest montowany na /data . Dzięki temu system Android może w razie potrzeby pytać o hasło, pokazywać postęp lub sugerować wymazanie danych. Narzuca to ograniczenie, że aby przełączyć się z tymczasowego systemu plików na prawdziwy system plików /data , system musi zatrzymać każdy proces z otwartymi plikami w tymczasowym systemie plików i ponownie uruchomić te procesy w rzeczywistym systemie plików /data . Aby to zrobić, wszystkie usługi muszą należeć do jednej z trzech grup: core , main i late_start .

  • core : Nigdy nie wyłączaj po uruchomieniu.
  • main : Zamknij, a następnie uruchom ponownie po wprowadzeniu hasła do dysku.
  • late_start : Nie uruchamia się, dopóki /data nie zostanie odszyfrowane i zamontowane.

Aby wywołać te akcje, właściwość vold.decrypt jest ustawiana na różne ciągi znaków . Aby zabić i ponownie uruchomić usługi, polecenia init to:

  • class_reset : zatrzymuje usługę, ale umożliwia jej ponowne uruchomienie za pomocą class_start.
  • class_start : Ponownie uruchamia usługę.
  • class_stop : Zatrzymuje usługę i dodaje flagę SVC_DISABLED . Zatrzymane usługi nie odpowiadają na class_start .

przepływy

Istnieją cztery przepływy dla zaszyfrowanego urządzenia. Urządzenie jest szyfrowane tylko raz, a następnie następuje normalny proces rozruchu.

  • Zaszyfruj wcześniej niezaszyfrowane urządzenie:
    • Zaszyfruj nowe urządzenie za pomocą forceencrypt : Obowiązkowe szyfrowanie przy pierwszym uruchomieniu (począwszy od Androida L).
    • Zaszyfruj istniejące urządzenie: szyfrowanie inicjowane przez użytkownika (Android K i wcześniejsze).
  • Uruchom zaszyfrowane urządzenie:
    • Uruchamianie zaszyfrowanego urządzenia bez hasła: Uruchamianie zaszyfrowanego urządzenia, które nie ma ustawionego hasła (dotyczy urządzeń z systemem Android 5.0 lub nowszym).
    • Uruchamianie zaszyfrowanego urządzenia z hasłem: Uruchamianie zaszyfrowanego urządzenia z ustawionym hasłem.

Oprócz tych przepływów urządzenie może również nie zaszyfrować /data . Każdy z przepływów został szczegółowo wyjaśniony poniżej.

Zaszyfruj nowe urządzenie za pomocą forceencrypt

Jest to normalne pierwsze uruchomienie urządzenia z systemem Android 5.0.

  1. Wykryj niezaszyfrowany system plików za pomocą flagi forceencrypt

    /data nie jest szyfrowane, ale musi być, ponieważ wymusza to forceencrypt . Odmontuj /data .

  2. Rozpocznij szyfrowanie /data

    vold.decrypt = "trigger_encryption" wyzwala init.rc , co spowoduje, że vold zaszyfruje /data bez hasła. (Żaden nie jest ustawiony, ponieważ powinno to być nowe urządzenie).

  3. Zamontuj tmpfs

    vold montuje tmpfs /data (używając opcji tmpfs z ro.crypto.tmpfs_options ) i ustawia właściwość vold.encrypt_progress na 0. vold przygotowuje tmpfs /data do uruchomienia zaszyfrowanego systemu i ustawia właściwość vold.decrypt na: trigger_restart_min_framework

  4. Wyświetl ramkę, aby pokazać postęp

    Ponieważ urządzenie praktycznie nie ma danych do zaszyfrowania, pasek postępu często nie pojawia się, ponieważ szyfrowanie odbywa się bardzo szybko. Zobacz Szyfrowanie istniejącego urządzenia, aby uzyskać więcej informacji na temat interfejsu postępu.

  5. Gdy /data jest zaszyfrowany, zdejmij platformę

    vold ustawia vold.decrypt na trigger_default_encryption , który uruchamia usługę defaultcrypto . (Spowoduje to rozpoczęcie poniższego przepływu montowania domyślnych zaszyfrowanych danych użytkownika.) trigger_default_encryption sprawdza typ szyfrowania, aby zobaczyć, czy /data jest szyfrowane z hasłem czy bez. Ponieważ urządzenia z Androidem 5.0 są szyfrowane przy pierwszym uruchomieniu, nie powinno być ustawione żadne hasło; dlatego odszyfrowujemy i montujemy /data .

  6. Zamontuj /data

    init następnie montuje /data na tmpfs RAMDisk używając parametrów pobieranych z ro.crypto.tmpfs_options , które są ustawione w init.rc .

  7. Uruchom framework

    vold ustawia vold.decrypt na trigger_restart_framework , co kontynuuje zwykły proces uruchamiania.

Zaszyfruj istniejące urządzenie

Tak się dzieje, gdy szyfrujesz niezaszyfrowane urządzenie z Androidem K lub starszym, które zostało przeniesione do L.

Ten proces jest inicjowany przez użytkownika i jest określany w kodzie jako „szyfrowanie w miejscu”. Gdy użytkownik zdecyduje się zaszyfrować urządzenie, interfejs użytkownika upewnia się, że bateria jest w pełni naładowana, a zasilacz sieciowy jest podłączony, aby zapewnić wystarczającą moc do zakończenia procesu szyfrowania.

Ostrzeżenie: jeśli urządzenie wyczerpie się i wyłączy przed zakończeniem szyfrowania, dane pliku pozostaną w stanie częściowo zaszyfrowanym. Urządzenie musi zostać zresetowane do ustawień fabrycznych, a wszystkie dane zostaną utracone.

Aby włączyć szyfrowanie w miejscu, vold uruchamia pętlę w celu odczytania każdego sektora rzeczywistego urządzenia blokowego, a następnie zapisania go w urządzeniu kryptograficznym. vold sprawdza, czy sektor jest używany przed odczytaniem i zapisaniem, co sprawia, że ​​szyfrowanie jest znacznie szybsze na nowym urządzeniu, które ma niewiele danych lub nie ma ich wcale.

Stan urządzenia : Ustaw ro.crypto.state = "unencrypted" i wykonaj wyzwalacz init on nonencrypted aby kontynuować uruchamianie.

  1. Sprawdź hasło

    Interfejs użytkownika wywołuje vold za pomocą polecenia cryptfs enablecrypto inplace , gdzie passwd to hasło użytkownika do ekranu blokady.

  2. Zdejmij ramkę

    vold sprawdza błędy, zwraca -1, jeśli nie może zaszyfrować i wypisuje przyczynę w dzienniku. Jeśli może szyfrować, ustawia właściwość vold.decrypt na trigger_shutdown_framework . Powoduje to, że init.rc zatrzymuje usługi w klasach late_start i main .

  3. Utwórz stopkę kryptograficzną
  4. Utwórz plik nawigacyjny
  5. Ponowne uruchomienie
  6. Wykryj plik breadcrumb
  7. Rozpocznij szyfrowanie /data

    vold następnie konfiguruje mapowanie kryptograficzne, które tworzy wirtualne urządzenie blokowe szyfrujące, które mapuje na rzeczywiste urządzenie blokowe, ale szyfruje każdy sektor podczas zapisywania i odszyfrowuje każdy sektor podczas odczytu. vold następnie tworzy i zapisuje metadane kryptograficzne.

  8. Podczas szyfrowania zamontuj tmpfs

    vold montuje tmpfs /data (używając opcji tmpfs z ro.crypto.tmpfs_options ) i ustawia właściwość vold.encrypt_progress na 0. vold przygotowuje tmpfs /data do uruchomienia zaszyfrowanego systemu i ustawia właściwość vold.decrypt na: trigger_restart_min_framework

  9. Wyświetl ramkę, aby pokazać postęp

    trigger_restart_min_framework powoduje, że init.rc uruchamia main klasę usług. Kiedy framework widzi, że vold.encrypt_progress jest ustawiony na 0, wyświetla interfejs paska postępu, który co pięć sekund wysyła zapytanie o tę właściwość i aktualizuje pasek postępu. Pętla szyfrowania aktualizuje vold.encrypt_progress za każdym razem, gdy szyfruje kolejny procent partycji.

  10. Gdy /data jest szyfrowane, zaktualizuj stopkę kryptograficzną

    Gdy polecenie /data zostanie pomyślnie zaszyfrowane, vold czyści flagę ENCRYPTION_IN_PROGRESS w metadanych.

    Gdy urządzenie zostanie pomyślnie odblokowane, hasło jest następnie używane do zaszyfrowania klucza głównego, a stopka kryptograficzna jest aktualizowana.

    Jeśli ponowne uruchomienie nie powiedzie się z jakiegoś powodu, vold ustawia właściwość vold.encrypt_progress na error_reboot_failed , a interfejs użytkownika powinien wyświetlić komunikat z prośbą o naciśnięcie przycisku w celu ponownego uruchomienia. Nie oczekuje się, że kiedykolwiek to nastąpi.

Uruchamianie zaszyfrowanego urządzenia z domyślnym szyfrowaniem

Tak się dzieje, gdy uruchamiasz zaszyfrowane urządzenie bez hasła. Ponieważ urządzenia z Androidem 5.0 są szyfrowane przy pierwszym uruchomieniu, nie powinno być ustawionego hasła i dlatego jest to domyślny stan szyfrowania .

  1. Wykryj zaszyfrowane /data bez hasła

    Wykryj, że urządzenie z Androidem jest zaszyfrowane, ponieważ /data nie może być zamontowane i ustawiona jest jedna z flag encryptable lub forceencrypt .

    vold ustawia vold.decrypt na trigger_default_encryption , co uruchamia usługę defaultcrypto . trigger_default_encryption sprawdza typ szyfrowania, aby zobaczyć, czy /data jest szyfrowane z hasłem czy bez niego.

  2. Odszyfruj /dane

    Tworzy urządzenie dm-crypt na urządzeniu blokowym, dzięki czemu urządzenie jest gotowe do użycia.

  3. Zamontuj /dane

    vold następnie montuje odszyfrowaną partycję rzeczywistą /data , a następnie przygotowuje nową partycję. Ustawia właściwość vold.post_fs_data_done na 0, a następnie ustawia vold.decrypt na trigger_post_fs_data . To powoduje, że init.rc uruchamia swoje polecenia post-fs-data . Stworzą wszelkie niezbędne katalogi lub linki, a następnie ustawią vold.post_fs_data_done na 1.

    Gdy vold zobaczy 1 w tej właściwości, ustawia właściwość vold.decrypt na: trigger_restart_framework. Powoduje to, że init.rc ponownie uruchamia usługi w klasie main , a także uruchamia usługi w klasie late_start po raz pierwszy od uruchomienia.

  4. Uruchom framework

    Teraz framework uruchamia wszystkie swoje usługi przy użyciu odszyfrowanego /data , a system jest gotowy do użycia.

Starting an encrypted device without default encryption

This is what happens when you boot up an encrypted device that has a set password. The device's password can be a pin, pattern, or password.

  1. Detect encrypted device with a password

    Detect that the Android device is encrypted because the flag ro.crypto.state = "encrypted"

    vold sets vold.decrypt to trigger_restart_min_framework because /data is encrypted with a password.

  2. Mount tmpfs

    init sets five properties to save the initial mount options given for /data with parameters passed from init.rc . vold uses these properties to set up the crypto mapping:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (ASCII 8-digit hex number preceded by 0x)
  3. Start framework to prompt for password

    The framework starts up and sees that vold.decrypt is set to trigger_restart_min_framework . This tells the framework that it is booting on a tmpfs /data disk and it needs to get the user password.

    First, however, it needs to make sure that the disk was properly encrypted. It sends the command cryptfs cryptocomplete to vold . vold returns 0 if encryption was completed successfully, -1 on internal error, or -2 if encryption was not completed successfully. vold determines this by looking in the crypto metadata for the CRYPTO_ENCRYPTION_IN_PROGRESS flag. If it's set, the encryption process was interrupted, and there is no usable data on the device. If vold returns an error, the UI should display a message to the user to reboot and factory reset the device, and give the user a button to press to do so.

  4. Decrypt data with password

    Once cryptfs cryptocomplete is successful, the framework displays a UI asking for the disk password. The UI checks the password by sending the command cryptfs checkpw to vold . If the password is correct (which is determined by successfully mounting the decrypted /data at a temporary location, then unmounting it), vold saves the name of the decrypted block device in the property ro.crypto.fs_crypto_blkdev and returns status 0 to the UI. If the password is incorrect, it returns -1 to the UI.

  5. Stop framework

    The UI puts up a crypto boot graphic and then calls vold with the command cryptfs restart . vold sets the property vold.decrypt to trigger_reset_main , which causes init.rc to do class_reset main . This stops all services in the main class, which allows the tmpfs /data to be unmounted.

  6. Mount /data

    vold then mounts the decrypted real /data partition and prepares the new partition (which may never have been prepared if it was encrypted with the wipe option, which is not supported on first release). It sets the property vold.post_fs_data_done to 0 and then sets vold.decrypt to trigger_post_fs_data . This causes init.rc to run its post-fs-data commands. They will create any necessary directories or links and then set vold.post_fs_data_done to 1. Once vold sees the 1 in that property, it sets the property vold.decrypt to trigger_restart_framework . This causes init.rc to start services in class main again and also start services in class late_start for the first time since boot.

  7. Start full framework

    Now the framework boots all its services using the decrypted /data filesystem, and the system is ready for use.

Failure

A device that fails to decrypt might be awry for a few reasons. The device starts with the normal series of steps to boot:

  1. Detect encrypted device with a password
  2. Mount tmpfs
  3. Start framework to prompt for password

But after the framework opens, the device can encounter some errors:

  • Password matches but cannot decrypt data
  • User enters wrong password 30 times

If these errors are not resolved, prompt user to factory wipe :

If vold detects an error during the encryption process, and if no data has been destroyed yet and the framework is up, vold sets the property vold.encrypt_progress to error_not_encrypted . The UI prompts the user to reboot and alerts them the encryption process never started. If the error occurs after the framework has been torn down, but before the progress bar UI is up, vold will reboot the system. If the reboot fails, it sets vold.encrypt_progress to error_shutting_down and returns -1; but there will not be anything to catch the error. This is not expected to happen.

If vold detects an error during the encryption process, it sets vold.encrypt_progress to error_partially_encrypted and returns -1. The UI should then display a message saying the encryption failed and provide a button for the user to factory reset the device.

Storing the encrypted key

The encrypted key is stored in the crypto metadata. Hardware backing is implemented by using Trusted Execution Environment's (TEE) signing capability. Previously, we encrypted the master key with a key generated by applying scrypt to the user's password and the stored salt. In order to make the key resilient against off-box attacks, we extend this algorithm by signing the resultant key with a stored TEE key. The resultant signature is then turned into an appropriate length key by one more application of scrypt. This key is then used to encrypt and decrypt the master key. To store this key:

  1. Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
  2. Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
  3. Pad IK1 with zero bytes to the size of the hardware-bound private key (HBK). Specifically, we pad as: 00 || IK1 || 00..00; one zero byte, 32 IK1 bytes, 223 zero bytes.
  4. Sign padded IK1 with HBK to produce 256-byte IK2.
  5. Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
  6. Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
  7. Encrypt DEK with AES_CBC, with key KEK, and initialization vector IV.

Changing the password

When a user elects to change or remove their password in settings, the UI sends the command cryptfs changepw to vold , and vold re-encrypts the disk master key with the new password.

Encryption properties

vold and init communicate with each other by setting properties. Here is a list of available properties for encryption.

Vold properties

Property Description
vold.decrypt trigger_encryption Encrypt the drive with no password.
vold.decrypt trigger_default_encryption Check the drive to see if it is encrypted with no password. If it is, decrypt and mount it, else set vold.decrypt to trigger_restart_min_framework.
vold.decrypt trigger_reset_main Set by vold to shutdown the UI asking for the disk password.
vold.decrypt trigger_post_fs_data Set by vold to prep /data with necessary directories, et al.
vold.decrypt trigger_restart_framework Set by vold to start the real framework and all services.
vold.decrypt trigger_shutdown_framework Set by vold to shutdown the full framework to start encryption.
vold.decrypt trigger_restart_min_framework Set by vold to start the progress bar UI for encryption or prompt for password, depending on the value of ro.crypto.state .
vold.encrypt_progress When the framework starts up, if this property is set, enter the progress bar UI mode.
vold.encrypt_progress 0 to 100 The progress bar UI should display the percentage value set.
vold.encrypt_progress error_partially_encrypted The progress bar UI should display a message that the encryption failed, and give the user an option to factory reset the device.
vold.encrypt_progress error_reboot_failed The progress bar UI should display a message saying encryption completed, and give the user a button to reboot the device. This error is not expected to happen.
vold.encrypt_progress error_not_encrypted The progress bar UI should display a message saying an error occurred, no data was encrypted or lost, and give the user a button to reboot the system.
vold.encrypt_progress error_shutting_down The progress bar UI is not running, so it is unclear who will respond to this error. And it should never happen anyway.
vold.post_fs_data_done 0 Set by vold just before setting vold.decrypt to trigger_post_fs_data .
vold.post_fs_data_done 1 Set by init.rc or init.rc just after finishing the task post-fs-data .

init properties

Property Description
ro.crypto.fs_crypto_blkdev Set by the vold command checkpw for later use by the vold command restart .
ro.crypto.state unencrypted Set by init to say this system is running with an unencrypted /data ro.crypto.state encrypted . Set by init to say this system is running with an encrypted /data .

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

These five properties are set by init when it tries to mount /data with parameters passed in from init.rc . vold uses these to setup the crypto mapping.
ro.crypto.tmpfs_options Set by init.rc with the options init should use when mounting the tmpfs /data filesystem.

Init actions

on post-fs-data
on nonencrypted
on property:vold.decrypt=trigger_reset_main
on property:vold.decrypt=trigger_post_fs_data
on property:vold.decrypt=trigger_restart_min_framework
on property:vold.decrypt=trigger_restart_framework
on property:vold.decrypt=trigger_shutdown_framework
on property:vold.decrypt=trigger_encryption
on property:vold.decrypt=trigger_default_encryption