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:
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:
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 Operacjablk_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 Operacjablk_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” aplikacjavold
używa możliwości, aby wygenerować nowe miejsce na dane do użycia w Androidzie, a funkcja importowania umiejętność jest używana przezvts_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 przezvold
ivts_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
dofileencryption
. Na przykład użyj wartościfileencryption=::inlinecrypt_optimized+wrappedkey_v0
Dla: więcej szczegółów znajdziesz w FBE dokumentacji. - Szyfrowanie metadanych: dodaj flagę
wrappedkey_v0
dometadata_encryption
. Na przykład użyj wartościmetadata_encryption=:wrappedkey_v0
Więcej informacji: metadane dokumentacji dotyczącej szyfrowania.