Klucze opakowane sprzętowo

Podobnie jak w przypadku większości programów do szyfrowania dysków i plików, szyfrowanie miejsca na dane na Androidzie tradycyjnie polega na nieprzetworzonych kluczach szyfrowania dostępnych w pamięci systemowej w celu przeprowadzenia szyfrowania. Nawet po przeprowadzeniu szyfrowania za pomocą specjalnego sprzętu, a nie oprogramowania, oprogramowanie nadal musi i zarządzanie nieprzetworzonymi kluczami szyfrowania.

Zazwyczaj nie jest to traktowane jako problem, ponieważ klucze są niedostępne. podczas ataku offline, który jest głównym rodzajem ataku przed szyfrowaniem. Istnieje jednak potrzeba udostępnienia zwiększona ochrona przed innymi rodzajami ataków, takimi jak zimny rozruch i online, gdzie haker może wycieknąć pamięci bez pełnej szkody dla urządzenia.

Aby rozwiązać ten problem, w Androidzie 11 wprowadzono obsługę w przypadku kluczy opakowanych sprzętowo, które obsługują sprzęt. Klucze opakowane sprzętowo to klucze pamięci znane tylko w postaci nieprzetworzonej dedykowany sprzęt; oprogramowanie wykrywa te klucze i działa z nimi tylko w opakowaniu (zaszyfrowanego). Musi on mieć możliwość generowania i importowania klucze pamięci masowej, opakowanie kluczy pamięci w postaci efemerycznej i długoterminowej, uzyskiwanie bezpośrednio we wbudowanym mechanizmie kryptograficznym. przez zwrócenie osobnego podklucza do oprogramowania.

Uwaga: wbudowany mechanizm kryptograficzny (lub wbudowany) ) odnosi się do sprzętu, który szyfruje/odszyfrowuje dane podczas jest w drodze do/z urządzenia pamięci masowej. Zwykle jest to host UFS lub eMMC. kontroler, który implementuje rozszerzenia kryptograficzne zdefiniowane przez odpowiednie Specyfikacja JEDEC.

Projektowanie

W tej sekcji omawiamy projekt funkcji opakowanych sprzętowo kluczy, w tym jaka pomoc sprzętowa jest do niego wymagana. Koncentrujemy się na szyfrowaniu na podstawie plików (FBE), ale rozwiązanie ma zastosowanie do metadanych także szyfrowanie.

Jednym ze sposobów uniknięcia potrzeby nieprzetworzonych kluczy szyfrowania w pamięci systemowej jest Przechowuj je wyłącznie w blokach kluczy wbudowanego mechanizmu kryptograficznego. Jednak natrafią na pewne problemy:

  • Liczba kluczy szyfrowania może być większa niż liczba przedziałów kluczy.
  • Wbudowane silniki kryptograficzne mogą być używane tylko do szyfrowania/odszyfrowywania pełnych bloków na dysku. Jednak w przypadku FBE oprogramowanie nadal musi mieć możliwość wykonywanie innych działań kryptograficznych, takich jak szyfrowanie nazw plików czy pobieranie kluczy; i identyfikatorów. Oprogramowanie musi mieć dostęp do nieprzetworzonych kluczy FBE, i zająć się czymś innym.

Aby uniknąć tych problemów, klucze pamięci masowej są zamiast tego przekształcane w klucze opakowane sprzętowo, które mogą być tylko wyodrębnione i używane przez dedykowanego sprzętu. Umożliwia to obsługę nieograniczonej liczby kluczy. W hierarchia kluczy zostaje zmodyfikowana i częściowo przeniesiona na ten sprzęt, który pozwala na zwrócenie klucza podrzędnego do oprogramowania w przypadku zadań, które nie mogą używać wbudowany mechanizm kryptograficzny.

Hierarchia kluczy

Klucze można wywnioskować z innych kluczy za pomocą KDF (funkcji derywacji kluczy), np. HKDF, w efekcie hierarchii kluczy.

Poniższy diagram przedstawia typową hierarchię kluczy dla FBE, gdy klucze opakowane sprzętowo nie są używane:

Hierarchia kluczy FBE (standardowa)
Rysunek 1. Hierarchia kluczy FBE (standardowa)
.

Klucz klasy FBE to nieprzetworzony klucz szyfrowania, który Android przekazuje do systemu Linux jądro, aby odblokować określony zestaw zaszyfrowanych katalogów, takich jak szyfrowana danymi uwierzytelniającymi dla konkretnego użytkownika Androida. (W jądrze jest nazywany kluczem głównym fscrypt). Z tego klucza jądro wywodzi tych podkluczy:

  • Identyfikator klucza. Nie jest ona używana do szyfrowania, lecz stanowi wartość. używany do identyfikowania klucza, z którym dany plik lub katalog i chronione.
  • Klucz szyfrowania zawartości pliku
  • Klucz szyfrowania nazw plików

Poniższy diagram przedstawia hierarchię FBE, gdy: są używane klucze opakowane sprzętowo:

Hierarchia kluczy FBE (z kluczem opakowanym sprzętowo)
Rysunek 2. Hierarchia kluczy FBE (z kluczem opakowanym sprzętowo)
.

W porównaniu z wcześniejszym przypadkiem do klucza dodaliśmy dodatkowy poziom. i przenieśliśmy klucz szyfrowania zawartości plików. Poziom główny wciąż reprezentuje klucz, który Android przekazuje do Linuksa, aby odblokować zestaw zaszyfrowanych katalogów. Teraz jednak ten klucz jest zawijany na bieżąco, Aby mógł być używany, musi zostać przekazany do dedykowanego sprzętu. Wymagania sprzętowe: wdrożyć 2 interfejsy, które przyjmują klucz opakowany na bieżąco:

  • Jeden interfejs do dedykowania funkcji inline_encryption_key i bezpośrednio zaprogramować go w bloku kluczy wbudowanego mechanizmu kryptograficznego. Zezwala na plik do szyfrowania/odszyfrowywania bez dostępu oprogramowania do . W typowych jądrach Androida interfejs ten odpowiada Operacja blk_crypto_ll_ops::keyslot_program, którą musi być zaimplementowane przez sterownik pamięci.
  • Jeden interfejs do pobierania i zwracania wartości sw_secret („oprogramowanie tajny" zwany też „nieprzetworzonym tajnym kluczem”, w niektórych miejscach), co jest kluczowe, Linux używa do wyodrębniania kluczy podrzędnych dla wszystkiego oprócz zawartości pliku szyfrowaniem. W typowych jądrach Androida interfejs ten odpowiada Operacja blk_crypto_ll_ops::derive_sw_secret, którą musi być zaimplementowane przez sterownik pamięci.

Aby uzyskać dane inline_encryption_key i sw_secret z funkcji nieprzetworzony klucz pamięci masowej, sprzęt musi korzystać z silnego kryptograficznie silnego klucza KDF. Ten KDF musi przestrzegać sprawdzonych metod kryptograficznych; musi mieć poziom zabezpieczeń co najmniej 256 bitów, czyli tyle, ile wystarczy, aby każdy algorytm, który zostanie później użyty, Musi także używać tagu odrębną etykietę, kontekst i/lub ciąg informacji specyficznych dla aplikacji, gdy wszystkich typów podkluczy, aby zagwarantować, że otrzymane są odizolowane kryptograficznie, tzn. wiedza o jednym z nich nie ujawnia inne. Rozciąganie klucza nie jest wymagane, ponieważ nieprzetworzony klucz pamięci masowej jest już jednolicie losowy klucz.

Technicznie rzecz biorąc, można użyć dowolnego KDF, który spełnia wymagania dotyczące bezpieczeństwa. Do celów testowych należy jednak ponownie wdrożyć tę samą funkcję KDF w i testowania kodu. Obecnie sprawdzono i wdrożono 1 KDF. to da się go znaleźć w kodzie źródłowym strony vts_kernel_encryption_test. Zaleca się, aby sprzęt używał tego kodu KDF, który używa NIST SP 800-108 „KDF w trybie licznika” z AES-256-CMAC jako PRF. Pamiętaj, że aby zapewnić zgodność, wszystkie części algorytmu muszą być identyczne, w tym wybór kontekstów KDF i etykiety poszczególnych podkluczy.

Zawijanie kluczy

Aby osiągnąć cele w zakresie bezpieczeństwa kluczy opakowanych sprzętowo, 2 sposoby dodawania kluczy są zdefiniowane:

  • Zawijanie efemeryczne: sprzęt szyfruje nieprzetworzony klucz za pomocą klucza. który jest generowany losowo przy każdym uruchomieniu i nie jest bezpośrednio ujawniany na zewnątrz urządzenia.
  • Długoterminowe pakowanie: sprzęt szyfruje nieprzetworzony klucz za pomocą metody unikalny, trwały klucz wbudowany w sprzęt, który nie jest bezpośrednio nie są widoczne na zewnątrz sprzętu.

Wszystkie klucze przekazywane do jądra Linuksa w celu odblokowania pamięci masowej są efemerycznie zapakowane. Dzięki temu, jeśli osoba przeprowadzająca atak będzie w stanie wyodrębnić z pamięci systemowej, będzie on bezużyteczny nie tylko poza urządzeniem, ale też na urządzeniu po jego ponownym uruchomieniu.

Jednocześnie Android nadal musi mieć możliwość przechowywania zaszyfrowanej wersji kluczy na dysku, dzięki czemu można je odblokować. Nieprzetworzone do tego celu. Powinniśmy jednak nigdy nie używać klucze są w ogóle dostępne w pamięci systemowej, dzięki czemu nie można ich wyodrębnić być używane poza urządzeniem, nawet jeśli zostały wyodrębnione podczas uruchamiania. Z tego powodu koncepcja długoterminowego pakowania danych.

Aby można było zarządzać kluczami opakowanymi na 2 różne sposoby, sprzęt musi zaimplementuj następujące interfejsy:

  • Interfejsy do generowania i importowania kluczy pamięci, zwracanie ich długoterminową formę zawijaną przez długi czas. Dostęp do tych interfejsów jest możliwy pośrednio przez: KeyMint i odpowiadają tagowi KeyMint (TAG_STORAGE_KEY). Przycisk „Wygeneruj” aplikacja vold używa możliwości, aby wygenerować nowe miejsce na dane do użycia w Androidzie, a funkcja importowania umiejętność jest używana przez vts_kernel_encryption_test, aby zaimportować klucze testowe.
  • Interfejs do konwertowania długoterminowego opakowanego klucza pamięci masowej efemerycznie opakowany klucz pamięci masowej. Odpowiada to Metoda convertStorageKeyToEphemeral KeyMint. Ta metoda jest używana przez vold i vts_kernel_encryption_test w kolejności , aby odblokować miejsce na dane.

Algorytm dodawania kluczy to szczegóły implementacji, ale powinien silny sygnał AEAD, np. AES-256-GCM z losowymi IVW.

Wymagane zmiany w oprogramowaniu

AOSP ma już podstawową platformę do obsługi kluczy opakowanych sprzętowo. Ten obejmuje obsługę komponentów przestrzeni użytkownika, takich jak vold, a także jak ją obsługują w językach blk-crypto, fscrypto oraz dm-default-key.

Wymaga to jednak wprowadzenia pewnych zmian w kontekście implementacji.

Zmiany w KeyMint

Implementację KeyMint urządzenia należy zmodyfikować, aby obsługiwać TAG_STORAGE_KEY i zaimplementuj kod Metoda convertStorageKeyToEphemeral.

W Keymasterze użyto exportKey zamiast convertStorageKeyToEphemeral

Zmiany jądra Linuksa

Musisz zmodyfikować sterownik jądra systemu Linux dla wbudowanego silnika kryptograficznego urządzenia na potrzeby obsługi kluczy opakowanych sprzętowo.

W przypadku jądra systemu android14 i nowszych wersji ustaw BLK_CRYPTO_KEY_TYPE_HW_WRAPPED w blk_crypto_profile::key_types_supported, zrób blk_crypto_ll_ops::keyslot_program i blk_crypto_ll_ops::keyslot_evict obsługi programowania/usuwania opakowanych sprzętowo kluczy, i zaimplementuj blk_crypto_ll_ops::derive_sw_secret.

W przypadku jąder android12 i android13 ustaw BLK_CRYPTO_FEATURE_WRAPPED_KEYS w: blk_keyslot_manager::features, ustaw blk_ksm_ll_ops::keyslot_program i blk_ksm_ll_ops::keyslot_evict obsługi programowania/usuwania opakowanych sprzętowo kluczy, i zaimplementuj blk_ksm_ll_ops::derive_raw_secret.

W przypadku jąder systemu android11 ustaw BLK_CRYPTO_FEATURE_WRAPPED_KEYS w keyslot_manager::features, zrób keyslot_mgmt_ll_ops::keyslot_program i keyslot_mgmt_ll_ops::keyslot_evict obsługi programowania/usuwania opakowanych sprzętowo kluczy, i zaimplementuj keyslot_mgmt_ll_ops::derive_raw_secret.

Testowanie

Chociaż szyfrowanie za pomocą kluczy opakowanych sprzętowo jest trudniejsze do przetestowania niż szyfrowanie za pomocą kluczy standardowych, można przeprowadzać testy przez zaimportowanie klucza testowego i ponownie zaimplementowanie pochodnej kluczy wykorzystywanego przez sprzęt. Ta funkcja jest wdrożona w sekcji vts_kernel_encryption_test. Aby przeprowadzić ten test: bieg:

atest -v vts_kernel_encryption_test

Przeczytaj dziennik testowy i sprawdź, czy najważniejsze przypadki testowe opakowane sprzętowo (np. FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy i DmDefaultKeyTest.TestHwWrappedKey) nie zostały pominięte ze względu na obsługę o ile klucze opakowane sprzętowo nie są wykrywane, ponieważ wyniki testu "zaliczono" w tej sprawie.

Włączam

Gdy obsługa kluczy opakowanych sprzętowo na urządzeniu będzie działać prawidłowo, możesz wprowadź te zmiany w pliku fstab na urządzeniu, Android używa go do szyfrowania FBE i metadanych:

  • FBE: dodaj flagę wrappedkey_v0 do fileencryption. Na przykład użyj wartości fileencryption=::inlinecrypt_optimized+wrappedkey_v0 Dla: więcej szczegółów znajdziesz w FBE dokumentacji.
  • Szyfrowanie metadanych: dodaj flagę wrappedkey_v0 do metadata_encryption. Na przykład użyj wartości metadata_encryption=:wrappedkey_v0 Więcej informacji: metadane dokumentacji dotyczącej szyfrowania.